[英]Setting up a second vertex array object has led to odd rendering
所以我有几节课。 一个renderer和box2drenderer。 现在,它们都使用自己的顶点缓冲区和自己的顶点数组对象。 首先使用以下代码实例化渲染器:
glGenBuffers(1, &ebo);
glGenBuffers(1, &vbo);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLfloat vertices[] = {
// Position(2) Color(3) Texcoords(2)
0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // Top-left
1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // Top-right
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-left
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(GLfloat), (void*)(5 * sizeof(GLfloat)));
glBindVertexArray(0);
glUseProgram(shaderProgram);
projection = glm::ortho(0.0f, width, height, 0.0f);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUseProgram(0);
然后,我为box2d调用设置函数:
void Box2DRenderer::setRenderer(Renderer * r) {
this->renderer = r;
const GLchar * fragSource =
"#version 150 core\n\
precision mediump float;\n\
uniform vec4 u_color;\n\
out vec4 Color;\n\
\n\
void main()\n\
{\n\
Color = u_color;\n\
}";
const GLchar * vertSource =
"#version 150 core\n\
uniform mediump mat4 u_projection;\n\
uniform mediump float u_pointSize;\n\
in vec2 a_position;\n\
\n\
void main()\n\
{\n\
gl_PointSize = u_pointSize;\n\
gl_Position = u_projection * vec4(a_position, 0.0, 1.0);\n\
}";
this->renderer->compileProgram(vertSource, fragSource, vertShader, fragShader, shaderProgram);
glUseProgram(shaderProgram);
glGenBuffers(1, &vbo);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "u_projection"), 1, GL_FALSE, glm::value_ptr(this->renderer->getProjectionMatrix()));
GLuint positionLocation = glGetAttribLocation(shaderProgram, "a_position");
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
glBindVertexArray(0);
colorLocation = glGetUniformLocation(shaderProgram, "u_color");
pointSizeLocation = glGetUniformLocation(shaderProgram, "u_pointSize");
glUseProgram(0);
}
现在,渲染器仅绘制纹理。 因此,我通过以下方法绘制了播放器:
void Renderer::renderTexture(sf::FloatRect &bounds, Texture &texture, Region *region) {
glm::mat4 model;
model = glm::translate(model, glm::vec3(bounds.left, bounds.top, 0.0f));
model = glm::scale(model, glm::vec3(bounds.width, bounds.height, 0.0f));
GLint modelMat = glGetUniformLocation(shaderProgram, "mMatrix");
glUniformMatrix4fv(modelMat, 1, GL_FALSE, glm::value_ptr(model));
float x = region->pos.x / texture.getWidth();
float y = region->pos.y / texture.getHeight();
float rx = (region->width + region->pos.x) / texture.getWidth();
float ry = (region->height + region->pos.y) / texture.getHeight();
GLfloat vertices[] = {
// Position(2) Color(3) Texcoords(2)
0.0f, 0.0f, 1.0f, 1.0f, 1.0f, x, y, // Top-left
1.0f, 0.0f, 1.0f, 1.0f, 1.0f, rx, y, // Top-right
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, rx, ry, // Bottom-right
0.0f, 1.0f, 1.0f, 1.0f, 1.0f, x, ry // Bottom-left
};
glBindTexture(GL_TEXTURE_2D, texture.getTextureId());
glBindVertexArray(vao);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
现在,如果我不初始化box2d渲染器,它将正常工作。 如果我有box2d渲染器,则纹理坐标变得一团糟。 整个纹理似乎在屏幕上绘制,而不是在正确位置绘制区域。
鉴于我要打开和关闭BindVertexArray,我觉得我不应该有问题,但是对于我的一生,我无法弄清楚。 如果您愿意,我可以发布差异截图。
您可能是一个相当普遍的误解的受害者:与您预期的相反, GL_ARRAY_BUFFER
绑定不是 VAO状态的一部分。
在发布的代码的末尾,您具有以下顺序:
glBindVertexArray(vao);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glBufferSubData()
调用将修改当前绑定的GL_ARRAY_BUFFER
中的数据,这是您上次调用glBindBuffer(GL_ARRAY_BUFFER, ...)
所需的缓冲区。 这与以前使用VAO时绑定的缓冲区无关。
为了进一步说明,这是一个典型的调用序列:
glBindVertexArray(vaoA);
glBindBuffer(GL_ARRAY_BUFFER, vboA);
glBindVertexArray(vaoB);
glBindBuffer(GL_ARRAY_BUFFER, vboB);
glBindVertexArray(vaoA);
此序列末尾的当前GL_ARRAY_BUFFER
绑定为vboB
。 由于绑定不是VAO状态的一部分,因此它仅基于最新的glBindBuffer()
调用。
所有你需要做的,解决这个问题是添加glBindBuffer()
调用之前glBufferSubData()
请注意, GL_ELEMENT_ARRAY_BUFFER
绑定是 VAO状态的一部分。 这看似不一致,但事实并非如此。 VAO捆绑了绘制命令使用的所有顶点设置状态。 GL_ELEMENT_ARRAY_BUFFER
绑定控制绘制命令使用哪个索引缓冲区,因此它是此状态的一部分。 另一方面,当前的GL_ARRAY_BUFFER
绑定对绘制命令没有影响,因此不属于VAO状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.