Почему люди не используют тетраэдры для скайбоксов?

При рендеринге неба с фиксированной текстурой в 3D-играх люди часто сначала создают 6 текстур на карте куба, а затем визуализируют куб вокруг камеры. В GLSL вы можете получить доступ к пикселям в текстурах с помощью нормали вместо координаты текстуры, и вы можете легко получить эту нормаль, нормализуя положение фрагмента относительно камеры. Однако этот процесс может быть выполнен с любой формой, которая окружает камеру, потому что, когда вы нормализуете каждую позицию, это всегда приводит к сфере. Теперь я задаюсь вопросом: почему это всегда куб, а не тетраэдр? Рендеринг куба занимает 12 треугольников, а тетраэдра - только 4. И, как я уже сказал, любая форма, которая окружает камеру, работает. То есть тетраэдры занимают меньше VRAM и быстрее рендерится, без каких-либо недостатков? Почему бы не использовать их?

2 ответа

Решение

Вам вообще не нужна геометрия окружения. Все, что вам нужно сделать, это нарисовать четырехэкранный полноэкранный режим и просто вычислить правильные координаты текстуры для него. Теперь с современным GL нам даже не нужно предоставлять данные вершин для этого, мы можем использовать рендеринг без атрибутов:

Вершинный шейдер:

#version 330 core
out vec3 dir;
uniform mat4 invPV;
void main()
{
        vec2 pos  = vec2( (gl_VertexID & 2)>>1, 1 - (gl_VertexID & 1)) * 2.0 - 1.0;
        vec4 front= invPV * vec4(pos, -1.0, 1.0);
        vec4 back = invPV * vec4(pos,  1.0, 1.0);

        dir=back.xyz / back.w - front.xyz / front.w;
        gl_Position = vec4(pos,1.0,1.0);
}

где invPV является inverse(Projection*View), поэтому он будет учитывать ориентацию камеры и проекцию. Это в принципе может быть еще более простым, в зависимости от того, сколько ограничений вы можете наложить на матрицу проекции.

Фрагмент шейдера:

#version 330 core
in vec3 dir;
out color;
uniform samplerCube uTexEnv;
void main()
{
        color=texture(uTexEnv, dir);
}

Чтобы использовать это, вам просто нужно связать пустой VAO и вашу текстуру, загрузить invPV матрица и вызов glDrawArrays(GL_TRIANGLE_STRIP, 0, 4),

Этот подход, конечно, можно использовать для сферического наложения текстур вместо кубических карт.

  1. это вопрос глубины и формы обзора

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

    пример искажения куба

    это связано с изменением расстояния между скайбоксом и камерой. Если вы сравните его со звездой, отображаемой напрямую:

    рендеринг неба (без скайбокса

    тогда вы можете увидеть разницу. Первое изображение - это первое релевантное изображение, найденное Google (из какой-то игры), второе - снимок экрана, созданный космическими инженерами, я думаю, и последнее изображение отображается в моем приложении astro

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

    использование 4-сторонней пирамиды еще хуже, чем куба, потому что углы между сторонами хуже, создавая еще большие артефакты. Другая проблема заключается в том, что вам нужен больший размер пирамиды, чтобы покрыть то же пространство. Если вы используете Depth Buffer для каких-то целей во время рендеринга скайбокса, вы можете существенно повлиять на точность, увеличив плоскость Z_far.

  2. накладные расходы

    разница между 6 и 4 полигонами не так уж и велика, потому что скайбокс очень большой (охватывает весь вид), скорость определяется в основном количеством пикселей / текселей, поданных на экран, а не количеством вершин. Таким образом, пирамида может быть даже медленнее, чем куб, потому что она должна иметь большие грани (требуется больше итераций интерполятора). Но если вы хотите использовать сферический скайбокс, тогда вам также понадобится сферическая текстура, потому что, если вы будете использовать стандартную текстуру куба, искажение все равно будет присутствовать, и его будет сложнее поддерживать, и именно поэтому кубики более используются.

  3. Сферические скайбоксы

    им нужен другой тип текстуры. Полусферическая текстура выглядит так:

    полусферическая текстура

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