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 函数。

相关推荐
丁小未2 天前
基于MVVM框架的XUUI 扩展的UI管理系统教程
unity·mvvm·ui框架·xuui·ui管理器
丁小未2 天前
基于MVVM框架的XUUI HelloWorld 新手教程
unity·性能优化·c#·游戏引擎
丁小未2 天前
基于MVVM框架的XUUI MoreComplex案例
unity·c#
EQ-雪梨蛋花汤2 天前
【Unity笔记】VR 一体机画面锯齿、模型边缘闪烁、接缝抖动排查:MSAA、Mipmap、Render Scale、Z-Fighting 全流程记录
笔记·unity·vr
松树戈3 天前
【Godot4精进之路】03~Godot编辑器常用界面介绍
编辑器·游戏引擎·godot
YigAin3 天前
Unity Spine 资源出现白边的解决办法
unity·游戏引擎·spine
郝学胜-神的一滴3 天前
中级OpenGL教程 013:渲染器类架构设计与逐帧渲染流程详解
开发语言·c++·unity·游戏引擎·图形渲染·opengl·unreal
_helen_5204 天前
unreal engine 虚拟现实 + airsim
游戏引擎·vr·虚幻
真鬼1235 天前
【Unity WebGL】内嵌网页与双向通信
unity·游戏引擎·webgl
zyh______6 天前
C#语法糖(按照实用性排序)
unity·c#