2013-11-11 3 views
1

Итак, в моей программе я использую OpenGL/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); 
} 

Как это можно сделать более эффективным, так когда делает второй треугольник можно использовать верт [х], который уже был использован вместо того, чтобы объявить те же, снова (пункты 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 
} 

Очевидно, что я предполагаю, что это нормально, чтобы сделать это так, как у меня есть только два треугольника, но я не хотел бы, чтобы написать сотни вершин, если по какой-то причине, я вдруг захотел целую кучу треугольников ...

ответ

3

Используйте glDrawElements() вместо glDrawArrays(), если вы хотите повторно использовать вершины.

glDrawElements принимает аргумент массива индекса, который позволяет вам указывать индексы вершин в массиве вершин, что позволяет использовать их несколько раз.

+0

Охх ... Так просто! Я посмотрю. Спасибо за публикацию. – Reanimation

1

То, о чем вы просите, называется индексированный рендеринг. Основная идея состоит в том, чтобы предоставить index buffer эти элементы ссылаются на идентификаторы вершин в массивах вершин. Таким образом, для двух треугольников, разделяющих одно ребро, вы можете определить только 4 угловые вершины и можете использовать и индексировать массив, как {0,1,2, 2,1,3}. Чтобы сделать рисунок, вам нужно будет использовать glDrawElements().

Возможно, вы также захотите взглянуть на this wiki page, чтобы узнать, какие пути рисования доступны в современном GL.

2

В качестве альтернативы (правильные) ответы с помощью glDrawElements, вы могли бы использовать glDrawArrays с GL_TRIANGLE_FAN вместо GL_TRIANGLES. Фанер использует первые три вершины для рисования треугольника, затем каждая последующая вершина будет генерировать треугольник, используя новую вершину, последнюю вершину и первую вершину. Теперь вам нужно только четыре вершины (расположены против часовой стрелки) в вашем массиве, и вызов выглядит следующим образом:

+0

О, круто. Это удобно знать. Спасибо за публикацию. Я также попробую. – Reanimation