源码 / Ch05/Phong.shader
Ch05/Phong.shader
// 案例 5.4 Phong 高光:反射向量 R 与视线 V 的夹角决定高光 Shader "Cookbook/Ch05/Phong" { Properties { [MainColor] _BaseColor("Base Color", Color) = (0.2, 0.35, 0.6, 1) _SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 1) _Shininess("Shininess", Range(1, 512)) = 32 _AmbientStrength("Ambient Strength", Range(0, 1)) = 1 } SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" "Queue"="Geometry" } HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" CBUFFER_START(UnityPerMaterial) half4 _BaseColor; half4 _SpecColor; float _Shininess; half _AmbientStrength; CBUFFER_END ENDHLSL Pass { Name "ForwardLit" Tags { "LightMode"="UniversalForward" } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; }; struct Varyings { float4 positionCS : SV_POSITION; float3 positionWS : TEXCOORD0; float3 normalWS : TEXCOORD1; }; Varyings vert(Attributes input) { Varyings output; VertexPositionInputs pos = GetVertexPositionInputs(input.positionOS.xyz); output.positionCS = pos.positionCS; output.positionWS = pos.positionWS; output.normalWS = TransformObjectToWorldNormal(input.normalOS); return output; } half4 frag(Varyings input) : SV_Target { float3 N = normalize(input.normalWS); float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS); // 指向相机 Light mainLight = GetMainLight(); float3 L = mainLight.direction; // 指向光源 half3 radiance = mainLight.color * mainLight.distanceAttenuation; float NdotL = dot(N, L); half3 diffuse = _BaseColor.rgb * saturate(NdotL); // reflect(i, n) 要求 i 是“射入”方向,所以传 -L float3 R = reflect(-L, N); float RdotV = saturate(dot(R, V)); // 高光指数常常上百,用 float 计算,避免 half 精度下出现色带 float spec = pow(RdotV, _Shininess); // 背光面不应该出现高光(R 可能恰好朝向相机) spec *= step(0.0, NdotL); half3 color = (diffuse + _SpecColor.rgb * spec) * radiance; color += _BaseColor.rgb * SampleSH(N) * _AmbientStrength; return half4(color, 1); } ENDHLSL } // ---- 投影与深度:本章先照抄,原理见第 6 章 ---- Pass { Name "ShadowCaster" Tags { "LightMode"="ShadowCaster" } ZWrite On ZTest LEqual ColorMask 0 HLSLPROGRAM #pragma vertex ShadowDepthVert #pragma fragment ShadowDepthFrag #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW #include "Assets/Cookbook/Ch05/Ch05ShadowDepth.hlsl" ENDHLSL } Pass { Name "DepthOnly" Tags { "LightMode"="DepthOnly" } ZWrite On ColorMask R HLSLPROGRAM #pragma vertex DepthOnlyVert #pragma fragment DepthOnlyFrag #include "Assets/Cookbook/Ch05/Ch05ShadowDepth.hlsl" ENDHLSL } } }