Можно ли сделать так, чтобы текстура кубической карты (GL_TEXTURE_CUBE_MAP_POSITIVE_X...) повторялась на данной грани с помощью OpenGL?
У меня есть простой единичный куб с 24 вершинами, центрированными вокруг начала координат (xyz между (-0,5, -0,5, -0,5) и (0,5, 0,5, 0,5)). Среди его атрибутов изначально я установил координаты uvw в положение xyz во фрагментном шейдере, как это было сделано в кубической карте обучающий курс Learnopengl.com. Очевидно, я также пытался установить отдельные uvw-координаты со значениями, равными масштабу, но текстура не повторялась ни на одной грани куба, как видно из показанного ниже (я нарисовал uvw-координаты во фрагментном шейдере):
высота (координата y верхних пикселей) = 3,5 на изображении выше, поэтому, установив v = 3,5 для вершины вверху, я ожидаю, что градиент будет повторяться по вертикали (что не так).
Если это невозможно, единственный способ исправить это — назначить 2D-текстуру с пользовательскими координатами uv для каждой вершины, верно?
Сначала я думал о том, чтобы на каждую грань нанести разную текстуру.
@Hakim, тогда вам нужна текстура массива.
@YakovGalka В итоге я использовал 2D-текстуру с 2D-координатами UV (думаю, кубические карты не предназначены для того, что я думал сделать). Буду признателен, если у кого-нибудь есть ссылка, подтверждающая мои сомнения, чтобы я мог закрыть эту тему.
Нет, для кубических карт нельзя использовать обертку с помощью GL_REPEAT
. Вероятно, вам следует взглянуть на альтернативы, которые люди предложили в комментариях..
Причина этого в том, что координаты, которые вы передаете сэмплеру кубической карты, интерпретируются как направление. Длина этого направления игнорируется. Вы можете думать об этом так, как если бы vec3, используемый для выборки, нормализовался, поэтому перенос никогда не произойдет.
Если по какой-либо причине вам нужно использовать кубическую карту, вы можете изменить направление выборки в шейдере.
vec3 tweakSampleDirForReapeat(vec3 dir, float repeatScale)
{
for(int i = 0; i < 3; i++) {
float d = abs(dir[i]);
if (abs(d) >= 0.5) // skip dominant direction (assuming a coordinate in a unit cube centered at the origin)
continue;
d += 0.5; // transform from [-0.5, +0.5] range to [0, 1]
d *= repeatScale; // transform from [0, 1] range to [0, repeatScale]
d = fract(d); // wrap [0, repeatScale] to multiple [0, 1] ranges
d -= 0.5; // transform from [0, 1] range to [-0.5, +0.5]
dir[i] = d;
}
return dir;
}
Отказ от ответственности: этот код должен работать, но я на самом деле его не пробовал.
Этот код можно адаптировать для поддержки различных масштабов repearScales для каждой грани.
Обновлено: Я попытаюсь объяснить, что делает этот код.
Представьте, что у нас есть точка, лежащая на грани +X куба.
Мы пытаемся изменить местоположение этой синей точки. Мы пока не знаем, где именно разместить эту точку. Но эта точка будет в том же лице.
В этом случае значение X равно +0,5. Остальные координаты (Y и Z) будут иметь значения меньше 0,5 по абсолютной величине.
Вот что мы проверяем, если:
if (abs(d) >= 0.5) // skip dominant direction
continue;
Таким образом, в основном, если X равно -0,5 или +0,5, мы не хотим изменять X, чтобы сохранить его на той же грани.
Мы изменим только Y и Z.
Теперь давайте посмотрим на куб с другой точки зрения. Теперь мы видим лицо +X, обращенное к нам.
С этой точки зрения мы можем ясно видеть, что Y и Z оба <0,5 (по абсолютной величине), так как точка находится внутри прямоугольника.
Теперь добавим текстуру.
По умолчанию мы получаем целую текстуру, нанесенную на лицо.
Но мы хотели бы что-то вроде этого.
Вот что пытается сделать это преобразование:
d += 0.5; // transform from [-0.5, +0.5] range to [0, 1]
d *= repeatScale; // transform from [0, 1] range to [0, repeatScale]
d = fract(d); // wrap [0, repeatScale] to multiple [0, 1] ranges
d -= 0.5; // transform from [0, 1] range to [-0.5, +0.5]
Я рекомендую вам пройти алгоритм с несколькими примерами, используя бумагу и карандаш. Я уверен, что вы в конечном итоге поймете это, это просто вопрос времени. Удачи!
Вопрос викторины: что будет «repeatScale» для предыдущего изображения?
Спасибо, а не могли бы вы уточнить, что делает этот шейдер? Я понимаю, что означают функции, но не смысл
@Hakim Я исправил код, добавил несколько комментариев и немного объяснений.
Почему вы используете текстуру кубической карты на кубе?