当前位置:  开发笔记 > 编程语言 > 正文

循环中单个像素的渲染速度

如何解决《循环中单个像素的渲染速度》经验,为你挑选了1个好方法。

我正在努力将单个像素绘制到a UIView来创建分形图像.我的问题是我的渲染速度.我目前正在运行此循环260,000次,但想渲染更多像素.实际上,在iPad Mini上运行大约需要5秒钟.

UIBezierPath之前使用的是,但这甚至有点慢(大约7秒).我一直在寻找NSBitMap东西,但我不确定这是否会加速它或如何实现它.

我还在考虑尝试将我的循环中的像素存储到一个数组中,然后在循环后将它们全部绘制在一起.尽管如此,我不太确定存储然后从数组中检索像素的最佳过程是什么.

任何加速这个过程的帮助都会很棒.

for (int i = 0; i < 260000; i++) {

    float RN = drand48();

    for (int i = 1; i < numBuckets; i++) {
        if (RN < bucket[i]) {
            col = i;
            CGContextSetFillColor(context, CGColorGetComponents([UIColor colorWithRed:(colorSelector[i][0]) green:(colorSelector[i][1]) blue:(colorSelector[i][2]) alpha:(1)].CGColor));
            break;
        }
    }

    xT = myTextFieldArray[1][1][col]*x1 + myTextFieldArray[1][2][col]*y1 + myTextFieldArray[1][5][col];
    yT = myTextFieldArray[1][3][col]*x1 + myTextFieldArray[1][4][col]*y1 + myTextFieldArray[1][6][col];

    x1 = xT;
    y1 = yT;
    if (i > 10000) {
        CGContextFillRect(context, CGRectMake(xOrigin+(xT-xMin)*sizeScalar,yOrigin-(yT-yMin)*sizeScalar,.5,.5));

    }
    else if (i < 10000) {
        if (x1 < xMin) {
            xMin = x1;
        }
        else if (x1 > xMax) {
            xMax = x1;
        }
        if (y1 < yMin) {
            yMin = y1;
        }
        else if (y1 > yMax) {
            yMax = y1;
        }
    }
    else if (i == 10000) {
        if (xMax - xMin > yMax - yMin) {
            sizeScalar = 960/(xMax - xMin);
            yOrigin=1000-(1000-sizeScalar*(yMax-yMin))/2;
        }
        else {
            sizeScalar = 960/(yMax - yMin);
            xOrigin=(1000-sizeScalar*(xMax-xMin))/2;
        }
    }
}

编辑

我创建了一个多维数组来存储UIColors,所以我可以使用位图来绘制我的图像.它明显更快,但我的颜色现在不能正常工作.

这是我将UIColors存储到数组中的位置:

int xPixel = xOrigin+(xT-xMin)*sizeScalar;
int yPixel = yOrigin-(yT-yMin)*sizeScalar;
pixelArray[1000-yPixel][xPixel] = customColors[col];

这是我的绘图材料:

CGDataProviderRef provider = CGDataProviderCreateWithData(nil, pixelArray, 1000000, nil);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

CGImageRef image = CGImageCreate(1000,
                                 1000,
                                 8,
                                 32,
                                 4000,
                                 colorSpace,
                                 kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast,
                                 provider,
                                 nil, //No decode
                                 NO,  //No interpolation
                                 kCGRenderingIntentDefault); // Default rendering

CGContextDrawImage(context, self.bounds, image);

不仅颜色不是它们应该是的颜色,而且每次渲染我的图像时,颜色都与前一次完全不同.我一直在用颜色测试不同的东西,但我仍然不知道为什么颜色是错误的,而且我更加困惑他们如何不断变化.



1> rickster..:

每像素绘图 - 每个像素的复杂计算,如分形渲染 - 是您可以要求计算机执行的最难的事情之一.这里的每个其他答案都涉及其难度的一个方面,但这并不是全部.(幸运的是,这种渲染也是现代硬件优化的东西,如果你知道要问什么.我会做到的.)

@jcaron和@JustinMeiners都注意到CoreGraphics中的矢量绘图操作(甚至是矩形填充)会对基于CPU的光栅化造成损失.操纵位图数据的缓冲区会更快,但速度要快得多.

将缓冲区放到屏幕上也需要时间,特别是如果你不得不经历一个创建位图图像缓冲区然后在CG上下文中绘制它们的过程 - 那就是在CPU上进行大量的顺序绘图工作内存带宽可以复制该缓冲区.所以@JustinMeiners是正确的,直接访问GPU纹理内存将是一个很大的帮助.

但是,如果你仍在用CPU代码填充你的缓冲区,你仍然会受到两个成本的阻碍(充其量,如果你天真地这样做会更糟):

顺序工作以渲染每个像素

渲染时从纹理内存到帧缓冲区的内存传输成本

@JustinMeiners的回答对他的用例很有用 - 图像序列是预先渲染的,所以他确切地知道每个像素将是什么,他只需将其转换为纹理记忆.但是您的用例需要大量的每像素计算.

幸运的是,每像素计算是GPU的设计目标!欢迎来到像素着色器的世界.对于屏幕上的每个像素,您可以运行一个独立的计算来确定该点与分形集之间的关系,从而确定绘制它的颜色.可以同时为多个像素并行运行该计算,并且输出直接进入屏幕,因此没有内存开销将位图转储到帧缓冲区.

在iOS上使用像素着色器的一种简单方法是SpriteKit - 它可以为您处理大部分必要的OpenGL/Metal设置,因此您需要编写的是GLSL中的每像素算法(实际上,GLSL的子集是在Metal支持的设备上自动翻译为金属着色器语言).这是一个很好的教程,这是另一个关于iOS的OpenGL ES像素着色器.

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有