Tuesday, April 12, 2016

Implementing stencil shaders in Unity

Hi, I want to share how I used stencil shaders in Unity to change from this:



To this:



As you can see the game use 3D envioroments, but because the camera has a top down view I can see my models clipping through the walls thus killing the effect that I want to achieve.

First we have to create a model that is going to work as our mask like the white mesh in the next image:



Then we are going the create a material called Mask or something that is going to be assigned to that model and it's going to use the next shader:

Mask.shader
Shader "Custom/Mask" {  
      SubShader {  
           Tags { "Queue" = "Geometry-1" }   
           ColorMask 0   
           ZWrite Off   
            Pass {  
                   Stencil {  
                     Ref 1  
                     Comp always  
                     Pass replace  
                   }  
            }  
      }  
 }  

This shader itself does nothing if we don't modify the shader that our objects to be masked are using (in this case the walls, pipes and almost everything), so far I have modified the standard shader and the addive shader without problems, I included the modified versions of thsese shaders to download but you can try to modify any shader.

Mask.shader

Modified additive shader

Modified standard shader

For example to modify the additive shader and get the one that I'm using in my fake light shafts in the aircraft from the second picture you have to:
  • Download the unity built-in shaders 
  • Find the shader inside the folder DefaultResourcesExtra\Particle Add.shader
  • Add it to your project
  • Open the shader and you may find something like this:
Particle Add.shader
Shader "Custom/Additive" {  
 Properties {  
      _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)  
      _MainTex ("Particle Texture", 2D) = "white" {}  
      _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0  
 }  
 Category {  
      Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }  
      Blend SrcAlpha One  
      ColorMask RGB  
      Cull Off Lighting Off ZWrite Off  
      SubShader {  
           Pass {  
                CGPROGRAM  
                #pragma vertex vert  
                #pragma fragment frag  
                #pragma multi_compile_particles  
                #pragma multi_compile_fog  

Inside SubShader you have to add:

Stencil{  
     Ref 1  
     Comp equal  
}  

And you end up with something like this:

Particle Add.shader

Shader "Custom/Additive" {  
 Properties {  
      _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)  
      _MainTex ("Particle Texture", 2D) = "white" {}  
      _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0  
 }  
 Category {  
      Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }  
      Blend SrcAlpha One  
      ColorMask RGB  
      Cull Off Lighting Off ZWrite Off  
      SubShader {  
           Stencil{  
                 Ref 1  
                 Comp equal  
            }  
           Pass {  
                CGPROGRAM  
                #pragma vertex vert  
                #pragma fragment frag  
                #pragma multi_compile_particles  
                #pragma multi_compile_fog  

And that's it, you assign your mask shader to the object you're going to use as the mask and the modified versions of the your shaders to the rest of the objects.

I'm not a shader expert, I just learnt to do this trick from the web and just wanted to shared, any questions, errors or typos, let me know.



No comments:

Post a Comment