在OpenGL中绘制多个三角形

时间:2017-12-11 19:48:13

标签: c++ opengl

我刚刚开始使用OpenGL,我已经制作了自己的'OOP'版本,用c ++绘制三角形。

如果重要,我正在使用glfw和glew。

我不明白为什么我不能画出超过1个三角形。

这是主要功能:

int main()
{
    Graphics::Window window(1280, 720, "Take me to heaven");
    window.MakeOpenGLAvailable(); // makes context with OpenGL after which initializes GLEW

    Graphics::Objects::Triangle firstTriangle(Graphics::Vec2( 0.0f,  0.0f),
                                              Graphics::Vec2( 1.0f,  1.0f),
                                              Graphics::Vec2(-1.0f,  1.0f));

    Graphics::Objects::Triangle secondTriangle(Graphics::Vec2( 0.0f,  0.0f),
                                               Graphics::Vec2(-1.0f, -1.0f),
                                               Graphics::Vec2( 1.0f, -1.0f));

    window.SetBackground(0.0f, 0.0f, 0.0f, 1.0f);

    while (!window.isClosed() && !window.isKeyPressed(256)/*Escape*/)
    {
        window.DrawBackGround();

        firstTriangle.Draw();
        secondTriangle.Draw();

        window.Update();
        window.CheckForEvents();
    }

    return 0;
}

以下是三角形类的构造函数:

namespace Graphics { namespace Objects {

Triangle::Triangle(Vec2& a, Vec2& b, Vec2& c, bool normalised, short drawtype)
            : points{ a, b, c }
        {
            glGenBuffers(1, &this->triangleID);
            glBindBuffer(GL_ARRAY_BUFFER, this->triangleID);
            glBufferData(GL_ARRAY_BUFFER, sizeof(Vec2) * 3, points, (drawtype == 0) ? GL_STATIC_DRAW : ((drawtype == 1) ? GL_STREAM_DRAW : GL_DYNAMIC_DRAW));

            glEnableVertexAttribArray(0);
            glVertexAttribPointer(0, 2, GL_FLOAT, (normalised == false) ? GL_FALSE : GL_TRUE, sizeof(Vec2), 0);
        }
    }
}

这是三角形类的绘制方法:

void Triangle::Draw()
        {
            glBindBuffer(GL_ARRAY_BUFFER, this->triangleID);
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }

如果有帮助,这是Triangle类的原型:

    class Triangle : public Shape
            {
            public:
                Triangle();
                Triangle(Vec2& a, Vec2& b, Vec2& c, bool normalised = false, short drawtype = 0);
                virtual ~Triangle();

                void Prepare(); // this just binds the buffer though I didn't use it since I bound the buffer inside the Draw method
                void Draw();

            private:
                Vec2 points[3];
                unsigned int triangleID;
}

如果有必要,我会赠送更多代码,但问题是该程序只绘制了secondTriangle,我似乎不明白为什么...... 我在互联网上的大多数教程只是定义了一个像6个顶点位置的浮点数而不是调用

glDrawArrays(GL_TRIANGLES, 0, 3)
他们打电话给

glDrawArrays(GL_TRIANGLES, 0, 6); // 12 etc.

什么阻止第一个三角形被绘制?还是它被画了,我看不到它?我做了什么蠢事吗?

1 个答案:

答案 0 :(得分:2)

顶点数组

e.g。顶点(x,y,z),法线(x,y,z)和纹理oordinates(u,v)的缓冲区:

绘制数组:

GLsizei              no_of_points; // number of vertices and attrbuts
std::vector<GLfloat> vertex;       // linearized array (no_of_points * 3): [ Vx0, Vy0, Vz0, Vx1, Vy1, Vz1, .... ] 
std::vector<GLfloat> normal;       // linearized array (no_of_points * 3): [ Nx0, Ny0, Nz0, Nx1, Ny1, Nz1, .... ] 
std::vector<GLfloat> color;        // linearized array (no_of_points * 5): [ R0, G0, B0, A0, R1, G1, B1, A1, .... ] 

GLuint vetexAttribIndex;  // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint colorAttribIndex;  // index of the color attribute (shader)

glVertexAttribPointer( vetexAttribIndex,  3, GL_FLOAT, GL_FALSE, 0, vertex.data() ); // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE,  0, normal.data() ); // 3: Nx, Ny, Nz  -  GL_TRUE: values should be normalized
glVertexAttribPointer( colorAttribIndex,  4, GL_FLOAT, GL_FALSE, 0, color.data() );  // 4: R, G, B, A 

glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( colorAttribIndex );

glDrawArrays( GL_TRIANGLES, 0, no_of_points ); 

glDisableVertexAttribArray( vetexAttribIndex );
glDisableVertexAttribArray( normalAttribIndex );
glDisableVertexAttribArray( colorAttribIndex );

请参阅:

顶点缓冲区对象

关于Vertex Specification的Khronos OpenGL wiki清楚地说:

  

glVertexAttribPointer函数状态,其中属性索引从中获取其数组数据。

可以使用glGetVertexAttrib检索此状态。

有关顶点属性的更多信息可以在第10.2章到第10.6节的OpenGL 4.6. core specification中找到。

e.g。顶点,法线向量和纹理坐标

[ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0,
  Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1,
  .....
]   

创建顶点数组缓冲区:

GLsizei no_of_points;
std::vector<GLfloat> data; // attribute set: [ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0, Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1, .... ]

GLuint vbo;

glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

请参阅:

绘制数组:

GLuint vetexAttribIndex;  // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint texCorAttribIndex; // index of the texture coordinate attribute (shader)

glBindBuffer( GL_ARRAY_BUFFER, vbo );

