GPU优化
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
// 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,
|
||||
// allowing illuminated objects to retain proper transparency.
|
||||
// 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"
|
||||
{
|
||||
@@ -20,31 +20,26 @@ Shader "Soullies/BlendUnlit"
|
||||
[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)]
|
||||
// When toggled ON : uses the Red channel of the texture as Alpha (for single-channel masks).
|
||||
// When toggled OFF : uses the A channel of the texture (standard RGBA sprite).
|
||||
[Toggle] _UseRedAsAlpha ("Use Red Channel as Alpha", Float) = 0
|
||||
|
||||
[Space(8)]
|
||||
[Header(Blend Mode)]
|
||||
// 0 = Alpha Blend (SrcAlpha, OneMinusSrcAlpha) – standard transparent
|
||||
// 1 = Additive (SrcAlpha, One) – add light, black = invisible
|
||||
// 2 = Multiply (DstColor, Zero) – darken underlying pixels
|
||||
// 3 = Premultiplied(One, OneMinusSrcAlpha) – for pre-multiplied alpha textures
|
||||
[KeywordEnum(Alpha, Additive, Multiply, Premultiplied)] _BlendMode ("Blend Mode", Float) = 0
|
||||
|
||||
[Space(8)]
|
||||
[Header(Render State)]
|
||||
[Enum(UnityEngine.Rendering.CullMode)] _CullMode ("Cull Mode", Float) = 2 // Back
|
||||
[Enum(UnityEngine.Rendering.CullMode)] _CullMode ("Cull Mode", Float) = 2
|
||||
[Enum(Off, 0, On, 1)] _ZWrite ("Z Write", Float) = 0
|
||||
|
||||
// Internal blend equation floats – managed by BlendUnlitShaderGUI.
|
||||
// Default values = Alpha blend: SrcAlpha(5), OneMinusSrcAlpha(10).
|
||||
// MUST be declared here so Unity serialises them into the .mat asset
|
||||
// and they survive domain reloads / Ctrl+S without resetting to 0(Zero,Zero=black).
|
||||
[HideInInspector] _SrcBlendRGB ("Src Blend (Internal)", Float) = 5
|
||||
[HideInInspector] _DstBlendRGB ("Dst Blend (Internal)", Float) = 10
|
||||
}
|
||||
@@ -62,26 +57,18 @@ Shader "Soullies/BlendUnlit"
|
||||
"CanUseSpriteAtlas" = "True"
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Blend equations for each mode (controlled by shader_feature variants):
|
||||
// Alpha : SrcAlpha, OneMinusSrcAlpha (standard transparency)
|
||||
// Additive : SrcAlpha, One (screen-style additive, black is invisible)
|
||||
// Multiply : DstColor, Zero (multiply blend, darkens below)
|
||||
// Premultiplied : One, OneMinusSrcAlpha (for pre-multiplied textures/HDR)
|
||||
// ---------------------------------------------------------------------------
|
||||
Cull [_CullMode]
|
||||
ZWrite [_ZWrite]
|
||||
ZTest LEqual
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Pass 1 – Universal 2D (sprite renderer main path)
|
||||
// Pass 1 – Universal 2D
|
||||
// ---------------------------------------------------------------------------
|
||||
Pass
|
||||
{
|
||||
Name "BlendUnlit_Universal2D"
|
||||
Tags { "LightMode" = "Universal2D" }
|
||||
|
||||
// Blend state driven by shader_feature variant
|
||||
Blend [_SrcBlendRGB] [_DstBlendRGB]
|
||||
|
||||
HLSLPROGRAM
|
||||
@@ -93,35 +80,35 @@ Shader "Soullies/BlendUnlit"
|
||||
|
||||
#pragma multi_compile_instancing
|
||||
#pragma multi_compile_vertex _ SKINNED_SPRITE
|
||||
|
||||
// Blend mode variants (local_fragment: blend equation changes are per-draw, not per-pass)
|
||||
#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"
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Shared CBUFFER (SRP Batcher compatible)
|
||||
// -----------------------------------------------------------------------
|
||||
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
|
||||
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
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Vertex / Fragment structs
|
||||
// -----------------------------------------------------------------------
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
half4 color : COLOR;
|
||||
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
|
||||
};
|
||||
@@ -129,41 +116,30 @@ Shader "Soullies/BlendUnlit"
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
half4 color : COLOR;
|
||||
float4 uvAndEmissionRG : TEXCOORD0;
|
||||
float4 emissionBAAndCustomUV: TEXCOORD1;
|
||||
half4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Shared pixel logic (inlined as a function to avoid copy-paste)
|
||||
// -----------------------------------------------------------------------
|
||||
half4 ComputeColor(float2 uv, half4 vertexColor)
|
||||
half4 ComputeColor(float2 uv, half4 vertexColor, float4 customEmissionData)
|
||||
{
|
||||
half4 texSample = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
|
||||
|
||||
// Alpha channel selection (Lerp instead of macro avoids variant stripping issues)
|
||||
half texAlpha = lerp(texSample.a, texSample.r, _UseRedAsAlpha);
|
||||
|
||||
// Reconstruct colour from texture
|
||||
half4 texColor = half4(texSample.rgb, texAlpha);
|
||||
|
||||
// Base colour multiply (tint)
|
||||
half4 color = texColor * _BaseColor;
|
||||
|
||||
// Emission multiply
|
||||
half4 emissionMult = lerp(half4(1, 1, 1, 1), _EmissionColor, _EnableEmission);
|
||||
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;
|
||||
|
||||
// Vertex color (Sprite tint / SpriteRenderer.color)
|
||||
color *= vertexColor;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Vertex Shader
|
||||
// -----------------------------------------------------------------------
|
||||
Varyings vert(Attributes IN)
|
||||
{
|
||||
Varyings OUT = (Varyings)0;
|
||||
@@ -172,32 +148,36 @@ Shader "Soullies/BlendUnlit"
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
|
||||
UNITY_SKINNED_VERTEX_COMPUTE(IN);
|
||||
|
||||
// Respect SpriteRenderer Flip X/Y
|
||||
IN.positionOS = UnityFlipSprite(IN.positionOS, unity_SpriteProps.xy);
|
||||
|
||||
VertexPositionInputs vpi = GetVertexPositionInputs(IN.positionOS);
|
||||
OUT.positionCS = vpi.positionCS;
|
||||
OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
|
||||
OUT.color = IN.color * unity_SpriteColor;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Fragment Shader
|
||||
// -----------------------------------------------------------------------
|
||||
half4 frag(Varyings IN) : SV_Target
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(IN);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
|
||||
|
||||
return ComputeColor(IN.uv, IN.color);
|
||||
}
|
||||
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 (MeshRenderer / 3D object fallback path)
|
||||
// Pass 2 – Universal Forward
|
||||
// ---------------------------------------------------------------------------
|
||||
Pass
|
||||
{
|
||||
@@ -215,20 +195,24 @@ Shader "Soullies/BlendUnlit"
|
||||
|
||||
#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);
|
||||
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;
|
||||
@@ -237,31 +221,34 @@ Shader "Soullies/BlendUnlit"
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
half4 color : COLOR;
|
||||
float4 uvAndEmissionRG : TEXCOORD0;
|
||||
float4 emissionBAAndCustomUV: TEXCOORD1;
|
||||
half4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
half4 color : COLOR;
|
||||
half fogFactor : TEXCOORD1;
|
||||
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)
|
||||
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 emissionMult = lerp(half4(1, 1, 1, 1), _EmissionColor, _EnableEmission);
|
||||
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;
|
||||
@@ -277,9 +264,13 @@ Shader "Soullies/BlendUnlit"
|
||||
|
||||
VertexPositionInputs vpi = GetVertexPositionInputs(IN.positionOS);
|
||||
OUT.positionCS = vpi.positionCS;
|
||||
OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
|
||||
OUT.color = IN.color;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -288,36 +279,44 @@ Shader "Soullies/BlendUnlit"
|
||||
UNITY_SETUP_INSTANCE_ID(IN);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
|
||||
|
||||
half4 color = ComputeColor(IN.uv, IN.color);
|
||||
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 (Editor picking highlight)
|
||||
// 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;
|
||||
@@ -325,10 +324,8 @@ Shader "Soullies/BlendUnlit"
|
||||
|
||||
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;
|
||||
@@ -337,46 +334,43 @@ Shader "Soullies/BlendUnlit"
|
||||
OUT.positionCS = TransformObjectToHClip(IN.positionOS);
|
||||
return OUT;
|
||||
}
|
||||
|
||||
half4 frag(Varyings IN) : SV_Target
|
||||
{
|
||||
return half4(_ObjectId, _PassValue, 1.0, 1.0);
|
||||
}
|
||||
half4 frag(Varyings IN) : SV_Target { return half4(_ObjectId, _PassValue, 1.0, 1.0); }
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Pass 4 – Scene Picking (Editor object picking)
|
||||
// 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;
|
||||
@@ -385,19 +379,10 @@ Shader "Soullies/BlendUnlit"
|
||||
OUT.positionCS = TransformObjectToHClip(IN.positionOS);
|
||||
return OUT;
|
||||
}
|
||||
|
||||
half4 frag(Varyings IN) : SV_Target
|
||||
{
|
||||
return unity_SelectionID;
|
||||
}
|
||||
half4 frag(Varyings IN) : SV_Target { return unity_SelectionID; }
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Custom Editor: drives the Blend Mode property → actual GPU Blend state
|
||||
// ---------------------------------------------------------------------------
|
||||
CustomEditor "BlendUnlitShaderGUI"
|
||||
|
||||
FallBack "Hidden/Universal Render Pipeline/FallbackError"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user