我正在使用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个三角形。
有什么我没看到的,或者某种解决方法吗? 任何建议或指示将不胜感激。
答案 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支持这一点。