GLsizei stride = 8 * sizeof(GL_float); // size of one record in bytes: 8 * float [ Vx, Vy, Vz, Nx, Ny, Nz, Tv, Tu]
GLsizei offsV  = 0 * sizeof(GL_float); // offset of the vertex inside the reccord
GLsizei offsNV = 3 * sizeof(GL_float); // offset of the normal vector inside the reccord
GLsizei offsTC = 6 * sizeof(GL_float); // offset of the tecture coordinate inside the reccord

glVertexAttribPointer( vetexAttribIndex,  3, GL_FLOAT, GL_FALSE, stride, offsV );  // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE,  stride, offsNV ); // 3: Nx, Ny, Nz  -  GL_TRUE: values should be normalized
glVertexAttribPointer( texCorAttribIndex, 2, GL_FLOAT, GL_FALSE, stride, offsTC ); // 2: Tu, Tv 

glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( texCorAttribIndex );

glDrawArrays( GL_TRIANGLES, 0, no_of_points ); 

glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDisableVertexAttribArray( vetexAttribIndex );
glDisableVertexAttribArray( normalAttribIndex );
glDisableVertexAttribArray( texCorAttribIndex );

索引缓冲区对象

e.g。顶点,法线向量和纹理坐标

[ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0,
  Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1,
  .....
]

创建顶点数组缓冲区和索引缓冲区:

GLsizei no_of_points;
std::vector<GLfloat> data;    // attribute set: [ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0, Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1, .... ]
std::vector<GLuint>  indices; // indces: [ I0, I1, I2, I3, I4, ..... ]

GLuint vbo;

glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

GLuint ibo;

glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );

绘制数组:

GLuint vetexAttribIndex;  // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint texCorAttribIndex; // index of the texture coordinate attribute (shader)

glBindBuffer( GL_ARRAY_BUFFER, vbo );

GLsizei stride = 8 * sizeof(GL_float); // size of one record in bytes: 8 * float [ Vx, Vy, Vz, Nx, Ny, Nz, Tv, Tu]
GLsizei offsV  = 0 * sizeof(GL_float); // offset of the vertex inside the reccord
GLsizei offsNV = 3 * sizeof(GL_float); // offset of the normal vector inside the reccord
GLsizei offsTC = 6 * sizeof(GL_float); // offset of the tecture coordinate inside the reccord

glVertexAttribPointer( vetexAttribIndex,  3, GL_FLOAT, GL_FALSE, stride, offsV );  // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE,  stride, offsNV ); // 3: Nx, Ny, Nz  -  GL_TRUE: values should be normalized
glVertexAttribPointer( texCorAttribIndex,  2, GL_FLOAT, GL_FALSE, stride, offsTC ); // 2: Tu, Tv 

glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( texCorAttribIndex );

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glDrawElements( GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, nullptr );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); 

glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDisableVertexAttribArray( vetexAttribIndex );
glDisableVertexAttribArray( normalAttribIndex );
glDisableVertexAttribArray( texCorAttribIndex );

顶点数组对象

要处理不同的顶点属性指针而不是交替指定和启用或禁用它们,可以生成顶点数组对象(glGenVertexArrays,它存储有关缓冲区位置,数据格式,状态和属性索引的所有信息:

请参阅OpenGL 4.6 core Specification - 10.3.1 Vertex Array Objects

  

GL的顶点阶段要使用的缓冲区对象被收集在一起以形成顶点数组对象。   与顶点处理器使用的数据定义相关的所有状态都封装在顶点数组对象中。

     

...

     

当前绑定的顶点数组对象用于修改顶点数组状态的所有命令,例如VertexAttribPointer和EnableVertexAttribArray;   从顶点数组中绘制的所有命令,例如DrawArrays和DrawElements;

e.g。顶点,法线向量和纹理坐标

[ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0,
  Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1,
  .....
]

创建顶点数组缓冲区和索引缓冲区:

GLsizei no_of_points;
std::vector<GLfloat> data;    // attribute set: [ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0, Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1, .... ]
std::vector<GLuint>  indices; // indces: [ I0, I1, I2, I3, I4, ..... ]

GLuint vbo;

glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

GLuint ibo;

glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );

创建顶点数组对象:

GLuint vao;

glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

GLuint vetexAttribIndex;  // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint texCorAttribIndex; // index of the texture coordinate attribute (shader)

glBindBuffer( GL_ARRAY_BUFFER, vbo );

GLsizei stride = 8 * sizeof(GL_float); // size of one record in bytes: 8 * float [ Vx, Vy, Vz, Nx, Ny, Nz, Tv, Tu]
GLsizei offsV  = 0 * sizeof(GL_float); // offset of the vertex inside the reccord
GLsizei offsNV = 3 * sizeof(GL_float); // offset of the normal vector inside the reccord
GLsizei offsTC = 6 * sizeof(GL_float); // offset of the tecture coordinate inside the reccord

glVertexAttribPointer( vetexAttribIndex,  3, GL_FLOAT, GL_FALSE, stride, offsV );  // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE,  stride, offsNV ); // 3: Nx, Ny, Nz  -  GL_TRUE: values should be normalized
glVertexAttribPointer( texCorAttribIndex,  2, GL_FLOAT, GL_FALSE, stride, offsTC ); // 2: Tu, Tv 

glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( texCorAttribIndex );

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo ); // Associate the element array buffer (index buffer) to the vertex array object

glBindVertexArray( 0 ); // Unbind the vertex array object

glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); // Unbinde the element array buffer. This has to be done after the vertex array object is unbound, otherwise the association to the vertex array object would be lost.

请参阅:

绘制数组:

glBindVertexArray( vao );
glDrawElements( GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, nullptr );
glBindVertexArray( 0 );