Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Passing variables (not parameters) from ShaderLab into CGPROGRAM re-using passes

Discussion in 'Shaders' started by Pi_3-14, Sep 28, 2012.

  1. Pi_3-14

    Pi_3-14

    Joined:
    May 9, 2012
    Posts:
    168
    Say I have a 2 pass shader, where the passes are identical save for a colour change: the first pass uses white and the second uses black.

    The actual shader I'm looking at is here.

    As you can see from inspection, the only difference between the passes is that the blend mode is different, and that half4(1,1,1,1) in the first pass becomes half4(0,0,0,0) in the second.

    Would it be possible to restructure this shader to eliminate code duplication?

    Something like:

    Code (csharp):
    1. Shader "Mobile/Mobile-XrayEffect" {
    2.     Properties {
    3.         _Color( "_Color",   Color       )           = (0,1,0,1)
    4.         _Inside("_Inside",  Range(0,1)  )           = 0
    5.         _Rim(   "_Rim",     Range(0,2)  )           = 1.2
    6.     }
    7.    
    8.     SubShader {
    9.         Tags { "Queue" = "Transparent" }
    10.         LOD 80
    11.        
    12.         Cull Off
    13.         Zwrite Off
    14.        
    15.        
    16.         Blend DstColor Zero     // multiply the color already on the screen by generated color
    17.         myColor = (1,1,1,1);
    18.         DO_CG_PASS
    19.        
    20.         Blend OneMinusDstColor One
    21.         myColor = (0,0,0,0);
    22.         DO_CG_PASS
    23.     }
    24.    
    25.     FallBack "Mobile/VertexLit"
    26. }
    ...and then DO_CG_PASS somehow extracts the myColor variable

    Can this be done? I am aware of ShaderLab having 'UsePass' but I can see two difficulties:

    • It looks like I can only use a valid existing pass, so maybe I would have to create a separate shader file containing a single pass and then use that twice from the main shader file
    • I can't see how to pass a colour into the CG code from ShaderLab. I'm aware of how to get properties through as Uniforms, but that doesn't help
     
  2. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    I'm not sure about UsePass, but I think you can do something similar using #include (but your #include files might have to be located in the same directory as all the other include files).
     
  3. Pi_3-14

    Pi_3-14

    Joined:
    May 9, 2012
    Posts:
    168
    The problem is that the colour is different both times.

    Maybe I can use:

    Code (csharp):
    1. #define MyColor (1,1,1,1)
    2. #include X
    3.  
    4. :
    5.  
    6. #define MyColor (0,0,0,0)
    7. #include X
    ...but that is ugly as hell.

    I wonder if there is any way of using SetColor(1,1,1,1) in the ShaderLab shell and having Cg pick it up.
     
  4. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Yes, that's what I was thinking of. :)

    Not that I know of.
     
  5. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    You can use CGINCLUDE blocks. These are like CGPROGRAM blocks except that everything inside of them will be copied into the CGPROGRAM blocks of each pass in your shader.

    Meaning you could copy/paste up until the final frag shader into your CGINCLUDE block then in your CGPROGRAM block you copy/paste your fragment shader and change that one variable.
     
  6. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Is there any official documentation about CGINCLUDE? As far as I can figure it out, CGINLCUDE blocks are included at the start of each CGPROGRAM block. Is there a way of including them at another line or at the end?
     
  7. Pi_3-14

    Pi_3-14

    Joined:
    May 9, 2012
    Posts:
    168
    Thanks Farfarer for pointing me towards CGINCLUDE.

    This must be very obscure; it isn't referenced in either the reference nor the user manual from nVidia. Also Google hardly throws up anything.

    I've made use of CGINCLUDE to restructure brn's excellent XRay shader to eliminate the code duplication:

    Code (csharp):
    1.  
    2. // http://www.photonworkshop.com/index.php/blog/x-ray-shader/
    3. // Mobile Xray Shader created by Bruno Rime 2012
    4. // Free for personal and comercial use
    5. //
    6. // Fiddled to avoid duplication of Cg code by π 28.9.12
    7.  
    8. /*
    9.     This is an elegant 2 pass shader that offers an 'x-ray vision'
    10.         effect through enhancing the silhouette ( or outline )
    11.    
    12.     Complete explanation of the process and discussion can be found here:
    13.         http://forum.unity3d.com/threads/152761-Shader-for-illustrating-meshes-(including-edges-backfaces)-in-Scene-view
    14.    
    15.     π  28.9.12 */
    16.  
    17.  
    18. CGINCLUDE
    19.    
    20.     #pragma vertex vert_surf
    21.     #pragma fragment frag_surf
    22.     #pragma fragmentoption ARB_precision_hint_fastest
    23.     //#pragma multi_compile_fwdbase
    24.  
    25.     #include "HLSLSupport.cginc"
    26.     #include "UnityCG.cginc"
    27.  
    28.     struct v2f_surf {
    29.         half4   pos        : SV_POSITION;
    30.         fixed4  finalColor : COLOR;
    31.     };
    32.    
    33.     uniform half4 _Color;
    34.     uniform half  _Rim;
    35.     uniform half  _Inside;
    36.    
    37.    
    38.     v2f_surf FOO( appdata_base v, half4 targetColor )
    39.     {
    40.         v2f_surf o;
    41.        
    42.         o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
    43.        
    44.         half3 unitNormal_ViewSpace = normalize(
    45.                     mul( (float3x3)UNITY_MATRIX_IT_MV, v.normal )
    46.                     );
    47.        
    48.         half nZ = unitNormal_ViewSpace.z;
    49.        
    50.         o.finalColor = lerp(
    51.                             targetColor,
    52.                             _Color,
    53.                             saturate(
    54.                                 max( 1 - pow( nZ, _Rim ),  _Inside )
    55.                                 )
    56.                             );
    57.         return o;
    58.     }
    59.    
    60.    
    61.     fixed4 frag_surf( v2f_surf IN ) : COLOR
    62.     {
    63.         return IN.finalColor;
    64.     }
    65.  
    66. ENDCG
    67.  
    68. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    69.  
    70. Shader "Mobile/Mobile-XrayEffect2" {
    71.     Properties {
    72.         _Color( "_Color",   Color       )           = (0,1,0,1)
    73.         _Inside("_Inside",  Range(0,1)  )           = 0
    74.         _Rim(   "_Rim",     Range(0,2)  )           = 1.2
    75.     }
    76.    
    77.     SubShader {
    78.         Tags { "Queue" = "Transparent" }
    79.         LOD 80
    80.        
    81.         Cull Off
    82.         Zwrite Off
    83.        
    84.         Pass {
    85.             Name "Darken"
    86.            
    87.             //  Multiply the color already on the screen by generated color
    88.             //  This effectively moves pixel towards black.
    89.             Blend DstColor Zero
    90.                    
    91.             CGPROGRAM
    92.                 v2f_surf vert_surf( appdata_base v ) {
    93.                     return FOO( v, half4(1,1,1,1) );
    94.                 }
    95.             ENDCG
    96.         }
    97.        
    98.         Pass {
    99.             Name "Lighten"
    100.             // This moves the colour already on the screen towards white
    101.             Blend OneMinusDstColor One
    102.                    
    103.             CGPROGRAM
    104.                 v2f_surf vert_surf( appdata_base v ) {
    105.                     return FOO( v, half4(0,0,0,0) );
    106.                 }
    107.             ENDCG
    108.         } // Pass
    109.        
    110.     }
    111.  
    112.     FallBack "Mobile/VertexLit"
    113. }
    114.  
    EDIT 12.10.10
    New revision here
     
    Last edited: Oct 12, 2012
  8. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    No idea, I think it gets a mention in the docs somewhere? But literally a mention, no further examples or documentation.

    I dunno if it's possible to use it elsewhere in a shader, as far as I can tell it's essentially a this-file-only version of #include "file.cginc" ...

    I've seen it used a bit in the built-in shader source - can't remember where - but nothing official.
     
    Last edited: Sep 28, 2012