Last active
October 8, 2022 17:15
-
-
Save geolands/9a69d85fac3fe8102b0f77eadf003459 to your computer and use it in GitHub Desktop.
A replacement for the Unity 2D default lit sprite shader which supports correct lighting of sprites rotated relative to the camera. This shader was created by making small modifications to the shader from URP 12.1.7. The only change was to move the lighting uv calculation from the vertex shader to the fragment shader.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Shader "Universal Render Pipeline/2D/Sprite-Lit-Rotatable" | |
{ | |
Properties | |
{ | |
_MainTex("Diffuse", 2D) = "white" {} | |
_MaskTex("Mask", 2D) = "white" {} | |
_NormalMap("Normal Map", 2D) = "bump" {} | |
// Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader. | |
[HideInInspector] _Color("Tint", Color) = (1,1,1,1) | |
[HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1) | |
[HideInInspector] _Flip("Flip", Vector) = (1,1,1,1) | |
[HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {} | |
[HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0 | |
} | |
SubShader | |
{ | |
Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" } | |
Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha | |
Cull Off | |
ZWrite Off | |
Pass | |
{ | |
Tags { "LightMode" = "Universal2D" } | |
HLSLPROGRAM | |
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" | |
#pragma vertex CombinedShapeLightVertex | |
#pragma fragment CombinedShapeLightFragment | |
#pragma multi_compile USE_SHAPE_LIGHT_TYPE_0 __ | |
#pragma multi_compile USE_SHAPE_LIGHT_TYPE_1 __ | |
#pragma multi_compile USE_SHAPE_LIGHT_TYPE_2 __ | |
#pragma multi_compile USE_SHAPE_LIGHT_TYPE_3 __ | |
#pragma multi_compile _ DEBUG_DISPLAY | |
struct Attributes | |
{ | |
float3 positionOS : POSITION; | |
float4 color : COLOR; | |
float2 uv : TEXCOORD0; | |
UNITY_VERTEX_INPUT_INSTANCE_ID | |
}; | |
struct Varyings | |
{ | |
float4 positionCS : SV_POSITION; | |
half4 color : COLOR; | |
float2 uv : TEXCOORD0; | |
float4 screenPos : TEXCOORD1; | |
#if defined(DEBUG_DISPLAY) | |
float3 positionWS : TEXCOORD2; | |
#endif | |
UNITY_VERTEX_OUTPUT_STEREO | |
}; | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl" | |
TEXTURE2D(_MainTex); | |
SAMPLER(sampler_MainTex); | |
TEXTURE2D(_MaskTex); | |
SAMPLER(sampler_MaskTex); | |
half4 _MainTex_ST; | |
float4 _Color; | |
half4 _RendererColor; | |
#if USE_SHAPE_LIGHT_TYPE_0 | |
SHAPE_LIGHT(0) | |
#endif | |
#if USE_SHAPE_LIGHT_TYPE_1 | |
SHAPE_LIGHT(1) | |
#endif | |
#if USE_SHAPE_LIGHT_TYPE_2 | |
SHAPE_LIGHT(2) | |
#endif | |
#if USE_SHAPE_LIGHT_TYPE_3 | |
SHAPE_LIGHT(3) | |
#endif | |
Varyings CombinedShapeLightVertex(Attributes v) | |
{ | |
Varyings o = (Varyings)0; | |
UNITY_SETUP_INSTANCE_ID(v); | |
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); | |
o.positionCS = TransformObjectToHClip(v.positionOS); | |
#if defined(DEBUG_DISPLAY) | |
o.positionWS = TransformObjectToWorld(v.positionOS); | |
#endif | |
o.uv = TRANSFORM_TEX(v.uv, _MainTex); | |
o.screenPos = ComputeScreenPos(o.positionCS); | |
o.color = v.color * _Color * _RendererColor; | |
return o; | |
} | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/CombinedShapeLightShared.hlsl" | |
half4 CombinedShapeLightFragment(Varyings i) : SV_Target | |
{ | |
const half4 main = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); | |
const half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv); | |
SurfaceData2D surfaceData; | |
InputData2D inputData; | |
InitializeSurfaceData(main.rgb, main.a, mask, surfaceData); | |
half2 lightingUV = i.screenPos.xy / i.screenPos.w; | |
InitializeInputData(i.uv, lightingUV, inputData); | |
return CombinedShapeLightShared(surfaceData, inputData); | |
} | |
ENDHLSL | |
} | |
Pass | |
{ | |
Tags { "LightMode" = "NormalsRendering"} | |
HLSLPROGRAM | |
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" | |
#pragma vertex NormalsRenderingVertex | |
#pragma fragment NormalsRenderingFragment | |
struct Attributes | |
{ | |
float3 positionOS : POSITION; | |
float4 color : COLOR; | |
float2 uv : TEXCOORD0; | |
float4 tangent : TANGENT; | |
UNITY_VERTEX_INPUT_INSTANCE_ID | |
}; | |
struct Varyings | |
{ | |
float4 positionCS : SV_POSITION; | |
half4 color : COLOR; | |
float2 uv : TEXCOORD0; | |
half3 normalWS : TEXCOORD1; | |
half3 tangentWS : TEXCOORD2; | |
half3 bitangentWS : TEXCOORD3; | |
UNITY_VERTEX_OUTPUT_STEREO | |
}; | |
TEXTURE2D(_MainTex); | |
SAMPLER(sampler_MainTex); | |
TEXTURE2D(_NormalMap); | |
SAMPLER(sampler_NormalMap); | |
half4 _NormalMap_ST; // Is this the right way to do this? | |
Varyings NormalsRenderingVertex(Attributes attributes) | |
{ | |
Varyings o = (Varyings)0; | |
UNITY_SETUP_INSTANCE_ID(attributes); | |
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); | |
o.positionCS = TransformObjectToHClip(attributes.positionOS); | |
o.uv = TRANSFORM_TEX(attributes.uv, _NormalMap); | |
o.color = attributes.color; | |
o.normalWS = -GetViewForwardDir(); | |
o.tangentWS = TransformObjectToWorldDir(attributes.tangent.xyz); | |
o.bitangentWS = cross(o.normalWS, o.tangentWS) * attributes.tangent.w; | |
return o; | |
} | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl" | |
half4 NormalsRenderingFragment(Varyings i) : SV_Target | |
{ | |
const half4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); | |
const half3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, i.uv)); | |
return NormalsRenderingShared(mainTex, normalTS, i.tangentWS.xyz, i.bitangentWS.xyz, i.normalWS.xyz); | |
} | |
ENDHLSL | |
} | |
Pass | |
{ | |
Tags { "LightMode" = "UniversalForward" "Queue"="Transparent" "RenderType"="Transparent"} | |
HLSLPROGRAM | |
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" | |
#pragma vertex UnlitVertex | |
#pragma fragment UnlitFragment | |
struct Attributes | |
{ | |
float3 positionOS : POSITION; | |
float4 color : COLOR; | |
float2 uv : TEXCOORD0; | |
UNITY_VERTEX_INPUT_INSTANCE_ID | |
}; | |
struct Varyings | |
{ | |
float4 positionCS : SV_POSITION; | |
float4 color : COLOR; | |
float2 uv : TEXCOORD0; | |
#if defined(DEBUG_DISPLAY) | |
float3 positionWS : TEXCOORD2; | |
#endif | |
UNITY_VERTEX_OUTPUT_STEREO | |
}; | |
TEXTURE2D(_MainTex); | |
SAMPLER(sampler_MainTex); | |
float4 _MainTex_ST; | |
float4 _Color; | |
half4 _RendererColor; | |
Varyings UnlitVertex(Attributes attributes) | |
{ | |
Varyings o = (Varyings)0; | |
UNITY_SETUP_INSTANCE_ID(attributes); | |
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); | |
o.positionCS = TransformObjectToHClip(attributes.positionOS); | |
#if defined(DEBUG_DISPLAY) | |
o.positionWS = TransformObjectToWorld(v.positionOS); | |
#endif | |
o.uv = TRANSFORM_TEX(attributes.uv, _MainTex); | |
o.color = attributes.color * _Color * _RendererColor; | |
return o; | |
} | |
float4 UnlitFragment(Varyings i) : SV_Target | |
{ | |
float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); | |
#if defined(DEBUG_DISPLAY) | |
SurfaceData2D surfaceData; | |
InputData2D inputData; | |
half4 debugColor = 0; | |
InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData); | |
InitializeInputData(i.uv, inputData); | |
SETUP_DEBUG_DATA_2D(inputData, i.positionWS); | |
if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor)) | |
{ | |
return debugColor; | |
} | |
#endif | |
return mainTex; | |
} | |
ENDHLSL | |
} | |
} | |
Fallback "Sprites/Default" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment