OpenGLES2 iOS:如何最好地为动态地形传输顶点动画?

时间:2012-04-02 09:50:25

标签: objective-c ios optimization opengl-es opengl-es-2.0

我正在编写一个创建动态640 * 480地形的应用程序(每帧都会更改)。每个地形都存储在原始数据文件中,该文件表示一串(浮点)高度值。到目前为止,我可以按顺序将文件读​​入内存,并根据每帧的高度值动态创建一个网格(并且帧速率实际上是合理的),但是在我的应用程序退出之前我没有出现任何错误或堆栈时最大约20帧跟踪。

我怀疑我接近这个错误。我如何传输这些数据,以便我不必将每个帧保存在内存中?

以下是我的数据类的一个部分,其中包含一系列地形:

- (void)addModelWithID:(int)modelID;
{
    NSString* resourcePath  = [[NSBundle mainBundle] resourcePath];
    NSString* fileName      = [NSString stringWithFormat:@"depth_%i.raw", modelID];
    NSString* fullPath = [resourcePath stringByAppendingPathComponent:fileName];

    NSData *myData = [NSData dataWithContentsOfFile:fullPath];
    if (!myData)
      return;

    const float *data = [myData bytes];

    int meshWidth               = 640;
    int meshHeight              = 480;

    Model *kModel = [[Model alloc] init];

    int indicesPtr  = 0;
    int depthPtr = 2;

    for (int y=0;y<meshHeight;y++)    // Loop through y pixels
        {
            for (int x=0;x<meshWidth;x++)   // Loop through x pixels
            {
                // Set up vertex positions
                int index  = y*meshWidth+x;
                float xpos = ((float)x/(float)(meshWidth-1)) - 0.5f;
                float ypos = ((float)y/(float)(meshHeight-1)) - 0.5f;
                float zpos = (float)data[index];

                kModel.vertices1[index*3+0] = xpos;
                kModel.vertices1[index*3+1] = ypos;
                kModel.vertices1[index*3+2] = zpos;

                // Create a new index based on whether the current line is even or odd (flipped horizontally if odd)
                int _index = (y%2==0) ? index : (y*meshWidth) + ((meshWidth-1)-x); 

                //Create the first index
                kModel.indices[indicesPtr++] = _index;

                // Create the second index
                if ((x<meshWidth-1) || (x==meshWidth-1 && y==meshHeight-2))
                    kModel.indices[indicesPtr++] = _index+meshWidth;
            }
        }
    }

    // Add the model to the data object
    [Models addObject:kModel];
    [kModel release];
}

我的绘图代码(每个框架我称之为不同的地形,希望高达500左右,但我最多可以在20左右:

{
    ...
        Model *kModel = [kData.kinectModels objectAtIndex:sequenceCurrentFrame];

        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)kModel.vertices1);

        glEnableVertexAttribArray(vertexHandle);

        glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE, (const GLfloat*)&modelViewProjection.data[0]);
        glDrawElements(GL_TRIANGLE_STRIP, kModel.numIndices, GL_UNSIGNED_SHORT, (const GLvoid*)kModel.indices);
    ...
}

万分感谢你的帮助,

约什

1 个答案:

答案 0 :(得分:3)

您可以将高度数据存储在纹理中,然后在顶点着色器中使用texture2D函数来修改顶点的当前高度。

使用此设置,您可以使用单个网格,只需使用纹理中存储的值调整每个顶点的高度。

如果您确定自己受GPU限制,则可以进一步优化用于查找高度数据的纹理格式。假设您的高度图范围为0-255,给定GL_RGBA格式,您可以使用相同的纹理渲染最多4帧(第一帧从红色组件读取高度,从蓝色组件读取下一帧,等等)。 使背景纹理大两倍(1280x960)将进一步允许您在单个纹理中存储多达16个帧。 关于纹理值得一提的另一件事是,使用GPU的原生格式也可以提高GPU / IO绑定方案的性能。对于iDevices,此格式为PVRTC

我真的认为问题只是每帧单独分配300k +顶点...每帧分配最多640 * 480 * 3 * 4 = 3 686 400字节没有提到你停止分配内存多少帧(等等...... 你呢?)。对于这种资源有限的环境来说,这太过分了。