GLSL sampler2D в структуре
В GLSL, похоже, существует ошибка связывания шейдеров, когда я пытаюсь передать единую структуру с атрибутом sampler2D в функцию, которая объявлена вперед. Код работает, если я удаляю предварительное объявление и перемещаю функцию выше основной. Это незаконный код?
#version 330 core
in vec2 texcoords;
out vec4 color;
struct Material{
sampler2D tex; // Sampler inside a struct
};
uniform Material material;
// Forward Declaration
vec4 add(Material m);
void main() {
color = add(material);
}
// Function Definition
vec4 add(Material m) {
return vec4(texture(m.tex, texcoords));
}
// C++
glUniform1f(glGetUniformLocation(shader, "material.tex"), 0);
glBindTexture(GL_TEXTURE_2D, texture);
РЕДАКТИРОВАТЬ: Таким образом, после небольшого поиска, кажется, что это ошибка в драйвере AMD. Я лично использую ATI Mobility Radeon HD 4670, который довольно старый, но все еще работает с OpenGL 3.3. На форумах AMD я нашел похожий пост, поэтому было бы интересно узнать, насколько он велик для видеокарт AMD. Потому что, если вы разрабатываете на Intel или NVidia, то откуда вы знаете, что ваши шейдеры не будут компилироваться на некоторых видеокартах AMD? Должны ли мы оставаться в безопасности и не использовать прототипы на структурах с сэмплерами, или даже пойти так далеко, что не поместим сэмплеры в struct полностью?... Стоит также отметить, что WebGL даже не допускает сэмплеры внутри структур.
Сообщение об ошибке:
Vertex shader(s) failed to link, fragment shader(s) failed to link.
unexpected error.
unexpected error.
1 ответ
Это на самом деле не должно работать, потому что вы не можете создать экземпляр структуры, которая содержит непрозрачный тип данных (сэмплер, изображение, атомный счетчик). Допустимо иметь структуру с непрозрачным типом как униформу, но вы не можете реализовать функцию add (...)
передавая экземпляр Material
,
Тип данных (GLSL) - непрозрачные типы
Переменные непрозрачных типов могут быть объявлены только одним из двух способов. Они могут быть объявлены в глобальной области видимости, как единообразные переменные. Такими переменными могут быть массивы непрозрачного типа. Они могут быть объявлены как члены структуры, но если это так, то структура может использоваться только для объявления единой переменной (или для объявления члена структуры / массива, который сам является единой переменной). Они не могут быть частью интерфейсного блока с буферной поддержкой или входной / выходной переменной, прямо или косвенно.
Это изменение в вашем коде должно работать во всех совместимых реализациях OpenGL:
// Must be in, because you cannot assign values to an opaque type.
vec4 add (in sampler2D tex) {
return vec4(texture(tex, texcoords));
}
Это также будет работать, так как он использует сэмплер в material.tex
форма:
vec4 add (void) {
return vec4(texture(material.tex, texcoords));
}