Search Unity

Question How to make my 2D palette swapping shader be affected by lighting

Discussion in 'Shaders' started by josfeld, Sep 24, 2020.

  1. josfeld

    josfeld

    Joined:
    Dec 14, 2017
    Posts:
    1
    I am not really very familiar with shaders, but I have been using the shader below to swap sprites colors at runtime to recolor them for cosmetic variety. The shader works great but it is unlit and I want to try and use it in a project with lit sprites, and can't figure out how I should modify it to do so. I was wondering if someone could take a look at the shader and let me know if there is an easy way to modify it to make it a surface shader but still keep the render texture color swapping. I have taken a look at the default Unity sprite diffuse shader but am not sure what parts of it I should include in this shader to make it into a lit shader. Here is the shader:

    Code (CSharp):
    1. Shader "Sprites/BatchingColorSwap"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
    6.         _SwapTex("Color Data", 2D) = "transparent" {}
    7.         _Color("Tint", Color) = (1,1,1,1)
    8.         [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
    9.     }
    10.  
    11.         SubShader
    12.         {
    13.             Tags
    14.             {
    15.                 "Queue" = "Transparent"
    16.                 "IgnoreProjector" = "True"
    17.                 "RenderType" = "Transparent"
    18.                 "PreviewType" = "Plane"
    19.                 "CanUseSpriteAtlas" = "True"
    20.             }
    21.  
    22.             Cull Off
    23.             Lighting Off
    24.             ZWrite Off
    25.             Blend One OneMinusSrcAlpha
    26.  
    27.             Pass
    28.             {
    29.             CGPROGRAM
    30.                 #pragma vertex vert
    31.                 #pragma fragment frag
    32.                 #pragma multi_compile _ PIXELSNAP_ON
    33.                 #pragma multi_compile_instancing
    34.                 #include "UnityCG.cginc"
    35.  
    36.                 struct appdata_t
    37.                 {
    38.                     float4 vertex   : POSITION;
    39.                     float4 color    : COLOR;
    40.                     float2 texcoord : TEXCOORD0;
    41.                 };
    42.  
    43.                 struct v2f
    44.                 {
    45.                     float4 vertex   : SV_POSITION;
    46.                     fixed4 color : COLOR;
    47.                     half2 texcoord  : TEXCOORD0;
    48.                 };
    49.  
    50.                 fixed4 _Color;
    51.  
    52.                 v2f vert(appdata_t IN)
    53.                 {
    54.                     v2f OUT;
    55.                     OUT.vertex = UnityObjectToClipPos(IN.vertex);
    56.                     OUT.texcoord = IN.texcoord;
    57.                     OUT.color = IN.color * _Color;
    58.                     #ifdef PIXELSNAP_ON
    59.                     OUT.vertex = UnityPixelSnap(OUT.vertex);
    60.                     #endif
    61.  
    62.                     return OUT;
    63.                 }
    64.  
    65.                 sampler2D _MainTex;
    66.                 sampler2D _AlphaTex;
    67.                 float _AlphaSplitEnabled;
    68.  
    69.                 sampler2D _SwapTex;
    70.  
    71.                 fixed4 SampleSpriteTexture(float2 uv)
    72.                 {
    73.                     fixed4 color = tex2D(_MainTex, uv);
    74.  
    75.                     if (_AlphaSplitEnabled)
    76.                         color.a = tex2D(_AlphaTex, uv).r;
    77.  
    78.                     return color;
    79.                 }
    80.  
    81.                 fixed4 frag(v2f IN) : SV_Target
    82.                 {
    83.                     fixed4 c = SampleSpriteTexture(IN.texcoord);
    84.                     fixed4 swapCol = tex2D(_SwapTex, float2(c.x, IN.color.a * (255.0 / 256.0) + (0.5 / 255.0)));
    85.                     fixed4 final = lerp(c, swapCol, swapCol.a) * IN.color;
    86.                     final.a = c.a;
    87.                     final.rgb *= c.a;
    88.  
    89.                     return final;
    90.                 }
    91.             ENDCG
    92.             }
    93.         }
    94. }


    The shader was from this tutorial originally then I modified it to make it batchable based on this thread.
     
  2. treecki

    treecki

    Joined:
    Feb 6, 2017
    Posts:
    29
    It's been a year since this thread has been made and I figured I'd try to respond with what I've found. I've been trying to tackle the same issue with almost the exact same shader from that tutorial. I want to precursor and say I've not been able to find a full solution, but maybe my progress might help someone else to figure what's wrong.

    I took unity's base Sprite-Lit-Default shader to see if I can add the shader to it. I found that I was able to both add a pass for the shader and write a HLSL version of the shader which allowed it to "work". Atleast, the palette swap works but it doesn't respond to lighting. I tried digging into the "CombinedShapeLightShared.HLSL" and create a custom one to work with lighting but that also didn't seem to help. I also tried adding a Grab Pass after the first pass (palette swap) and using that texture to show the lighting on top of it in the next pass. That didn't work either. Here's the shader script I've made so far:

    Code (CSharp):
    1. Shader "Universal Render Pipeline/2D/PaletteSwap"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Diffuse", 2D) = "white" {}
    6.         _MaskTex("Mask", 2D) = "white" {}
    7.         _NormalMap("Normal Map", 2D) = "bump" {}
    8.         _Color ("Tint", Color) = (1,1,1,1)
    9.         [PerRendererData] _SwapTex("Color Data", 2D) = "transparent" {}
    10.         [PerRendererData] _ColorIndex("Color Index", Int) = 0
    11.         [PerRendererData] _TotalPalettes("Total Palettes", Range(1, 255)) = 1
    12.         [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
    13.  
    14.         // Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
    15.         [HideInInspector] _Color("Tint", Color) = (1,1,1,1)
    16.         [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
    17.         [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1)
    18.         [HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {}
    19.         [HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    20.     }
    21.  
    22.     HLSLINCLUDE
    23.     #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    24.     ENDHLSL
    25.  
    26.     SubShader
    27.     {
    28.         Tags {
    29.               "Queue" = "Transparent"
    30.               "RenderType" = "Transparent"
    31.               "RenderPipeline" = "UniversalPipeline"
    32.               "PreviewType"="Plane"
    33.               "CanUseSpriteAtlas"="True"
    34.               "IgnoreProjector"="True"
    35.             }
    36.  
    37.         Blend SrcAlpha OneMinusSrcAlpha
    38.         Cull Off
    39.         ZWrite Off
    40.  
    41.        
    42.         Pass
    43.         {
    44.             CGPROGRAM
    45.             #pragma vertex vert
    46.             #pragma fragment frag
    47.             #pragma multi_compile _ PIXELSNAP_ON
    48.             #include "UnityCG.cginc"
    49.            
    50.             struct appdata_t
    51.             {
    52.                 float4 vertex   : POSITION;
    53.                 float4 color    : COLOR;
    54.                 float2 texcoord : TEXCOORD0;
    55.             };
    56.  
    57.             struct v2f
    58.             {
    59.                 float4 vertex   : SV_POSITION;
    60.                 fixed4 color    : COLOR;
    61.                 half2 texcoord  : TEXCOORD0;
    62.             };
    63.            
    64.             fixed4 _Color;
    65.             uniform float _ColorIndex;
    66.  
    67.             v2f vert(appdata_t IN)
    68.             {
    69.                 v2f OUT;
    70.                 OUT.vertex = UnityObjectToClipPos(IN.vertex);
    71.                 OUT.texcoord = IN.texcoord;
    72.                 OUT.color = IN.color * _Color;
    73.                 #ifdef PIXELSNAP_ON
    74.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    75.                 #endif
    76.  
    77.                 return OUT;
    78.             }
    79.  
    80.             sampler2D _MainTex;
    81.             sampler2D _AlphaTex;
    82.             float _AlphaSplitEnabled;
    83.             uniform int _TotalPalettes;
    84.  
    85.             sampler2D _SwapTex;
    86.  
    87.             fixed4 SampleSpriteTexture (float2 uv)
    88.             {
    89.                 fixed4 color = tex2D (_MainTex, uv);
    90.                 if (_AlphaSplitEnabled)
    91.                     color.a = tex2D (_AlphaTex, uv).r;
    92.  
    93.                 return color;
    94.             }
    95.  
    96.             fixed4 frag(v2f IN) : SV_Target
    97.             {
    98.                 //Decimal Index is the float version of a y value between 0 - 1
    99.                 //So in order to find each index we have to get each sixth (6 colors)
    100.                 //I take away 1/12 in order to be safe of rounding errors
    101.                 float decimalIndex = (_ColorIndex + 1.0)/(float)_TotalPalettes - 1.0/((float)_TotalPalettes * 2);
    102.                 fixed4 c = SampleSpriteTexture (IN.texcoord);
    103.                 fixed4 swapCol = tex2D(_SwapTex, float2(c.x, decimalIndex));
    104.                 fixed4 final = lerp(c, swapCol, swapCol.a) * IN.color;
    105.                 final.a = c.a;
    106.                 final.rgb *= c.a;
    107.                 return final;
    108.             }
    109.         ENDCG
    110.         }
    111.  
    112.         //GrabPass{ "_GrabTex" }
    113.  
    114.         Pass
    115.         {
    116.             Tags { "LightMode" = "Universal2D" }
    117.             HLSLPROGRAM
    118.             #pragma vertex CombinedShapeLightVertex
    119.             #pragma fragment CombinedShapeLightFragment
    120.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_0 __
    121.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_1 __
    122.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_2 __
    123.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_3 __
    124.  
    125.             struct Attributes
    126.             {
    127.                 float3 positionOS   : POSITION;
    128.                 float4 color        : COLOR;
    129.                 float2  uv           : TEXCOORD0;
    130.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    131.             };
    132.  
    133.             struct Varyings
    134.             {
    135.                 float4  positionCS  : SV_POSITION;
    136.                 half4   color       : COLOR;
    137.                 float2    uv          : TEXCOORD0;
    138.                 half2    lightingUV  : TEXCOORD1;
    139.                 UNITY_VERTEX_OUTPUT_STEREO
    140.             };
    141.  
    142.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl"
    143.  
    144.             TEXTURE2D(_MainTex);
    145.             SAMPLER(sampler_MainTex);
    146.             TEXTURE2D(_MaskTex);
    147.             SAMPLER(sampler_MaskTex);
    148.             TEXTURE2D(_NormalMap);
    149.             SAMPLER(sampler_NormalMap);
    150.             half4 _MainTex_ST;
    151.             half4 _NormalMap_ST;
    152.  
    153.             SAMPLER(sampler_AlphaTex);
    154.             float _AlphaSplitEnabled;
    155.  
    156.             uniform int _TotalPalettes;
    157.             uniform float _ColorIndex;
    158.             SAMPLER(sampler_SwapTex);
    159.             //TEXTURE2D(_GrabTex);
    160.             //SAMPLER(sampler_GrabTex);
    161.             //half4 _GrabTex_ST;
    162.  
    163.             #if USE_SHAPE_LIGHT_TYPE_0
    164.             SHAPE_LIGHT(0)
    165.             #endif
    166.  
    167.             #if USE_SHAPE_LIGHT_TYPE_1
    168.             SHAPE_LIGHT(1)
    169.             #endif
    170.  
    171.             #if USE_SHAPE_LIGHT_TYPE_2
    172.             SHAPE_LIGHT(2)
    173.             #endif
    174.  
    175.             #if USE_SHAPE_LIGHT_TYPE_3
    176.             SHAPE_LIGHT(3)
    177.             #endif
    178.  
    179.             Varyings CombinedShapeLightVertex(Attributes v)
    180.             {
    181.                 Varyings o = (Varyings)0;
    182.                 UNITY_SETUP_INSTANCE_ID(v);
    183.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    184.  
    185.                 o.positionCS = TransformObjectToHClip(v.positionOS);
    186.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    187.                 float4 clipVertex = o.positionCS / o.positionCS.w;
    188.                 o.lightingUV = ComputeScreenPos(clipVertex).xy;
    189.                 o.color = v.color;
    190.                 return o;
    191.             }
    192.  
    193.             #include "CombinedShapeLightShared_CustomPaletteSwap.hlsl"
    194.  
    195.             float4 SampleSpriteTexture(float2 uv)
    196.             {
    197.                 float4 color = tex2D(sampler_MainTex, uv);
    198.  
    199.                 if(_AlphaSplitEnabled)
    200.                     color.a = tex2D(sampler_AlphaTex, uv).r;
    201.  
    202.                 return color;
    203.             }
    204.  
    205.             half4 CombinedShapeLightFragment(Varyings i) : SV_Target
    206.             {
    207.                 float decimalIndex = (_ColorIndex + 1.0)/(float)_TotalPalettes - 1.0/((float)_TotalPalettes * 2.0);
    208.                 float4 c = SampleSpriteTexture(i.uv);
    209.                 float4 swapCol = tex2D(sampler_SwapTex, float2(c.x, decimalIndex));
    210.                 float4 final = lerp(c, swapCol, swapCol.a) * i.color;
    211.                 final.a = c.a;
    212.                 final.xyz *= c.a;
    213.  
    214.  
    215.                 float4 main = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    216.                 final = final * main;
    217.                 half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv);
    218.                 return CombinedShapeLightShared(main, final, mask, i.lightingUV);
    219.             }
    220.             ENDHLSL
    221.         }
    222.  
    223.         Pass
    224.         {
    225.             Tags { "LightMode" = "NormalsRendering"}
    226.             HLSLPROGRAM
    227.             #pragma vertex NormalsRenderingVertex
    228.             #pragma fragment NormalsRenderingFragment
    229.  
    230.             struct Attributes
    231.             {
    232.                 float3 positionOS   : POSITION;
    233.                 float4 color        : COLOR;
    234.                 float2 uv            : TEXCOORD0;
    235.                 float4 tangent      : TANGENT;
    236.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    237.             };
    238.  
    239.             struct Varyings
    240.             {
    241.                 float4  positionCS        : SV_POSITION;
    242.                 half4   color            : COLOR;
    243.                 float2    uv                : TEXCOORD0;
    244.                 half3   normalWS        : TEXCOORD1;
    245.                 half3   tangentWS        : TEXCOORD2;
    246.                 half3   bitangentWS        : TEXCOORD3;
    247.                 UNITY_VERTEX_OUTPUT_STEREO
    248.             };
    249.  
    250.             TEXTURE2D(_MainTex);
    251.             SAMPLER(sampler_MainTex);
    252.             TEXTURE2D(_NormalMap);
    253.             SAMPLER(sampler_NormalMap);
    254.             half4 _NormalMap_ST;  // Is this the right way to do this?
    255.  
    256.             Varyings NormalsRenderingVertex(Attributes attributes)
    257.             {
    258.                 Varyings o = (Varyings)0;
    259.                 UNITY_SETUP_INSTANCE_ID(attributes);
    260.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    261.  
    262.                 o.positionCS = TransformObjectToHClip(attributes.positionOS);
    263.                 o.uv = TRANSFORM_TEX(attributes.uv, _NormalMap);
    264.                 o.uv = attributes.uv;
    265.                 o.color = attributes.color;
    266.                 o.normalWS = TransformObjectToWorldDir(float3(0, 0, -1));
    267.                 o.tangentWS = TransformObjectToWorldDir(attributes.tangent.xyz);
    268.                 o.bitangentWS = cross(o.normalWS, o.tangentWS) * attributes.tangent.w;
    269.                 return o;
    270.             }
    271.  
    272.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl"
    273.  
    274.             half4 NormalsRenderingFragment(Varyings i) : SV_Target
    275.             {
    276.                 half4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    277.                 half3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, i.uv));
    278.                 return NormalsRenderingShared(mainTex, normalTS, i.tangentWS.xyz, i.bitangentWS.xyz, i.normalWS.xyz);
    279.             }
    280.             ENDHLSL
    281.         }
    282.  
    283.         Pass
    284.         {
    285.             Tags { "LightMode" = "UniversalForward" "Queue"="Transparent" "RenderType"="Transparent"}
    286.  
    287.             HLSLPROGRAM
    288.             #pragma vertex UnlitVertex
    289.             #pragma fragment UnlitFragment
    290.  
    291.             struct Attributes
    292.             {
    293.                 float3 positionOS   : POSITION;
    294.                 float4 color        : COLOR;
    295.                 float2 uv            : TEXCOORD0;
    296.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    297.             };
    298.  
    299.             struct Varyings
    300.             {
    301.                 float4  positionCS        : SV_POSITION;
    302.                 float4  color            : COLOR;
    303.                 float2    uv                : TEXCOORD0;
    304.                 UNITY_VERTEX_OUTPUT_STEREO
    305.             };
    306.  
    307.             TEXTURE2D(_MainTex);
    308.             SAMPLER(sampler_MainTex);
    309.             float4 _MainTex_ST;
    310.  
    311.             Varyings UnlitVertex(Attributes attributes)
    312.             {
    313.                 Varyings o = (Varyings)0;
    314.                 UNITY_SETUP_INSTANCE_ID(attributes);
    315.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    316.  
    317.                 o.positionCS = TransformObjectToHClip(attributes.positionOS);
    318.                 o.uv = TRANSFORM_TEX(attributes.uv, _MainTex);
    319.                 o.uv = attributes.uv;
    320.                 o.color = attributes.color;
    321.                 return o;
    322.             }
    323.  
    324.             float4 UnlitFragment(Varyings i) : SV_Target
    325.             {
    326.                 float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    327.                 return mainTex;
    328.             }
    329.             ENDHLSL
    330.         }  
    331.     }
    332.  
    333.     Fallback "Sprites/Default"
    334. }
    335.  
    Here's the custom HLSL file I added in with it:

    Code (CSharp):
    1. #if !defined(COMBINED_SHAPE_LIGHT_PASS)
    2. #define COMBINED_SHAPE_LIGHT_PASS
    3.  
    4. half _HDREmulationScale;
    5. half _UseSceneLighting;
    6. half4 _RendererColor;
    7.  
    8. half4 CombinedShapeLightShared(half4 color, half4 swapColor, half4 mask, half2 lightingUV)
    9. {
    10.     if (color.a == 0.0)
    11.         discard;
    12.  
    13.     //color = color * _RendererColor; // This is needed for sprite shape
    14.     color = swapColor * _RendererColor;
    15.  
    16. #if USE_SHAPE_LIGHT_TYPE_0
    17.     half4 shapeLight0 = SAMPLE_TEXTURE2D(_ShapeLightTexture0, sampler_ShapeLightTexture0, lightingUV);
    18.  
    19.     if (any(_ShapeLightMaskFilter0))
    20.     {
    21.         half4 processedMask = (1 - _ShapeLightInvertedFilter0) * mask + _ShapeLightInvertedFilter0 * (1 - mask);
    22.         shapeLight0 *= dot(processedMask, _ShapeLightMaskFilter0);
    23.     }
    24.  
    25.     half4 shapeLight0Modulate = shapeLight0 * _ShapeLightBlendFactors0.x;
    26.     half4 shapeLight0Additive = shapeLight0 * _ShapeLightBlendFactors0.y;
    27. #else
    28.     half4 shapeLight0Modulate = 0;
    29.     half4 shapeLight0Additive = 0;
    30. #endif
    31.  
    32. #if USE_SHAPE_LIGHT_TYPE_1
    33.     half4 shapeLight1 = SAMPLE_TEXTURE2D(_ShapeLightTexture1, sampler_ShapeLightTexture1, lightingUV);
    34.  
    35.     if (any(_ShapeLightMaskFilter1))
    36.     {
    37.         half4 processedMask = (1 - _ShapeLightInvertedFilter1) * mask + _ShapeLightInvertedFilter1 * (1 - mask);
    38.         shapeLight1 *= dot(processedMask, _ShapeLightMaskFilter1);
    39.     }
    40.  
    41.     half4 shapeLight1Modulate = shapeLight1 * _ShapeLightBlendFactors1.x;
    42.     half4 shapeLight1Additive = shapeLight1 * _ShapeLightBlendFactors1.y;
    43. #else
    44.     half4 shapeLight1Modulate = 0;
    45.     half4 shapeLight1Additive = 0;
    46. #endif
    47.  
    48. #if USE_SHAPE_LIGHT_TYPE_2
    49.     half4 shapeLight2 = SAMPLE_TEXTURE2D(_ShapeLightTexture2, sampler_ShapeLightTexture2, lightingUV);
    50.  
    51.     if (any(_ShapeLightMaskFilter2))
    52.     {
    53.         half4 processedMask = (1 - _ShapeLightInvertedFilter2) * mask + _ShapeLightInvertedFilter2 * (1 - mask);
    54.         shapeLight2 *= dot(processedMask, _ShapeLightMaskFilter2);
    55.     }
    56.  
    57.     half4 shapeLight2Modulate = shapeLight2 * _ShapeLightBlendFactors2.x;
    58.     half4 shapeLight2Additive = shapeLight2 * _ShapeLightBlendFactors2.y;
    59. #else
    60.     half4 shapeLight2Modulate = 0;
    61.     half4 shapeLight2Additive = 0;
    62. #endif
    63.  
    64. #if USE_SHAPE_LIGHT_TYPE_3
    65.     half4 shapeLight3 = SAMPLE_TEXTURE2D(_ShapeLightTexture3, sampler_ShapeLightTexture3, lightingUV);
    66.  
    67.     if (any(_ShapeLightMaskFilter3))
    68.     {
    69.         half4 processedMask = (1 - _ShapeLightInvertedFilter3) * mask + _ShapeLightInvertedFilter3 * (1 - mask);
    70.         shapeLight3 *= dot(processedMask, _ShapeLightMaskFilter3);
    71.     }
    72.  
    73.     half4 shapeLight3Modulate = shapeLight3 * _ShapeLightBlendFactors3.x;
    74.     half4 shapeLight3Additive = shapeLight3 * _ShapeLightBlendFactors3.y;
    75. #else
    76.     half4 shapeLight3Modulate = 0;
    77.     half4 shapeLight3Additive = 0;
    78. #endif
    79.  
    80.     half4 finalOutput;
    81. #if !USE_SHAPE_LIGHT_TYPE_0 && !USE_SHAPE_LIGHT_TYPE_1 && !USE_SHAPE_LIGHT_TYPE_2 && ! USE_SHAPE_LIGHT_TYPE_3
    82.     finalOutput = color;
    83. #else
    84.     half4 finalModulate = shapeLight0Modulate + shapeLight1Modulate + shapeLight2Modulate + shapeLight3Modulate;
    85.     half4 finalAdditve = shapeLight0Additive + shapeLight1Additive + shapeLight2Additive + shapeLight3Additive;
    86.     finalOutput = _HDREmulationScale * (color * finalModulate + finalAdditve);
    87. #endif
    88.  
    89.     finalOutput.a = color.a;
    90.  
    91.     finalOutput = finalOutput *_UseSceneLighting + (1 - _UseSceneLighting)*color;
    92.     return max(0, finalOutput);
    93. }
    94. #endif
    95.  
    If anyone has any leads on how to make this work or on how to combine 2d lighting with a custom shader I'd love any more advice.
     
  3. treecki

    treecki

    Joined:
    Feb 6, 2017
    Posts:
    29
    I figured out how to implement the palette swapping into URP, the issue had to do with properly porting from CGPROGRAM to HLSL and injecting that into the existing Default Sprite Lit shader. This site helped me understand how to properly write a shader in HLSL and compare it to the previous shader in CGPROGRAM.

    I'll include the shader below. Keep in mind I added the custom HLSL "CombinedShapeLightShared" above but this can be done without changing or creating the custom HLSL. The #include line needs to be changed if you use the older one though.

    Code (CSharp):
    1. Shader "Universal Render Pipeline/2D/PaletteSwap"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Diffuse", 2D) = "white" {}
    6.         _MaskTex("Mask", 2D) = "white" {}
    7.         _NormalMap("Normal Map", 2D) = "bump" {}
    8.         _Color ("Tint", Color) = (1,1,1,1)
    9.         [PerRendererData] _SwapTex("Color Data", 2D) = "transparent" {}
    10.         [PerRendererData] _ColorIndex("Color Index", Int) = 0
    11.         [PerRendererData] _TotalPalettes("Total Palettes", Range(1, 255)) = 1
    12.         [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
    13.  
    14.         // Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
    15.         [HideInInspector] _Color("Tint", Color) = (1,1,1,1)
    16.         [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
    17.         [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1)
    18.         [HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {}
    19.         [HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    20.     }
    21.  
    22.     HLSLINCLUDE
    23.     #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    24.     ENDHLSL
    25.  
    26.     SubShader
    27.     {
    28.         Tags {
    29.               "Queue" = "Transparent"
    30.               "RenderType" = "Transparent"
    31.               "RenderPipeline" = "UniversalPipeline"
    32.               "PreviewType"="Plane"
    33.               "CanUseSpriteAtlas"="True"
    34.               "IgnoreProjector"="True"
    35.             }
    36.  
    37.         Blend SrcAlpha OneMinusSrcAlpha
    38.         Cull Off
    39.         ZWrite Off
    40.  
    41.         HLSLINCLUDE
    42.             CBUFFER_START(UnityPerMaterial)
    43.  
    44.             uniform int _ColorIndex;
    45.             uniform float _TotalPalettes;
    46.  
    47.             CBUFFER_END
    48.         ENDHLSL
    49.  
    50.         Pass
    51.         {
    52.             Tags { "LightMode" = "Universal2D" }
    53.  
    54.             HLSLPROGRAM
    55.             #pragma vertex CombinedShapeLightVertex
    56.             #pragma fragment CombinedShapeLightFragment
    57.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_0 __
    58.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_1 __
    59.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_2 __
    60.             #pragma multi_compile USE_SHAPE_LIGHT_TYPE_3 __
    61.  
    62.             struct Attributes
    63.             {
    64.                 float3 positionOS   : POSITION;
    65.                 float4 color        : COLOR;
    66.                 float2  uv           : TEXCOORD0;
    67.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    68.             };
    69.  
    70.             struct Varyings
    71.             {
    72.                 float4  positionCS  : SV_POSITION;
    73.                 half4   color       : COLOR;
    74.                 float2    uv          : TEXCOORD0;
    75.                 half2    lightingUV  : TEXCOORD1;
    76.                 UNITY_VERTEX_OUTPUT_STEREO
    77.             };
    78.  
    79.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl"
    80.  
    81.             TEXTURE2D(_MainTex);
    82.             SAMPLER(sampler_MainTex);
    83.             TEXTURE2D(_MaskTex);
    84.             SAMPLER(sampler_MaskTex);
    85.             TEXTURE2D(_NormalMap);
    86.             SAMPLER(sampler_NormalMap);
    87.             half4 _MainTex_ST;
    88.             half4 _NormalMap_ST;
    89.  
    90.             TEXTURE2D(_AlphaTex);
    91.             SAMPLER(sampler_AlphaTex);
    92.             half4 _AlphaTex_ST;
    93.  
    94.             float _AlphaSplitEnabled;
    95.  
    96.             TEXTURE2D(_SwapTex);
    97.             SAMPLER(sampler_SwapTex);
    98.             half4 _SwapTex_ST;
    99.  
    100.             #if USE_SHAPE_LIGHT_TYPE_0
    101.             SHAPE_LIGHT(0)
    102.             #endif
    103.  
    104.             #if USE_SHAPE_LIGHT_TYPE_1
    105.             SHAPE_LIGHT(1)
    106.             #endif
    107.  
    108.             #if USE_SHAPE_LIGHT_TYPE_2
    109.             SHAPE_LIGHT(2)
    110.             #endif
    111.  
    112.             #if USE_SHAPE_LIGHT_TYPE_3
    113.             SHAPE_LIGHT(3)
    114.             #endif
    115.  
    116.             Varyings CombinedShapeLightVertex(Attributes v)
    117.             {
    118.                 Varyings o = (Varyings)0;
    119.                 UNITY_SETUP_INSTANCE_ID(v);
    120.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    121.  
    122.                 o.positionCS = TransformObjectToHClip(v.positionOS);
    123.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    124.                 float4 clipVertex = o.positionCS / o.positionCS.w;
    125.                 o.lightingUV = ComputeScreenPos(clipVertex).xy;
    126.                 o.color = v.color;
    127.                 return o;
    128.             }
    129.  
    130.             #include "CombinedShapeLightShared_CustomPaletteSwap.hlsl"
    131.  
    132.             float4 SampleSpriteTexture(float2 uv)
    133.             {
    134.                 half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
    135.  
    136.                 if(_AlphaSplitEnabled)
    137.                     color.a = SAMPLE_TEXTURE2D(_AlphaTex, sampler_AlphaTex, uv).r;
    138.  
    139.                 return color;
    140.             }
    141.  
    142.             half4 CombinedShapeLightFragment(Varyings i) : SV_Target
    143.             {
    144.                 float decimalIndex = (_ColorIndex + 1.0)/(float)_TotalPalettes - 1.0/((float)_TotalPalettes * 2.0);
    145.                 float4 c = SampleSpriteTexture(i.uv);
    146.                 half4 swapCol = SAMPLE_TEXTURE2D(_SwapTex, sampler_SwapTex, float2(c.x, decimalIndex));
    147.                 float4 final = lerp(c, swapCol, swapCol.a) * i.color;
    148.                 final.a = c.a;
    149.                 final.xyz *= c.a;
    150.  
    151.                 float4 main = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    152.                 half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv);
    153.                 return CombinedShapeLightShared(final, mask, i.lightingUV);
    154.             }
    155.             ENDHLSL
    156.         }
    157.  
    158.         Pass
    159.         {
    160.             Tags { "LightMode" = "NormalsRendering"}
    161.             HLSLPROGRAM
    162.             #pragma vertex NormalsRenderingVertex
    163.             #pragma fragment NormalsRenderingFragment
    164.  
    165.             struct Attributes
    166.             {
    167.                 float3 positionOS   : POSITION;
    168.                 float4 color        : COLOR;
    169.                 float2 uv            : TEXCOORD0;
    170.                 float4 tangent      : TANGENT;
    171.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    172.             };
    173.  
    174.             struct Varyings
    175.             {
    176.                 float4  positionCS        : SV_POSITION;
    177.                 half4   color            : COLOR;
    178.                 float2    uv                : TEXCOORD0;
    179.                 half3   normalWS        : TEXCOORD1;
    180.                 half3   tangentWS        : TEXCOORD2;
    181.                 half3   bitangentWS        : TEXCOORD3;
    182.                 UNITY_VERTEX_OUTPUT_STEREO
    183.             };
    184.  
    185.             TEXTURE2D(_MainTex);
    186.             SAMPLER(sampler_MainTex);
    187.             TEXTURE2D(_NormalMap);
    188.             SAMPLER(sampler_NormalMap);
    189.             half4 _NormalMap_ST;  // Is this the right way to do this?
    190.  
    191.             Varyings NormalsRenderingVertex(Attributes attributes)
    192.             {
    193.                 Varyings o = (Varyings)0;
    194.                 UNITY_SETUP_INSTANCE_ID(attributes);
    195.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    196.  
    197.                 o.positionCS = TransformObjectToHClip(attributes.positionOS);
    198.                 o.uv = TRANSFORM_TEX(attributes.uv, _NormalMap);
    199.                 o.uv = attributes.uv;
    200.                 o.color = attributes.color;
    201.                 o.normalWS = TransformObjectToWorldDir(float3(0, 0, -1));
    202.                 o.tangentWS = TransformObjectToWorldDir(attributes.tangent.xyz);
    203.                 o.bitangentWS = cross(o.normalWS, o.tangentWS) * attributes.tangent.w;
    204.                 return o;
    205.             }
    206.  
    207.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl"
    208.  
    209.             half4 NormalsRenderingFragment(Varyings i) : SV_Target
    210.             {
    211.                 half4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    212.                 half3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, i.uv));
    213.                 return NormalsRenderingShared(mainTex, normalTS, i.tangentWS.xyz, i.bitangentWS.xyz, i.normalWS.xyz);
    214.             }
    215.             ENDHLSL
    216.         }
    217.  
    218.         Pass
    219.         {
    220.             Tags { "LightMode" = "UniversalForward" "Queue"="Transparent" "RenderType"="Transparent"}
    221.  
    222.             HLSLPROGRAM
    223.             #pragma vertex UnlitVertex
    224.             #pragma fragment UnlitFragment
    225.  
    226.             struct Attributes
    227.             {
    228.                 float3 positionOS   : POSITION;
    229.                 float4 color        : COLOR;
    230.                 float2 uv            : TEXCOORD0;
    231.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    232.             };
    233.  
    234.             struct Varyings
    235.             {
    236.                 float4  positionCS        : SV_POSITION;
    237.                 float4  color            : COLOR;
    238.                 float2    uv                : TEXCOORD0;
    239.                 UNITY_VERTEX_OUTPUT_STEREO
    240.             };
    241.  
    242.             TEXTURE2D(_MainTex);
    243.             SAMPLER(sampler_MainTex);
    244.             float4 _MainTex_ST;
    245.  
    246.             Varyings UnlitVertex(Attributes attributes)
    247.             {
    248.                 Varyings o = (Varyings)0;
    249.                 UNITY_SETUP_INSTANCE_ID(attributes);
    250.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    251.  
    252.                 o.positionCS = TransformObjectToHClip(attributes.positionOS);
    253.                 o.uv = TRANSFORM_TEX(attributes.uv, _MainTex);
    254.                 o.uv = attributes.uv;
    255.                 o.color = attributes.color;
    256.                 return o;
    257.             }
    258.  
    259.             float4 UnlitFragment(Varyings i) : SV_Target
    260.             {
    261.                 float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    262.                 return mainTex;
    263.             }
    264.             ENDHLSL
    265.         }  
    266.     }
    267.  
    268.     Fallback "Sprites/Default"
    269. }
    270.  
    Here is the shader without any 2D lighting and just in HLSL:

    Code (CSharp):
    1. Shader "Custom/HLSLPaletteSwap"
    2. {
    3.     Properties
    4.     {
    5.  
    6.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    7.         _Color ("Color", Color) = (1,1,1,1)
    8.         [PerRendererData] _SwapTex("Color Data", 2D) = "transparent" {}
    9.         [PerRendererData] _ColorIndex("Color Index", Int) = 0
    10.         [PerRendererData] _TotalPalettes("Total Palettes", Range(1, 255)) = 1
    11.  
    12.         [HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {}
    13.         [HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    14.     }
    15.  
    16.     HLSLINCLUDE
    17.         #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    18.     ENDHLSL
    19.  
    20.     SubShader
    21.     {
    22.         Tags
    23.         {
    24.             "Queue" = "Transparent"
    25.             "RenderType" = "Transparent"
    26.             "RenderPipeline" = "UniversalPipeline"
    27.             "PreviewType"="Plane"
    28.             "CanUseSpriteAtlas"="True"
    29.             "IgnoreProjector"="True"
    30.         }
    31.  
    32.         Blend SrcAlpha OneMinusSrcAlpha
    33.         Cull Off
    34.         Lighting Off
    35.         ZWrite Off
    36.  
    37.         HLSLINCLUDE
    38.             CBUFFER_START(UnityPerMaterial)
    39.  
    40.             uniform int _ColorIndex;
    41.             uniform float _TotalPalettes;
    42.  
    43.             CBUFFER_END
    44.         ENDHLSL
    45.  
    46.         Pass
    47.         {
    48.             Tags { "LightMode" = "Universal2D" }
    49.  
    50.             HLSLPROGRAM
    51.  
    52.             #pragma vertex UnlitPassVertex
    53.             #pragma fragment UnlitPassFragment
    54.  
    55.             struct Attributes {
    56.                 float4 positionOS : POSITION;
    57.                 float4 color : COLOR;
    58.                 float2 uv : TEXCOORD0;
    59.             };
    60.  
    61.             struct Varyings {
    62.                 float4 positionCS : SV_POSITION;
    63.                 float4 color : COLOR;
    64.                 float2 uv : TEXCOORD0;
    65.             };
    66.  
    67.             TEXTURE2D(_MainTex);
    68.             SAMPLER(sampler_MainTex);
    69.             half4 _MainTex_ST;
    70.  
    71.             TEXTURE2D(_AlphaTex);
    72.             SAMPLER(sampler_AlphaTex);
    73.             half4 _AlphaTex_ST;
    74.  
    75.             float _AlphaSplitEnabled;
    76.  
    77.             //uniform int _TotalPalettes;
    78.             //uniform float _ColorIndex;
    79.             TEXTURE2D(_SwapTex);
    80.             SAMPLER(sampler_SwapTex);
    81.             half4 _SwapTex_ST;
    82.  
    83.             Varyings UnlitPassVertex(Attributes v)
    84.             {
    85.                 Varyings o = (Varyings)0;
    86.                 o.positionCS = TransformObjectToHClip(v.positionOS);
    87.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    88.                 o.color = v.color;
    89.                 return o;
    90.             }
    91.  
    92.             half4 SampleSpriteTexture(float2 uv)
    93.             {
    94.                 half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
    95.  
    96.                 if(_AlphaSplitEnabled)
    97.                     color.a = SAMPLE_TEXTURE2D(_AlphaTex, sampler_AlphaTex, uv).r;
    98.  
    99.                 return color;
    100.             }
    101.  
    102.             half4 UnlitPassFragment(Varyings i) : SV_Target
    103.             {
    104.                 half decimalIndex = (_ColorIndex + 1.0)/(float)_TotalPalettes - 1.0/((float)_TotalPalettes * 2.0);
    105.                 half4 c = SampleSpriteTexture(i.uv);
    106.                 half4 swapCol = SAMPLE_TEXTURE2D(_SwapTex, sampler_SwapTex, float2(c.x, decimalIndex));
    107.                 half4 final = lerp(c, swapCol, swapCol.a) * i.color;
    108.                 final.a = c.a;
    109.                 final.xyz *= c.a;
    110.                 return final;
    111.             }
    112.  
    113.             ENDHLSL
    114.         }
    115.     }
    116.  
    117. }
    118.  
    I hope this helps anyone in the future!
     
    NotaNaN, Apocryphus and spryx like this.