在OpenGL中绘制多个三角形 [英] Drawing multiple triangles in OpenGL

查看:83
本文介绍了在OpenGL中绘制多个三角形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是从OpenGL开始,我已经制作了自己的'OOP'版本,可以在c ++中绘制三角形.

I'm just starting out with OpenGL and I have made my own 'OOP' version of drawing a triangle in c++.

我正在使用glfw和glew,如果那很重要.

I am using glfw and glew if that matters.

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

I don't understand why I can't draw more than 1 triangle.

这是主要功能:

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

这是三角形类的构造函数:

Here is what the constructor looks like for the triangle class:

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

这是三角形类的draw方法:

And this is the draw method for the triangle class:

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

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

This is the prototype for the Triangle class if that helps:

    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个顶点位置的float数组之类的东西,而不是调用

I will give away more code if necessary, but the thing is that the program only draws the secondTriangle and I don't seem to understand why... The majority of tutorials on the internet that I have come accross just define something like an array of floats with 6 vertex positions and instead of calling

glDrawArrays(GL_TRIANGLES, 0, 3)

他们的电话

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

是什么导致第一个三角形停止绘制?还是正在绘制而我看不到?我在做蠢事吗?

What is stopping the first triangle from being drawn? Or is it being drawn and I can't see it? Am I doing anything stupid?

推荐答案

顶点数组

例如顶点(x,y,z),法线(x,y,z)和纹理坐标(u,v)的缓冲区:

Vertex array

e.g. Buffers for vertices (x, y, z), normals (x, y, z) and texture 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 );

请参阅:

关于顶点规范的Khronos OpenGL Wiki明确指出:

The Khronos OpenGL wiki about Vertex Specification clearly says:

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

The glVertexAttribPointer functions state where an attribute index gets its array data from.

可以使用 glGetVertexAttrib .

有关顶点属性的更多信息,请参见 OpenGL4.6.核心规范,从第10.2章到第10.6章.

More information about vertex attrbutes can be found in the OpenGL 4.6. core specification from Chapter 10.2 to 10.6.

例如顶点,法向矢量和纹理坐标

e.g. Vertex, Normal vector and Texture coordiante

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


索引缓冲区对象

例如顶点,法向矢量和纹理坐标


Index buffer object

e.g. Vertex, Normal vector and Texture coordiante

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

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

Create the vertex array buffer and the index buffer:

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


顶点数组对象

要处理不同的顶点属性指针,而不是交替指定和启用或禁用它们,可以生成一个顶点数组对象(


Vertex array object

To handle different vertex attribute pointers and not to specify and enable or disable them alternately, a vertex array object can be generated (glGenVertexArrays, which stores all the information about buffer location, data format, state and attribute index:

请参见 OpenGL 4.6核心规范-10.3.1顶点数组对象:

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

The buffer objects that are to be used by the vertex stage of the GL are collected together to form a vertex array object. All state related to the definition of data used by the vertex processor is encapsulated in a vertex array object.

....

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

The currently bound vertex array object is used for all commands which modify vertex array state, such as VertexAttribPointer and EnableVertexAttribArray; all commands which draw from vertex arrays, such as DrawArrays and DrawElements;

例如顶点,法向矢量和纹理坐标

e.g. Vertex, Normal vector and Texture coordiante

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

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

Create the vertex array buffer and the index buffer:

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


请注意,与索引缓冲区( ELEMENT_ARRAY_BUFFER),顶点缓冲区绑定( ARRAY_BUFFER )为全局状态.
VAO状态向量中陈述的每个属性都可以引用不同的 ARRAY_BUFFER .当 glVertexAttribPointer 被调用,然后当前绑定到目标 ARRAY_BUFFER 的缓冲区与指定的属性索引关联,并且对象的名称(值)存储在当前对象的状态向量中绑定的VAO.
但是索引缓冲区是VAO的状态.当缓冲区绑定到目标 ELEMENT_ARRAY_BUFFER 时,该缓冲区将与当前绑定的顶点数组对象相关联.


Note, in compare to the index buffer (ELEMENT_ARRAY_BUFFER), the vertex buffer binding (ARRAY_BUFFER) is a global state.
Each attribute which is stated in the VAOs state vector may refer to a different ARRAY_BUFFER. This reference is stored when glVertexAttribPointer is called, then the buffer which is currently bound to the target ARRAY_BUFFER, is associated to the specified attribute index and the name (value) of the object is stored in the state vector of the currently bound VAO.
But the index buffer is a state of the VAO. When a buffer is bound to the target ELEMENT_ARRAY_BUFFER, then this buffer is associated to the vertex array object which is currently bound.

这篇关于在OpenGL中绘制多个三角形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