2016-09-28 7 views
1

Это, пожалуй, самая сумасшедшая техническая проблема, и у меня нет большой надежды получить решение, но я все равно попробую. Может быть, у кого-то может быть предложение, которое я мог бы попробовать, хотя, возможно, и не объяснял причину проблемы, все равно мог ее решить.Форма вершинного шейдера SceneKit не обновляется должным образом при использовании пульта AppleTV

У меня есть игра SpriteKit, которую я разрабатываю для tvOS (Xcode 8.0, Mac OS 10.12), и у меня есть SK3DNode, который имеет треугольную сетку, которая использует вершинный шейдер для перемещения вершин вокруг.

Вершинный шейдер имеет пару форматов mat4 (хотя это не имеет большого значения, проблема возникает, даже если я использую, например, униформу vec4), которую я использую для передачи данных из моего кода в шейдер, из метода обновления текущего SKScene. Для этого я использую [SCNMaterial setValue: forKeyPath:] материала треугольной сетки.

Это работает хорошо и гладко, за исключением случаев, когда происходит одно: когда я использую сенсорную панель пульта AppleTV, обновление этих мундиров сильно задерживается (например, может быть до полусекундной задержки между обновлениями).

Обратите внимание, что я не сказал, что игра отстает. Или что даже рендеринг треугольной сетки или вершинного шейдера или метода обновления SKScene отстает. Это буквально и явно обновление новых ценностей для тех конкретных униформ, которые отстают, и ничего другого. И только и явным образом, когда я использую сенсорную панель пульта AppleTV.

Да, проблема абсолютно безумная. Чтобы понять, почему это абсолютно безумен, обратите внимание, что:

  • Я не сделал дополнительно убедиться, что запаздывает только обновляет значения своих мундиров, и ничего другого. Например, если в дополнение к их использованию я добавляю некоторое перемещение к вершинам в вершинном шейдере, используя унифицированную u_time в системе, которая работает просто отлично. (Другими словами, униформа u_time обновляется только штрафом, 60 раз в секунду, но моя форма макса не является, что приводит к тому, что движение, рассчитанное из u_time, будет полностью гладким, в то время как дополнительное перемещение из моей формы поверх этого действительно отстает .) Точно так же ничего не происходит на экране.

  • Да, метод обновления, в котором я устанавливаю значения этих униформ, вызывается 60 раз в секунду. Я проверил это, используя часы системы. Здесь нет задержек. Это не похоже на то, что система пропускает вызов моей функции обновления, и это вызывает проблему. Он называется 60 раз в секунду, и я обновляю униформу (используя [SCNMaterial setValue: forKeyPath:]) каждый раз. Я проверил это полностью.

  • И это не просто несколько пропущенных кадров здесь и там. Как говорилось ранее, мы говорим о задержках на полсекунды и даже больше, в худшем случае; и часто неоднократно при этом. (Обновленные значения ускоряются в эквивалентной сумме, когда они, наконец, попадают к самому шейдеру.)

  • И да, это происходит, только когда я использую трекпад пульта AppleTV. (Я не уверен, что это происходит при использовании его кнопок.Это может быть, но физически невозможно нажимать их достаточно быстро, чтобы это могло иметь эффект. Скольжение по трекпаду вызывает непрерывный поток ввода в систему, и это когда это произойдет.) Если я не использую трекпад, униформа обновляется красиво 60 раз в секунду, а движения вершин гладкие.

  • Проблема не возникает с геймпадом. Несмотря на то, что аналоговый джойстик геймпада создает аналогичный поток ввода, он, похоже, не вызывает такого же эффекта.

Я подозреваю, что, так или иначе, SCNMaterial не обновляется мундиров с ценностями, которые он получает от своего SetValue: forKeyPath: метод, когда что-то происходит с сенсорной панелью пульта. У меня нет ни малейшего понятия, что и почему, и это совершенно безумная проблема.

Конечно, проблема в том, что, поскольку игра управляется с помощью пульта дистанционного управления, это делает его в основном непригодным для использования. Вершинный шейдер просто не работает должным образом. Измените направления с трекпадом, и искажение сетки начнет отставать, как сумасшедшее. Это непригодно. И я понятия не имею, почему это происходит, или как это исправить.

+0

Во-первых, это звучит как классный эффект, деформация треугольника как часть игрового процесса. Вид как современный Qix. Или что-то, я думаю. Во-вторых, можете ли вы построить его для iPad или iPhone и проведите пальцем и посмотрите, есть ли проблема и там ... в этом случае это что-то в «touchhesMoved». В-третьих, попробовали ли вы установить пульт в качестве геймпада через GCMicroGamepad, чтобы он работал как устройство с геймпад-иш? В-четвертых, вы можете показать видео? – Confused

ответ

0

Я подозреваю, что runloop потока рендеринга SpriteKit работает «медленно», когда возникает ваша проблема. Для того, чтобы убедиться, что изменения SceneKit совершаются «как можно скорее» к визуализации дерева, вы можете обернуть изменения внутри явной транзакции:

[SCNTransaction begin]; 
[SCNTransaction setAnimationDuration:0]; 

// your changes 

[SCNTransaction commit]; 

Обратите внимание, что делать это не нужно, когда вы пишете «SceneKit» приложение и обращаясь непосредственно к обратным вызовам SceneKit. Поскольку SceneKit обязательно зафиксирует ваши изменения в конце обратных вызовов SceneKit. Но здесь вы изменяете модель SceneKit из игрового цикла SpriteKit.

Однако стоит наложить ошибку.

+0

Это на самом деле работает! Я ранее пробовал SCNTransaction (поскольку он упоминался в документации для SCNShadable), но без setAnimationDuration. Тогда это не сработало. Однако эта настройка продолжительности анимации сделала все возможное. Я полагаю, что это что-то вроде kludge (потому что мы не просим систему запускать какую-либо анимацию), но если она работает, она работает. – Warp

 Смежные вопросы

  • Нет связанных вопросов^_^