Производительность комплекта сцен с тестом куба

Изучая программирование трехмерной графики для игр, я решил начать с простого, используя Scene Kit 3D API. Моей первой игровой целью было создать очень упрощенную мимику MineCraft. Игра только в кубики - как это может быть сложно.

Ниже приведен цикл, который я написал, чтобы разместить 100 кубов (10000), и производительность FPS была ужасной (~ 20 кадров в секунду). Является ли моя первоначальная игровая цель слишком большой для Scene Kit или есть лучший способ приблизиться к этому?

Я читал другие темы на StackExchange, но не чувствую, что они отвечают на мой вопрос. Преобразование открытых блоков поверхности в одну сетку не будет работать, так как SCNGeometry является неизменным.

func createBoxArray(scene : SCNScene, lengthCount: Int, depthCount: Int) {
    let startX : CGFloat = -(CGFloat(lengthCount) * CUBE_SIZE) + (CGFloat(lengthCount) * CUBE_MARGIN) / 2.0
    let startY : CGFloat = 0.0
    let startZ : CGFloat = -(CGFloat(lengthCount) * CUBE_SIZE) + (CGFloat(lengthCount) * CUBE_MARGIN) / 2.0

    var currentZ : CGFloat = startZ

    for z in 0 ..< depthCount {
        currentZ += CUBE_SIZE + CUBE_MARGIN

        var currentX = startX
        for x in 0 ..< lengthCount {
            currentX += CUBE_SIZE + CUBE_MARGIN

            createBox(scene, x: currentX, y: startY, z: currentZ)
        }
    }
}


func createBox(scene : SCNScene, x: CGFloat, y: CGFloat, z: CGFloat) {
    var box = SCNBox(width: CUBE_SIZE, height: CUBE_SIZE, length: CUBE_SIZE, chamferRadius: 0.0)
    box.firstMaterial?.diffuse.contents = NSColor.purpleColor()

    var boxNode = SCNNode(geometry: box)
    boxNode.position = SCNVector3Make(x, y, z)
    scene.rootNode.addChildNode(boxNode)
}

ОБНОВЛЕНИЕ 12-30-2014: Я изменил код так, что SCNBoxNode создается один раз, а затем каждый дополнительный блок в массиве 100 x 100 создается с помощью:

var newBoxNode = firstBoxNode.clone()
newBoxNode.position = SCNVector3Make(x, y, z)

Это изменение, похоже, увеличило FPS до ~ 30 кадров в секунду. Другие статистические данные следующие (из статистики, отображаемой в SCNView):

10K (я предполагаю, что это вызовы отрисовки?) 120K (я предполагаю, что это лица) 360K (при условии, что это число вершин)

Большая часть цикла выполнения находится в рендеринге (я предполагаю, 98%). Общее время цикла составляет 26,7 мс (ой). Я работаю на Mac Pro Late 2013 (6-ядерный с Dual D500 GPU).

Учитывая, что игра в стиле MineCraft имеет ландшафт, который постоянно меняется в зависимости от действий игроков, я не понимаю, как я могу оптимизировать это в рамках Scene Kit. Большое разочарование, так как мне очень нравятся рамки. Я хотел бы услышать чьи-то идеи о том, как я могу решить эту проблему - без этого я вынужден пойти с OpenGL.

ОБНОВЛЕНИЕ 12-30-2014 @ 2:00 вечера ET: Я вижу значительное улучшение производительности при использовании flateredClone (). FPS теперь составляет 60 кадров в секунду даже с большим количеством ящиков и ДВУХ вызовов. Однако адаптация динамической среды (как поддерживает MineCraft) по-прежнему проблематична - см. Ниже.

Поскольку массив со временем меняет состав, я добавил обработчик keyDown, чтобы добавить еще больший массив ящиков к существующему, и рассчитал разницу между добавлением массива ящиков, что привело к гораздо большему количеству вызовов по сравнению с добавлением в виде flatlinedClone. Вот что я нашел:

На keyDown я добавляю еще один массив размером 120 x 120 (14 400 ящиков)

// This took .0070333 milliseconds
scene?.rootNode.addChildNode(boxArrayNode)
// This took .02896785 milliseconds
scene?.rootNode.addChildNode(boxArrayNode.flattenedClone())

Повторный вызов flatenedClone () в 4 раза медленнее, чем добавление массива.

Это приводит к двум вызовам рисования, имеющим 293 тыс. Граней и 878 тыс. Вершин. Я все еще играю с этим и буду обновлять, если найду что-нибудь новое. В итоге, с моим дополнительным тестированием я все еще чувствую неизменные геометрические ограничения Scene Kit, означающие, что я не могу использовать каркас.

Ответы на вопрос(1)

Ваш ответ на вопрос