不幸的是,OpenGL ES 2.0 不允许你写入gl_FragDepth,因此我需要将这些值输出到自定义深度纹理中。我使用帧缓冲对象(FBO)对场景进行一次遍历,仅渲染与深度值相对应的颜色,并将结果存储到纹理中。然后将该纹理加载到我的渲染过程的第二部分中,生成实际的屏幕图像。如果该阶段的片段处于存储在该点屏幕上的深度纹理中的深度级别,则会显示它。否则,就会被丢弃。更多关于该过程的信息,包括图表,可以在我的帖子这里中找到。
这个深度纹理的生成过程是我渲染流程中的瓶颈,我正在寻找一种方法使它更快。似乎比它应该的要慢,但我无法想出原因。为了实现深度纹理的正确生成,禁用了
GL_DEPTH_TEST
,启用了GL_BLEND
和glBlendFunc(GL_ONE, GL_ONE)
,并将glBlendEquation()
设置为GL_MIN_EXT
。我知道像这样以瓦片为基础的延迟渲染器(如iOS设备中的PowerVR系列)输出的场景不是最快的,但我想不出更好的方法。
对于球体(最常见的显示元素)的深度片段着色器似乎是这个瓶颈的核心(仪器中的渲染器利用率达到了99%,表明我的限制在于片段处理)。它目前看起来像下面这样:
precision mediump float;
varying mediump vec2 impostorSpaceCoordinate;
varying mediump float normalizedDepth;
varying mediump float adjustedSphereRadius;
const vec3 stepValues = vec3(2.0, 1.0, 0.0);
const float scaleDownFactor = 1.0 / 255.0;
void main()
{
float distanceFromCenter = length(impostorSpaceCoordinate);
if (distanceFromCenter > 1.0)
{
gl_FragColor = vec4(1.0);
}
else
{
float calculatedDepth = sqrt(1.0 - distanceFromCenter * distanceFromCenter);
mediump float currentDepthValue = normalizedDepth - adjustedSphereRadius * calculatedDepth;
// Inlined color encoding for the depth values
float ceiledValue = ceil(currentDepthValue * 765.0);
vec3 intDepthValue = (vec3(ceiledValue) * scaleDownFactor) - stepValues;
gl_FragColor = vec4(intDepthValue, 1.0);
}
}
在iPad 1上,使用透传着色器显示一个DNA空间填充模型的一帧需要35-68毫秒的时间(在iPhone 4上为18-35毫秒)。根据PowerVR PVRUniSCo编译器(他们的SDK的一部分)的说法,该着色器最佳情况下使用11个GPU周期,最差情况下使用16个周期。我知道你不建议在着色器中使用分支,但在这种情况下,这比其他方式表现更好。
当我将其简化为
precision mediump float;
varying mediump vec2 impostorSpaceCoordinate;
varying mediump float normalizedDepth;
varying mediump float adjustedSphereRadius;
void main()
{
gl_FragColor = vec4(adjustedSphereRadius * normalizedDepth * (impostorSpaceCoordinate + 1.0) / 2.0, normalizedDepth, 1.0);
}
iPad 1需要18-35毫秒,而iPhone 4只需要1.7-2.4毫秒。该着色器的估计GPU周期数为8个周期。基于周期计算的渲染时间变化似乎不是线性的。
最后,如果我只输出一个恒定的颜色:
precision mediump float;
void main()
{
gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);
}
iPad 1上的渲染时间降至1.1-2.3毫秒(iPhone 4上为1.3毫秒)。
第二个着色器中的非线性缩放和iPad和iPhone 4之间的突然变化使我觉得我可能漏掉了什么。如果您希望自行尝试,可以从here下载包含这三种着色器变体(请查看SphereDepth.fsh文件并注释适当的部分)和测试模型的完整源项目。
如果您已经阅读到这里,我的问题是:基于这些分析信息,如何提高iOS设备上自定义深度着色器的渲染性能?