LWJGL中OpenGL Uniform无法设置导致渲染失效求助
看起来你遇到的核心问题是:一旦在着色器中使用Uniform变量,物体就无法渲染,但无Uniform的着色器或不用着色器时正常。结合你提供的代码,我梳理了几个关键问题点和修复步骤:
1. 最直接的原因:物体在透视视锥体之外被裁剪了
你的Mesh顶点Z坐标全是0,但在MeshRenderer里设置的zNear=0.001F——透视投影规则中,所有Z值小于zNear的物体都会被直接裁剪掉。这就导致你的三角形完全处在近平面之外,自然看不到任何东西。
修复方法:
修改Mesh的顶点Z坐标为大于zNear的值,比如0.1:
Mesh mesh = new Mesh(new float[] { 0.0f, 0.5f, 0.1f, -0.5f, -0.5f, 0.1f, 0.5f, -0.5f, 0.1f });
2. 窗口Resize时透视矩阵未更新,导致投影参数失效
当前perspectiveMatrix只在第一次渲染时初始化,窗口大小改变后,宽高比aspectRatio发生变化,但透视矩阵没有重新计算,这会导致投影变形或者物体被意外裁剪。
修复方法:
在MeshRenderer.render()方法中,检查宽高比是否变化,动态更新透视矩阵:
@Override public void render() { float currentAspectRatio = (float)Application.getWidth() / Application.getHeight(); float fov = Mathg.DEG2RAD * 90F; float zNear = 0.001F; float zFar = 1000F; // 宽高比变化时重新计算透视矩阵 if (this.perspectiveMatrix == null || Math.abs(currentAspectRatio - (this.perspectiveMatrix.get(1,1) / this.perspectiveMatrix.get(0,0))) > 0.001) { this.perspectiveMatrix = Matrix4x4f.createPerspectiveFieldOfView(currentAspectRatio, fov, zNear, zFar); } shader.bind(); shader.setUniform("projectionMatrix", this.perspectiveMatrix); // 其余渲染代码保持不变 }
3. 验证矩阵传递的存储顺序是否正确
OpenGL的glUniformMatrix4fv默认期望矩阵数据是列主序的(transpose=false),如果你的Matrix4x4f.updateBuffer()方法是按行存储矩阵数据的,就会导致矩阵传递错误。
检查与修复:
- 如果你的矩阵类是行主序存储,修改
Shader.setUniform方法,将transpose设为true:public void setUniform(String uniformName, Matrix4x4f matrix) { try (MemoryStack stack = MemoryStack.stackPush()) { FloatBuffer fb = stack.mallocFloat(16); matrix.updateBuffer(fb); glUniformMatrix4fv(uniforms.get(uniformName), true, fb); // 这里改为true } } - 或者调整
Matrix4x4f.updateBuffer()方法,按列主序写入数据。
4. 清理冗余的固定管线代码
在ApplicationWindow.render()中,窗口Resize时调用的glMatrixMode(GL_MODELVIEW)是旧的固定管线API,你现在用的是可编程着色器,这句代码完全没用,反而可能引起混淆,建议删除:
public void render() { if (this.resized) { glViewport(0, 0, width, height); // 移除下面这句冗余代码 // glMatrixMode(GL_MODELVIEW); this.resized = false; } // 其余渲染代码保持不变 }
总结
优先解决物体Z坐标小于zNear的问题,这是导致看不到物体的最直接原因。然后处理窗口Resize时的透视矩阵更新,确保矩阵传递顺序正确,最后清理冗余代码。按照这些步骤修改后,你应该就能正常渲染出灰色的三角形了。
内容的提问来源于stack exchange,提问作者Fluffy Doggo

