2
\$\begingroup\$

I want to Implement dissolve shader like this youtube video

as you can see minions projected light on house to burning it out.

I like to know how to make a similar effect.

enter image description here

\$\endgroup\$
  • \$\begingroup\$ that picture is awesome! \$\endgroup\$ – Millard Sep 7 '19 at 17:08
3
\$\begingroup\$

you can make this effect by dissolve in world space.

(I explained the world space in this post)

let's Implement this shader:

Masking Objects by World Space

Record_2019_09_06_19_10_42_503

you can make array of positions and sizes in shader and use world space to fade them.

we also have to signal to the shader that these variables will be modified from outside, hence the uniform qualifier. As it happens in C, there is an extra variable which indicates how many points are actually used.

https://www.alanzucconi.com/2016/01/27/arrays-shaders-heatmaps-in-unity3d/

Shader "Smkgames/worldSpaceFade" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _NormalMap("Normal Map",2D) = "bump" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
    Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
         Pass {
            ZWrite On
            ColorMask 0
        }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows alpha:fade

        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _NormalMap;

        struct Input {
            float2 uv_MainTex;
            float3 worldPos: TEXCOORD2; // using world position
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void vert (inout appdata_full v, out Input o){
            UNITY_INITIALIZE_OUTPUT(Input,o);
            o.worldPos = mul(unity_ObjectToWorld, v.vertex); // calculating world position in vertex shader
        }

        uniform float4 _arrayPosition [5]; // declare array position 
        uniform float _arraySize [5]; // declare array size 

        UNITY_INSTANCING_BUFFER_START(Props)
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;


         float4 color = float4(0,0,0,0); // temp color for using in alpha

         for(int i = 0; i < 5;i++){
             float dist = distance(IN.worldPos, 
               float4(_arrayPosition[i].xyz, 1.0)); // calculate distance in world position

            if (dist < _arraySize[i]) // if distance is smaller than size of each object result is white in mask
            {
               color += float4(1.0, 1.0, 1.0, 1.0); // sum result of dynamic masks
            }
            }


            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha =  saturate(1-color); // saturate to make sure is between 0 and 1 that is equivalent of clamp(value,0,1)
            o.Normal = UnpackNormal(tex2D(_NormalMap,IN.uv_MainTex));
        }
        ENDCG
    }
    FallBack "Diffuse"
    }

then you should initialize the positions and sizes of objects in shader:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class WorldMask : MonoBehaviour
{
    public Transform[] arrayTransform;
    public Vector4[] arrayPosition;
    public float[] arraySize;
    public Material material;

    private void Awake()
    {
        arrayPosition = new Vector4[arrayTransform.Length];
        arraySize = new float[arrayTransform.Length];
    }

    private void Update()
    {
        for (int i = 0; i < arrayTransform.Length; i++)
        {
            arrayPosition[i]= arrayTransform[i].position;
            arraySize[i]= arrayTransform[i].localScale.x;

        }

        material.SetVectorArray("_arrayPosition",arrayPosition);
        material.SetFloatArray("_arraySize",arraySize);
    }
}

Making World Position Dissolve Shader

I found a good tutorial that explained how to Dissolving Objects in the world:

Image1

Dissolving the world Part 1

Dissolving the world Part 2

enter image description here

Dissolving the world Chris Chen

Final Result:

Record_2019_09_06_19_13_17_857

Shader "Smkgames/WorldDissolve" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _NormalMap("Normal Map",2D) = "bump" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0

        _DissolvePoint("Dissolve point", Vector) = (0,0,0,0)
        _DissolveAmount("Disolve amount", Range(0,1)) = 1
        _MaxDistance("Max distance", float) = 1
        _Intensity("Intensity", Range(1,5)) = 1
        _NoiseFreq("Noise frequency", float) = 1
        _Border("Border size", float) = 0.1
        [HDR]_BorderColor("Border color", Color) = (1,0,0,1)
        [HDR]_BorderEmission("Border emission", Color) = (1,0,0,1)
    }
    SubShader {
        Tags {
            "RenderType"="TransparentCutout"
            "Queue"="AlphaTest"
        }
        Cull Off

        CGPROGRAM
        #pragma target 3.0
        #pragma surface surf Standard fullforwardshadows addshadow
        #include "UnityCG.cginc"
        #include "noiseSimplex.cginc"

        sampler2D _MainTex;
        sampler2D _NormalMap;
        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        fixed _NoiseFreq;
        fixed _Border;
        fixed4 _BorderColor;
        fixed4 _BorderEmission;

        uniform fixed _DissolveAmount;
        uniform fixed _MaxDistance;
        uniform fixed _Intensity;
        uniform float3 _DissolvePoint;


        struct Input {
            float2 uv_MainTex;
            float3 worldPos;
        };

        uniform float4 _arrayPosition [5];
        uniform float _arraySize [5];

        void surf (Input IN, inout SurfaceOutputStandard o) {

            // texture and color
            fixed4 color = tex2D(_MainTex, IN.uv_MainTex) * _Color;

         fixed isBorder = 0;
         for(int i = 0; i < 5;i++){




            // calculate distance between current position and dissolve point
            float dist = distance(IN.worldPos, _arrayPosition[i].xyz);

            // get gradient by distance
            float gradient = clamp(dist / _arraySize[i], 0, 2);

            // calculate final value
            float finalValue = (_DissolveAmount - gradient) * _Intensity;



            // snoise is expensive
            // do not call it if we are sure the final value is large enough
            if (finalValue > _Border + 1) {
                discard;
            }

            // get noise by world position, snoise return -1~1
            // make the noise 0~1
            float ns = snoise(IN.worldPos * _NoiseFreq) / 2 + 0.5f;

            if (ns + _Border < finalValue) {
                discard;
            }

            // after clip, ns should be finalValue ~ (finalValue - _Border)
            // if (finalValue >= ns)
            //      isBorder
            // else
            //      !isBorder
             isBorder += step(ns, finalValue);

            o.Albedo = lerp(color, _BorderColor, isBorder);
            o.Emission = lerp(fixed4(0, 0, 0, 0), _BorderEmission, isBorder);
            }

            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Normal = UnpackNormal(tex2D(_NormalMap,IN.uv_MainTex));
        }

        ENDCG
    }
    FallBack "Diffuse"
}

Github

source is Available in my github

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.