时间:2025-09-02 08:58
人气:
作者:admin
【从UnityURP开始探索游戏渲染】专栏-直达
光源点L0,光源方向L,光源距离要投影的的平面距离d;要投影的平面的向上法线向量TerrainNormal,平面上的任意点TerrainPos;现在要计算出光源投向空间中模型上的点在平面上的平面投影点坐标P。
创建材质并指定该Shader
通过C#脚本设置_LightPos等参数
将材质应用到需要投射阴影的物体上
确保接收阴影的平面有适当渲染材质
PlaneShadow.shader
Shader "Custom/PlaneShadow"
{
Properties
{
_ShadowColor("Shadow Color", Color) = (0,0,0,0.5)
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float alpha : TEXCOORD0;
};
CBUFFER_START(UnityPerMaterial)
float4 _ShadowColor;
CBUFFER_END
// 外部传入参数
float3 _LightPos; // 光源位置L0
float3 _LightDir; // 光源方向L(需归一化)
float3 _TerrainPos; // 平面上任意点
float3 _TerrainNormal; // 平面法线(需归一化)
Varyings vert(Attributes IN)
{
Varyings OUT;
// 计算投影参数d
float d = dot((_TerrainPos - _LightPos), _TerrainNormal) /
dot(_LightDir, _TerrainNormal);
// 计算模型顶点到光源的向量
float3 lightToVertex = IN.positionOS.xyz - _LightPos;
// 计算投影点P = L0 + (d / (L·(V-L0))) * (V-L0)
float t = d / dot(_LightDir, lightToVertex);
float3 shadowPos = _LightPos + t * lightToVertex;
// 转换到裁剪空间
OUT.positionCS = TransformWorldToHClip(shadowPos);
// 根据距离计算透明度衰减
OUT.alpha = saturate(1.0 - length(shadowPos - IN.positionOS.xyz) * 0.1);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
half4 col = _ShadowColor;
col.a *= IN.alpha;
return col;
}
ENDHLSL
}
}
}
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,????)
