Search Unity

How to Declare Global Constant in CG?

Discussion in 'Shaders' started by topsekret, Nov 19, 2014.

  1. topsekret

    topsekret

    Joined:
    Apr 18, 2013
    Posts:
    69
    I am trying to declare a global (ie, not local to a function) constant in a shader. In my actual use for this, I want to declare a global constant in a cginc file so that other shaders can reference it. However, it seems that no matter what I initialize my constant to, it is always treated as the default value for the type.

    NVidia's CG tutorial seems to imply that it should be possible to have globally scoped constants, but in their code snippet, you can't tell if their constant is global or local.

    Here is a simple example to demonstrate the problem.

    Code (CSharp):
    1. Shader "Custom/ConstantTest"
    2. {
    3.     SubShader
    4.     {
    5.         Tags { "RenderType"="Opaque" }
    6.        
    7.         Pass
    8.         {
    9.             CGPROGRAM
    10.             #pragma vertex vert
    11.             #pragma fragment frag
    12.             #include "UnityCG.cginc"
    13.            
    14.             const fixed4 SPECIAL_COLOR = fixed4(1, 0, 0, 1);
    15.            
    16.             struct v2f
    17.             {
    18.                 float4 pos : POSITION;
    19.             };
    20.            
    21.             v2f vert(appdata_base input)
    22.             {
    23.                 v2f output;
    24.                 output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
    25.                 return output;
    26.             }
    27.            
    28.             fixed4 frag(v2f input) : COLOR
    29.             {
    30.                 //If I return the color as a constant, it just
    31.                 //shows up as black, regardless of the color
    32.                 //I have set the constant to.
    33.                 return SPECIAL_COLOR;
    34.                
    35.                 //If I return a "magic number" like this it
    36.                 //works, the cube is red.
    37.                 //return fixed4(1, 0, 0, 1);
    38.                
    39.                 //If I make the constant local scope, it works
    40.                 //and the cube is red.
    41.                 //const fixed4 SPECIAL_COLOR = fixed4(1, 0, 0, 1);
    42.                 //return SPECIAL_COLOR;
    43.             }
    44.             ENDCG
    45.         }
    46.     }
    47. }

    As you can see, I have a global constant color declared as the color red. However, when I put this shader on an object, it shows up as all black instead of all red.

    I can make this work by just returning a "magic number" in my fragment shader, or by declaring and using a locally scoped constant in the fragment shader. However, I would like to get this to work with a global constant since in my actual use for this, I would like multiple shaders to be able to access a single constant.

    How do you declare a global constant in CG?
     
  2. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Must be static...

    Code (CSharp):
    1. static const fixed4 SPECIAL_COLOR = fixed4(1, 0, 0, 1);
     
  3. topsekret

    topsekret

    Joined:
    Apr 18, 2013
    Posts:
    69
    Awesome, it works! Thank you so much! I guess I was just used to not needing the static keyword for global constants in C#.
     
  4. Kirk Clawson

    Kirk Clawson

    Joined:
    Nov 4, 2014
    Posts:
    65
    CG is much more like C/C++ than C#.
    C/C++ have the concept of instance consts as well as static consts, so you need the static keyword to let it know which one you mean. C# you only get one kind of const - static.
     
    u3d455 likes this.