Search Unity

Passing keyword from script to shader

Discussion in 'Image Effects' started by ifurkend, May 20, 2018.

  1. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    Hi. I am learning to write my own image effect with the new Postprocessing (2.0.5 preview) but I am having trouble to pass the keyword from my script to the shader. Technically the following codes work as intended by passing the _ARITHMETICS keyword, but it is definitely inefficient when I have more keywords to switch. Please recommend a better way to handle this, especially for KeywordEnum. Thank you.

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Rendering.PostProcessing;
    4.  
    5. public enum ArithTypeDrawer
    6. {
    7.     ADDITIVE,
    8.     MULTIPLICATION,
    9.     POWER
    10. }
    11. [Serializable]
    12. public sealed class ArithTypeParameter : ParameterOverride<ArithTypeDrawer> {}
    13.  
    14. [PostProcess(typeof(ArithmeticsRenderer), PostProcessEvent.AfterStack, "Hidden/Custom/Arithmetics")]
    15.  
    16. public sealed class Arithmetics : PostProcessEffectSettings
    17. {
    18.     public FloatParameter _Constant = new FloatParameter { value = 1f };
    19.     public ArithTypeParameter ArithType = new ArithTypeParameter { value = ArithTypeDrawer.Additive };
    20. }
    21. public sealed class ArithmeticsRenderer : PostProcessEffectRenderer<Arithmetics>
    22. {
    23.     public override void Render(PostProcessRenderContext context)
    24.     {
    25.         var sheet = context.propertySheets.Get(Shader.Find("Hidden/Custom/Arithmetics"));
    26.         sheet.properties.SetFloat("_Constant", settings._Constant);
    27.         if (settings.ArithType == ArithTypeDrawer.ADDITIVE) {
    28.             DisableAllKeywords(sheet);
    29.             sheet.EnableKeyword("_ARITHMETICS_ADDITIVE");
    30.         } else if (settings.ArithType == ArithTypeDrawer.MULTIPLICATION) {
    31.             DisableAllKeywords(sheet);
    32.             sheet.EnableKeyword("_ARITHMETICS_MULTIPLICATION");
    33.         } else if (settings.ArithType == ArithTypeDrawer.POWER) {
    34.             DisableAllKeywords(sheet);
    35.             sheet.EnableKeyword("_ARITHMETICS_POWER");
    36.         }
    37.         context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
    38.     }
    39.  
    40.    void DisableAllKeywords(PropertySheet sheet) {
    41.        sheet.DisableKeyword("_ARITHMETICS_ADDITIVE");
    42.        sheet.DisableKeyword("_ARITHMETICS_MULTIPLICATION");
    43.        sheet.DisableKeyword("_ARITHMETICS_TEST");
    44.    }
    45. }
    Code (CSharp):
    1. Shader "Hidden/Custom/Arithmetics"
    2. {
    3.     HLSLINCLUDE
    4.         #include "PostProcessing/Shaders/StdLib.hlsl"
    5.  
    6.         TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
    7.         float _Constant;
    8.         #pragma multi_compile _ARITHMETICS_ADDITIVE _ARITHMETICS_MULTIPLICATION_ARITHMETICS_POWER
    9.  
    10.         float4 Frag(VaryingsDefault i) : SV_Target
    11.         {
    12.             #ifdef _ARITHMETICS_ADDITIVE
    13.             i.texcoord.x += _Constant;
    14.             #elif _ARITHMETICS_MULTIPLICATION
    15.             i.texcoord.x *= _Constant + 1;
    16.             #elif _ARITHMETICS_POWER
    17.             i.texcoord.x = pow(abs(i.texcoord.x), _Constant);
    18.             #endif
    19.      
    20.             return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
    21.         }
    22.     ENDHLSL
    23.  
    24.     SubShader
    25.     {
    26.         Cull Off ZWrite Off ZTest Always
    27.  
    28.         Pass
    29.         {
    30.             HLSLPROGRAM
    31.  
    32.                 #pragma vertex VertDefault
    33.                 #pragma fragment Frag
    34.  
    35.             ENDHLSL
    36.         }
    37.     }
    38. }
     
    Last edited: May 20, 2018
  2. jasonchan35

    jasonchan35

    Joined:
    Aug 23, 2017
    Posts:
    2
    On the C# side, System.Enum.GetValues() might help


    Code (CSharp):
    1.     public override void Render(PostProcessRenderContext context)
    2.     {
    3.         var sheet = context.propertySheets.Get(Shader.Find("Hidden/Custom/Arithmetics"));
    4.         sheet.properties.SetFloat("_Constant", settings._Constant);
    5.  
    6. //-----------      
    7.         var enumValues = System.Enum.GetValues(typeof(ArithTypeDrawer));
    8.         foreach (ArithTypeDrawere in enumValues) {
    9.             var s = "_ARITHMETICS_" + e.ToString();
    10.             if (e == settings.ArithType) {
    11.                 sheet.EnableKeyword(s);
    12.             } else {
    13.                 sheet.DisableKeyword(s);
    14.             }
    15.         }
    16. //-------------
    17.      
    18.         context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
    19.     }
     
    Last edited: May 20, 2018
    ifurkend likes this.
  3. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    Thanks. It seems it works once I changed foreach (var e in enumValues) { to foreach (ArithTypeDrawer e in enumValues) {.
     
    Last edited: May 20, 2018
  4. jasonchan35

    jasonchan35

    Joined:
    Aug 23, 2017
    Posts:
    2
    right, the enumValues is Array of object, need to tell the type explicitly
    so I changed my code above
    from
    Code (CSharp):
    1. foreach (var in enumValues)
    to
    Code (CSharp):
    1. foreach (ArithTypeDrawere in enumValues)