Unity shader中TransformWorldToShadowCoord原理解析

TransformWorldToShadowCoord 的核心作用很简单:将你提供的世界坐标,转换到一个可以用于采样 Shadow Map 的坐标空间。它本质上是为你省去了手动编写矩阵乘法的繁琐步骤。

🔍 核心原理:一个"三步走"的幕后过程

函数内部主要执行了以下三个步骤:

  1. 获取矩阵 :获取从"世界空间"转换到"阴影空间"的核心矩阵 unity_WorldToShadow

    • 方向光 :需处理阴影级联(Shadow Cascades),因此是一个包含最多4个矩阵的数组 unity_WorldToShadow[4]

    • 聚光灯/点光源 :通常只用一个矩阵 unity_WorldToLight

  2. 执行变换 :执行矩阵乘法 mul(unity_WorldToShadow[selectedIndex], float4(worldPos, 1.0)),将世界坐标转换到阴影空间的齐次坐标。

  3. 处理齐次坐标 :对于聚光灯点光源 这类透视投影,需要执行透视除法(shadowCoord.xyz / shadowCoord.w),将坐标映射到0-1范围以得到最终的Shadow Map UV坐标;而方向光 由于是正交投影(w 分量为1),则无需此步骤。

此外,函数内部还会根据是否启用级联阴影映射(_MAIN_LIGHT_SHADOWS_CASCADE)进行相应处理。当启用时,它会选择正确的 unity_WorldToShadow 矩阵索引来计算坐标。

💡 一个更直观的理解

你可以将这个过程类比为:

  • TransformWorldToShadowCoord:是一个翻译器,它将物体的世界坐标,翻译成Shadow Map上每个像素点的"门牌号"。

  • Shadow Map:是由光源"拍摄"的深度信息图,记录了场景中每个点离光源的远近。

  • MainLightRealtimeShadow 等采样函数 :拿着翻译出来的"门牌号"(shadowCoord),去Shadow Map这张"地图"上,找到对应的深度信息进行比较,最终判定当前像素点是否处于阴影中。

🔧 实际使用示例

一个典型的URP Shader中接收阴影的流程大致如下:

cs 复制代码
// 1. 在着色器代码中包含必要的头文件并声明编译宏
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE

// ... 顶点着色器中输出世界坐标
VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.positionOS.xyz);
OUT.positionWS = vertexInput.positionWS;

// 2. 在片元着色器中,将世界坐标转换为阴影坐标
float4 shadowCoord = TransformWorldToShadowCoord(IN.positionWS);

// 3. 获取主光源,传入阴影坐标,得到带有阴影衰减值的光源信息
Light mainLight = GetMainLight(shadowCoord);
float3 attenuatedLightColor = mainLight.color * mainLight.shadowAttenuation;

⚠️ 注意事项

  • 宏定义_MAIN_LIGHT_SHADOWS_MAIN_LIGHT_SHADOWS_CASCADE 宏是正确启用功能的"开关",确保它们被正确定义非常重要。

  • 性能考量 :在顶点着色器中计算 shadowCoord 通常更高效(只计算一次),但在顶点动画较多时,为了保证阴影准确,可能需要在片元着色器中计算。

  • 管线差异 :该函数主要适用于URP,Built-in管线通常使用TRANSFER_SHADOW宏,而HDRP则使用 EvalShadow_WorldToShadow 函数。

相关推荐
mxwin3 小时前
Unity Shader 中 ShadowCaster的作用和疑问
unity·游戏引擎
mxwin3 小时前
Unity Shader中如何学习阴影技术 产生阴影,接受阴影,联级阴影,软阴影
学习·unity·游戏引擎·shader
♡すぎ♡4 小时前
ShaderLab:线条几何体旋转
unity·计算机图形学·着色器·shaderlab
小贺儿开发4 小时前
【MediaPipe】Unity3D 指间游鱼互动演示
游戏·unity·人机交互·摄像头·手势识别·互动·康复训练
mxwin6 小时前
Unity Shader中CastShadows 和 ReceiveShadows 在代码中的区分
unity·游戏引擎·shader
努力长头发的程序猿10 小时前
Unity2D当中的A*寻路算法
算法·unity·c#
RReality21 小时前
【Unity Shader URP】Matcap 材质捕捉实战教程
java·ui·unity·游戏引擎·图形渲染·材质
魔士于安21 小时前
unity urp材质球大全
游戏·unity·游戏引擎·材质·贴图·模型
南無忘码至尊1 天前
Unity学习90天 - 第 6 天 -学习物理 Material + 重力与阻力并实现弹跳球和冰面滑动效果
学习·unity·游戏引擎