在Opengl-es 2.0中渲染三角形的问题

时间:2011-07-01 08:38:49

标签: c++ c opengl-es opengl-es-2.0

  

可能重复:
  Problem when going from opengl 1.1 to Opengl-es 2.0

我试图通过绘制三角形来渲染等值面,三角形从文本文件中获取数据并使用opengl-es 2.0渲染它。我能够在Opengl 1.1中做到这一点,但因为在opengl-es 2.0中有些函数不存在所以我在缓冲区遇到困难,或者可能是其他一些我实际上无法理解的问题。我正在粘贴我的两个绘制三角形代码opengl和opengl-es 2.0。你能告诉我为什么不能得到相同的结果。我正在使用pvrsdk在ubuntu 10.10中进行编码。

OpenGL-ES 2.0代码:

    for (surfnum=0;surfnum<surftotal;surfnum++)
    {
        glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
        for (i=0;i<triNum[surfnum];i++)
        {
            GLfloat *Vertices[] = {    
                            triArray[surfnum][i].pt1, 
                            triArray[surfnum][i].pt2,
                            triArray[surfnum][i].pt3
                        };


            glGenBuffers(1, &ui32Vbo);
            glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);
            unsigned int uiSize = 3 * (sizeof(GLfloat) * 3); 
            glBufferData(GL_ARRAY_BUFFER, uiSize,*Vertices, GL_DYNAMIC_DRAW);

        }

        for(int i = 0; i < 8000; ++i)
        {
            glClear(GL_COLOR_BUFFER_BIT);
            int i32Location = glGetUniformLocation(uiProgramObject, "projmatrix");
            glUniformMatrix4fv( i32Location, 1, GL_FALSE, projmatrix);
            glEnableVertexAttribArray(VERTEX_ARRAY);
            glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0);
            //glDrawElements(GL_TRIANGLE_FAN, triNum[surfnum], GL_UNSIGNED_BYTE,Vertices);
            glDrawArrays(GL_TRIANGLES,0,triNum[surfnum]);
            eglSwapBuffers(eglDisplay, eglSurface);
        }
    }

我在OpenGL中做过同样的事情: OpenGL代码:

for (surfnum=0;surfnum<surftotal;surfnum++)
{
    for (i=0;i<triNum[surfnum];i++)
    {
        glBegin(GL_TRIANGLES);
        glVertex3fv(triArray[surfnum][i].pt1);
        glVertex3fv(triArray[surfnum][i].pt2);
        glVertex3fv(triArray[surfnum][i].pt3);
        glEnd();
        glFlush();
        glutSwapBuffers();
    }
}

surfnum,vertex_array,surftotal是定义的变量。 我也得到一个结果,但两者都不一样,我也得到了一个警告: libegl:软件后备

P.S =这里如果我试图获得所有顶点然后尝试将其绑定在单个缓冲区中,那么它会给出分段错误。可能是我做错了。如果这是一个正确的方法,你可以告诉我如何做到这一点。 如果您想要任何其他信息告诉我。

HI基督徒,因为你说我可以在不使用glmapbuffer的情况下做到这一点我尝试这样做但它仍然给我错误:

glGenBuffers(surftotal, uiVBO);
{
    for(surfnum=0; surfnum<surftotal; ++surfnum)
    {
            glBindBuffer(GL_ARRAY_BUFFER, uiVBO[surfnum]);
            size_t buf_size = 9*sizeof(GLfloat)*triNum[surfnum];
            GLfloat* const pData = (GLfloat*)malloc(buf_size);
            for(i=0; i<triNum[surfnum]; ++i) {
                memcpy(pData+i*9,   triArray[surfnum][i].pt1, 3*sizeof(GLfloat));
                memcpy(pData+i*9+3, triArray[surfnum][i].pt2, 3*sizeof(GLfloat));
                memcpy(pData+i*9+6, triArray[surfnum][i].pt3, 3*sizeof(GLfloat));
            }
            glBufferData(GL_ARRAY_BUFFER, buf_size, pData, GL_STATIC_DRAW);
            free(pData);
    }   
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glEnableVertexAttribArray(VERTEX_ARRAY);
    for(surfnum=0; surfnum<surftotal; ++surfnum)
    {
            glBindBuffer(GL_ARRAY_BUFFER, uiVBO[surfnum]);
            glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0);
            glDrawArrays(GL_TRIANGLES, 0, 3*triNum[surfnum]);
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);        //clean up, of course      

}

这是我在编译上述程序时遇到的错误

  

libEGL警告:使用软件回退

1 个答案:

答案 0 :(得分:3)

首先,不要在绘图函数中创建一个缓冲区(应该经常运行),而是在一些初始化代码中(例如在从文件加载数据之后),因为我认为它在加载之后不会改变该文件(如果是,则只更新缓冲区数据)。其次,不要为每个三角形创建一个缓冲区,而是为所有三角形(或者surftotal个缓冲区创建一个缓冲区,每个三角形一个)。

首先我们创建surftotal缓冲区,希望不在绘图例程中:

GLuint uiVBO[surftotal];
glGenBuffers(surftotal, uiVBO);

接下来我们复制数据(只有在更改后,可能只在加载后一次,如果是这种情况,GL_STATIC_DRAW可能会更好)。对于每个三角形,我们需要存储其三个顶点的位置数据,每个三角形制作9个浮点数(您的代码非常混乱,存储顶点的地址或甚至不存在)。我们将为缓冲区分配存储而不提供数据,然后映射缓冲区数据以直接写入其中。这样我们就不需要为自己的数据分配临时CPU内存(驱动程序会为我们这样做)。当然,我们在复制数据后取消映射,以便缓冲区可以用于渲染:

for(surfnum=0; surfnum<surftotal; ++surfNum)
{
    glBindBuffer(GL_ARRAY_BUFFER, uiVBO[surfnum]);
    glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat)*triNum[surfnum], NULL, GL_DYNAMIC_DRAW);
    GLfloat *pData = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
    for(i=0; i<triNum[surfnum]; ++i,pData+=9)
    {
        mempcy(pData, triArray[surfnum][i].pt1, 3*sizeof(GLfloat));
        mempcy(pData+3, triArray[surfnum][i].pt2, 3*sizeof(GLfloat));
        mempcy(pData+6, triArray[surfnum][i].pt3, 3*sizeof(GLfloat));
    }
    glUnmapBuffer(GL_ARRAY_BUFFER);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);      //clean up behind us

当最终渲染数据时,我们绑定缓冲区,告诉OpenGL从中获取顶点数据并渲染它(给予glDrawArrays顶点数而不是三角形)。当然,我们为每个表面都这样做:

glEnableVertexAttribArray(VERTEX_ARRAY);
for(surfnum=0; surfnum<surftotal; ++surfnum)
{
    glBindBuffer(GL_ARRAY_BUFFER, uiVBO[surfnum]);
    glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glDrawArrays(GL_TRIANGLES, 0, 3*triNum[surfnum]);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);        //clean up, of course

将所有曲面的三角形打包到单个缓冲区中以使用单个绘制调用绘制所有曲面可能是更好的主意。使用glDrawElementsGL_ELEMENT_ARRAY_BUFFER来考虑索引三角形集可能也是一个好主意,但我想你的数据结构甚至没有这些信息,你首先应该真正理解数组和缓冲区是如何工作的在使事情复杂化之前(我希望我的答案有助于此)。试着理解这个答案代码的每一行真正做的事情,如果需要的话,查询其他文档来源。一般来说,不要通过盯着一些代码示例来学习像OpenGL或3d图形这样复杂的东西,而是通过一些真实的文档和学习资源来真正理解你在做什么。