将附近的对象渲染到其他对象上时,OpenGL会变慢

时间:2013-01-18 01:49:44

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

我正在使用OpenGL ES 2.0编写一个iOS应用程序来向屏幕渲染大量对象。 目前,这些对象是简单的形状(正方形,球形和圆柱形)。

当没有任何对象相互重叠时,程序以30 fps平稳运行。

当我添加出现在其余模型后面的对象(例如背景矩形)时,我的问题就出现了。当我尝试绘制背景矩形时,我只能在它前面绘制占用不到一半屏幕的对象。如果大于此值,帧速率将降至15至20 fps之间。

目前,我的所有模型(包括背景)都使用以下代码绘制:

- (void)drawSingleModel:(Model *)model
{
    //Create a model transform matrix.
    CC3GLMatrix *modelView = [CC3GLMatrix matrix];

    //Transform model view
    // ...
    //Pass matrix to shader.
    glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);

    //Bind the correct buffers to openGL.
    glBindBuffer(GL_ARRAY_BUFFER, [model vertexBuffer]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, [model indexBuffer]);
    glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);

    glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));

    //Load vertex texture coordinate attributes into the texture buffer.
    glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, [model textureIndex]);
    glUniform1i(_textureUniform, 0);

    glDrawElements([model drawMode], [model numIndices], GL_UNSIGNED_SHORT, 0);
}

此代码是从我的draw方法调用的,其定义如下:

- (void)draw
{
    glUseProgram(_programHandle);
    //Perform OpenGL rendering here.
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    _camera = [CC3GLMatrix matrix];

    //Camera orientation code.
    //...

    //Pass the camera matrix to the shader program.
    glUniformMatrix4fv(_projectionUniform, 1, 0, _camera.glMatrix);

    glViewport(0, 0, self.frame.size.width, self.frame.size.height);
    //Render the background.
    [self drawSingleModel:_background];

    //Render the objects.
    for(int x = 0; x < [_models count]; ++x)
    {
        [self drawSingleModel:[_models objectAtIndex:x]];
    }

    //Send the contents of the render buffer to the UI View.
    [_context presentRenderbuffer:GL_RENDERBUFFER];
}

我发现通过更改渲染顺序如下:

    for(int x = 0; x < [_models count]; ++x)
    {
        [self drawSingleModel:[_models objectAtIndex:x]];
    } 
    [self drawSingleModel:_background];

在背景上渲染时的帧速率是30 fps。

当然,如果_models中的任何对象必须在彼此前面渲染,则仍会发生减速。此外,按此顺序渲染会使半透明和透明对象绘制为黑色。

我对OpenGL还不熟悉,所以我不太清楚我的问题在哪里。我的假设是执行深度测试的速度有所下降,我也意识到我正在使用移动设备。但我无法相信iOS设备执行此操作的速度太慢。该程序仅渲染5个模型,每个模型大约有180个三角形。

有什么我没看到的,或者某种解决方法吗? 任何建议或指示将不胜感激。

2 个答案:

答案 0 :(得分:2)

您正在使用移动GPU的一个特点:那些东西(除了NVidia Tegra)不会对隐藏表面移除进行深度测试。大多数移动GPU,包括iPad中的移动GPU都是基于磁贴的光栅化器。这样做的原因是为了节省内存带宽,因为内存访问实际上是一项功耗密集型操作。在移动设备的功率受限环境中,减少所需的内存带宽可以显着延长电池寿命。

基于平铺的渲染器将视口拆分为多个平铺。将几何体发送到其中时,会将其拆分为切片,然后对于每个切片,它将与切片中已有的几何体相交。大多数情况下,图块仅由单个图元覆盖。如果传入的图元恰好位于已存在的几何图形的前面,则它将替换它。如果有切割交叉点,则添加新边。只有达到一定数量的边缘阈值时,该单个图块才会切换到深度测试模式。

仅在同步点处,准备好的图块被栅格化,然后。

现在很明显为什么重叠对象会降低渲染性能:原始图像重叠越多,设置图块的预处理就越多。

答案 1 :(得分:1)

请参阅&#34; transparency sorting&#34; /&#34; alpha sorting&#34;。

我怀疑你看到的缓慢很大程度上是由于&#34; overdraw&#34;,即帧缓冲像素不止一次被绘制。当你从前到后绘制场景时,这是最糟糕的,因为深度测试总是通过。虽然iPhone 4 / 4S / 5可能有一个强大的GPU,但最后我检查了内存带宽非常糟糕(我不知道GPU缓存有多大)。

如果你从前到后渲染,问题是透明像素仍会写入深度缓冲区,导致它们遮挡后面的多边形。您可以使用alpha测试稍微减少(但只是略微)。

简单的解决方案:从前到后渲染不透明多边形,然后从后到前渲染透明多边形。这可能意味着在您的场景中进行两次通过,理想情况下,您希望对透明多边形进行排序,而这种多边形并不容易做好。

我认为(原则上)也可以将所有内容从前到后渲染并在目标alpha上执行alpha测试,但我不认为OpenGL支持这一点。