Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Predefined Functions with #ifdef KEYWORD

Discussion in 'Shaders' started by danielgamar, Jun 27, 2019.

  1. danielgamar

    danielgamar

    Joined:
    Jun 13, 2019
    Posts:
    5
    I have this shader and what I want to do is set the param for ColorMask based on a keyword.

    I use this Occlusion Shader to enhance the experience with HoloLens but it's really annoying while developing and I would like to make an option to turn on and off the mask from a menu item.


    Shader "Hololens/Occlusion"
    {
    Properties
    {
    }

    SubShader
    {
    Tags
    {
    "RenderType" = "Opaque"
    "Queue" = "Geometry-1"
    }

    Pass
    {
    ColorMask 0 //[ColourMask]

    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #pragma target 5.0
    #pragma only_renderers d3d11
    #pragma multi_compile HOLOLENS_OCCLUSION_OFF HOLOLENS_OCCLUSION_ON

    #include "UnityCG.cginc"

    struct v2f
    {
    float4 pos : SV_POSITION;
    };

    v2f vert(appdata_base v)
    {
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);
    return o;
    }

    half4 frag(v2f i) : COLOR
    {
    #ifdef HOLOLENS_OCCLUSION_OFF
    discard;
    #endif
    return float4(1, 1, 1, 1);
    }
    ENDCG
    }
    }
    }


    basically this


    #ifdef HOLOLENS_OCCLUSION_ON
    ColorMask 0
    #else
    ColorMask RGBA
    #endif
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,556
    The discard should work, though you don't need to define _ON and _OFF versions of the keyword in that case, just define
    #pragma multi_compile __ _HOLOLENS_OCCLUSION
    as the multi compile and check #ifdef for it.

    Also, there's another route you can go. Remove the multi-compile option. Instead, change your
    ColorMask
    line to
    ColorMask [_HOLOLENS_OCCLUSION_MASK]


    Now, from a script, instead of setting keyword, you can do:
    Shader.SetGlobalInt("_HOLOLENS_OCCLUSION_MASK", 0);

    That will set it invisible.
    And
    Shader.SetGlobalInt("_HOLOLENS_OCCLUSION_MASK", 16);

    This will set the mask to "RGBA".

    This will change the value on all materials using the shader, and avoid creating any extra shader variants.
     
    Last edited: Jun 28, 2019
    danielgamar likes this.
  3. danielgamar

    danielgamar

    Joined:
    Jun 13, 2019
    Posts:
    5
    Amazing stuff. Thank you very much. Exactly what I was looking for! Any chance you know how to do tags based on defined keywords?
     
    Last edited: Jun 28, 2019
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,556
    As far as I'm aware, the compile conditionals only work within the CGPROGRAM/HLSLPROGRAM section, since that is where they are defined too.

    What in your Tags section do you need to control with a keyword? Tags aren't really part of the shader for the most part, they are properties Unity uses for the default settings a material should have that dictates how Unity should render those materials, such as a render queue value and if it should be included in projector passes, it's not a value that gets changed in the shader itself, thus shader variants can't affect that part, but you can manually set that stuff on a given material from code.
     
  5. danielgamar

    danielgamar

    Joined:
    Jun 13, 2019
    Posts:
    5
    I was wondering if I can change the RenderType and Queue. It's not that I needed now just wanted to know if it is possible for further use.
     
  6. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,556
    Naw, not with keywords. You can set the render queue on the material from code though. And same for RenderType.
     
  7. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,057
    A good example of how to do this can be found with Unity's builtin shaders for the 'Standard' shaders ( i.e physically based rendering ones ). If you grab the Unity BuiltIn shaders download ( from the archives ) and check out both the shader but more importantly the editor script 'StandardShaderGUI.cs' you'll see how Unity allows you to change render type ( and by virtue queue ) in the code.
     
  8. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    357
  9. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,556
    True. For some reason I had thought I'd read this wasn't needed anymore in a recent update, but I just tried and I guess it is, lame.
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,375
    Doesn’t have to be a double underscore, can be a single, or triple, or any number of underscores. Official Unity shaders use many different numbers of underscores, the only important part is that it is only underscores.

    Not needed for #pragma shader_feature, and there’s been some talk of making #pragma multi_compile work the same, but I’d guess it never actually made it to a live version due to worries about backwards compatibility (mainly, someone somewhere a sometime writing a shader with #pragma multi_compile _JUST_ONE_KEYWORD and that now sometimes compiling versions of the shader without that keyword potentially causing compiler issues.
     
    grizzly likes this.
  11. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    357
    Interesting. Have always used doubles as per the doc.

    So, although this wouldn't work;

    #pragma multi_compile _HOLOLENS_OCCLUSION


    These will;

    #pragma multi_compile _ HOLOLENS_OCCLUSION
    #pragma multi_compile __ HOLOLENS_OCCLUSION