OpenGl / GLSL - 绘制多个三角形的更有效方法

时间:2013-11-11 22:56:34

标签: arrays opengl matrix glsl

所以在我的程序中,我使用OpenGL / GLSL构建一个正方形并对其进行纹理化。

现代OpenGL 4.0+因此不使用glBegin / glEnd等。

我的方块由2个三角形组成,使用glDrawArrays(GL_TRIANGLES, 0, 6);

构建

正如您在下面的函数中看到的,它创建了2个三角形。我在数组中使用了18个顶点,实际上我只需要12来创建一个正方形,因为其中有6个用于两个三角形。它与24种颜色和8种文本坐标相同。

void Ground::constructGeometry(Shader* myShader)
{
    //Triangle 1 (x,y,z)
    vert[0]  =-dimY;  vert[1] = dimX;  vert[2] = dimZ; //Point 2
    vert[3]  =-dimY;  vert[4] =-dimX;  vert[5] = dimZ; //Point 1
    vert[6]  = dimY;  vert[7] =-dimX;  vert[8] = dimZ; //Point 4
    //Triangle 2 (x,y,z)
    vert[9]  = dimY; vert[10] =-dimX; vert[11] = dimZ; //Point 4
    vert[12] = dimY; vert[13] = dimX; vert[14] = dimZ; //Point 3
    vert[15] =-dimY; vert[16] = dimX; vert[17] = dimZ; //Point 2
    //Colours 1 (r,g,b,a)
    col[0]  = 1.0f;   col[1] = 0.0f;   col[2] = 0.0f;  col[3] = 1.0f;
    col[4]  = 1.0f;   col[5] = 0.0f;   col[6] = 0.0f;  col[7] = 1.0f;
    col[8]  = 1.0f;   col[9] = 0.0f;  col[10] = 0.0f; col[11] = 1.0f;
    //Colours 2 (r,g,b,a)
    col[12] = 1.0f;  col[13] = 0.0f;  col[14] = 0.0f; col[15] = 1.0f;
    col[16] = 1.0f;  col[17] = 0.0f;  col[18] = 0.0f; col[19] = 1.0f;
    col[20] = 1.0f;  col[21] = 0.0f;  col[22] = 0.0f; col[23] = 1.0f;

    //(s,t) coords for Tri 1
    tex[0] = 0.0;   tex[1] = 1.0;
    tex[2] = 0.0;   tex[3] = 0.0;
    tex[4] = 1.0;   tex[5] = 0.0;
    //(s,t) coords for Tri 2
    tex[6]  = 1.0;  tex[7] = 0.0;
    tex[8]  = 1.0;  tex[9] = 1.0;
    tex[10] = 0.0; tex[11] = 1.0;

    glGenVertexArrays(2, &m_vaoID[0]);
    glBindVertexArray(m_vaoID[0]);

    glGenBuffers(3, m_vboID);

    GLint vertexLocation= glGetAttribLocation(myShader->handle(), "in_Position");
    GLint colorLocation= glGetAttribLocation(myShader->handle(), "in_Color");
    GLint texCoordLocation = glGetAttribLocation(myShader->handle(), "in_TexCoord");
    glUniform1i(glGetUniformLocation(myShader->handle(), "DiffuseMap"), 0);

    glBindBuffer(GL_ARRAY_BUFFER, m_vboID[0]);
    glBufferData(GL_ARRAY_BUFFER, totalVerts *sizeof(GLfloat), vert, GL_STATIC_DRAW);
    glEnableVertexAttribArray(vertexLocation);
    glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, m_vboID[1]);
    glBufferData(GL_ARRAY_BUFFER, totalCols *sizeof(GLfloat), col, GL_STATIC_DRAW);
    glEnableVertexAttribArray(colorLocation);
    glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, m_vboID[2]);
    glBufferData(GL_ARRAY_BUFFER, totalTexs *sizeof(GLfloat), tex, GL_STATIC_DRAW);

    glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0,0);
    glEnableVertexAttribArray(texCoordLocation);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glEnableVertexAttribArray(0);
    glBindVertexArray(0);
}

如何提高效率,以便在制作第二个三角形时我可以使用已经使用过的vert [x]而不是再次声明相同的三角形(第4点和第2点)? 颜色一样吗?

这对我的渲染功能有何影响?

void Ground::render(GLuint texName, Shader* myShader)                                   
{
    glUseProgram(myShader->handle());       //find shader passed
    glBindTexture(GL_TEXTURE_2D, texName);  //blending needed to use alpha channel
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glBindVertexArray(m_vaoID[0]);          //select first VAO
    glDrawArrays(GL_TRIANGLES, 0, 6);       //draw first object 0-3, then second 3-6

    glDisable(GL_BLEND);
    glUseProgram(0);
    glBindVertexArray(0);                   //unbind the vertex array object
}

显然我觉得按照我只有2个三角形的方式做它是可以的,但是如果由于某种原因,我突然想要一大堆三角形,我就不想写出数百个顶点... < / p>

3 个答案:

答案 0 :(得分:3)

如果您想重复使用顶点,请使用glDrawElements()代替glDrawArrays()

glDrawElements采用索引数组参数,该参数允许您指定顶点数组中的顶点索引,从而可以多次使用它们。

答案 1 :(得分:2)

作为使用glDrawElements的(正确)答案的替代方案,您可以glDrawArrays使用GL_TRIANGLE_FAN代替GL_TRIANGLES。扇子使用前三个顶点绘制三角形,然后每个后续顶点将使用新顶点,最后一个顶点和第一个顶点生成三角形。现在你只需要在数组中有四个顶点(逆时针排列),调用如下:

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

答案 2 :(得分:1)

您要求的内容称为索引呈现。基本思想是提供index buffer这些元素引用顶点数组中的顶点ID。因此,对于共享一个边的两个三角形,您可以仅定义4个角顶点,并且可以使用和索引数组,如{0,1,2, 2,1,3}。您必须使用glDrawElements()进行绘图。

您可能还想查看this wiki page,以了解现代GL中可用的绘图路径。