Комментарии 12
У себя в движке использовал комбинацию объёмов освещения с прямым рендерингом.
Вместе с каждым объектом передаётся список источников света, которые его освещают.
Таким образом из 150 источников света объект обрабатывает только 1-2.
Получилось довольно быстро и не затратно по памяти.
Вместе с каждым объектом передаётся список источников света, которые его освещают.
Таким образом из 150 источников света объект обрабатывает только 1-2.
Получилось довольно быстро и не затратно по памяти.
0
Поделитесь ссылкой на исходники, если возможно?
Технику Forward+ не смотрели? Немного похоже по описанию на реализацию из вашего движка.
Технику Forward+ не смотрели? Немного похоже по описанию на реализацию из вашего движка.
0
Не смотрел, но стоит взять пару приёмчиков из неё.
github.com/Temtaime/aesir/blob/master/source/perfontain/shader/res/lighting.c
GLSL с макроподстановками эдакими, но основной смысл ясен — есть массив с индексами источников света, а у каждого объекта передаются lightStart и lightEnd — начало и конец элементов в этом массиве. Далее по индексу из него получается сам источник света и объект освещается.
На старых гелях произвольное обращение к массиву было невозможно, да.
github.com/Temtaime/aesir/blob/master/source/perfontain/shader/res/lighting.c
GLSL с макроподстановками эдакими, но основной смысл ясен — есть массив с индексами источников света, а у каждого объекта передаются lightStart и lightEnd — начало и конец элементов в этом массиве. Далее по индексу из него получается сам источник света и объект освещается.
На старых гелях произвольное обращение к массиву было невозможно, да.
0
Кто-нибудь ткните носом пожалуйста, как в один проход обернуть qubemap пусть даже в плоскую текстуру. Пусть даже каждая грань кубика будет в этой плоской текстуре. Понимаю, что надо юзать геометрический шейдер, но руки никак не доходят разобраться. С одной стороны вроде как GL — это древнейший и всевозможно описанный где только можно API, но с другой стороны когда начинаешь что-то искать — одна половина найденного уже depricated, одна под 2.0+ и малюсенький процент под 3.3+ и вообще мизер под 4+
0
Неплохо бы картинку или чуть более подробное пояснение того, что вы хотите сделать.
Я не понял вашу задачу, но геометрический шейдер судя по набору слов вряд ли поможет.
Я не понял вашу задачу, но геометрический шейдер судя по набору слов вряд ли поможет.
0
Кадр 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 текстуры.
0
Вот в вопросах проекций я мало смыслю, увы.
Но из того, что я видел в разных туториалах (в основном про 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 текстур «параллельно».
Но из того, что я видел в разных туториалах (в основном про 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 текстур «параллельно».
0
Так как в данном туториале отсутствуют вершинные шейдеры я малость попутал где и как используются матрицы 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;
...
}
Поправьте меня если я что-то не так понял.
0
Вы всё правильно поняли.
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
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
+1
Спасибо! Я только не понял, что там за трюк с нормалями, зачем этот фрагмент:
P.S. В первый раз мы с пацанами попробовали OpenGL…
mat3 normalMatrix = transpose(inverse(mat3(model)));
Normal = normalMatrix * aNormal;
P.S. В первый раз мы с пацанами попробовали OpenGL…
0
normalMatrix это — обычно матрица которая преобразует нормали из пространства координат модели в пространство координат камеры. Если её не вычислили за вас, то она может быть вычислена из матрицы ModelView вот так:
Т.к. тут в текстуры решили записать значения в world space, то соответственно здесь преобразование будет такое же, но от другой исходной матрицы:
Формулы выше нужны для общего случая(т.е. когда в ModelMatrix или ModelViewMatrix записано что угодно). Если у вас не используется неравномерное масштабирование по осям [то, что раньше было известно как glScale()] при переходе из model-->world, то формулу можно упростить до:
mat3 normalMatrix = transpose(inverse(mat3(ModelViewMatrix)));
Т.к. тут в текстуры решили записать значения в world space, то соответственно здесь преобразование будет такое же, но от другой исходной матрицы:
mat3 normalMatrix = transpose(inverse(mat3(ModelMatrix)));
Формулы выше нужны для общего случая(т.е. когда в ModelMatrix или ModelViewMatrix записано что угодно). Если у вас не используется неравномерное масштабирование по осям [то, что раньше было известно как glScale()] при переходе из model-->world, то формулу можно упростить до:
mat3 normalMatrix = mat3(ModelMatrix);
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Learn OpenGL. Урок 5.9 — Отложенный рендеринг