В OpenGL, как мне сделать так, чтобы мой скайбокс не покрывал ни одну из моих сущностей?

Я работаю над игрой OpenGL на Java с LWJGL (учебники ThinMatrix на данный момент), и я только что добавил свой скайбокс. Однако, как вы можете видеть из рисунка, он прорезает деревья и покрывает все, что находится за определенной точкой.

Вот мой код рендеринга для скайбокса:

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

Образ

4 ответа

Решение

Есть две вещи, которые вы можете сделать

Если вы сначала нарисуете свой скайбокс, вы можете отключить тест глубины glDisable(GL_DEPTH_TEST) или свою глубину напиши glDepthMask(false), Это предотвратит то, что ваш скайбокс будет отображать значения глубины, и скайбокс никогда не будет находиться перед чем-либо, что будет нарисовано позже.

Если вы рисуете свой скайбокс последним, вы можете сделать его буквально бесконечно большим, используя координаты вершины с w-координировать как 0. вершина (x y z 0) означает, что это вершина бесконечно далеко в направлении вектора (x y z), Чтобы предотвратить отсечение, вы должны включить глубинный зажим glEnable(GL_DEPTH_CLAMP) это не позволит OpenGl обрезать лица вашего скайбокса, и вы уверены, что скайбокс всегда находится на максимальном расстоянии и никогда не скроет ничего, что вы нарисовали ранее.

Преимущество второго метода в тесте глубины. Поскольку у вас уже есть значения глубины, записанные для вашей сцены, конвейер OpenGL может пропустить расчет пикселей скайбокса, которые уже покрыты вашей сценой. Но фрагментный шейдер для скайбоксов обычно очень тривиален, так что это не должно иметь большого значения.

Я не знаком с LWJGL, вам разрешено писать шейдеры? В обычном opengl вам не нужно беспокоиться о размере куба скайбокса, это может быть {1.0, 1.0, 1.0} если хочешь. То, что вам нужно, это сначала поставить камеру на {0.0, 0.0, 0.0} и заставьте скайбокс испытать глубину на все сцены, вы можете сделать это, сделав скайбокс z значение в нормированной координате устройства будет 1.0,

Сделайте это в вашем вершинном шейдере

gl_Position = (mvp_mat * vec4(xyz, 1.0)).xyww;

после перспективы разделить на w, z будет w / w или же 1.0,

Во-первых, вы должны удалить скайбокс и снова визуализировать сцену, чтобы проверить, является ли скайбокс клипом дерева.

Если это скайбокс, просто масштабируйте скайбокс, чтобы он содержал весь объект на местности.

Если нет, то, скорее всего, это проблема камеры (как сказал Ханстон). Вам нужно установить дальнюю плоскость отсечения хотя бы за скайбоксом. То есть он должен быть больше диаметра вашего скайбокса.

Если вы хотите масштабировать скайбокс или любой другой объект, используйте translationMatrix. игровой движок использует матрицу 4х4 для управления размером, расположением и вращением модели. Вы можете увидеть пример в источнике TerrainRenderer.java, в функции loadModelMatrix. Он создает матрицу преобразования и загружает ее в шейдер. Вы должны сделать то же самое, но изменить параметр масштаба на то, что вы хотите.

Возможно, вы захотите проверить, как я могу увеличить расстояние (zfar/gluPerspective), когда openGL останавливает рисование объектов? Проблема в этом случае в том, что сам скайбокс был слишком мал и пересекался с геометрией.

Я также вижу, что вы сначала визуализируете свою местность, а затем свой скайбокс. Я бы попробовал перевернуть там заказ; Сначала нарисуйте скайбокс, затем ландшафт.

Другие вопросы по тегам