Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
SceneKit на практике
Search
CocoaHeads
September 29, 2018
Programming
150
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
SceneKit на практике
CocoaHeads
September 29, 2018
More Decks by CocoaHeads
See All by CocoaHeads
Тесты: Повторение. Виктор Суриков
cocoaheads
0
110
Sign In with Apple (client + server). Петр Третьяков
cocoaheads
0
320
Эволюция антипаттернов в Java и Kotlin. Михаил Горюнов
cocoaheads
0
190
Рефакторинг в условиях быстрорастущего стартапа. Егор Фесенко
cocoaheads
0
80
Make Experiments Great Again, или Как iOS Браузер А/Б тестирование улучшал
cocoaheads
0
140
Лотерея в приложении: отрисовка, анимация и никакого мошенничества
cocoaheads
0
120
Микроинтеракции в iOS
cocoaheads
0
260
Пишем под iOS на Flutter
cocoaheads
0
170
Выходные с Kotlin/Native
cocoaheads
0
80
Other Decks in Programming
See All in Programming
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
200
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
0
100
cdk deploy JawsSonic #MARATHONしながらAWSリソースをデプロイしてみよう
akihisaikeda
2
130
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
330
AIを上手に使っていこうとしたら越境せざるを得なくなった話 〜実践1年で見えた境界を越えなければならない理由と進め方〜 / Crossing borders with AI
tomoyakitaura
4
1.1k
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
160
アクセシビリティから考える情報設計
high_g_engineer
0
370
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
170
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
390
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
190
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
3
540
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
150
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
699
190k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.3k
How to build a perfect <img>
jonoalderson
1
6k
So, you think you're a good person
axbom
PRO
2
2.2k
A Soul's Torment
seathinner
7
3.6k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
660
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
430
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
900
Claude Code のすすめ
schroneko
67
230k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.8k
Transcript
Вячеслав Гилевич, разработчик SceneKit на практике
None
› Загрузка моделей › Уменьшение размера ресурсов › Констрейнты ›
Зеркальные отражения › Видеотекстуры › Модификаторы шейдров › Запись видео SceneKit на практике 3
Немного про SceneKit
SceneKit — фреймворк для 3D сцен 5 Как создать сцену?
› Геометрия › Материалы › Освещение › Камеры › Анимация
SceneKit — фреймворк для 3D сцен. Кроме графики, в
нём есть: › Генератор частиц › Физический движок 6
Загрузка моделей в SceneKit
› Из бандла › По URL › Через MDLAsset ›
Через ReferenceNode Варианты загрузки 3D модели 8
SCNScene.init(url:options:) › Настраиваемый импорт › Поддерживает .scn и .dae файлы
› Синхронная загрузка › Необходимо копировать структуру из сцены в ноду URL + настройки импорта 9
SCNScene.init(mdlAsset:) › Загружает obj, ply, stl, usd, usda, usdc, usdz,
abc, bsp, vox, md3 › Синхронная загрузка › Необходимо копировать структуру сцены › Оверхед на конвертацию Используем MDLAsset 10
SCNReferenceNode.init(url:) › Поддерживает .scn и .dae файлы › Ленивая загрузка
› Теряет глобальные параметры сцены Используем SCNReferenceNode 11
› Конвертируйте в .scn заранее › Проверяйте сцену в Xcode
› Конвертируйте все ресурсы в .heic › Загружайте сцену с ассетами архивом Загрузка моделей: советы 12
Добавление эффектов: Констрейнты
› SCNBillboardConstraint › SCNLookAtConstraint › SCNDistanceConstraint › SCNAvoidOccluderConstraint › SCNSliderConstraint
› SCNReplicatorConstraint › SCNIKConstraint Констрейнты 14
Просто повторяет позицию, поворот и размер, и добавляет дополнительное оффсеты.
SCNReplicatorConstraint 15
Параметры констрейнтов 16 Стандартные параметры Уменьшили силу в 10 раз
Параметры констрейнтов 17 Стандартные параметры Уменьшили силу в 10 раз
и убрали инкрементальность
Используется для: › Деревьев вдалеке › Мелких объектов › Спецэффектов,
вроде огня или взрыва › Привязка камеры к персонажу SCNBillboardConstraint | SCNLookAtConstraint 18
SCNDistanceConstraint | SCNSliderConstraint 19 Держит дистанцию между выбранными объектами Держит
дистанцию до всех физических тел
› Inverse Kinematics из коробки › Нет возможности задать ориентацию
› Нет ограничений углов в зависимости от оси SCNIKConstraint 20
Добавление эффектов: Тени
Тени для ARKit’a: › Включи отложенные тени › Отключи запись
всех компонент Тени на прозрачной поверхности 22
Добавление эффектов: Зеркала
Как сделать? › SCNFloor › Своя модель поверх него Зеркальные
отражения 24
Зеркальные отражения с картой нормалей 25 Вода на зеркале Кривое
зеркало
Добавление эффектов: Видеотекстуры
Как сделать? › SKScene › SKVideoNode › SCNMaterialProperty Видеотекстуры 27
Как заставить работать? › Поправить Binary Plist › Внутри Binary
Plist’а › Внутри другуго Binary Plist’а Видеотекстуры: сохранение 28
Добавление эффектов: Shader Modifiers
› Доступны в визуальном редакторе › Поддерживают glsl и metal
shading language › Доступны результаты работы стандартных шейдеров Shader Modifiers 30
Мех и Parallax Mapping 31 Мех Parallax Mapping
Ray Casting 32
Запись видео
Запись видео 34 На девайсе Записывается
Запись видео: ReplayKit 35 RPScreenRecorder.shared() Начать запись: Закончить запись: RPScreenRecorder.shared()
func startRecording() func stopRecording(callback:)
› Работает в пару строк кода › Нельзя записывать конкретную
вьюху › Неудобный стандартный превью Запись видео: ReplayKit 36
Запись видео: основы 37 AVAssetWriter Процесс записи: Закончить запись: AVAssetWriterInput
func appendPixelBuffer(…) func markAsFinished() AVAssetWriterInput AVAssetWriterInputPixelBufferAdaptor AVAssetWriter func finishWriting()
UIImage → CVPixelBuffer 38 var pixelBuffer: CVPixelBuffer? = nil guard
CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA , nil, &pixelBuffer) == kCVReturnSuccess else { return } CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags.init(rawValue: 0)) let data = CVPixelBufferGetBaseAddress(pixelBuffer!) let rgbColorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGBitmapInfo(rawValue: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue) let context = CGContext(data: data, width: width, height: height, bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: bitmapInfo.rawValue) context?.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height)) CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
UIImage → CVPixelBuffer 39 CVPixelBufferCreate(… width:height:pixelFormat: …) CVPixelBufferLockBaseAddress(_ pixelBuffer:) CVPixelBufferGetBaseAddress(_
pixelBuffer:) CGContext(data: ... bitsPerComponent: bytesPerRow:… colorSpace: ...) CVPixelBufferUnlockBaseAddress(_ pixelBuffer:) func draw(image: UIImage)
Теперь нужно это делать каждый кадр 40 CADisplayLink(target:selector) Начать запись:
Закончить запись: func add(to:forModes:) func invalidate()
Производительность 41
Оптимизации: раунд 1! 42 DispatchQueue.global() func async(execute:)
Оптимизации: раунд 1! 43
Оптимизации: раунд 1.5! 44 DispatchQueue.global() func async(execute:) guard isRecording else
{ return } isRecording = true isRecording = false
Оптимизации: раунд 1.5! 45
Оптимизации: раунд 2! 46 Причина Следствие
Оптимизации: раунд 2! 47 ? CAMetalDrawable CAMetalLayer SCNView ? ✓
via backingLayer()
Пул CAMetalLayer’а 48 Drawable 0 Drawable 1 Drawable 2 Drawable
3 func present()
Оптимизации: раунд 2! 49 ✓ via nextDrawable() CAMetalDrawable CAMetalLayer SCNView
✓ via backingLayer() ?
Оптимизации: раунд 2! 50 CVPixelBufferCreate(… width:height:pixelFormat: …) CVPixelBufferLockBaseAddress(_ pixelBuffer:) CVPixelBufferGetBaseAddress(_
pixelBuffer:) CGContext(data: ... bitsPerComponent: bytesPerRow:… colorSpace: ...) CVPixelBufferUnlockBaseAddress(_ pixelBuffer:) func draw(image: UIImage) CAMetalDrawable var texture: MTLTexture func getBytes(data: …)
Оптимизации, раунд 3? 51
Оптимизации, раунд 3! 52
Оптимизации, раунд 3! 53
Оптимизации, раунд 3! 54
Оптимизации, раунд 3! 55
Оптимизации, раунд 3! 56
Оптимизации, раунд 3! 57
› Загрузка моделей › Уменьшение размера ресурсов › Констрейнты ›
Зеркальные отражения › Видеотекстуры › Модификаторы шейдров › Запись видео SceneKit на практике 58
За выходные дня города: › Пройдено > 2000 км ›
Показано > 3000 объектов › Записано > 1000 видео Немного статистики 59
Подписывайтесь на наш блог! https://medium.com/yandex-maps-ios/