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

Shaderlab rejecting int property

Discussion in 'Shaders' started by Reahreic, Aug 9, 2017.

  1. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    I've run into a weird problem while trying to extend the functionality of a shader tutorial and need some understanding as to what's happening.

    When i declare my shader properties all is well until i declare an Int type property, at which point the shader inspector reports the property as a float and not an int, as well as then throwing an undeclared identifier error when i try to use the property.

    According to the docs (https://docs.unity3d.com/Manual/SL-Properties.html) i should be able to use an Int type in the properties section.



    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    3.  
    4. Shader "Custom/Post Outline"
    5. {
    6.     Properties
    7.     {
    8.         _MainTex("Main Texture", 2D) = "black"{}
    9.         _SceneTex("Scene Texture", 2D) = "black"{}
    10.         _hltColor("Highlight Color", Color) = (0,1,1,1)
    11.        
    12.         _hltThickness("Highlight Thickness", Int) = 4
    13.  
    14.     }
    15.     SubShader
    16.     {
    17.         Pass
    18.         {
    19.             CGPROGRAM
    20.             sampler2D _MainTex;
    21.  
    22.             //<SamplerName>_TexelSize is a float2 that says how much screen space a texel occupies.
    23.             float2 _MainTex_TexelSize;
    24.  
    25.             #pragma vertex vert
    26.             #pragma fragment frag
    27.             #include "UnityCG.cginc"
    28.            
    29.             struct v2f {
    30.                 float4 pos : SV_POSITION;
    31.                 float2 uvs : TEXCOORD0;};
    32.            
    33.             v2f vert (appdata_base v) {
    34.                 v2f o;
    35.                
    36.                 //Despite the fact that we are only drawing a quad to the screen, Unity requires us to multiply vertices by our MVP matrix, presumably to keep things working when inexperienced people try copying code from other shaders.
    37.                 o.pos = UnityObjectToClipPos(v.vertex);
    38.                
    39.                 //Also, we need to fix the UVs to match our screen space coordinates. There is a Unity define for this that should normally be used.
    40.                 o.uvs = o.pos.xy / 2 + 0.5;
    41.                
    42.                 return o;}
    43.            
    44.            half4 frag(v2f i) : COLOR {
    45.                 //arbitrary number of iterations for now (Outline Thickness)
    46.                 int thickness = _hltThickness;
    47.                 //split texel size into smaller words
    48.                 float TX_x=_MainTex_TexelSize.x;
    49.                 //and a final intensity that increments based on surrounding intensities.
    50.                 float ColorIntensityInRadius;
    51.                 //for every iteration we need to do horizontally
    52.                 for(int k = 0; k < thickness; k++)
    53.                 {
    54.                     //increase our output color by the pixels in the area
    55.                     ColorIntensityInRadius += tex2D(_MainTex, i.uvs.xy + float2((k - thickness / 2) * TX_x, 0)).r / thickness;
    56.                 }
    57.                 return ColorIntensityInRadius;
    58.             }
    59.            
    60.             ENDCG
    61.         }
    62.  
    63.         GrabPass{}
    64.  
    65.         Pass{
    66.             CGPROGRAM
    67.             sampler2D _MainTex;
    68.             sampler2D _SceneTex;
    69.            
    70.             //we need to declare a sampler2D by the name of "_GrabTexture" that Unity can write to during GrabPass{}
    71.             sampler2D _GrabTexture;
    72.             //<SamplerName>_TexelSize is a float2 that says how much screen space a texel occupies.
    73.             float2 _GrabTexture_TexelSize;
    74.             #pragma vertex vert
    75.             #pragma fragment frag
    76.             #include "UnityCG.cginc"
    77.            
    78.             struct v2f
    79.             {
    80.                 float4 pos : SV_POSITION;
    81.                 float2 uvs : TEXCOORD0;
    82.             };
    83.            
    84.             v2f vert (appdata_base v)
    85.             {
    86.                 v2f o;
    87.                
    88.                 //Despite the fact that we are only drawing a quad to the screen, Unity requires us to multiply vertices by our MVP matrix, presumably to keep things working when inexperienced people try copying code from other shaders.
    89.                 o.pos=UnityObjectToClipPos(v.vertex);
    90.                 //Also, we need to fix the UVs to match our screen space coordinates. There is a Unity define for this that should normally be used.
    91.                 o.uvs = o.pos.xy / 2 + 0.5;
    92.                
    93.                 return o;
    94.             }
    95.            
    96.            
    97.             half4 frag(v2f i) : COLOR
    98.             {
    99.                 //arbitrary number of iterations for now (Outline Thickness)
    100.                 int thickness = _hltThickness;
    101.                 //split texel size into smaller words
    102.                 float TX_y = _GrabTexture_TexelSize.y;
    103.                 //and a final intensity that increments based on surrounding intensities.
    104.                 half ColorIntensityInRadius = 0;
    105.                 //if something already exists underneath the fragment (in the original texture), discard the fragment.
    106.                 if(tex2D(_MainTex, i.uvs.xy).r > 0)
    107.                 {
    108.                     return tex2D(_SceneTex, float2(i.uvs.x, i.uvs.y));
    109.                 }
    110.                 //for every iteration we need to do vertically
    111.                 for(int j = 0; j < thickness; j += 1)
    112.                 {
    113.                     //increase our output color by the pixels in the area
    114.                     ColorIntensityInRadius += tex2D(_GrabTexture, float2(i.uvs.x, 1 - i.uvs.y) + float2(0, (j - thickness / 2) * TX_y)).r / thickness;
    115.                 }
    116.                 //this is alpha blending, but we can't use HW blending unless we make a third pass, so this is probably cheaper.
    117.                 //half4 outcolor=ColorIntensityInRadius*half4(0,1,1,1)*2+(1-ColorIntensityInRadius)*tex2D(_SceneTex,float2(i.uvs.x,i.uvs.y));
    118.                 half4 outcolor = ColorIntensityInRadius * _hltColor * 2 + (1 - ColorIntensityInRadius) * tex2D(_SceneTex, float2(i.uvs.x, i.uvs.y));
    119.                 return outcolor;
    120.             }
    121.            
    122.             ENDCG
    123.         }
    124.     }
    125. }
     
  2. brn

    brn

    Joined:
    Feb 8, 2011
    Posts:
    320
    Without testing your shader Reahreic my first guess is that you have accidentally missed a define in both or one pass.
    Try adding "int _hltThickness; " in after the CGPROGRAM line of each pass.
    You may notice that even though "_Maintex" is listed as a property it still needs to be defined as a sampler2D.

    Cheers
    brn
     
  3. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    ... 2 ours of starting at it for a simple variable re-declaration... i wouldn't have through (Shader Novice Here) that it'd need to be declared again after being initially set, but ok.

    well that solves that problem, although now i have warnings about using gradient instructions in a loop with varying iterations. (The int is used to set the number of iterations in the loop from the editor, so at least it's not a run time change that could cause out of range problems.)

    Thank you.
     
    brn likes this.
  4. brownboot67

    brownboot67

    Joined:
    Jan 5, 2013
    Posts:
    375
    The properties block is just the definitions for the inspector. Everything else is the actual program.
     
    brn likes this.
  5. leci

    leci

    Joined:
    Nov 19, 2012
    Posts:
    8
    Sorry for the bump. I need to know which datatypes exactly does Unity support for the Properties block.

    ATM, I've already tried with Float and Int, but, can I use lower precision types, like Byte, or UInt, etc?
    The compiler brings me errors with all of these...

    I want to pass a multiple choice for a property, but Enum limits me up to 7 values max...
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,236
    The property is always serialized and treated as a float on the script side, regardless of it being a Float or Int. You can however define the uniform to be whatever type you want and Unity will cast the float value to that data type, assuming the shader API supports it.
     
    Nomadjackalope likes this.
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,236
    You can use a script based enum, like those defined in UnityEngine.Rendering, though I've never figured out how to drive the enum from a custom script enum. So usually the answer is to use a custom material editor.