以下 glsl 代码出现在我的片段着色器中。结构体定义不会造成任何问题,但我尝试将其用作统一数组的类型会导致“无效操作”错误,这并不是特别有帮助。
struct InstanceData
{
vec3 rotation;
vec3 scale;
mat4 position;
};
layout (std140) uniform InstanceData instances[100];
Run Code Online (Sandbox Code Playgroud)
如何正确构建此代码,使其编译时不会出现错误,从而准备好填充数据?请注意,我使用的是核心配置文件版本 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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我还没有在外部编写任何代码来填充统一缓冲区,正如您在上面看到的,我也没有调整我的代码以利用数据。我只是希望它最初按原样编译和工作(即声明但未使用),此时我将添加额外的代码来开始使用它。如果程序一开始不喜欢该声明,那么走那么远就没有意义。
编辑:最后通过使用着色器信息日志找出了问题,如下所示:
GLint infoLogLength;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(id, infoLogLength, NULL, strInfoLog);
Run Code Online (Sandbox Code Playgroud)
简而言之,正如安东所说,我使用layout不正确,并且我的统一块与我的结构具有相同的名称,为编译器造成了各种混乱。
目前,您的结构使用 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];
};
Run Code Online (Sandbox Code Playgroud)
上面的结构体没有正确对齐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)
Run Code Online (Sandbox Code Playgroud)
vec3vec4类型的处理方式与 GLSL 中相同,并且mat4实际上是 4 的数组vec4,因此这意味着它们都需要从 4-float 边界开始。GLSL自动插入填充来满足这些对齐规则;我上面所做的更改是为了向您展示在 C 中编写此数据结构的正确方法。您必须在结构中考虑 2 个浮点数的隐式填充。
struct关于您的编辑,在开始使用缓冲区对象之前,您不必担心 GLSL 如何打包 a 。
如果不使用统一缓冲区对象,您必须使用诸如glUniform3f (...)设置制服之类的函数。这些函数不会直接向您公开数据结构,因此打包并不重要。要设置实例的值,N您可以使用“instances [N].rotation”和“instances [N].scale”以及“instances [N].position”glUniform3f (...)的位置进行调用。glUniformMatrix4fv (...)
这将需要 300 个 API 调用来初始化结构体的所有 100 个实例,因此您可以明白为什么 UBO 更实用(甚至忽略上面提到的 1024 个限制)。
| 归档时间: |
|
| 查看次数: |
12759 次 |
| 最近记录: |