Java 在OpenGL中,如何使skybox不覆盖任何实体?
我正在用LWJGL(ThinMatrix目前的教程)用Java开发OpenGL游戏,我刚刚添加了我的skybox。然而,正如你从图片中看到的,它正在穿过树木,覆盖某个点后面的一切 以下是我对skybox的渲染代码:Java 在OpenGL中,如何使skybox不覆盖任何实体?,java,opengl,lwjgl,skybox,Java,Opengl,Lwjgl,Skybox,我正在用LWJGL(ThinMatrix目前的教程)用Java开发OpenGL游戏,我刚刚添加了我的skybox。然而,正如你从图片中看到的,它正在穿过树木,覆盖某个点后面的一切 以下是我对skybox的渲染代码: public void render(Camera camera, float r, float g, float b) { shader.start(); shader.loadViewMatrix(camera); shader.loadFogColor(
public void render(Camera camera, float r, float g, float b) {
shader.start();
shader.loadViewMatrix(camera);
shader.loadFogColor(r, g, b);
GL30.glBindVertexArray(cube.getVaoID());
GL20.glEnableVertexAttribArray(0);
bindTextures();
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, cube.getVertexCount());
GL30.glBindVertexArray(0);
shader.stop();
}
private void bindTextures() {
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture);
GL13.glActiveTexture(GL13.GL_TEXTURE1);
GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, nightTexture);
shader.loadBlendFactor(getBlendFactor());
}
如果需要,下面是我的主渲染器代码:
public void render(List<Light> lights, Camera camera){
prepare();
shader.start();
shader.loadSkyColor(RED, GREEN, BLUE);
shader.loadLights(lights);
shader.loadViewMatrix(camera);
renderer.render(entities);
shader.stop();
terrainShader.start();
terrainShader.loadSkyColor(RED, GREEN, BLUE);
terrainShader.loadLight(lights);
terrainShader.loadViewMatrix(camera);
terrainRenderer.render(terrains);
terrainShader.stop();
skyboxRenderer.render(camera, RED, GREEN, BLUE);
terrains.clear();
entities.clear();
}
public void渲染(列表灯光、摄影机){
准备();
shader.start();
loadSkyColor(红色、绿色、蓝色);
shader.loadLights(灯光);
shader.loadViewMatrix(摄影机);
渲染器。渲染(实体);
shader.stop();
terrainShader.start();
地形阴影。loadSkyColor(红色、绿色、蓝色);
地形阴影。装载灯(灯);
terrainShader.loadViewMatrix(摄像头);
地形渲染器。渲染(地形);
terrainShader.stop();
渲染(相机、红色、绿色、蓝色);
地形;
实体。清除();
}
您可能想退房 该实例中的问题是skybox本身太小,并且与几何体相交
我还看到您首先渲染地形,然后渲染skybox。我会尝试在那里翻转订单;首先绘制天空盒,然后绘制地形。首先,应移除天空盒并再次渲染场景,以检查是否是天空盒剪辑了树 如果是skybox,只需缩放skybox,使其包含地形中的所有对象 如果不是,很可能是相机的问题(就像汉斯顿说的)。您需要至少在skybox后面设置远剪裁平面。也就是说,它应该比你的天空盒的直径大
如果要缩放skybox或任何其他对象,请使用transformationMatrix。游戏引擎使用4x4矩阵控制模型的大小、位置和旋转。您可以在源TerrainRenderer.java中的函数loadModelMatrix中看到示例。它创建一个变换矩阵并将其上载到着色器中。你应该做同样的事情,但是把scale参数改成你想要的。我对LWJGL不熟悉,你愿意写shader吗?在普通opengl中,您不必担心skybox多维数据集的大小,如果您愿意,它可以是
{1.0,1.0,1.0}
。您需要的是首先将您的相机放置在{0.0,0.0,0.0}
处,并对场景中的所有内容进行skybox失败深度测试,您可以通过使skybox在标准化设备坐标中的z
值为1.0
来实现这一点
在顶点着色器中执行此操作
gl_Position = (mvp_mat * vec4(xyz, 1.0)).xyww;
在透视图除以
w
之后,z
将是w/w
或1.0
您可以做两件事
如果先绘制skybox,则可以禁用深度测试glDisable(GL\u depth\u test)
或深度写入glDepthMask(false)
。这将防止skybox绘制深度值,并且skybox将永远不会位于稍后绘制的任何对象的前面
如果您最后绘制skybox,您可以使用顶点坐标,将w
-坐标设为0,从而使其实际上无限大。顶点(x y z 0)
表示它是向量(x y z)
方向上无限远的顶点。要防止剪裁,您必须启用深度夹持glEnable(GL\u depth\u CLAMP)
这将防止OpenGl剪裁您的skybox面,并且您可以确保skybox始终处于最大距离,并且永远不会隐藏您之前绘制的任何内容
第二种方法的优点是在深度测试范围内。因为已经为场景编写了深度值,所以OpenGL管道可以跳过已被场景覆盖的skybox像素的计算。但是Skybox的片段着色器通常非常简单,所以不会有太大的区别。是的,如果我向前移动相机,剪裁的模型就会出现。对于第二部分,是的,我试着先画它,但我发现它的效率稍低,因为它必须计算天空盒中的每个像素。我听说有一种方法可以将深度设置得尽可能远,但是找不到,所以我想我在这里可能会更走运。哦,openGL停止绘制对象的距离并不是那么远,因为当我禁用skybox时,我的视图会走得更远。如果有帮助的话,我可以给你看一个线框。基本上,在线框上,切点正好是skybox所在的位置,而不是OpenGL停止渲染的实际距离。这听起来像是同一个问题,那么,如果禁用skybox本身可以让更多的模型更远地绘制。听起来skybox太小了,需要放大以包围你的世界,而不是一小块。移除skybox并在线框上查看它,我非常肯定是skybox剪辑了树。我将如何缩放skybox?好的,这是一个我不知道的好技巧,它不需要更改任何opengl状态。好的,我看到我的答案中写了一些非常奇怪的东西,我现在修复了它。