Передать текстуру в шейдер GLSL без использования одинакового? - PullRequest
1 голос
/ 06 февраля 2020

Чтобы придать текстуры моему шейдеру, я использую униформу типа Sampler2D, но, поскольку у меня много вершин, использующих разные текстуры и разные шейдеры, я достигаю узкого места, когда передаю для каждой вершины правильную текстуру. Поэтому я попытался использовать глобальный массив использованных текстур и передать его в качестве макета в свой шейдер:

layout (location = 6) in sampler2D aTexture;\n

Проблема в том, что мой шейдер не скомпилирует сообщение об ошибке:

0(24) : error C7514: OpenGL does not allow varying of type sampler2D
0(24) : error C7554: OpenGL requires sampler variables to be explicitly declared as uniform

Поскольку мы не можем дать текстуру шейдеру с помощью макета, как вы, ребята, используете текстуры, уклоняясь от такого узкого места? Я вынужден использовать униформу?

1 Ответ

2 голосов
/ 06 февраля 2020

Короче говоря: нет, вы не можете использовать сэмплеры текстур в качестве ввода вершин. Они должны быть одинаковыми.

Итак, есть два возможных решения, каждое решение лучше по специфике Scenr ios:

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

  2. Если каждая ваша геометрия имеет довольно похожий код шейдера, но разные текстуры, вы можете использовать текстуры Array, они не дружественны к памяти (потому что все текстуры в массиве должны иметь одинаковый размер), но вы можете нарисовать их, используя один вызов draw:

    • на стороне ЦП: текстуры массива создаются как обычные 2D-текстуры (просто используйте GL_TEXTURE_2D_ARRAY для создания и привязки)
    • при загрузке в GPU вы должны загружаться как 3D текстура, т. е. используя glTexSubImage3D. Ваш zoffset представляет индекс текстуры, и ваша глубина должна быть 1 для каждого элемента в массиве
    • на стороне шейдера, который вы используете sampler2DArray, и сэмплируйте его как 3D-текстуру, где Z - индекс текстуры.

Вот пример фрагмента кода шейдера:

uniform sampler2DArray myArrayTexture;
in vec2 texCoord;
...
vec4 color1 = texture(myArrayTexture, vec3(texCoord, 0)); // sampling index 0
vec4 color2 = texture(myArrayTexture, vec3(texCoord, 1)); // sampling index 1

вот как вы загружаете массив в графический процессор:

glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, 1, format, type, dataAtIndex0);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, width, height, 1, format, type, dataAtIndex1);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, width, height, 1, format, type, dataAtIndex2);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 3, width, height, 1, format, type, dataAtIndex3);
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...