OpenGL:旋转网格(环面)时镜面光照静态、角度变化后发黑问题
问题根源
你遇到的光照异常核心原因是动态几何体(环面)的模型变换没有被同步应用到法向量、光照相关的坐标计算逻辑中,静态几何体因为模型矩阵为单位矩阵,所以没有暴露问题,具体错误点如下:
- 法向量变换矩阵未同步更新
你在C++代码中仅初始化时传递了一次来自相机的法向量矩阵,该矩阵仅包含视图变换的信息,没有包含环面的模型变换分量。环面旋转后,法向量没有跟着同步旋转,所以镜面光照表现为静态,旋转到部分角度时法向量与光照方向夹角为负,就会出现整体变暗的问题。 - 光照向量计算未引入模型矩阵
顶点着色器中计算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
相关产品推荐
相关产品推荐

