GLSL: искажение данных
Я использую OpenGL 3.3 GLSL 1.5 совместимость. У меня странная проблема с данными вершин. Я пытаюсь передать значение индекса фрагментному шейдеру, но значение, похоже, меняется в зависимости от положения моей камеры.
Это должно быть просто: я передаю GLfloat через вершинный шейдер фрагментному шейдеру. Затем я конвертирую это значение в целое число без знака. Значение является правильным в большинстве случаев, за исключением краев фрагмента. Неважно, что я делаю, появляется одно и то же искажение. Почему положение моей камеры меняет это значение? Даже в нелепом примере, приведенном ниже, случайным образом получается что-то отличное от 1,0;
uint i;
if (tI == 1.0) i = 1;
else i = 0;
vec4 color = texture2D(tex[i], t) ;
Если я посылаю целочисленные данные вместо данных с плавающей точкой, я получаю точно такую же проблему. Кажется, не имеет значения, что я ввожу как данные вершины. Значение, которое я ввожу в данные, не соответствует всему фрагменту. Искажение даже выглядит одинаково каждый раз.
1 ответ
То, что вы делаете здесь, недопустимо в OpenGL/GLSL 3.30.
Позвольте мне процитировать спецификацию GLSL 3.30, раздел 4.1.7 "Пробоотборники" (выделено мной):
Сэмплеры, агрегированные в массивы внутри шейдера (с использованием квадратных скобок [ ]), могут индексироваться только с помощью целочисленных константных выражений (см. Раздел 4.3.3 "Выражения констант").
Использование варьирования в качестве индекса для текстуры не представляет собой постоянное выражение, как определено в спецификации.
Начиная с GL 4.0, это было несколько смягчено. В спецификации GLSL 4.00 говорится следующее (все еще мой акцент):
Сэмплеры, агрегированные в массивы внутри шейдера (с использованием квадратных скобок [ ]), могут индексироваться только с помощью динамически однородного интегрального выражения, в противном случае результаты не определены.
При этом динамически равномерное определяется следующим образом:
Выражение фрагмент-шейдер является динамически однородным, если все оценивающие его фрагменты получают одинаковое результирующее значение. Когда задействованы циклы, это относится к значению выражения для той же итерации цикла. Когда задействованы функции, это относится к вызовам из одной и той же точки вызова.
Так что теперь это немного сложно. Если бы все вызовы фрагментного шейдера фактически получали одно и то же значение для этого изменения, я думаю, это было бы разрешено. Но неясно, что ваш код гарантирует это. Также следует учитывать, что фрагмент может быть даже выбран за пределами примитива.
Тем не менее, вы никогда не должны проверять поплавки на равенство. Там будут численные проблемы. Я не знаю, чего именно вы здесь пытаетесь достичь, но вы можете использовать простое поведение округления или использовать целочисленные переменные. Вы также должны отключить интерполяцию значения в любом случае, используя flat
квалификатор (который в любом случае требуется для целочисленного регистра), который должен значительно улучшить изменения этой конструкции, чтобы она стала динамически однородной.