You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL:旋转网格(环面)时镜面光照静态、角度变化后发黑问题

问题根源

你遇到的光照异常核心原因是动态几何体(环面)的模型变换没有被同步应用到法向量、光照相关的坐标计算逻辑中,静态几何体因为模型矩阵为单位矩阵,所以没有暴露问题,具体错误点如下:

  1. 法向量变换矩阵未同步更新
    你在C++代码中仅初始化时传递了一次来自相机的法向量矩阵,该矩阵仅包含视图变换的信息,没有包含环面的模型变换分量。环面旋转后,法向量没有跟着同步旋转,所以镜面光照表现为静态,旋转到部分角度时法向量与光照方向夹角为负,就会出现整体变暗的问题。
  2. 光照向量计算未引入模型矩阵
    顶点着色器中计算v_surface_to_light和v_surface_to_view时,直接使用了模型空间的顶点坐标a_position和世界/视图空间的光源、相机位置做差,所有参与光照计算的向量不在同一坐标系下,结果完全错误。

修复方案

1. C++逻辑修改

每次更新环面的modelMatrix后,需要重新计算并传入包含模型变换的法向量矩阵:

state
    .setShaderMatrix<MODEL>(modelMatrix)
    // 新增:计算包含视图+模型变换的法向量矩阵,取逆转置的3x3分量
    .setShaderMatrix<NORMAL>((camera.getViewMatrix() * modelMatrix).inverse().transpose().getMatrix3())
    .apply();

2. 顶点着色器修改

统一光照计算的坐标空间,将顶点先转换到世界空间再计算光照向量:

void main() {
  v_normal = u_normal_matrix * a_normal;
  v_color = a_color;
  v_coord = a_coord;

  // 新增:将顶点从模型空间转到世界空间
  vec4 world_position = u_model_matrix * a_position;
  v_surface_to_light = u_light_position - world_position.xyz;
  v_surface_to_view = u_eye_position - world_position.xyz;

  gl_Position = u_projection_matrix * u_view_matrix * world_position;
}

如果你的光源和相机位置是在视图空间下传递的,也可以统一转换到视图空间计算,只要保证所有相关向量在同一坐标系即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:24:05