// ───────────────────────────────────────────────────────────────────────────── // 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 }