GLSL sampler2D in struct

匿名 (未验证) 提交于 2019-12-03 02:26:02

问题:

In GLSL there seems to be linking error of shaders when I try to pass a uniform struct with a sampler2D attribute to a function which is forward declared. The code works if I remove forward declaration and move the function above main. Is this illegal code?

#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); 

EDIT: So after a bit of searching it appears to be a bug in AMD's driver. I personally use ATI Mobility Radeon HD 4670 which is pretty old, but it still runs OpenGL 3.3. On AMD's forums I found a similar post, and so it would be interesting to know how big this is on AMD's graphic cards. Because if you're developing on Intel or NVidia, then how are you to know your shaders won't compile on some AMD's graphic cards? Should we stay safe and not use prototypes on structs with samplers, or even go as far as not putting samplers in struct completely?... It's also worth noting that WebGL doesn't even allow for samplers inside structs.

Error Message:

Vertex shader(s) failed to link, fragment shader(s) failed to link. unexpected error. unexpected error. 

回答1:

This actually is not supposed to work because you cannot instantiate a struct that contains an opaque data type (sampler, image, atomic counter). It is acceptable to have a struct with an opaque type as a uniform, but you cannot implement the function add (...) by passing an instance of Material.

Data Type (GLSL) - Opaque Types

They can be declared as members of a struct, but if so, then the struct (or to declare a member of a struct/array that itself a uniform variable). They cannot be part of a buffer-backed interface block or an input/output variable, either directly or indirectly.


This change to your code should work across all compliant implementations of OpenGL:

// Must be in, because you cannot assign values to an opaque type. vec4 add (in sampler2D tex) {   return vec4(texture(tex, texcoords)); } 

This would also work, since it uses the sampler in the material.tex uniform:

vec4 add (void) {   return vec4(texture(material.tex, texcoords)); } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!