我可以在不转换所有顶点的情况下进行openGL几何批处理吗?

时间:2009-11-05 23:59:40

标签: iphone opengl-es

我一直在努力设置某种几何形状的批处理一周左右,网上没有关于其他人如何实现这一点的大量信息。基本上我只想“捕捉”每个绘图调用,按纹理对相应的网格进行排序,然后一次性绘制共享纹理的所有网格。

我一直在做的是遍历网格中的每个顶点,通过模型 - 视图矩阵(将其放入世界空间)进行转换,然后将该顶点存储在更大的数组中以等待稍后的渲染。这很有效,但它的运行速度非常慢......因为我似乎正在用软件做什么openGL将在硬件中做什么(所有的矩阵变换)。是否还有其他方法可以进行批量处理,而不需要您手动进行转换?我可以说“嘿,GL,这里有一堆顶点,这里是它们应该如何转换”,然后以快乐的方式发送它?

我应该提到我在iPhone上这样做,所以我受到openGLES和有限硬件的约束。我看过Stanford ngmoco presentation on optimizations,我一直关注this guide来建模我自己的纹理贴片。

这是我正在做的一个例子。这是用于蒙皮网格...我使用PowerVR的.pod格式导出交错的顶点信息数组。

TextureBatcher * tb = [TextureBatcher getSharedTextureBatcher];

// The next line gives me the indices of the verts used by this batch
GLushort * indices = (GLushort*) (mesh.sFaces.pData + (uint) &((GLushort *)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]);
[tb addIndices:indices Count:i32Tris * 3];

NSMutableSet * alreadyVisitedIndices = [NSMutableSet setWithCapacity:i32Tris*3];

for(int i = 0; i < i32Tris*3; i++){
 if([alreadyVisitedIndices containsObject:[NSNumber numberWithInt:indices[i]]]){
  continue;
 } else {
  GLfloat * verts   = (GLfloat*)(mesh.pInterleaved + (uint)mesh.sVertex.pData   + (indices[i]*mesh.sVertex.nStride));
  GLfloat * normals = (GLfloat*)(mesh.pInterleaved + (uint)mesh.sNormals.pData  + (indices[i]*mesh.sNormals.nStride));
  GLfloat * uvs     = (GLfloat*)(mesh.pInterleaved + (uint)mesh.psUVW[uvSet].pData + (indices[i]*mesh.psUVW[uvSet].nStride));


  PVRTVec4 vert = PVRTVec4(verts[0], verts[1], verts[2], 1);
  PVRTVec4 normal = PVRTVec4(normals[0], normals[1], normals[2], 0); //w=0 to skip translation      
  GLfloat u = uvs[0];
  GLfloat v = uvs[1];

  PVRTVec4 newVert = PVRTVec4(0.f);
  PVRTVec4 newNormal = PVRTVec4(0.f);
  if(bSkinning){
   for(int j = 0; j < mesh.sBoneIdx.n; j++){
    PVRTMat4 mat = boneMatrices[(mesh.pInterleaved + (uint)mesh.sBoneIdx.pData + (indices[i]*mesh.sBoneIdx.nStride))[j]];
    GLfloat weight = ((GLfloat*)(mesh.pInterleaved + (uint)mesh.sBoneWeight.pData + (indices[i]*mesh.sBoneWeight.nStride)))[j];
    PVRTMat4 weightedMatrix = mat * weight;

    newVert += weightedMatrix * vert;
    // TODO this should use the inverse transpose but whatever it works.
    newNormal += weightedMatrix * normal;
   }

   [tb addVertex: newVert Normal: newNormal U: u V: v];
  }
  else {
   [tb addVertex: (mModelView * vert) Normal: (mModelView * normal) U: u V: v];
  }
  [alreadyVisitedIndices addObject:[NSNumber numberWithInt:indices[i]]];
 }

1 个答案:

答案 0 :(得分:2)

所以你想要一个包含多个网格的绘图调用,每个网格都有自己独特的模型视图矩阵?如果您正在使用OpenGL ES 2.0,那么您可以使用一系列统一的 mat4 来执行此操作,然后将其应用于您的顶点着色器。

但是,我敢打赌你正在使用OpenGL ES 1.1。如果是这样,您可以使用GL_OES_matrix_palette扩展程序完成类似的操作,甚至在较旧的iPhone上也支持此扩展程序。但是,这个扩展可能会有性能损失,因为你需要向每个顶点发送一个混合权重。