Files
ichni_Official/Assets/Shaders/BlendUnlit.shader
SoulliesOfficial 1bc9af280b 同步
2026-04-03 10:53:11 -04:00

404 lines
15 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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,
// allowing illuminated objects to retain proper transparency.
// New Feature : Runtime-selectable Blend Mode (Alpha, Additive, Multiply, Premultiplied).
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
[HDR] _EmissionColor ("Emission Color (HDR)", Color) = (0, 0, 0, 1)
[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(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
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"RenderType" = "Transparent"
"Queue" = "Transparent"
"UniversalMaterialType" = "Unlit"
"IgnoreProjector" = "True"
"PreviewType" = "Plane"
"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
{
Name "BlendUnlit_Universal2D"
Tags { "LightMode" = "Universal2D" }
// Blend state driven by shader_feature variant
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
// 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);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
half4 _BaseColor;
half4 _EmissionColor;
float _ZWrite;
float _SrcBlendRGB;
float _DstBlendRGB;
CBUFFER_END
// -----------------------------------------------------------------------
// Vertex / Fragment structs
// -----------------------------------------------------------------------
struct Attributes
{
float3 positionOS : POSITION;
float2 uv : TEXCOORD0;
half4 color : COLOR;
UNITY_SKINNED_VERTEX_INPUTS
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
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 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);
color *= emissionMult;
// Vertex color (Sprite tint / SpriteRenderer.color)
color *= vertexColor;
return color;
}
// -----------------------------------------------------------------------
// Vertex Shader
// -----------------------------------------------------------------------
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);
// 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;
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);
}
ENDHLSL
}
// ---------------------------------------------------------------------------
// Pass 2 Universal Forward (MeshRenderer / 3D object fallback path)
// ---------------------------------------------------------------------------
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 _UseRedAsAlpha;
float _ZWrite;
float _SrcBlendRGB;
float _DstBlendRGB;
CBUFFER_END
struct Attributes
{
float3 positionOS : POSITION;
float2 uv : TEXCOORD0;
half4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
half4 color : COLOR;
half fogFactor : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
half4 ComputeColor(float2 uv, half4 vertexColor)
{
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);
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.uv = TRANSFORM_TEX(IN.uv, _MainTex);
OUT.color = IN.color;
OUT.fogFactor = ComputeFogFactor(vpi.positionCS.z);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
half4 color = ComputeColor(IN.uv, IN.color);
color.rgb = MixFog(color.rgb, IN.fogFactor);
return color;
}
ENDHLSL
}
// ---------------------------------------------------------------------------
// Pass 3 Scene Selection (Editor picking highlight)
// ---------------------------------------------------------------------------
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 _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 (Editor object 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 _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
}
}
// ---------------------------------------------------------------------------
// Custom Editor: drives the Blend Mode property → actual GPU Blend state
// ---------------------------------------------------------------------------
CustomEditor "BlendUnlitShaderGUI"
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}