Pull to refresh

Comments 12

У себя в движке использовал комбинацию объёмов освещения с прямым рендерингом.
Вместе с каждым объектом передаётся список источников света, которые его освещают.
Таким образом из 150 источников света объект обрабатывает только 1-2.
Получилось довольно быстро и не затратно по памяти.
Поделитесь ссылкой на исходники, если возможно?

Технику Forward+ не смотрели? Немного похоже по описанию на реализацию из вашего движка.
Не смотрел, но стоит взять пару приёмчиков из неё.
github.com/Temtaime/aesir/blob/master/source/perfontain/shader/res/lighting.c
GLSL с макроподстановками эдакими, но основной смысл ясен — есть массив с индексами источников света, а у каждого объекта передаются lightStart и lightEnd — начало и конец элементов в этом массиве. Далее по индексу из него получается сам источник света и объект освещается.
На старых гелях произвольное обращение к массиву было невозможно, да.
Кто-нибудь ткните носом пожалуйста, как в один проход обернуть qubemap пусть даже в плоскую текстуру. Пусть даже каждая грань кубика будет в этой плоской текстуре. Понимаю, что надо юзать геометрический шейдер, но руки никак не доходят разобраться. С одной стороны вроде как GL — это древнейший и всевозможно описанный где только можно API, но с другой стороны когда начинаешь что-то искать — одна половина найденного уже depricated, одна под 2.0+ и малюсенький процент под 3.3+ и вообще мизер под 4+
Неплохо бы картинку или чуть более подробное пояснение того, что вы хотите сделать.
Я не понял вашу задачу, но геометрический шейдер судя по набору слов вряд ли поможет.
Кадр YouTube видеоролика 360 градусов надо натянуть на Cubemap, чтобы отрисовать fisheye картинку. Раньше, когда YouTube использовал equirectangular проекцию для видео 360, я без проблем конвертил ее во фрагментном шейдере сразу в fisheye. Сейчас они используют Equi-Angular Cubemap почти во всех роликах. Соответственно для того чтобы отобразить fisheye, я сначала преобразую каждую грань Equi-Angular Cubemap в грань обычного Cubemap, и только затем отрисовываю fisheye картинку. Это 6 + 1 вызовов на отрисовку. Соответственно было бы круто вообще в одном шейдере взять ютюбовский Equi-Angular Cubemap и загнать его с соответствующими преобразованиями сразу в обычную Cubemap текстуру. Про геометрический шейдер упомянул, поскольку наверное понадобится использовать Layer в шейдере для Cubemap текстуры.
Вот в вопросах проекций я мало смыслю, увы.

Но из того, что я видел в разных туториалах (в основном про Image Based Lighting), в cubemap рисуют последовательным проходом по 6 граням куба с 6 разными камерами, смотрящими на текущую грань.

Но, судя по отрывочным сведениям из Интернета, можно и правда использовать геометрический шейдер с указанием переменной gl_Layer для каждой вершины, но полноценного рабочего примера я увы не нашёл. Также я не уверен, что это выигрышно по скорости, учитывая что у вас по сути нет никакой геометрии, а шейдер будет выполнять математические манипуляции с текстурами.

P. S. Далее я фантазирую, но можно попробовать использовать Multiple Render Target во фрагментном шейдере, где в качестве GL_COLOR_ATTACHMENT«I» будут GL_TEXTURE_CUBE_MAP_POSITIVE_X + «I». Соотвественно в шейдере использовать 6 разных ViewProjection матриц для отрисовки в 6 текстур «параллельно».
Так как в данном туториале отсутствуют вершинные шейдеры я малость попутал где и как используются матрицы MVP? Так как в текстуре позиций автор использует мировые координаты, то положения должны быть умножены на модельную матрицу как минимум, то есть получается вершинный шейдер должен работать примерно так:

in vec4 in_position;
...

uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;

out vec4 gl_Position;
out vec3 FragPos;

void main()
{
     FragPos = Model*in_position;
     gl_Position = Projection*View*FragPos;
     ...
}


Поправьте меня если я что-то не так понял.
Вы всё правильно поняли.

Vertex shader в случае Geometry Pass это — обычный passthrough шейдер, который помимо основной функции передаёт интерполированные varying атрибуты (FragPos, TexCoords, Normal) во фрагментный шейдер. FragPos и Normal представлены в мировой системе координат (умножены на Model Matrix), но на сколько я понимаю с тем же успехом могли быть представлены и в координатах камеры.

Вот исходники G-прохода из оригинальной статьи (учтите, адрес заблокирован на территории РФ):
learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/8.1.deferred_shading/8.1.g_buffer.vs
learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/8.1.deferred_shading/8.1.g_buffer.fs
Спасибо! Я только не понял, что там за трюк с нормалями, зачем этот фрагмент:
 mat3 normalMatrix = transpose(inverse(mat3(model)));
 Normal = normalMatrix * aNormal;


P.S. В первый раз мы с пацанами попробовали OpenGL…
normalMatrix это — обычно матрица которая преобразует нормали из пространства координат модели в пространство координат камеры. Если её не вычислили за вас, то она может быть вычислена из матрицы ModelView вот так:
mat3 normalMatrix = transpose(inverse(mat3(ModelViewMatrix)));


Т.к. тут в текстуры решили записать значения в world space, то соответственно здесь преобразование будет такое же, но от другой исходной матрицы:
mat3 normalMatrix = transpose(inverse(mat3(ModelMatrix)));


Формулы выше нужны для общего случая(т.е. когда в ModelMatrix или ModelViewMatrix записано что угодно). Если у вас не используется неравномерное масштабирование по осям [то, что раньше было известно как glScale()] при переходе из model-->world, то формулу можно упростить до:
mat3 normalMatrix = mat3(ModelMatrix);
А ещё лучше вычислить её один раз и передать в шейдер, потому что ворочать inverse в шейдере для каждой вершины может быть напряжно.
Sign up to leave a comment.

Articles