本文介绍了多对象绘图(OpenGL)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题是我无法弄清楚如何正确绘制两个对象,因为没有绘制另一个对象.

The issue is that I can't figure out how to properly draw two objects, because my another object isn't being drawn.

这是主要代码:

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();

  }

和着色器:

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);
}

我注意到只绘制了最后一个对象,所以问题是'gl_Position'覆盖了它的值,但是我应该怎么弄清楚呢?

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 =  MVP * vec4(vertexPosition_modelspace,1);
gl_Position =  MVP2 * vec4(vertexPosition_modelspace2,1);

这不是图形管道的工作方式.您不能同时绘制两个对象.仅最后一次写入gl_Position才有效,并且第一个对象将被完全忽略.在最基本的变体中,您想要绘制两个完全独立的对象,并且为此需要两个绘制调用-就像在代码中所做的那样.

That is not how the graphics pipeline work. You can not draw 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.

但是,这样做时,您不需要两个不同的顶点属性.着色器仅处理顶点,在您的情况下,该顶点仅具有verexPosition_modelspace属性.因此,您可以对要绘制的所有对象使用该属性.如果属性表示相同的东西,则对不同的对象使用不同的属性是没有意义的.

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.

让我们看看您的绘图代码:

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);

在这里,将顶点属性0设置为指向第一个缓冲区的顶点数据,然后启用该属性数组.因此,数据将不会用作vertexPosition_modelspace的来源.

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.

glDrawArrays(GL_TRIANGLES, 0, 12*3);

现在,您绘制对象.但是,正如我们已经看到的,您的着色器仅真正使用vertexPosition_modelspace2,而您尚未为其设置指针或启用数组.由于禁用了数组,因此GL将对所有顶点使用属性2的当前值.因此,在三角形的情况下,您将创建所有点都相同的三角形-不管表面积2当前具有什么值,都将获得表面积为0且仍然不可见的三角形.

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.

glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);

现在,您做了一件奇怪的事情:启用属性2数组,但不要为其设置指针!您应该重新指定属性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.

glDrawArrays(GL_TRIANGLES, 0, 4*3);

现在,您在启用属性0和2的情况下进行绘制.属性0将包含所需的数据,但被着色器忽略.属性2只是指向某处,您会得到未定义的行为-它可能会崩溃,但也可能显示奇怪的内容,或根本不显示任何内容.

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.

要执行此操作,只需从着色器中完全删除vertexPosition_modelspace2.也仅使用一个MVP矩阵.绘制任何对象时,您必须:

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:

  1. 设置对象的MVP均匀矩阵
  2. 设置属性0的属性指针
  3. 启用属性0的属性数组(或确保已启用)
  4. 发出抽奖电话
  1. Set the MVP uniform matrix for the object
  2. Set the attribute pointer for attribute 0
  3. Enable the attribute array for attribute 0 (or make sure it is already enabled)
  4. Issue the draw call

您可以根据需要使用任意数量的对象.

You can do this with as many objects as you want.

这篇关于多对象绘图(OpenGL)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 00:11