You need to enable JavaScript to run this app. 片元着色器实现世界空间光源位置转模型空间的光照异常排查
优惠活动
大模型
产品
解决方案
定价
更多

片元着色器实现世界空间光源位置转模型空间的光照异常排查

模型空间光照转换核心问题解答

1. 现有光源位置转换逻辑判定

当前实现的世界空间光源转模型空间的逻辑完全错误,核心问题有3处:

  • 矩阵选取完全错误:顶点着色器传递的outMat实际存储的是u_View * aInstanceModelMatrix,属于「模型空间->世界空间->观察空间」的组合矩阵,根本不是世界空间到模型空间变换的对应矩阵。
  • 变换方法用错:逆矩阵的转置(法线矩阵)仅用于变换方向类向量(如法线),不能直接用来变换带平移属性的点坐标。点坐标的空间转换需要使用源空间到目标空间的直接逆矩阵,不能套用方向向量的变换规则。
  • 基础空间定义混乱:当前片元着色器的outPos是通过模型矩阵计算得到的世界空间坐标,但法线输出是模型空间原始值,本身就存在空间不匹配的问题。

正确的点坐标空间转换规则:若要把世界空间的点光源位置转换到模型空间,需要使用inverse(模型矩阵) 乘以带w=1的世界坐标向量,和视图矩阵没有任何关系。这也解释了为什么你不做错误转换时,效果能大致符合预期——此时光照计算实际上是半套凑出来的世界空间逻辑,因为光源位置和片元位置都是世界空间值,仅法线未做正确变换,所以存在细节瑕疵,但不会出现完全错乱的效果。

2. 纯方向光的参数转换可行性

不能使用和点光源位置完全相同的方法转换方向参数,原因是点坐标和方向向量的数学属性存在本质差异:

  • 点坐标是带平移属性的空间位置,变换时w分量设为1,使用对应变换矩阵的直接逆矩阵完成转换。
  • 方向向量是没有平移属性的指向值,变换时w分量设为0,必须使用对应变换矩阵的逆转置矩阵(法线矩阵)完成转换,才能保证旋转、缩放变换后方向的正交性。
    如果要统一在模型空间计算方向光,正确的转换流程是:将世界空间传入的u_SpotDirection,通过模型矩阵对应的法线矩阵变换为模型空间的方向值,再参与后续光照计算,不能直接套用点坐标的变换公式。

3. 无旋转仅平移场景下的光源错位原因

你看到的“光源位置像绕X轴旋转90度”的异常,完全是前述矩阵选取错误、变换方法错配导致的连锁结果:

  • 你将观察空间矩阵(带相机俯仰、偏航旋转分量)的逆转置矩阵,用来转换世界空间的光源点坐标,相当于把相机自身的旋转分量错误的叠加到了光源位置计算中——而默认3D相机的俯仰角度通常接近90度,最终计算出的错位效果就和“光源绕X轴转了90度”的视觉感受完全一致。
  • 你给点坐标向量设置w=1来做变换,会把法线矩阵中原本不参与平移计算的分量,错误的引入到点坐标结果里,进一步放大坐标错位的程度。
  • 未做正确变换的模型空间法线、混算的世界空间片元位置,又进一步放大了光照的视觉错乱效果。

修正实现参考

如果坚持保留模型空间的光照计算逻辑,正确的实现流程为:

  1. 顶点着色器中仅传递模型空间的必要数据:
    • 片元位置直接使用原始输入的模型空间顶点坐标:outPos = a_Position
    • 法线直接使用原始输入的模型空间法线值:outNormal = aNormal
    • 提前在顶点阶段完成空间转换:将世界空间传入的光源位置、光源方向,通过模型矩阵的逆矩阵、法线矩阵转换为模型空间值后再传到片元着色器,不要将视图矩阵混入光照计算流程。
  2. 去掉片元着色器中原本的错误变换逻辑,直接使用提前转换好的模型空间光源参数参与运算。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.04 14:36:03