I don't know the difference between 'cg' and 'hlsl' in my custom shader (*noob...)

I would like to change the code below to be suitable for URP
The purpose of this shader is to chromakey a specific color in ‘_mainTex’
(Right now this shader is useful to me. It is used to erase blue-based colors.)

Shader "Custom/MRSReal" {
    Properties
    {
        _MainTex("Base (RGB) Trans (A)", 2D) = "" {}
        _CKMap("Chroma-key Map", 2D) = "" {}
    }

    CGINCLUDE
    #include "UnityCG.cginc"
    struct v2f
    {
        float4 pos : POSITION;
        float2 uv : TEXCOORD0;
    };

    sampler2D _MainTex;
    sampler2D _CKMap;

    float _CKAlpha = float(1.0f);

    v2f vert(appdata_img v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.uv.xy = v.texcoord.xy;

        return o;
    }

    float4 frag(v2f val) : COLOR
    {
        float4 yuv = tex2D(_MainTex, val.uv);
        float4 ckmask = tex2D(_CKMap, float2(yuv.r, yuv.b));

        float a = 1.0f - ckmask.a;


        float y = yuv.g;
        float u = yuv.r - 0.5f;
        float v = yuv.b - 0.5f;

        float r = y + (1.28033 * v);
        float g = y + (-0.21482 * u) + (-0.38059 * v);
        float b = y + (2.12798 * u);

        return float4(r, g, b, a);
    }

    ENDCG
    Subshader {
        Tags{ "Queue" = "Transparent+1000" "IgnoreProjector" = "True" "RenderType" = "Transparent"  }
        LOD 200
        Alphatest Greater 0 ZWrite Off ColorMask RGB ZTest Always
        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0
            ENDCG
        }
    }
    Fallback off
}

Below is my first output. It compiles, but the results are different from shaders written in CG.
The result is a greenish color, and none of the alpha values are properly applied.

Shader "Custom/MRSReal_urp" {
    Properties
    {
        _BaseMap("Base (RGB) Trans (A)", 2D) = "" {}
        _CKMap("Chroma-key Map", 2D) = "" {}
    }

    SubShader
    {
        Tags { "RenderType" = "Transparent" "RenderPipeline" = "UniversalRenderPipeline" }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"        

            struct Attributes
            {
                float4 positionOS   : POSITION;
                float2 uv           : TEXCOORD0;
            };

            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
                float2 uv           : TEXCOORD0;
            };

            TEXTURE2D(_BaseMap);
            TEXTURE2D(_CKMap);
            SAMPLER(sampler_BaseMap);
            SAMPLER(sampler_CKMap);

            CBUFFER_START(UnityPerMaterial)
            float4 _BaseMap_ST;
            float4 _CKMap_ST;
            CBUFFER_END

            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
                return OUT;
            }

            half4 frag(Varyings IN) : SV_Target
            {
                half4 yuv = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
                half4 ckmask = SAMPLE_TEXTURE2D(_CKMap, sampler_CKMap, float2(yuv.r, yuv.b));

                float a = 1.0f - ckmask.a;

                float y = yuv.g;
                float u = yuv.r - 0.5f;
                float v = yuv.b - 0.5f;

                float r = y + (1.28033 * v);
                float g = y + (-0.21482 * u) + (-0.38059 * v);
                float b = y + (2.12798 * u);

                return float4(r, g, b, a);
            }
            ENDHLSL
        }
    }
}

I struggled and forced myself to produce the following result. It worked, but again, the result was not the same as the CG. (My guess is that ‘_mainTex’(=_BaseMap) is the same as in CG, but _CKMap’ is different in the operation process.)

Shader "Custom/MRSReal_urp" {
    Properties
    {
        _MainTex("Base (RGB) Trans (A)", 2D) = "" {}
        _CKMap("Chroma-key Map", 2D) = "" {}
    }

    SubShader
    {
        Tags { "Queue" = "Transparent+1000" "IgnoreProjector" = "True" "RenderType" = "Transparent" "RenderPipeline" = "UniversalRenderPipeline" }

        ColorMask RGB
        ZTest Always
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 3.0

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"       

            struct appdata_img
            {
                float4 vertex   : POSITION;
                half2 texcoord  : TEXCOORD0;
            };

            struct Varyings
            {
                float4 pos  : POSITION;
                float2 uv   : TEXCOORD0;
            };

            Varyings vert(appdata_img IN)
            {
                Varyings OUT;
                OUT.pos = TransformObjectToHClip(IN.vertex.xyz);
                OUT.uv.xy = IN.texcoord.xy;
                return OUT;
            }

            sampler2D _MainTex;
            sampler2D _CKMap;
            float _CKAlpha = float(1.0f);

            float4 frag(Varyings IN) : SV_TARGET
            {
                float4 yuv = tex2D(_MainTex, IN.uv);
                float4 ckmask = tex2D(_CKMap, float2(yuv.r, yuv.b));

                float a = 1.0f - ckmask.a;

                float y = yuv.g;
                float u = yuv.r - 0.5f;
                float v = yuv.b - 0.5f;

                float r = y + (1.28033 * v);
                float g = y + (-0.21482 * u) + (-0.38059 * v);
                float b = y + (2.12798 * u);

                return float4(r, g, b, a);
            }
            ENDHLSL
        }
    }
    Fallback off
}

Maybe there’s a compilation order that I don’t know. Please tell me how can I get the same result as CG… THx… (please help X<)

Here’s the difference between CGPROGRAM and HLSLPROGRAM.

CGPROGRAM automatically includes the UnityCG.cginc file.

That’s it. They’re both using HLSL. They both work in the built in renderer and the SRPs.

CGPROGRAM comes from the fact Unity used to use a shader programming language called Cg, but they moved to pure HLSL many, many years ago. It was a gradual transition, and they didn’t take the time to remove the remaining references to “cg” until the SRPs.

There are differences between the built-in renderer and the SRPs in terms of what stuff is in the built-in UnityCG.cginc (and the files it includes) and those the SRP’s many #include lines. The stuff in UnityCG.cginc may collide with the stuff in the SRP’s .hlsl files as they cover a lot of the same ground (defining generic engine level transform variables and globals, etc.) so you only want to use either UnityCG.cginc or Core.hlsl but not both. And the functions for doing common things are named differently. For example the UnityObjectToClipPos() and TransformObjectToHClip() functions are named differently, but are under the hood effectively identical.

Outside of that the SRPs have different requirements and ways it uses things like the tags. But none of that explains the difference you’re seeing. The problem is I don’t know what difference you’re seeing as you haven’t posted any screenshots of the before and after. But honestly my guess is it has nothing to do with the shader code at this point. I didn’t notice anything obvious on a quick check over the first and last examples that would cause any problems.

6 Likes