⬆️ ⬇️

Writing Dissolve Shader

Introduction



Before the new year, I decided to try writing shaders. I chose the dissolving object shader as my goal, on December 31 I successfully completed it and now it's time to do something with it. On the asset store, they said that everything is fine but there are already a couple of similar ones, so I will try to make it out in this article. As a result, we should have this:







There are several ways of implementation:



As a result, we get 3 shaders, 2 using only alpha and which can take off to the mob. devices and one with AlphaTest which looks prettier but more voracious. Thanks to AlphaTest, we can turn off the cutting off of invisible polygons and not receive layering. But you have to pay a shader model 2.0 and use 3.0 because of what can not be used on the mob. devices



Frame



The general algorithm is as follows:



')

The result is not as beautiful as the first video.







We do not have enough normal maps, and the coolest. Lines!

I have the following inline algorithm:





I summarize the above, we get clipping by the mask and if we cut off the pixels, then we check if we don’t cut it, but if they are, we become the edge and set ourselves a certain color.



Closer to body code



If we add the normalization and offset of the line texture along sinusoidal time to all the above, we get this kind of canvas.



Main shader
Shader "HolyMonkey/Dissolve/Bumped" { Properties { _MainColor ("Main Color", Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _Mask("Mask To Dissolve", 2D) = "white" {} _LineTexture("Line Texture", 2D) = "white" {} _Range ("Range", Range(0,3)) = 0 _LineSize ("LineSize", Float) = 0.001 _Color ("Line Color", Color) = (1,1,1,1) _BumpMap ("Normalmap", 2D) = "bump" {} _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5 } SubShader { Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"} LOD 300 ZWrite On Cull Off CGPROGRAM #pragma target 3.0 #include "UnityCG.cginc" #pragma surface surf Lambert alphatest:_Cutoff sampler2D _MainTex; sampler2D _LineTexture; sampler2D _BumpMap; sampler2D _Mask; half4 _Color; half4 _MainColor; float _Range; float _LineSize; struct Input { float2 uv_MainTex; float2 uv_BumpMap; float2 uv_Detail; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); half4 m = tex2D (_Mask, IN.uv_MainTex); half4 lc = tex2D (_Mask, IN.uv_MainTex - _LineSize); half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize); half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color; o.Albedo = c * _MainColor; o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); o.Alpha = 1; float factor = m.rgb.x + m.rgb.y + m.rgb.z; if(factor >= _Range) { float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z; float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z; if(factor2 < _Range || factor3 < _Range) { o.Albedo = lc3; } else { o.Alpha = 0.0; } } } ENDCG } Fallback "Diffuse" } 






You can also play with some aspects and get the following



Cooling enabled
 Shader "HolyMonkey/Dissolve/Culling-Mobile" { Properties { _MainColor ("Main Color", Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _Mask("Mask To Dissolve", 2D) = "white" {} _LineTexture("Line Texture", 2D) = "white" {} _Range ("Range", Range(0,3)) = 0 _LineSize ("LineSize", Float) = 0.001 _Color ("Line Color", Color) = (1,1,1,1) _BumpMap ("Normalmap", 2D) = "bump" {} } SubShader { Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} LOD 300 CGPROGRAM #pragma target 2.0 #include "UnityCG.cginc" #pragma surface surf Lambert alpha sampler2D _MainTex; sampler2D _LineTexture; sampler2D _BumpMap; sampler2D _Mask; half4 _Color; half4 _MainColor; float _Range; float _LineSize; struct Input { float2 uv_MainTex; float2 uv_BumpMap; float2 uv_Detail; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); half4 m = tex2D (_Mask, IN.uv_MainTex); half4 lc = tex2D (_Mask, IN.uv_MainTex - _LineSize); half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize); half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color; o.Albedo = c * _MainColor; o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); o.Alpha = 1; float factor = m.rgb.x + m.rgb.y + m.rgb.z; if(factor >= _Range) { float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z; float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z; if(factor2 < _Range || factor3 < _Range) { o.Albedo = lc3; } else { o.Alpha = 0.0; } } } ENDCG } Fallback "Diffuse" } 






With one more texture instead of transparency
 Shader "HolyMonkey/Dissolve/NotTransparent" { Properties { _MainColor ("Main Color", Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _BackTexture ("Back Texture", 2D) = "white" {} _Mask("Mask To Dissolve", 2D) = "white" {} _LineTexture("Line Texture", 2D) = "white" {} _Range ("Range", Range(0,3)) = 0 _LineSize ("LineSize", Float) = 0.001 _Color ("Line Color", Color) = (1,1,1,1) _BumpMap ("Normalmap", 2D) = "bump" {} } SubShader { LOD 300 ZWrite On Cull Off CGPROGRAM #pragma target 2.0 #include "UnityCG.cginc" #pragma surface surf Lambert sampler2D _MainTex; sampler2D _LineTexture; sampler2D _BumpMap; sampler2D _Mask; sampler2D _BackTexture; half4 _Color; half4 _MainColor; float _Range; float _LineSize; struct Input { float2 uv_MainTex; float2 uv_BumpMap; float2 uv_Detail; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); half4 m = tex2D (_Mask, IN.uv_MainTex); half4 lc = tex2D (_Mask, IN.uv_MainTex - _LineSize); half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize); half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color; half4 bc = tex2D(_BackTexture, IN.uv_MainTex); o.Albedo = c * _MainColor; o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); float factor = m.rgb.x + m.rgb.y + m.rgb.z; if(factor >= _Range) { float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z; float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z; if(factor2 < _Range || factor3 < _Range) { o.Albedo = lc3; } else { o.Albedo = bc; o.Normal = float3(1,1,1); } } } ENDCG } Fallback "Diffuse" } 






Conclusion



It was not enough to write, but I think the deductive code redeems it. They use simple things, and there are articles on Habré with their analysis. Sources with all the necessary resources You can download from the repository on GitHub

Source: https://habr.com/ru/post/208532/



All Articles