【发布时间】:2014-02-03 20:57:56
【问题描述】:
我第一次在 3D 项目上工作(实际上,我正在编写一个 Quartz Composer 插件中的 Bullet Physics 集成),当我尝试优化我的渲染方法时,我开始使用 glDrawElements而不是 glVertex3d 直接访问顶点...
我对结果感到非常惊讶。我没有检查它是否真的更快,但我尝试了下面这个非常简单的场景。而且,从我的角度来看,即时模式下的渲染效果确实更好。
“绘制元素”方法不断显示三角形的边缘和立方体上非常难看的阴影。
我非常感谢有关此差异的一些信息,并且可能是使用 glDrawElements 保持质量的一种方式。我知道这可能真的是我的错误......
立即模式
绘图元素
在这两种方法中,顶点、索引和法线的计算方式相同。这是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++;
}
【问题讨论】:
-
你所谓的“直接访问”实际上是slow轨道,与GPU分离。为了获得最大的性能,您希望将顶点数据放置在位于 GPU 自己的内存中的顶点数组中。 (顶点缓冲区对象)。即时模式也已从现代版本的 OpenGL 中删除。
-
视觉质量与即时/可编程管道无关。两者最终都在 GPU 上
-
@datenwolf 作为 OpenGL 新手,我从这个论坛帖子中学到了很多东西。现在,我将顶点数据缓存在 C 数组中,并使用 glDrawElements 调用它们。我会尝试将 VBO 集成到我的程序中,但目前它似乎相当复杂。