C++ 多对象绘制 (OpenGL)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23458089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple objects drawing (OpenGL)
提问by RevanReborn
The issue is that I can't figure out how to properly draw two objects, because my another object isn't being drawn.
问题是我不知道如何正确绘制两个对象,因为我的另一个对象没有被绘制。
Here's the main code:
这是主要代码:
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint VertexArrayID2;
glGenVertexArrays(1, &VertexArrayID2);
glBindVertexArray(VertexArrayID2);
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
GLuint MatrixID2 = glGetUniformLocation(programID, "MVP2");
glm::mat4 Projection = glm::perspective(45.0f, 5.0f / 4.0f, 0.1f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(4*2,3*2,8*2),
glm::vec3(0,0,0),
glm::vec3(0,1,0)
);
glm::mat4 Model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glm::mat4 Model2 = glm::translate(glm::mat4(1.0f), glm::vec3(-5.0f, 0.0f, 0.0f));
glm::mat4 MVP2 = Projection * View * Model2;
glUniformMatrix4fv(MatrixID2, 1, GL_FALSE, &MVP2[0][0]);
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
(plenty of floats)
1.0f,-1.0f, 1.0f
};
static const GLfloat g_vertex_buffer_data2[] = {
-1.0f, -1.0f, 3.0f,
(plenty of floats)
0.0f, 1.0f, 2.0f,
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint vertexbuffer2;
glGenBuffers(1, &vertexbuffer2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data2), g_vertex_buffer_data2, GL_STATIC_DRAW);
do{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(MatrixID2, 1, GL_FALSE, &MVP2[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
glDrawArrays(GL_TRIANGLES, 0, 12*3);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,0,(void*)0);
glDrawArrays(GL_TRIANGLES, 0, 4*3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(2);
glfwSwapBuffers(window);
glfwPollEvents();
}
And shader:
和着色器:
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 2) in vec3 vertexPosition_modelspace2;
uniform mat4 MVP;
uniform mat4 MVP2;
void main(){
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
gl_Position = MVP2 * vec4(vertexPosition_modelspace2,1);
}
I have noticed that only last object is being drawn, so the issue is that 'gl_Position' overwrites it's values, but how should I figure it out?
我注意到只绘制了最后一个对象,所以问题是“gl_Position”覆盖了它的值,但我应该如何弄清楚?
采纳答案by derhass
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
gl_Position = MVP2 * vec4(vertexPosition_modelspace2,1);
That is not how the graphics pipeline work. You can notdraw two objects at the same time. Just the last write to gl_Position
will be effective, and your first object will be completely ignored. In the most basic variant, you want to draw two completely independent objects, and you will need two draw calls for that - as you do in your code.
这不是图形管道的工作方式。您不能同时绘制两个对象。只有最后一次写入gl_Position
才会有效,您的第一个对象将被完全忽略。在最基本的变体中,您想要绘制两个完全独立的对象,并且为此需要两次绘制调用 - 正如您在代码中所做的那样。
However, when doing so, you do not need two different vertex attributes. Your shader just processes vertices, which in your case only have the verexPosition_modelspace
attribute. So you can use that attribute for all the objects you want to draw. There is no point in using different attributes for different objects if the attribute means the same thing.
但是,这样做时,您不需要两个不同的顶点属性。您的着色器只处理顶点,在您的情况下只有该verexPosition_modelspace
属性。因此,您可以将该属性用于要绘制的所有对象。如果属性意味着相同的事情,那么为不同的对象使用不同的属性是没有意义的。
Let's have a look at your drawing code:
让我们来看看你的绘图代码:
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
Here, you set up vertex attribute 0 to point to the vertex data of the first buffer, and you enable the attribute array. So the data will not be used as source for vertexPosition_modelspace
.
在这里,您将顶点属性 0 设置为指向第一个缓冲区的顶点数据,并启用属性数组。因此,数据不会用作vertexPosition_modelspace
.
glDrawArrays(GL_TRIANGLES, 0, 12*3);
Now you draw the object. But as we already have seen, your shader does only really use vertexPosition_modelspace2
, for which you did not have set an pointer, or enabled the array. Since the array is disabled, the GL will use the current value of attribute 2 - for all vertices. So in the case of triangles, you create triangles with all points being the same - getting triangles with a surface area of 0 and are invisible anyways, no matter what actual value attribute 2 currently has.
现在您绘制对象。但是正如我们已经看到的,您的着色器仅真正使用vertexPosition_modelspace2
,您没有为其设置指针或启用数组。由于数组被禁用,GL 将使用属性 2 的当前值 - 对于所有顶点。因此,在三角形的情况下,您可以创建所有点都相同的三角形 - 获得表面积为 0 的三角形并且无论如何都是不可见的,无论当前的实际值属性 2 具有什么。
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
Now you do a strange thing: you enable attribute 2 array, but do not set a pointer for it! You should re-specify the pointer for attribute 0 to point to your second model.
现在您做了一件奇怪的事情:您启用了属性 2 数组,但没有为其设置指针!您应该重新指定属性 0 的指针以指向您的第二个模型。
glDrawArrays(GL_TRIANGLES, 0, 4*3);
Now you draw with both attribute 0 and 2 enabled. Attribute 0 will contain the data you want, but is ignored by the shader. Attribute 2 is just point somewhere, and you get undefined behavior - it might just crash, but It might also display strange stuff, or nothing at all.
现在您在启用属性 0 和 2 的情况下进行绘制。属性 0 将包含您想要的数据,但会被着色器忽略。属性 2 只是指向某个地方,您会得到未定义的行为 - 它可能会崩溃,但也可能会显示奇怪的东西,或者根本没有。
To make this work, just remove vertexPosition_modelspace2
completely from the shader. Use just one MVP
matrix also.
When drawing any object, you have to:
要vertexPosition_modelspace2
完成这项工作,只需从着色器中完全移除即可。MVP
也只使用一个矩阵。在绘制任何对象时,您必须:
- Set the
MVP
uniform matrix for the object - Set the attribute pointer for attribute 0
- Enable the attribute array for attribute 0 (or make sure it is already enabled)
- Issue the draw call
- 设置
MVP
对象的统一矩阵 - 为属性 0 设置属性指针
- 为属性 0 启用属性数组(或确保它已启用)
- 发出绘制调用
You can do this with as many objects as you want.
您可以根据需要对任意数量的对象执行此操作。