opengl文档说交错数据并使用步幅和偏移将多个顶点属性打包到一个缓冲区中。
api reference here列出了这种格式。
void glVertexAttribPointer( GLuint index,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
const GLvoid * pointer);
我在使用这种格式渲染内容时遇到了一些麻烦。我可以使用三个单独的缓冲区渲染一个场景并将数据放在那里但是使用一个缓冲区我渲染一个空白屏幕。
数据结构。
typedef struct {
vec3 angles;
GLshort vertex_count;
GLfloat vertices[12];
GLfloat colors[16];
GLshort indices[6];
GLfloat tex_coords[8];
} cg_sprite;
glGenVertexArrays(1, &big_vao);
glGenBuffers(1, &big_vbo);
glGenBuffers(1, &big_ibo);
glBindVertexArray(big_vao);
glBindBuffer(GL_ARRAY_BUFFER, big_vbo);
glBufferData(GL_ARRAY_BUFFER, big_vbo_size, big_v_buff, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, big_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, big_ibo_total, big_i_buff,
GL_STREAM_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),
(GLvoid*)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),
(GLvoid*)(4 * sizeof(float)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),
(GLvoid*)(7 * sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
设置我的vbo后,我在渲染循环中执行此操作。翻译后,旋转并缩放我在cpu上的顶点,我将它们打包成巨大的缓冲区,如下所示:
cg_sprite_back_2_front(sprites, sprite_count);
for (int i = 0; i < sprite_count; i++) {
//--------------- start packing data into buffers----------------
sp = sprites[i];
// v0
idx = 0;
big_v_buff[(i * 36) + idx++] = ov0.x;
big_v_buff[(i * 36) + idx++] = ov0.y;
big_v_buff[(i * 36) + idx++] = ov0.z;
big_v_buff[(i * 36) + idx++] = sp->quad->colors[0];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[1];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[2];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[3];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[0];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[1];
// v1
big_v_buff[(i * 36) + idx++] = ov1.x;
big_v_buff[(i * 36) + idx++] = ov1.y;
big_v_buff[(i * 36) + idx++] = ov1.z;
big_v_buff[(i * 36) + idx++] = sp->quad->colors[4];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[5];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[6];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[7];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[2];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[3];
// v2
big_v_buff[(i * 36) + idx++] = ov2.x;
big_v_buff[(i * 36) + idx++] = ov2.y;
big_v_buff[(i * 36) + idx++] = ov2.z;
big_v_buff[(i * 36) + idx++] = sp->quad->colors[8];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[9];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[10];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[11];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[4];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[5];
// v3
big_v_buff[(i * 36) + idx++] = ov3.x;
big_v_buff[(i * 36) + idx++] = ov3.y;
big_v_buff[(i * 36) + idx++] = ov3.z;
big_v_buff[(i * 36) + idx++] = sp->quad->colors[12];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[13];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[14];
big_v_buff[(i * 36) + idx++] = sp->quad->colors[15];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[6];
big_v_buff[(i * 36) + idx++] = sp->quad->tex_coords[7];
idx = 0;
big_i_buff[(i * 6) + idx++] = i * 4 + sp->quad->indices[0];
big_i_buff[(i * 6) + idx++] = i * 4 + sp->quad->indices[1];
big_i_buff[(i * 6) + idx++] = i * 4 + sp->quad->indices[2];
big_i_buff[(i * 6) + idx++] = i * 4 + sp->quad->indices[3];
big_i_buff[(i * 6) + idx++] = i * 4 + sp->quad->indices[4];
big_i_buff[(i * 6) + idx++] = i * 4 + sp->quad->indices[5];
idx = 0;
}
然后渲染电话
glBindBuffer(GL_ARRAY_BUFFER, big_vbo);
glBufferData(GL_ARRAY_BUFFER, big_vbo_total, big_v_buff, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, big_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, big_ibo_total, big_i_buff,
GL_STREAM_DRAW);
glDrawElements(GL_TRIANGLES, sprite_count* 6, GL_UNSIGNED_SHORT, 0);
这是一个空白屏幕。我无法找出可能出错的地方。
好的,这有点疯狂。我正在使用amd的gpuperf工作室来调试这个,但这会导致更多的混乱。我拍了两张应用程序的截图。
分析器显示代码应该呈现,但无论出于何种原因,它都不是。
您甚至可以从调试器中看到,假设四边形是两个三角形。我有一个非常简单的着色器,所有数据都进入了gpu但由于某种原因它没有正确渲染,这真的令人困惑。
现在我真的不明白发生了什么。有人有任何建议吗?
答案 0 :(得分:0)
除了调用glVertexAttribPointer
之外,还必须使用`glEnableVertexAttribArray启用顶点属性。另外,纹理坐标的偏移是错误的。他们必须从第8个元素开始,而不是从第7个元素开始。
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),
(GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),
(GLvoid*)(4 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),
(GLvoid*)(8 * sizeof(float)));
^
接下来的事情:如果你在vao仍被绑定的情况下取消绑定GL_ELEMENT_ARRAY_BUFFER
,它将从vao状态中删除。因此,禁用必须按以下顺序发生:
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
渲染:在初始化顶点属性指针后取消绑定vao,但看起来好像忘记在发出绘制调用之前绑定它。
侧注:如果VBO的数据在每一帧中没有变化,您应该在初始化期间而不是在每一帧中上传一次数据。