// BlendUnlit.shader // Soullies - Hand-written URP 17 Unlit Sprite/Mesh Shader // Derived from TrackShader (ASE), rewritten for clarity and extensibility. // // Core Feature: Base Color * Texture, optionally multiplied by an HDR Emission Color. // New Feature : Runtime-selectable Blend Mode (Alpha, Additive, Multiply, Premultiplied). // Updated : Tightly packed Custom Data (Emission RGBA & UV Offset XY) to perfectly match Unity Particle System streams. Shader "Soullies/BlendUnlit" { Properties { [Header(Texture)] _MainTex ("Main Texture", 2D) = "white" {} [Space(8)] [Header(Color)] [MainColor] _BaseColor ("Base Color", Color) = (1, 1, 1, 1) [Space(8)] [Header(Emission)] [Toggle] _EnableEmission ("Enable Emission", Float) = 0 [Toggle] _UseParticleDataForEmission ("Use Particle Data for Emission", Float) = 0 [HDR] _EmissionColor ("Emission Color (HDR)", Color) = (0, 0, 0, 1) [Space(8)] [Header(UV Animation)] [Toggle] _UseParticleDataForUV ("Use Particle Data for UV Panning", Float) = 0 [Space(8)] [Header(Alpha Source)] [Toggle] _UseRedAsAlpha ("Use Red Channel as Alpha", Float) = 0 [Space(8)] [Header(Blend Mode)] [KeywordEnum(Alpha, Additive, Multiply, Premultiplied)] _BlendMode ("Blend Mode", Float) = 0 [Space(8)] [Header(Render State)] [Enum(UnityEngine.Rendering.CullMode)] _CullMode ("Cull Mode", Float) = 2 [Enum(Off, 0, On, 1)] _ZWrite ("Z Write", Float) = 0 [HideInInspector] _SrcBlendRGB ("Src Blend (Internal)", Float) = 5 [HideInInspector] _DstBlendRGB ("Dst Blend (Internal)", Float) = 10 } SubShader { Tags { "RenderPipeline" = "UniversalPipeline" "RenderType" = "Transparent" "Queue" = "Transparent" "UniversalMaterialType" = "Unlit" "IgnoreProjector" = "True" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" } Cull [_CullMode] ZWrite [_ZWrite] ZTest LEqual // --------------------------------------------------------------------------- // Pass 1 – Universal 2D // --------------------------------------------------------------------------- Pass { Name "BlendUnlit_Universal2D" Tags { "LightMode" = "Universal2D" } Blend [_SrcBlendRGB] [_DstBlendRGB] HLSLPROGRAM #pragma target 3.5 #pragma prefer_hlslcc gles #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #pragma multi_compile_vertex _ SKINNED_SPRITE #pragma shader_feature_local _BLENDMODE_ALPHA _BLENDMODE_ADDITIVE _BLENDMODE_MULTIPLY _BLENDMODE_PREMULTIPLIED #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl" TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; half4 _BaseColor; half4 _EmissionColor; float _EnableEmission; float _UseParticleDataForEmission; float _UseParticleDataForUV; float _UseRedAsAlpha; float _BlendMode; float _CullMode; float _ZWrite; float _SrcBlendRGB; float _DstBlendRGB; CBUFFER_END struct Attributes { float3 positionOS : POSITION; float4 uvAndEmissionRG : TEXCOORD0; // xy = Base UV, zw = Custom1.xy (Emission R, G) float4 emissionBAAndCustomUV: TEXCOORD1; // xy = Custom1.zw (Emission B, Intensity), zw = Custom2.xy (UV Offset) half4 color : COLOR; UNITY_SKINNED_VERTEX_INPUTS UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; float4 uvAndEmissionRG : TEXCOORD0; float4 emissionBAAndCustomUV: TEXCOORD1; half4 color : COLOR; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; half4 ComputeColor(float2 uv, half4 vertexColor, float4 customEmissionData) { half4 texSample = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv); half texAlpha = lerp(texSample.a, texSample.r, _UseRedAsAlpha); half4 texColor = half4(texSample.rgb, texAlpha); half4 color = texColor * _BaseColor; half4 particleEmissionModifier = half4(customEmissionData.rgb * customEmissionData.a, 1.0); half4 targetEmissionColor = lerp(_EmissionColor, _EmissionColor * particleEmissionModifier, _UseParticleDataForEmission); half4 emissionMult = lerp(half4(1, 1, 1, 1), targetEmissionColor, _EnableEmission); color *= emissionMult; color *= vertexColor; return color; } Varyings vert(Attributes IN) { Varyings OUT = (Varyings)0; UNITY_SETUP_INSTANCE_ID(IN); UNITY_TRANSFER_INSTANCE_ID(IN, OUT); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); UNITY_SKINNED_VERTEX_COMPUTE(IN); IN.positionOS = UnityFlipSprite(IN.positionOS, unity_SpriteProps.xy); VertexPositionInputs vpi = GetVertexPositionInputs(IN.positionOS); OUT.positionCS = vpi.positionCS; OUT.uvAndEmissionRG.xy = TRANSFORM_TEX(IN.uvAndEmissionRG.xy, _MainTex); OUT.uvAndEmissionRG.zw = IN.uvAndEmissionRG.zw; OUT.emissionBAAndCustomUV = IN.emissionBAAndCustomUV; OUT.color = IN.color * unity_SpriteColor; return OUT; } half4 frag(Varyings IN) : SV_Target { UNITY_SETUP_INSTANCE_ID(IN); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN); float2 baseUV = IN.uvAndEmissionRG.xy; float2 uvOffset = IN.emissionBAAndCustomUV.zw; float2 finalUV = lerp(baseUV, baseUV + uvOffset, _UseParticleDataForUV); float4 customEmissionData = float4(IN.uvAndEmissionRG.zw, IN.emissionBAAndCustomUV.xy); return ComputeColor(finalUV, IN.color, customEmissionData); } ENDHLSL } // --------------------------------------------------------------------------- // Pass 2 – Universal Forward // --------------------------------------------------------------------------- Pass { Name "BlendUnlit_Forward" Tags { "LightMode" = "UniversalForwardOnly" } Blend [_SrcBlendRGB] [_DstBlendRGB] HLSLPROGRAM #pragma target 3.5 #pragma prefer_hlslcc gles #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #pragma multi_compile_fog #pragma shader_feature_local _BLENDMODE_ALPHA _BLENDMODE_ADDITIVE _BLENDMODE_MULTIPLY _BLENDMODE_PREMULTIPLIED #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl" TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; half4 _BaseColor; half4 _EmissionColor; float _EnableEmission; float _UseParticleDataForEmission; float _UseParticleDataForUV; float _UseRedAsAlpha; float _BlendMode; float _CullMode; float _ZWrite; float _SrcBlendRGB; float _DstBlendRGB; CBUFFER_END struct Attributes { float3 positionOS : POSITION; float4 uvAndEmissionRG : TEXCOORD0; float4 emissionBAAndCustomUV: TEXCOORD1; half4 color : COLOR; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; float4 uvAndEmissionRG : TEXCOORD0; float4 emissionBAAndCustomUV: TEXCOORD1; half fogFactor : TEXCOORD2; // 顺延至 TEXCOORD2 half4 color : COLOR; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; half4 ComputeColor(float2 uv, half4 vertexColor, float4 customEmissionData) { half4 texSample = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv); half texAlpha = lerp(texSample.a, texSample.r, _UseRedAsAlpha); half4 texColor = half4(texSample.rgb, texAlpha); half4 color = texColor * _BaseColor; half4 particleEmissionModifier = half4(customEmissionData.rgb * customEmissionData.a, 1.0); half4 targetEmissionColor = lerp(_EmissionColor, _EmissionColor * particleEmissionModifier, _UseParticleDataForEmission); half4 emissionMult = lerp(half4(1, 1, 1, 1), targetEmissionColor, _EnableEmission); color *= emissionMult; color *= vertexColor; return color; } Varyings vert(Attributes IN) { Varyings OUT = (Varyings)0; UNITY_SETUP_INSTANCE_ID(IN); UNITY_TRANSFER_INSTANCE_ID(IN, OUT); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); VertexPositionInputs vpi = GetVertexPositionInputs(IN.positionOS); OUT.positionCS = vpi.positionCS; OUT.uvAndEmissionRG.xy = TRANSFORM_TEX(IN.uvAndEmissionRG.xy, _MainTex); OUT.uvAndEmissionRG.zw = IN.uvAndEmissionRG.zw; OUT.emissionBAAndCustomUV = IN.emissionBAAndCustomUV; OUT.fogFactor = ComputeFogFactor(vpi.positionCS.z); OUT.color = IN.color; return OUT; } half4 frag(Varyings IN) : SV_Target { UNITY_SETUP_INSTANCE_ID(IN); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN); float2 baseUV = IN.uvAndEmissionRG.xy; float2 uvOffset = IN.emissionBAAndCustomUV.zw; float2 finalUV = lerp(baseUV, baseUV + uvOffset, _UseParticleDataForUV); float4 customEmissionData = float4(IN.uvAndEmissionRG.zw, IN.emissionBAAndCustomUV.xy); half4 color = ComputeColor(finalUV, IN.color, customEmissionData); color.rgb = MixFog(color.rgb, IN.fogFactor); return color; } ENDHLSL } // --------------------------------------------------------------------------- // Pass 3 – Scene Selection // --------------------------------------------------------------------------- Pass { Name "SceneSelectionPass" Tags { "LightMode" = "SceneSelectionPass" } Cull Off HLSLPROGRAM #pragma target 3.5 #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; half4 _BaseColor; half4 _EmissionColor; float _EnableEmission; float _UseParticleDataForEmission; float _UseParticleDataForUV; float _UseRedAsAlpha; float _BlendMode; float _CullMode; float _ZWrite; float _SrcBlendRGB; float _DstBlendRGB; CBUFFER_END int _ObjectId; int _PassValue; struct Attributes { float3 positionOS : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; Varyings vert(Attributes IN) { Varyings OUT = (Varyings)0; UNITY_SETUP_INSTANCE_ID(IN); UNITY_TRANSFER_INSTANCE_ID(IN, OUT); OUT.positionCS = TransformObjectToHClip(IN.positionOS); return OUT; } half4 frag(Varyings IN) : SV_Target { return half4(_ObjectId, _PassValue, 1.0, 1.0); } ENDHLSL } // --------------------------------------------------------------------------- // Pass 4 – Scene Picking // --------------------------------------------------------------------------- Pass { Name "ScenePickingPass" Tags { "LightMode" = "Picking" } Cull Off HLSLPROGRAM #pragma target 3.5 #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; half4 _BaseColor; half4 _EmissionColor; float _EnableEmission; float _UseParticleDataForEmission; float _UseParticleDataForUV; float _UseRedAsAlpha; float _BlendMode; float _CullMode; float _ZWrite; float _SrcBlendRGB; float _DstBlendRGB; CBUFFER_END float4 _SelectionID; struct Attributes { float3 positionOS : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; Varyings vert(Attributes IN) { Varyings OUT = (Varyings)0; UNITY_SETUP_INSTANCE_ID(IN); UNITY_TRANSFER_INSTANCE_ID(IN, OUT); OUT.positionCS = TransformObjectToHClip(IN.positionOS); return OUT; } half4 frag(Varyings IN) : SV_Target { return unity_SelectionID; } ENDHLSL } } CustomEditor "BlendUnlitShaderGUI" FallBack "Hidden/Universal Render Pipeline/FallbackError" }