При рендеринге неба с фиксированной текстурой в 3D-играх люди часто сначала создают 6 текстур в кубической карте, а затем рендерят куб вокруг камеры. В GLSL вы можете получить доступ к пикселям в текстурах с помощью нормали вместо координаты текстуры, и вы можете легко получить эту нормаль, нормализовав положение фрагмента относительно камеры. Однако этот процесс можно выполнить с любой формой, окружающей камеру, потому что при нормализации каждой позиции всегда получается сфера. Теперь мне интересно: почему всегда куб, а не тетраэдр? Рендеринг куба требует 12 треугольников, тетраэдра только 4. И, как я уже сказал, любая фигура, окружающая камеру, работает. Получается, что тетраэдры требуют меньше видеопамяти и быстрее рендерятся без каких-либо недостатков? Почему бы не использовать их?
Почему люди не используют тетраэдры для скайбоксов?
Ответы (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)
.
Этот подход, конечно, можно использовать для наложения сферических текстур вместо кубических карт.
это вопрос глубины и формы просмотра
наилучшей формой скайбокса является (полу)сфера, потому что ее визуализированная поверхность проецируется в пространство камеры почти без искажений. Если вы используете любую другую форму, то артефакты проекции будут возникать, особенно в углах, например, в большинстве приложений/игр используется куб скайбокс. Посмотрите на солнце с конечным радиусом (а не просто на одну точку) и поверните вид так, чтобы солнце попало из середины в сторону обзора. Затем обычно солнце искажается из круглой/дисковой формы в эллиптическую/овальную:
это связано с изменением расстояния между скайбоксом и камерой. Если вы сравните это с напрямую визуализированной звездой:
тогда вы можете увидеть разницу. Первое изображение — это первое релевантное изображение, найденное Google (из какой-то игры), второе — снимок экрана из Space Engineers, я думаю, а последнее — отрендерено моим астро-приложением.
Таким образом, чем дальше форма от сферы, тем больше искажений вы получите.
использование 4-сторонней пирамиды еще хуже, чем куба, потому что углы между сторонами хуже, создавая еще большие артефакты. Другая проблема заключается в том, что вам нужен больший размер пирамиды, чтобы покрыть то же пространство. Если вы используете Depth Buffer для какой-либо цели во время рендеринга skybox, вы можете значительно повлиять на точность, увеличив плоскость Z_far.
Накладные расходы
разница между 6 и 4 полигонами не так велика, потому что скайбокс огромен (покрывает весь вид), скорость определяется в основном количеством пикселей/текселей, поданных на экран, а не количеством вершин. Таким образом, пирамида может быть даже медленнее, чем куб, потому что у нее должны быть большие грани (требуется больше итераций интерполятора). Но если вы хотите использовать сферический скайбокс, вам также понадобится сферическая текстура, потому что, если вы будете использовать стандартную кубическую текстуру, искажение все равно будет присутствовать, и их сложнее поддерживать при создании,... и это почему кубы более используются.
Сферические скайбоксы
им нужен другой тип текстуры. Полусферическая текстура выглядит так: