ОБНОВЛЕНИЕ
Я преодолел ограничения компьютерной графики, рисуя все с помощью OpenGL. Еще есть глюки, но пока работает намного-намного быстрее.
Некоторые интересные моменты:
GLKView
:Это специальное представление для iOS -, и оно очень помогает в настройке контекста OpenGL и цикла рендеринга. Если вы не на iOS, боюсь, вы сами по себе.GL_LINES
:OpenGL ES изначально может рисовать простые линии. Не очень хорошо(без стыков, без заглушек, см. фиолетово-серую линию в верхней части снимка экрана ниже), но чтобы улучшить это, вам придется написать собственный шейдер, преобразовать каждую линию в полосу треугольника и молиться, чтобы это сработало!(предположительно, так поступают браузеры, когда говорят вам, что Canvas2D ускоряется на GPU -)Исходный вопрос
Я пытаюсь нарисовать много CGPath (, обычно более 1000 )в методе drawRect
моего представления прокрутки, которое обновляется, когда пользователь перемещает его пальцем. У меня есть такое же приложение на JavaScript для браузера, и я пытаюсь перенести его в родное приложение для iOS.
Тестовый код iOS: (со 100 строковыми операциями, path
— предварительно -, сделанный CGMutablePathRef
):
- (void) drawRect:(CGRect)rect {
// Start the timer
BSInitClass(@"Renderer");
BSStartTimedOp(@"Rendering");
// Get the context
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
CGContextTranslateCTM(context, 800, 800);
// Draw the points
CGContextAddPath(context, path);
CGContextStrokePath(context);
// Display the elapsed time
BSEndTimedOp(@"Rendering");
}
. В JavaScript, для справки, код (с 10000 строковыми операциями ):
window.onload = function() {
canvas = document.getElementById("test");
ctx = canvas.getContext("2d");
// Prepare the points before drawing
var data = [];
for (var i = 0; i < 100; i++) data.push ({x: Math.random()*canvas.width, y: Math.random()*canvas.height});
// Draw those points, and write the elapsed time
var __start = new Date().getTime();
for (var i = 0; i < 100; i++) {
for (var j = 0; j < data.length; j++) {
var d = data[j];
if (j == 0) ctx.moveTo (d.x, d.y);
else ctx.lineTo(d.x,d.y)
}
}
ctx.stroke();
document.write ("Finished in " + (new Date().getTime() - __start) + "ms");
};
. Теперь я гораздо лучше разбираюсь в оптимизации JavaScript, чем в iOS, но после некоторого профилирования кажется, что накладные расходы CGPath абсолютно, невероятно плохи по сравнению с JavaScript. Оба фрагмента работают примерно ната же скоростьна реальном устройстве iOS, а код JavaScript имеет в 100 раз больше строковых операций, чем код Quartz2D!
РЕДАКТИРОВАТЬ :Вот верхняя часть профилировщика времени в инструментах:
Running Time Self Symbol Name
6487.0ms 77.8% 6487.0 aa_render
449.0ms 5.3% 449.0 aa_intersection_event
112.0ms 1.3% 112.0 CGSColorMaskCopyARGB8888
73.0ms 0.8% 73.0 objc::DenseMap, objc::DenseMapInfo >::LookupBucketFor(objc_object* const&, std::pair*&) const
69.0ms 0.8% 69.0 CGSFillDRAM8by1
66.0ms 0.7% 66.0 ml_set_interrupts_enabled
46.0ms 0.5% 46.0 objc_msgSend
42.0ms 0.5% 42.0 floor
29.0ms 0.3% 29.0 aa_ael_insert
Насколько я понимаю, это должно быть намного быстрее на iOS, просто потому, что код нативный... Итак, знаете ли вы:
Большое спасибо!