以下glsl代码出现在我的片段着色器中。结构定义没有问题,但是我尝试将它用作统一数组的类型会导致"无效操作"错误,这不是特别有帮助。
struct InstanceData
{
vec3 rotation;
vec3 scale;
mat4 position;
};
layout (std140) uniform InstanceData instances[100];
如何正确构造此代码以使其无错误地编译,从而为我填充数据做好了准备?请注意,我使用的是核心配置文件版本4.5。
修改:这似乎与使用layout (std140)
有关。删除该部分允许代码编译,但我不需要这样做以确保glsl编译器以可预测的方式打包结构数据?
修改:仍然无效。我的整个顶点着色器代码如下所示:
#version 450
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
out vec4 ex_Color;
flat out int ex_Instance;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
// ------ preliminary addition of uniform block to be used soon ------
struct layout (std140) InstanceData
{
vec3 rotation;
vec3 scale;
mat4 position;
};
layout (std140, binding = 0) uniform InstanceData
{
InstanceData instances[100];
};
// -------------------------------------------------------------------
void main(void)
{
gl_Position = (projectionMatrix * viewMatrix * modelMatrix) * in_Position;
ex_Color = in_Color;
}
请注意,我还没有在外部编写任何代码来填充统一缓冲区,正如您在上面所看到的那样,我也没有调整代码来使用数据。我只是希望它按原样编译和工作(即声明但未使用),此时我将添加其他代码以开始使用它。如果程序不喜欢开头的声明,那么即使到目前为止也没有意义。
编辑:最后使用着色器信息日志解决了问题,如下所示:
GLint infoLogLength;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(id, infoLogLength, NULL, strInfoLog);
简而言之,正如Anton所说,我错误地使用了layout
,而我的统一块与我的结构名称相同,为编译器带来了各种各样的混淆。
答案 0 :(得分:2)
目前,您的struct使用3 + 3 + 16 = 22个浮点组件,并且您正在尝试构建一个包含100个这些组件的数组。 OpenGL实现只需要在任何阶段支持1024个浮点统一组件,并且您的阵列需要2200。
统一缓冲区对象允许您存储最多64 KiB(最小)的数据;远远超过上述限制。但是,在使用UBO时需要注意数据对齐,这就是您尝试使用的layout (std140)
限定符。
struct InstanceData
{
vec3 rotation;
vec3 scale;
mat4 position;
};
// Uniform block named InstanceBlock, follows std140 alignment rules
layout (std140, binding = 0) uniform InstanceBlock {
InstanceData instances [100];
};
上面的结构未正确对齐std140
,使用它时需要小心。
struct InstanceData
{
vec3 rotation; // 0,1,2
float padding03; // 3
vec3 scale; // 4,5,6
float padding07; // 7
mat4 position; // 8-23
} // Size: 24 * sizeof (float)
vec3
类型与GLSL中的vec4
相同,mat4
实际上是4 vec4
的数组,因此这意味着它们都需要在4开始浮动边界。 GLSL自动插入填充以满足这些对齐规则;我上面所做的更改是为了向您展示在C中编写此数据结构的正确方法。 您必须在结构中考虑2个浮点数的隐式填充。 < / p>
关于编辑,在开始使用缓冲区对象之前,您不必担心GLSL如何打包struct
。
如果不使用统一缓冲区对象,则必须使用glUniform3f (...)
之类的函数来设置制服。这些函数不直接向您公开数据结构,因此打包无关紧要。要设置实例N
的值,您可以使用“实例[N] .rotation”和“实例[N] .scale”的位置以及“实例glUniform3f (...)
来调用glUniformMatrix4fv (...)
[N] .POSITION”。
这需要300个API调用来初始化你的结构的所有100个实例,这样你就可以看到为什么UBO更实用(甚至忽略了上面提到的1024限制)。