可以使用iOS上的Accelerate框架绘制圆圈吗?

时间:2013-09-19 01:27:26

标签: ios opengl-es gpuimage accelerate-framework

我正在尝试编写一个GPUImageFilter子类,它可能呈现数千个羽状圆(是的,它是画笔描边)。我当前的方法包括绘制一吨正方形的glDrawArrays调用,以及每个通道的顶点属性,通知片段着色器每个的质心位置,以便着色器可以绘制一个alpha值逐渐变细的圆圈边缘(离质心最远)。

我的测试设备(iPad Mini)速度非常快,除非有(a)超过1,000个圆圈或(b)圆圈非常大。多边形很快,但着色器很快就会慢下来。

我想知道将圆圈直接渲染到字节缓冲区是否会更快,并且只要可以将(通过其他滤镜)渲染到屏幕,GPUImage(使用GPUImageRawDataInput)就会抓取字节。

Accelerate框架是我知道如何在iOS上操作字节的最快方式。我发现我可以使用这种方法非常快速地用vDSP填充RGBA缓冲区:

const int iValue = [RGBA colour as int];

vDSP_vfilli(&iValue, (int*)bytes, 1, width * height);

有人可以建议我如何使用vDSPvImage函数集将羽毛圆圈渲染到我的字节缓冲区中吗?我想到的唯一方法是让很多for循环具有高效性。

2 个答案:

答案 0 :(得分:3)

对于绘制许多羽状圆圈,您可能找不到比使用许多四边形和片段着色器更好的方法。您在这里遇到的性能问题是需要在单个帧中将任意数量的重叠圆形元素混合在一起。您不仅需要处理大量并行像素,而且还有大量可能影响每个像素的圆圈。

我在Molecules应用程序中遇到了类似的问题,并询问了如何在this question中调整我的着色器。在Molecules的情况下,我正在绘制硬边球体冒名顶替者,但我仍然需要将数千个或者非常大的球体混合在一起。

您可以采取一些直接的措施来提高片段着色器的性能(遗憾的是,如果没有您正在使用的代码,我只能猜测您是否正在执行此操作)。首先,如果您在着色器中有分支,请删除分支。使用step()(在您的情况下最有可能是smoothstep())来替换if语句。其次,将您可以进行的任何计算转移到顶点着色器。对于四边形,顶点着色器仅为每个顶点运行一次,而不是每个像素运行一次的片段着色器。我为四个顶点中的每一个传递了一个标准化的-1,-1到1,1坐标,这样可以更简单地计算片段着色器中心点的距离。

禁用混合会大大加快这些设备上的渲染速度,但我认为您无法在此处执行此操作。您可以通过iOS 6中的新帧缓冲区提取操作来做一些聪明的事情来提高混合性能,但我不确定这是否会有所帮助。

到目前为止,最大的表现胜利来自于试图减少你需要做的绘画量。在我的例子中,我能够在我的球体冒名顶替者的后面绘制一系列不透明的正方形(最后一次迭代中的八边形),并使用深度缓冲区来抛出在任何条件下永远不可见的像素。这导致了6倍的性能提升。如果您圈子的某些部分是不透明的,那么您可以像这样进行预先通过。

鉴于这是一个画笔描边,但在我看来,你应该能够做一个更简单的优化,因为你只能绘制从一帧到另一帧改变的任何东西。较旧版本的绘制画笔图像可以存储为平面纹理,该纹理仅使用新的笔刷笔划绘制(并再次保存为存储的纹理)。您不需要为每个帧重绘所有画笔笔划,这会显着降低渲染负荷。

答案 1 :(得分:0)

使用vImage有几种方法可以做到这一点,但没有任何意图可以做到这一点 - 它不做矢量图形 - 所以你可能最好将缓冲区转换为CGbitmapContext并使用CG绘制圈内,或使用各种方法,如布拉德拉森已经建议的那样。

无论如何,为了完整性,如果所有圆圈的大小和颜色相同,则可以绘制一个圆,然后使用vImage / Alpha.h中的一个alpha混合函数将其重复合成到位。我认为vImageDilate会将黑场上的亮点扩展到任意形状,包括圆形,但这可能很昂贵,可能非常昂贵。但是,它可以让您更好地控制颜色。同样,各种卷积可以模糊圆形图案中的亮点。如果这些方法中的任何一种方法都会让我感到非常惊讶,除了alpha方法可能比CG更快。