结构中的GLSL sampler2D

时间:2014-08-24 17:55:40

标签: opengl glsl

在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.

1 个答案:

答案 0 :(得分:6)

这实际上不应该起作用,因为你无法实例化包含不透明数据类型的结构(sampler,image,atomic counter)。将一个带有opaque类型的结构作为一个统一体是可以接受的,但是你不能通过传递add (...)的实例来实现函数Material

数据类型(GLSL) - Opaque Types

  

opaque类型的变量只能以两种方式之一声明。它们可以作为统一变量在全局范围内声明。这些变量可以是不透明类型的数组。 他们可以声明为结构的成员但是如果是,那么结构只能用于声明统一变量(或声明一个结构/数组的成员,它本身就是一个统一变量)。它们不能直接或间接地成为缓冲区支持的接口块或输入/输出变量的一部分。


对代码 的更改应适用于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));
}