Project_WL/Assets/WL/Look/Farm/Shaders/WLShoreSkirt.shader

205 lines
7.4 KiB
Plaintext

// ─────────────────────────────────────────────────────────────────────────────
// WLShoreSkirt.shader — 섬 둘레 물가 스커트(완만한 모래 경사) 전용 URP 언릿 정점색 (WL-816zg · #816)
//
// 왜 전용 셰이더인가:
// · 색은 전부 CPU 가 정점색으로 굽는다(풀 → 모래 → 물속 어둡기). 셰이더는 그 값을 그대로 내보낸다 = 텍스처 0 · 분기 0.
// · URP Unlit 은 정점색을 읽지 않고, Lit 계열은 조명·그림자 변형이 붙어 모바일에서 비싸다.
// · 물 셰이더(Farm_Water_Demo3)가 **깊이 텍스처**로 물가 흰 띠를 만든다 → URP 가 깊이 프리패스로 도는 설정에서도
// 경사가 깊이에 들어가야 하므로 DepthOnly · DepthNormals 패스를 함께 둔다(파이프라인이 요구할 때만 돈다 = 평소 비용 0).
//
// 모바일 제약 준수 (PD 상시 규칙 d):
// · geometry / tessellation 없음 · 불투명 · ZWrite On · 그림자 없음(ShadowCaster 패스 없음)
// · SRP Batcher 호환 (CBUFFER_START(UnityPerMaterial) — 모든 패스 동일)
// · #pragma target 2.0 · half 정밀도 · 텍스처 샘플 0회
//
// 정점색 규약 (WLShoreSkirt.cs 가 굽는다): RGB = 최종 색(리니어 파이프라인이면 리니어 값) · A = 미사용.
// ─────────────────────────────────────────────────────────────────────────────
Shader "WL/Shore Skirt"
{
Properties
{
_Tint ("색 배율 (정점색에 곱함)", Color) = (1, 1, 1, 1)
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull", Float) = 2
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"RenderType" = "Opaque"
"Queue" = "Geometry"
"IgnoreProjector" = "True"
}
// ── 본 패스: 정점색 그대로 ─────────────────────────────────────────
Pass
{
Name "ShoreSkirt"
Tags { "LightMode" = "UniversalForward" }
Blend Off
ZWrite On
ZTest LEqual
Cull [_Cull]
HLSLPROGRAM
#pragma target 2.0
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
half4 _Tint;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
half4 color : COLOR;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes IN)
{
Varyings OUT = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.color = half4(IN.color.rgb, 1.0) * _Tint;
return OUT;
}
half4 frag (Varyings IN) : SV_Target
{
return half4(IN.color.rgb, 1.0);
}
ENDHLSL
}
// ── 깊이 전용 패스: 물 셰이더가 깊이 텍스처에서 경사를 본다 ───────
Pass
{
Name "DepthOnly"
Tags { "LightMode" = "DepthOnly" }
ZWrite On
ColorMask R
Cull [_Cull]
HLSLPROGRAM
#pragma target 2.0
#pragma vertex vertDepth
#pragma fragment fragDepth
#pragma multi_compile_instancing
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
half4 _Tint;
CBUFFER_END
struct AttributesDepth
{
float4 positionOS : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VaryingsDepth
{
float4 positionCS : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
VaryingsDepth vertDepth (AttributesDepth IN)
{
VaryingsDepth OUT = (VaryingsDepth)0;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
return OUT;
}
half fragDepth (VaryingsDepth IN) : SV_Target
{
return IN.positionCS.z;
}
ENDHLSL
}
// ── 깊이+법선 패스: SSAO 등으로 URP 가 DepthNormals 프리패스를 돌릴 때도 깊이에서 빠지지 않게 ──
Pass
{
Name "DepthNormals"
Tags { "LightMode" = "DepthNormals" }
ZWrite On
Cull [_Cull]
HLSLPROGRAM
#pragma target 2.0
#pragma vertex vertNormals
#pragma fragment fragNormals
#pragma multi_compile_instancing
#pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
CBUFFER_START(UnityPerMaterial)
half4 _Tint;
CBUFFER_END
struct AttributesNormals
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VaryingsNormals
{
float4 positionCS : SV_POSITION;
float3 normalWS : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
VaryingsNormals vertNormals (AttributesNormals IN)
{
VaryingsNormals OUT = (VaryingsNormals)0;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS);
return OUT;
}
half4 fragNormals (VaryingsNormals IN) : SV_Target
{
float3 n = normalize(IN.normalWS);
#if defined(_GBUFFER_NORMALS_OCT)
float2 octNormalWS = PackNormalOctQuadEncode(n); // [-1, +1]
float2 remapped = saturate(octNormalWS * 0.5 + 0.5); // [ 0, 1]
half3 packed = PackFloat2To888(remapped);
return half4(packed, 0.0);
#else
return half4(n, 0.0);
#endif
}
ENDHLSL
}
}
Fallback Off
}