在OpenGL中,如何使我的天空盒不覆盖我的任何实体?

时间:2015-07-01 03:52:44

标签: java opengl lwjgl skybox

我正在使用LWJGL(目前的ThinMatrix教程)开发Java的OpenGL游戏,我刚刚添加了我的天空盒。然而,从图片中可以看出,它正在穿过树木并覆盖某一点后面的所有东西。

以下是天空盒的渲染代码:

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

Image

4 个答案:

答案 0 :(得分:4)

你可以做两件事

如果您先绘制天空盒,则可以禁用深度测试glDisable(GL_DEPTH_TEST)或深度写入glDepthMask(false)。这将阻止你的天空盒绘制深度值,天空盒永远不会出现在以后绘制的任何东西之前。

如果你最后绘制你的天空盒,你可以通过使用w坐标为0的顶点坐标来使它实际上无限大。顶点(x y z 0)意味着它是一个无限远的方向顶点向量(x y z)。为了防止削波,你必须启用深度钳位glEnable(GL_DEPTH_CLAMP)这将阻止OpenGl剪掉你的天空盒面,并且你确定天空盒始终处于最大距离并且永远不会隐藏你之前绘制的任何东西。 / p>

第二种方法的优点在于深度测试。由于您已经为场景编写了深度值,因此OpenGL管道可以跳过场景已经覆盖的天空盒像素的计算。但天空盒的片段着色器通常非常简单,所以它不应该产生那么大的差别。

答案 1 :(得分:1)

您可能需要查看How can I increase distance (zfar/gluPerspective) where openGL stops drawing objects? 那个例子的问题是天空盒本身太小而且与几何体相交。

我也看到你首先渲染你的地形,然后你的天空盒。我会尝试在那里翻转订单;首先绘制天空盒然后绘制地形。

答案 2 :(得分:1)

首先,你应该删除天空盒并再次渲染场景以检查它是否是剪辑树的天空盒。

如果是天空盒,只需缩放天空盒,使其包含地形中的所有物体。

如果没有,很可能是相机问题(如汉斯顿所说)。您需要至少在天空盒后面设置远剪裁平面。也就是说,天空盒的直径应该更大。

如果要缩放天空盒或任何其他对象,请使用transformationMatrix。游戏引擎使用4x4矩阵来控制模型的大小,位置和旋转。您可以在函数loadModelMatrix中看到源TerrainRenderer.java中的示例。它创建一个变换矩阵并将其上传到着色器。你应该做同样的事情,但是将scale参数改成你想要的。

答案 3 :(得分:1)

我对LWJGL不熟悉,你是不是很喜欢写着色器?在简单的opengl中,您不必担心天空盒立方体的大小,如果您愿意,可以{1.0, 1.0, 1.0}。您需要的是首先将相机放在{0.0, 0.0, 0.0}并对场景中的所有内容进行天空盒失败深度测试,您可以通过使标准化设备坐标中的天空盒z值为{ {1}}。

在顶点着色器中执行此操作

1.0

除以gl_Position = (mvp_mat * vec4(xyz, 1.0)).xyww; 后,w将为zw / w