源码 / shaders/Ch06/ShadowReceive.glsl
shaders/Ch06/ShadowReceive.glsl
// 案例 6.3 接收主光源阴影:Lambert + MainLightRealtimeShadow(GLSL 版,对应 Ch06/ShadowReceive.shader) Shader "Cookbook/Ch06/ShadowReceive" { SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" "Queue"="Geometry" } GLSLINCLUDE uniform vec4 _BaseMap_ST; uniform vec4 _BaseColor; uniform float _AmbientStrength; ENDGLSL Pass { Name "ForwardLit" Tags { "LightMode"="UniversalForward" } GLSLPROGRAM // 主光阴影:无 / 单张阴影图 / 级联 / 屏幕空间(由 URP Asset 与 Renderer 设置决定,运行时自动开关)。 // 软阴影:_SHADOWS_SOFT 在运行时按每盏灯的质量分支。 // 这两组是 URP 全局关键字,网页版引擎始终定义 _MAIN_LIGHT_SHADOWS 与 _SHADOWS_SOFT,不用声明。 // 材质级开关:不接收阴影 #pragma shader_feature_local _RECEIVE_SHADOWS_OFF uniform sampler2D _BaseMap; VARYING vec2 uv; VARYING vec3 positionWS; VARYING vec3 normalWS; #ifdef VERTEX void main() { VertexPositionInputs pos = GetVertexPositionInputs(positionOS.xyz); gl_Position = pos.positionCS; positionWS = pos.positionWS; normalWS = TransformObjectToWorldNormal(normalOS); uv = TransformTex(texcoord0.xy, _BaseMap_ST); } #endif #ifdef FRAGMENT void main() { vec3 albedo = texture(_BaseMap, uv).rgb * _BaseColor.rgb; vec3 N = normalize(normalWS); // 世界坐标 -> 阴影图坐标(xy = 阴影图 UV,z = 在光源空间里的深度)。 // 开了级联时,这里会先按距离选出级联号,再用对应的矩阵变换 vec4 shadowCoord = TransformWorldToShadowCoord(positionWS); // 采样阴影图并与 z 比较:1 = 受光,0 = 在阴影里(软阴影时是 0~1 的过渡)。 // URP 的 MainLightRealtimeShadow 在 _RECEIVE_SHADOWS_OFF 时直接返回 1(宏 MAIN_LIGHT_CALCULATE_SHADOWS 未定义) #if defined(_RECEIVE_SHADOWS_OFF) float shadow = 1.0; #else float shadow = MainLightRealtimeShadow(shadowCoord); #endif // 超出“阴影距离”的地方,阴影要平滑淡出,而不是突然消失 shadow = mix(shadow, 1.0, GetMainLightShadowFade(positionWS)); Light mainLight = GetMainLight(); vec3 radiance = mainLight.color * mainLight.distanceAttenuation * shadow; vec3 color = albedo * radiance * saturate(dot(N, mainLight.direction)); color += albedo * SampleSH(N) * _AmbientStrength; fragColor = vec4(color, 1.0); } #endif ENDGLSL } // ---- 投影与深度:见案例 6.4 与 6.8 ---- Pass { Name "ShadowCaster" Tags { "LightMode"="ShadowCaster" } ZWrite On ZTest LEqual ColorMask 0 GLSLPROGRAM #include "Ch06/ShadowCasterPass.glsl" ENDGLSL } Pass { Name "DepthOnly" Tags { "LightMode"="DepthOnly" } ZWrite On ColorMask R GLSLPROGRAM #include "Ch06/DepthOnlyPass.glsl" ENDGLSL } } }