c++ - glDrawElements 和立即模式之间的 OpenGL 质量差异

标签 c++ opengl graphics 3d

我第一次从事 3D 项目(实际上,我正在 Quartz Composer 插件中编写 Bullet Physics 集成程序),并且在尝试优化我的渲染方法时,我开始使用 glDrawElements而不是通过 glVertex3d 直接访问顶点...

我对结果感到非常惊讶。我没有检查它是否真的更快,但我尝试了下面这个非常简单的场景。而且,从我的角度来看,即时模式下的渲染效果确实更好。

“绘制元素”方法不断显示三角形的边缘和立方体上非常难看的阴影。

我真的很感激关于这种差异的一些信息,并且可能是保持 glDrawElements 质量的一种方式。我知道这可能真的是我的错误......

立即模式 enter image description here

绘制元素 enter image description here

在这两种方法中,顶点、索引和法线的计算方式相同。这是2个代码。

立即模式

glBegin (GL_TRIANGLES);
    int si=36;
    for (int i=0;i<si;i+=3)
    {
        const btVector3& v1 = verticesArray[indicesArray[i]];;
        const btVector3& v2 = verticesArray[indicesArray[i+1]];
        const btVector3& v3 = verticesArray[indicesArray[i+2]];


        btVector3 normal = (v1-v3).cross(v1-v2);
        normal.normalize ();
        glNormal3f(-normal.getX(),-normal.getY(),-normal.getZ());
        glVertex3f (v1.x(), v1.y(), v1.z());
        glVertex3f (v2.x(), v2.y(), v2.z());
        glVertex3f (v3.x(), v3.y(), v3.z());

    }
    glEnd();

glDrawElements

glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glNormalPointer(GL_FLOAT, sizeof(btVector3), &(normalsArray[0].getX()));
    glVertexPointer(3, GL_FLOAT, sizeof(btVector3), &(verticesArray[0].getX()));
    glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_BYTE, indicesArray);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

谢谢。

编辑

这是顶点/索引/法线的代码

GLubyte indicesArray[] = {
        0,1,2,
        3,2,1,
        4,0,6,
        6,0,2,
        5,1,4,
        4,1,0,
        7,3,1,
        7,1,5,
        5,4,7,
        7,4,6,
        7,2,3,
        7,6,2 };

    btVector3 verticesArray[] = {
        btVector3(halfExtent[0], halfExtent[1], halfExtent[2]),
        btVector3(-halfExtent[0], halfExtent[1], halfExtent[2]),
        btVector3(halfExtent[0], -halfExtent[1], halfExtent[2]),
        btVector3(-halfExtent[0], -halfExtent[1], halfExtent[2]),
        btVector3(halfExtent[0], halfExtent[1], -halfExtent[2]),
        btVector3(-halfExtent[0], halfExtent[1], -halfExtent[2]),
        btVector3(halfExtent[0], -halfExtent[1], -halfExtent[2]),
        btVector3(-halfExtent[0], -halfExtent[1], -halfExtent[2])
    };

    indicesCount = sizeof(indicesArray);
    verticesCount = sizeof(verticesArray);


    btVector3 normalsArray[verticesCount];

    int j = 0;
    for (int i = 0; i < verticesCount * 3; i += 3)
    {
        const btVector3& v1 = verticesArray[indicesArray[i]];;
        const btVector3& v2 = verticesArray[indicesArray[i+1]];
        const btVector3& v3 = verticesArray[indicesArray[i+2]];

        btVector3 normal = (v1-v3).cross(v1-v2);
        normal.normalize ();

        normalsArray[j] = btVector3(-normal.getX(), -normal.getY(), -normal.getZ());

        j++;
    }

最佳答案

您可以(并且将会)使用即时模式和基于顶点数组的渲染获得完全相同的结果。您的图像表明您的法线错误。由于您没有包含用于创建数组的代码,因此我只能猜测可能出了什么问题。我可以想象一件事:每个三角形使用一个法线,因此在法线数组中,您必须为每个顶点重复该法线。

你应该知道 GL 中的顶点不仅仅是位置(你在即时模式下通过 glVertex 指定),而是所有属性的集合,比如位置、法线、纹理坐标等。因此,如果您有一个网格,其中一个端点是不同三角形的一部分,那么如果共享所有属性而不仅仅是位置,则这只是一个顶点。在您的情况下,法线是每个三角形,因此每个三角形需要不同的顶点(与其他一些顶点共享位置,但使用不同的法线)。

关于c++ - glDrawElements 和立即模式之间的 OpenGL 质量差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18676729/

相关文章:

c++ - boost::spirit:导致匹配失败与来自语义操作的特定消息?

c++ - 由静态方法(或工厂(?))创建的 boost python 对象中的虚拟覆盖

c++ - 网格三角测量 : Seperate vs Nested loop Complexity

c++ - C++ 图形库的内部工作原理

algorithm - 组织结构图算法

c++ - 我真的不明白为什么我在创建模板类共享指针时出错

c++ - socket 之间的管道

c++ - OpenGL 3.x/4x 中的纹素/像素匹配

c++ - 如何使用 OpenGL 加载 8 位 bmp?

algorithm - 是否有任何好的技术可以使近乎排序的数据保持近乎排序?