设置第二个顶点数组对象会导致奇怪的渲染
Setting up a second vertex array object has led to odd rendering
所以我有几个类。一个渲染器和box2drenderer。现在它们都使用自己的顶点缓冲区和顶点数组对象。Renderer首先用下面的代码实例化:
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调用setup函数:
void Box2DRenderer::setRenderer(Renderer * r) {
this->renderer = r;
const GLchar * fragSource =
"#version 150 coren
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 coren
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()
调用。
你所需要做的就是在glBufferSubData()
之前添加glBindBuffer()
调用。
GL_ELEMENT_ARRAY_BUFFER
绑定是VAO状态的一部分。这可能看起来不一致,但事实并非如此。VAO捆绑了绘制命令使用的所有顶点设置状态。GL_ELEMENT_ARRAY_BUFFER
绑定控制绘制命令使用哪个索引缓冲区,因此它是该状态的一部分。另一方面,当前的GL_ARRAY_BUFFER
绑定对draw命令没有影响,因此不是VAO状态的一部分。
相关文章:
- 我有两个类需要在同一 cpp 文件中相互引用,但第一个类无法识别第二个类类型的对象
- 等待整个 omp 块完成,然后再调用第二个函数
- 我想在C++中读取一些多个字符,但它永远不会读取第二个字符
- 如何在创建自定义迭代器时获得 std::p air 的第一个和第二个?
- WinAPI 在单击第一个对话框上的按钮控件并销毁第一个对话框后创建第二个对话框
- 将第二个 GATT 服务添加到 Movesense 容器
- 如何在 c++ 中根据第二个元素按降序对列表进行排序
- 对的排序向量 (std::vector<pair<int, int>>) 按对的第一个元素搜索并更新第二个元素值
- 比较 2 个向量并从第二个向量中删除在第一个 - c++ 中找不到的元素
- 为什么这个程序没有打印返回的迭代器的正确第二个元素?
- 使第二个类的构造函数成为第一个类中的友元函数
- 为什么第二个代码给出了预期的结果,而第一个代码却没有?
- 为什么第一个代码块产生垃圾值,而第二个代码块将类成员的值相加?
- 打印无序映射的第二个元素,即集合
- 我有一个类,它创建了另一个类的实例.如何将变量通过第一个类传递到第二个类的实例化中?
- 需要使用模板查找数组的第二个最小和最小值
- c++:交换向量中所有元组的第一个和第二个元素
- 如果条件,当我想第二个参数时
- C DirectX 11从第二个顶点缓冲区呈现麻烦
- 设置第二个顶点数组对象会导致奇怪的渲染