【发布时间】:2014-01-12 00:44:11
【问题描述】:
我正在尝试将一个结构传递给一个简单的 GLSL vetrex 着色器。 以下是 C++ 端的结构:
struct Vertex
{
float position[3];
char boneIndex[4];
float weights[4];
float normals[3];
float textureCords[2];
};
是否可以将此顶点的数组传递给顶点着色器而不为每个组件创建单独的数组?
我可以这样做吗:
#version 330 core
uniform mat4 MVP;
layout(location = 0) in struct Vertex
{
vec3 position;
uint boneIndex;
vec4 weights;
vec3 normals;
vec2 textureCords;
} vertex;
out vec2 UV;
void main()
{
gl_Position = MVP * vec4(vertex.position, 1.0f);
UV = vertex.textureCords;
}
(不要介意并非所有组件都在使用中,这只是示例。)
如果可以的话,如何使用 glVertexAttribPointer() 函数从 C++ 端将数据传递给它? (据我了解,您只能将 1,2,3,4 传递给 size 参数)。
这是正确的做事方式吗? 我是 OpenGL 编程的初学者,所以如果你有答案,请不要犹豫,包括明显的细节。
编辑:
我最终做了这样的事情:
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); //float position[3]
glVertexAttribPointer(1, 1, GL_INT, GL_FALSE, 12, (void*)0); //char boneIndex[4]
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 16, (void*)0); //float weights[4]
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 32, (void*)0); //float normals[3]
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 44, (void*)0); //float textureCords[2]
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
关于 C++ 大小和 GLSL 顶点着色器:
#version 330 core
uniform mat4 MVP;
layout(location = 0) in vec3 position;
layout(location = 1) in int boneIndex;
layout(location = 2) in vec4 weight;
layout(location = 3) in vec3 normal;
layout(location = 4) in vec2 UVCords;
out vec2 UV;
void main()
{
gl_Position = MVP * vec4(position, 1.0f);
UV = UVCords;
}
但还是不行,模型渲染不正确
【问题讨论】:
-
使用接口块时,结构的每个字段都分配有顺序位置。任何
vec4或更小的东西都使用单个属性位置,像mat4这样的东西使用4 个位置(将它们视为4 个vec4s 的数组可能会有所帮助)。所以使用glVertexAttribPointer (...)分配应该非常简单。 -
那么实际上我可以使用相同的 C++ 代码将数据传递给这个着色器吗? vec3 位置的布局(位置 = 0); uint boneIndex 中的布局(位置 = 1); C++ OpenGL:glVertexAttribPointer(0, ... glVertexAttribPointer(1, ... 会一样吗?
-
我还没有看到您为此使用的实际 C++ 代码,但它应该可以工作。我还要指出,骨骼索引应该与
glVertexAttribIPointer (...)一起传递,因为它是一个整数字段,而所有其他顶点数据都是浮点数。 -
@Andon M. Coleman 请查看更新后的问题,您是否发现该代码有问题?
-
您必须为属性添加后续偏移量并更正步幅信息。当使用两个大小为
n的属性时,第一个将具有偏移量0和步幅2n,第二个将具有偏移量n和完全相同的步幅。一旦你明白了,就很容易为超过 2 个属性做到这一点。