我正在使用LWJGL(目前是ThinMatrix的教程)来用Java开发OpenGL游戏,我只是添加了我的skybox。但是,从图片中可以看到,它穿过树木,并覆盖了某个特定点之后的所有内容。

这是我对天空盒的渲染代码:

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();
}

最佳答案

您可以做两件事

如果先绘制天空盒,则可以禁用深度测试glDisable(GL_DEPTH_TEST)或深度写glDepthMask(false)。这样可以防止您的Skybox绘制深度值,并且Skybox永远不会在以后绘制的任何内容之前。

如果最后绘制天空盒,则可以通过使用w -coordinate为0的顶点坐标来使其无限大。顶点(x y z 0)表示它是在矢量(x y z)方向上无限远的顶点。为了防止裁剪,您必须启用深度夹紧glEnable(GL_DEPTH_CLAMP),这将阻止OpenGl裁剪天空盒的面孔,并且您确保天空盒始终处于最大距离,并且永远不会隐藏您之前绘制的任何内容。

第二种方法的优势在于深度测试。因为您已经为场景写入了深度值,所以OpenGL管线可以跳过场景已覆盖的天空盒像素的计算。但是,天空盒的片段着色器通常非常琐碎,因此不应有太大的区别。

08-16 05:05