unity光照衰减中的unity_worldToLight

本文详细探讨了Unity中unity_worldToLight矩阵的变换原理,通过实例展示了该变换如何将世界坐标转换为适合光照纹理采样的坐标。作者指出,经过unity_worldToLight变换后,坐标的模长范围确实限制在[0,1]内,且平方后用于非线性光照衰减纹理的采样。这一过程对于理解Unity中光照计算的细节至关重要。
摘要由CSDN通过智能技术生成

在Unity5.x某个版本升级后,_LightMatrix0变为unity_worldToLight。
按官方文档,unity_worldToLight是从世界空间到光源空间的变换矩阵,变换得到的坐标用于采样光强衰减纹理,具体使用方法:

	float3 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1)).xyz;
    fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;

疑问:tex2D函数应该使用uv坐标采样,也就是坐标的范围应该是[0,1],而lightCoord的点积得到的标量是距离的平方,范围明显不是[0,1],这如何采样呢?
《UnityShader入门精要》https://github.com/candycat1992/unity_shaders_book/issues/47 对此的解释:经过unity_worldToLight变换得到的坐标模范围会在[0,1]。下面来看看unity_worldToLight是怎么变换世界坐标的。

  1. 在场景中增加一个cube,并在cube的shader上增加一个AdditionPass,在该Pass中使用unity_worldToLight

  2. 在unity场景中放置一个点光源,设置光源的Range属性为5,设置光源的坐标(0,0,0)

  3. 打开Frame Debug工具
    在这里插入图片描述

  4. 设置光源的坐标为(1,2,3),并查看Frame Debug
    在这里插入图片描述

设光源的坐标为 L ( L x , L y , L z ) L(L_{x},L_{y},L_{z}) L(Lx,Ly,Lz),根据第3第4点,可推导得 u n i t y _ w o r l d T o L i g h t unity\_worldToLight unity_worldToLight 矩阵如下:
[ 1 R a n g e 0 0 − L x R a n g e 0 1 R a n g e 0 − L y R a n g e 0 0 1 R a n g e − L z R a n g e 0 0 0 1 ] \left[ \begin{matrix} \frac{1}{Range} & 0 & 0 & -\frac{L_{x}}{Range} \\ 0 & \frac{1}{Range} & 0 & -\frac{L_{y}}{Range} \\ 0 & 0 & \frac{1}{Range} & -\frac{L_{z}}{Range} \\ 0 & 0 & 0 & 1 \\ \end{matrix} \right] Range10000Range10000Range10RangeLxRangeLyRangeLz1
接下来看一下这个矩阵变换的本质,设顶点 P ( x , y , z , 1 ) P(x,y,z,1) P(x,y,z,1)经过变换:
[ 1 R a n g e 0 0 − L x R a n g e 0 1 R a n g e 0 − L y R a n g e 0 0 1 R a n g e − L z R a n g e 0 0 0 1 ] ⋅ [ x y z 1 ] = [ x − L x R a n g e y − L y R a n g e z − L z R a n g e 1 ] \left[ \begin{matrix} \frac{1}{Range} & 0 & 0 & -\frac{L_{x}}{Range} \\ 0 & \frac{1}{Range} & 0 & -\frac{L_{y}}{Range} \\ 0 & 0 & \frac{1}{Range} & -\frac{L_{z}}{Range} \\ 0 & 0 & 0 & 1 \\ \end{matrix} \right] \cdot \left[\begin{matrix} x \\ y \\ z \\ 1 \end{matrix}\right] = \left[\begin{matrix} \frac{x-L_{x}}{Range} \\ \frac{y-L_{y}}{Range} \\ \frac{z-L_{z}}{Range} \\ 1 \end{matrix} \right] Range10000Range10000Range10RangeLxRangeLyRangeLz1xyz1=RangexLxRangeyLyRangezLz1
现在很明显了,该矩阵变换其实就是:
l i g h t C o o r d = ( 顶 点 的 世 界 坐 标 − 光 源 坐 标 ) / R a n g e lightCoord =(顶点的世界坐标-光源坐标)/Range lightCoord=()/Range
∣ l i g h t C o o r d ∣ = ( x − L x ) 2 + ( y − L y ) 2 + ( z − L z ) 2 R a n g e 2 |lightCoord|=\sqrt{\frac{(x-L_{x})^2+(y-L_{y})^2+(z-L_{z})^2}{Range^2}} lightCoord=Range2(xLx)2+(yLy)2+(zLz)2
证实了 l i g h t C o o r d lightCoord lightCoord的模范围是[0,1],注意:模大于1的时候意味着超出了光照范围,Unity不会调用Pass计算光照,因此模的范围必定是[0,1]。
还有一点需要注意的,我们使用的是 ∣ l i g h t C o o r d ∣ 2 |lightCoord|^2 lightCoord2进行采样,平方意味着_LightTexture0里保存的光照衰减是非线性的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值