在GLSL中,当我尝试将带有sampler2D属性的统一结构传递给前向声明的函数时,似乎存在着色器的链接错误。如果我删除前向声明并将函数移到main之上,则代码有效。这是非法代码吗?
#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的论坛上,我找到了一个 similar post ,所以知道AMD的显卡有多大会很有趣。因为如果您在英特尔或NVidia上进行开发,那么您如何知道您的着色器无法在某些AMD的图形卡上进行编译?我们是否应该保持安全,不要在采样器上使用原型,甚至不要将采样器完全放入结构中?...还值得注意的是 WebGL 并不是这样。甚至允许结构内的采样器。
错误消息:
Vertex shader(s) failed to link, fragment shader(s) failed to link.
unexpected error.
unexpected error.
答案 0 :(得分:6)
这实际上不应该起作用,因为你无法实例化包含不透明数据类型的结构(sampler,image,atomic counter)。将一个带有opaque类型的结构作为一个统一体是可以接受的,但是你不能通过传递add (...)
的实例来实现函数Material
。
opaque类型的变量只能以两种方式之一声明。它们可以作为统一变量在全局范围内声明。这些变量可以是不透明类型的数组。 他们可以声明为结构的成员,但是如果是,那么结构只能用于声明统一变量(或声明一个结构/数组的成员,它本身就是一个统一变量)。它们不能直接或间接地成为缓冲区支持的接口块或输入/输出变量的一部分。
// 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));
}