SceneKit的厄运

SceneKit — 3Dграфики,которыйпоможетвомсоздаватьанимиреенныененные3D Онвключаетвсебяфизическийдвижок,генераторчастицинаборпростыхдействийдля3Dобъектов,которыепозволятвамописатьвашусценувтерминах контента – геометрии,материалов,освещения,камер – ианимироватьеёчерезописаниеизмененийдляэтих объектов

– 苹果

Сегоднямывнимательным,немногосуровымвзглядомпосмотримнаSceneKit,но,дляначала,обратимсякосновам,ипосмотрим,чтопредставляетизсебя3Dсцена,ичтонужносделать,чтобыеёсоздать。

Дляначала,нужносоздатьосновнуюструктурусцены,котораясостоитизнод,илиузловсцены。 Каждаянодаможетсодержатьвсебекакгеометрию,такидругиеноды。 Геометрияможетбытьпростой,вродешара,куба,илипирамиды,такиболеесложной,созданнойво。

Затем,дляэтойгеометриинеобходимозадатьматериалы,которыебудутопределятьбазовоепредставла。 Каждыйматериалсамзадаётсвоюмодельосвещения,и,взависимостиотнеё,используотвазличный。 Каждоетакоесвойствообычнопредставляетизсебяцветилитекстуру,но,помимоэтихчастоиспользуемыхвариантов,естьещёвозможностьиспользовать的CALayer,AVPlayer,иSKScene。

Послеэтого,необходимодобавитьисточникиосвещения,которыеопределяютто,насколькоооо Они,поаналогиисгеометрией,должнылежатьвнутрикакой-нибудьноды。 SceneKit是Поддерживаетмногоразныхтиповосвещения或такженескольковидовтеней的产品。

Затемнужносоздатькамеру(иположитьеёвотдельнуюноду)изадатьдлянеёосновныепараметры。 Ихдовольномного,но,спомощьюнихможносоздаватькрутыеэффекты。 Изкоробкиподдержибокэ(илиэффектразмытия),HDRсадаптацией,свечение,SSAOиоооии。

И,наконец,SceneKit在3Dобъектов,которыепозволяюннетевель Такжесценкитподдерживаетдействия,JavaScript,ноэтотемадляотдельнойстатьи。

Помимографики,главнымифишкамиSceneKit’аявляютсягенераторчастиципродвинутыйфизическийдвижок,которыйпозволяетзадаватьреальныефизическиесвойствакакобычнымобъектам,такисчастицамизгенератора。

Провсеэтифишкинаписанобольшоеколичествотуториалов,которыерассказываютпронихвововоо。 Новпроцессеразработкимыэтивозможностипрактическинеиспользовали…

Однажды,янаписалмодельосвещениядля3D-игрлучшереальногосолнечногосвета,дающуюприемлемуюFPSнаNvidia的8800,ноярешилневыпускатьдвижоквсвет,таккакБогмнесимпатичен,иянехочупоказыватьегонекомпетентностьв этомвопросе

—ДжонКармак

Подробноеизучениемыначнемсдовольнопростойзадачи,котораявозникаетпрактическиувсех,работающихсоSceneKit’омдовольносерьёзно:какзагрузитьмодельсосложнойгеометриейиподключеннымиматериалами,освещением,даещеисанимациями?

Естьнесколькоспособов,ивсеониимеютсвоиплюсыиминусы:

  1. SCNScene(named)—получаетсценуизбандла;
  2. SCNScene(url:options 🙂 —загружаетсценупоurl;
  3. SCNScene(mdlAsset 🙂 —конвертируетсценуизразныхформатов;
  4. SCNReferenceNode(URL 🙂 —ленивозагружаетсцену。

Получаемсценуизбандла

Можновоспользоватьсяметодом:положитьнашумодель。

Ночтоделать,есливыхотитесамиконтролироватьобновлениемоделей,невыпускаяобнове Иливыхотитеподдержатьсозданныепользователямикартыимодели? Илидажевепростонехотитеувеличиватьразмерприложения,таккак3Dграфиканеявоеосевашей

Загружаемсценупоurl

МожноиспользоватьконструкторсценыизURL .scnфайла。 Этотспособподдерживаетзагрузкунетолькоизфайловойсистемы,ноиизсети,но,воониеном。 Плюс,впотребуетсязаранеесконвертироватьмодельвформатscn。 Можно,конечно,использоватьиdae,носнимприходитнаборограничений,например,отсутствие基于物理渲染。

Главныйплюсэтогоспособа— —онпозволяетгибконастраиватьпараметрыимпорта。 Можно,например,модифициров​​атьжизненныйцикланимаций,изаставитьихбесконечноповторяться。 Можноявноуказатьместо,откудазагружатьвнешниересурсы,вродетекстур,можноконвертироватьориентациюимасштабсцены,создаватьотсутствующиенормалидлягеометрии,смержитьвсюгеометриюсценыводнубольшуюноду,илиотброситьвсенесоответствующиестандартуформатаэлементысцены。

Конвертируемсценуизразныхформатов

Третийвариант—和MDLAsset关联。 Тоесть,сначаламысоздаемMDLAsset,доступныйвфреймворкеModelIO,изатемпередаёмеговконструктордля。

хтотвариантхороштем,чтоумеетзагружатьмногоразличныхформатов。 ОфициальноMDLAssetумеетзагружатьOBJ,帘布层,STLиUSDформаты,но,прогнавсписоквсехвозможныхформатовхотькак-тосвязанныхскомпьютернойграфикой,янашёлеще4:ABC,BSP,VOXиMD3,ноонимогутподдерживатьсянеполностьюилине вовсехсистемах,идлянихнужнопроверятькорректностьимпорта。

Также,нужноучитывать,чтоэтотметодимеетоверхеднаконвертацию,такчтоегонужоокуниспользов。

在SCNScene中,或在SCNNode上。 Иединственныйспособдобавитьконтентвужесуществующуюсцену – скопироватьвседочерниеноды,и,чтоможнолегкопропустить,анимацииизкорневойноды(Они,например,могутпоявитьсята​​мприработесDAE)。 Ктомуже,нужноучитывать,чтовсценетекстураокруженияможетбытьтолькоодна(елеве

Ленивозагружаемсцену

—етвертыйвариант— SCNReferenceNode。 Онвозвращаетнесцену,аноду,котораяможетсамалениво(илипо-запросу)загружитевсебявсю。 Такимобразом,этотспособаналогиченпервому,ноонскрываетвнутрисебявсепроблемыскопирова。

Унегоестьодноно:онтеряетглобальныепараметрысцены。

Получается,этосамыйпростойибыстрыйспособзагрузитьвашумодельку,но,есливамнуженфайн-т

Витогемыостановилисьнапервомварианте,таккакнамбылоудобнеевсегоработатьвформате.scn,адизайнерам – конвертироватьвнегоизформатаDAE,инампонадобилсяфайн-тюнинганимацийпризагрузке。

Вовсенепреждевременныеоптимизации

Поработавсэтимпроцессомдостаточнодолго,ямогудатьвамнесколькосоветов:

Самыйглавныйсовет – конвертируйтефайлывSCNзаранее,тогдавысможете,открывфайлвовстроенномв的Xcodeредакторесцен,увидетькакименнобудетвыглядетьвашобъектвSceneKit’е。

。 Длятогожеdaeнужносачалараспарситьxml,потомсконвертироватьвеемеши,анимациииматериалы。

Темболее,чтоконвертацияанимацийиматериалов—потенциальныйисточникпроблем。 ВспоминаемотсутствиеподдержкиPBRвDAE:пол​​учается,есливыхотитеегоиспользовать,вамприйдётсяпослеконвертациисменитьтипвсехматериаловивручнуюпроставитьсоответствующиетекстуры。

Приэтойоперацииможнополучитьоченьполезныйсайдэффект:значительноесжатиетекстур。 Дляэтогооткройтеихв«просмотре»иэкспортируйте,сменивформатна.heic。 Всреднем,этапростаяоперациясэкономилапо5мегабайтнамодель。

Также,есливыскачиваетесценуизинтернета,могупосоветоватьзагружатьсценувае Этосэкономитвипользователюлишниемегабайты,чтоускоритзагрузку,атакженомоттель Согласитесь,накаждыйресурсделатьотдельныйзапрос,

Когдаяедунамашине,ячастослышу,какпотрескиваетжёсткийдискВселенной和подгружаяследуюуую。

—ДжонКармак

西班牙 Иужповерьте,здесьестьочемрассказать。 SceneKit’е中的Начнеммыстого,чтопройдёмсяпоразличнымконстрейнтам。

Констрейнтам,скажетевы? Какимконстрейнтам? Именнотак。 Малоктознает,атемболееирассказываетобэтом和SceneKit’еестьсвойнаборконстрейнтов。 Ихотяонинетакиегибкие,UIKit’екакконстрейнты,спомощьюнихвсёравноможноможносделатьнногои。

Начнёмспростогоконстрейнта— SCNReplicatorConstraint。 Всё,чтоонделает—этодублируетпозицию,поворотиразмердругогообъектаcдополнительнымиоф。 Какиувсехостальныхконстрейнтов,унегоможноменятьсилу,ивыставлятьфлагинкрементальности,илучшевсегоэтипараметрыможнопоказатьнаэтомконстрейнте。

Силавлияетнато,скакимкоэффициентомтрансформацияприменяетсякобъекту。 Иразположениеобъекта-целименяетсякаждыйкадр – шадоуобъектприближаетсякнемунаоднудесятуюотразницырасстояний,ииз-заэтогопоявляетсяэффектзапаздывания。

Инкрементальностьжевлияетнато,отменяетсяликонстрейнтпослерендеринга。 Еслиеговыключить-тооннакаждомкад​​реконестрейнтприменяетсяпередрендерингом, Врезультате,комбинируяэтидвапараметраможнополучитьдовольноинтересныйэффектстрелкичасов

Перейдёмкболееинтересномуконстрейнту:такназываемомубиллборду。

Допустим,необходимо,чтобынекоторыйобъектвсегданаходилсякнам«лицом»。 Дляэтого,нужновсеголишьиспользоватьSCNBillboardConstraint,иуказать,вокругкакихосейобъектможетповорачиваться,и,дальше,передпросчётомкаждогокадра(послешагасфизикой)позициииориентациивсехобъектовбудутобновляться,чтобыудовлетворитьвсемконстрейнтам。

Тутжеможноупомянуть看约束:онаналогиченBillboard’у,тольковместотекущейкамеры,объектможно

Чтоможносделатьсихпомощью? Чащевсего,конечноже,этиконстрейнтыприменяютсядлярисованиядеревьев,илимелкихобъектов。 Такжесихпомощьюсоедеффекты,

SCNDistanceConstraintпозволяетзадатьминимальноеи/илимаксимальноерасстояниедопозициидругогообъекта。 Ида,сегопомощьюможносделатьзмейку:)Этотконстрейнттожеможноиспользоватьдляпривязкикамерыкперсонажу,хотя,положениекамерыобычнозадаётсяболеесложно,иоднимиконстрейнтамиегосложноописать。 Тотжеэффектможнодостичьзасчётдобавленияпружинывфизическомдвижке,ноэтупружинуможнодополнитьконстрейнтомнаслучай,еслинужноизбежатьпроблемсизлишнимрастягиванием/сжатиемпружины。

Многиевидели,каквкаком-нибудьHitman’е,Fallout’еилиSkyrim’е,бываеттакое,чтотытащишьтелозасобой,ионозадеваетпрепятствие,ителовнезапноначинаетвестисебякакбудтовнеговселилсядемон。 Таквот,этотконстрейнтпомогбыизбежатьтакихбагов。

SCNSliderConstraintпозволяетзадатьминимальноерасстояниемеждузаданнымобъектомифизическимоисева Довольнозабавныйконстрейнт,но,опятьже,егостараютсясимулироватьспомощьюфизическоговзаим。 Основнаяидея—задатьрадиусмертвойзонысфизическимителамидляобъекта,которыйнеиеетфиз。

SCNIK约束。 Самыйинтересный,ноисамыйсложныйконстрейнт,которыйиспользуеттакназываемуюинверснуюкинематику,котораяитеративнопытаетсяприблизитьположениеноды,ккоторомувыприменяетеэтотконстрейнткнеобходимойточке,используяцепочкуродительскихузлов。 Посути,онпозволяетнедуматьотом,вкакомположениидолжнынаходитьсяплечоипредплечье,апростозадатьположениекистирукиивозможныеуглыповоротасвязующихузлов,аостальноепосчитаетсязавас。 Основнойнедостатокэтогоконстрейнта – онпозволяетлишьзадатьположениекистируки,нонееёориентацию,даиограничениянауглыможноделатьглобальное,безразбивкипоосям。

Итак,мыподробнопознакомилисьсконстрейнтами,ичтоониумеютделать。 Давайтепродолжимизтчининтересныеэффекты,以及разберемсясэффектомтеней。

Казалосьбы,чтоможетбытьпрощевдвижке,которыйподдерживаеттени,чемсозданиетеней? Но,иногда,тенинужноотброситьнаполностьюпрозрачнуюплоскость。 Kitтооченьполезно或ARKit’е,таккакзаплоскостьюотображаетсяизображениекамеры,атеньоотеньдолезно。 Трюкоказываетсядовольнопрост:нужносначалавключитьотложенныетенииотключитьзаписьвовсекомпонентыуплоскостивовкладкематериала,итеньпродолжитнакладыватьсянанеё。 Единственнаяпроблема—этаплоскостьбудетперекрыватьобъектынаходящиесязаней。

Нотени—неединственныйслабоизученныйэффектвсценките。 Давайтетеперьразберемсясзеркалами。

Все,ктоигралсясосценкитом,наверняказнаютоscnfloor,которыйдобавляетзеркальныеотражениядл。 Но,почему-то,оченьмалоктоиспользуетегодлячестныхзеркальныхотражений,ведьнадгеометриейполаможноположитьсвоюмодельку,немногонаклонить,ипревратитьего…вобычноезеркало。

Но,чтоещёменееизвестно – дляэтогополаможновыставитькартунормалей,и,засчётэтого,можносоздатьмногоразныхинтересныхэффектов,вродеэффектапотёков,иликривогозеркала。

Однаждыяцеловалсясдевушкойсоткрытымиглазами。 Ближнейплоскостьюотсечениядевушкерассеклолицо。 Стехпоряцелуюсьтолькосзакрытымиглазами。

—ДжонКармак

Тени,зеркала—интересныеэффекты。 Ноестьодинэффект,который,приумеломиспользовании,можетоказатьсяещёболееинтересным—виде

Онимогутвтонт,нт,чтогораддине Дляэтого,вамнужноположитьвидеотекстурускартойвысотвсвойство位移вашегоматериалаииспользоватьматериалнаплоскостисдостаточнобольшимколичествомсегментов。 Осталосьпонять,какжееётудаположить。

Яупоминалвописаниипроцессасозданиясцены,чтовкачествесвойстваматериалавыможетеиспользоватьSKScene,аэто – SpriteKit’оваясцена(SpriteKit – этокакSceneKit,нодля2Dграфики)。 使用SKVideoNode进行操作。 Всё,чтовамнужносделать—从SKVideoNode到SKScene,再到SKScene到SCNMaterialProperty,再到вссготово。

Но,экспортировавполученнуу3Dсценуиоткрывеёгде-нибудьеме,мыувидимчерныйквадрат。 Покопавшисьв.scnфайле,янашёлпричину。 Оказывается,присохранениивидеоноданесохраняетurlвидео。 Казалосьбы,берешьиправишь。 Ноневсётакпросто:.scnфайлпредставляетизсебятакназываемый二进制plist,由которомлежитрезультат密钥。 Иматериал,которыйявляетсяSpriteKit’овойсценой,представляетизсебятакой二进制plist,который,получее Хорошо,чтоуровнявложенностивсегодва。

Нуатеперьмыперейдёмдаженекэффекту,акинструменту,которыйпозволитвамсоддтткакие

Итак,передтем,какчто-томодифициров​​ать,надопонять,чтоименномымодифицируем。 GPUейдер,поопределению,этопрограммадляGPU,котораяпрогоняетсядлякаждойвершиныилликаждог。 Такимобразомшейдер—этопрограмма,котораяопределяет,каквыглядитобъектнаэкране。

ШейдермодификаторыжепозволяютменятьрезультатыработыстандартныхшейдеровнаGLSLили金属着色语言,и,которые,ктомуже,доступныввизуальномредакторе,чтопозволяетвидетьвидетьизменениявмодификаторевреальномвремени。

Спомощьюнихможносоздаватьсложнейшиевизуальныеэффекты。 Вот,например,парочкасамыхизвестныхэффектов:мехипараллаксмэппинг。

,тоещёинтереснее,никтонемешаетполностьювыкинутьрезультатыихработы,инаписатьсвойренд。 Например,МожнопопробоватьреализоватьRay Castingвшейдерах。 Ивсёэтоработаетдостаточнобыстро,чтобыобеспечить每秒30 fps。 Ноэтотемадляотдельногодоклада。 ПриходитенаMobius!

тнелюблюморгать,т。 к。 在BDPT上使用GPU或BDPT进行图形处理。

—ДжонКармак

Итак,您在кучаобъектовскласснымиэффектами。 Теперьосталосьнаучитьсяихзаписывать。 Дляэтогоперейдёмкболеесложнойтеме:какмынаучилисьзаписыватьвидеонапрямуюизSceneKit’aбезвнешнегоUI,икакмыоптимизировалиэтузаписьвдесяткираз。

Давайтесначалаобратимсяксамомупростомурешению:ReplayKit,ивыясним,почемуононеподходит。 Вообщеговоря,эторешениепозволяетвнесколькостроккодасоздатьзаписьэкрана,иссохранитье Но。 Унегоестьбольшойминус—在UI中,在UI中,在кнопкинаэкране中。 Этобылопервоенашерешение,но,поочевиднымпричинам,еговпродакшнпускатьбылонельзя,таккакэтимвидеодолжныбылиделитьсяпользователи,иделитьсянессистемногопревью。

Итак,мыоказалисьвситуации,когдарешениенужнобылонаписатьснуля。 Совсемснуля。 Итак,давайтепосмотрим,какимобразомвайосможносоздатьсвоёвидео,изаписатьтудасвоик。 Всёдовольнопросто:

Нужносоздатьсущность,котораябудетзаписыватьфайлы – AVAssetWriter,добавитьвнеёвидеопоток – AVAssetWriterInput,исоздатьдляэтогопотокаадаптер,которыйбудетконвертироватьнашпиксельбуфервнеобходимыйпотокуформат – AVAssetWriterPixelBufferAdaptor。

Навсякийслучайнапоминаю,чтопиксельбуффер – этосущность,котораяпредставляетсобойкусокпамяти,вкоторомкаким-тообразомзаписаныданныедляпикселей。 Посути—низкоуровневоепредставлениекартинки。

Но…Какполучитьэтотпиксельбуффер? Решениепростое—在SCNViewестьзамечательнаяфункция.snapshot(),котораявозвращатUIImage,иметеление

Теперьнужноэтоделатькаждыйкадр。 Дляэтогомысоздаеёмдисплейлинк,которыйбудетнакаждыйкадрвызыватьколлбек,вкотороммыибудемвызыватьметод快照,исоздаватьизкартинкипиксельбуффер。 Всёпросто!

Авотинет。 Такоерешениедаженамощныхтелефонахвызываетжуткиелагиипросадкифпс。 Давайтезаймёмсяоптимизацией。

Допустим,намненужно60фпс。 Идажемыбудемдовольны25.Нокакэтопрощевсегосделать? Конечно,простовынестивсёэтонафоновыйпоток,темболеечтопоутверждениямразраоооииков,

Хм,лагатьсталоменьше,новидеопересталозаписываться…

Всёпросто。 Какговорится,еслиутебяестьпроблема,итыеёбудешьрешатьприпомощинесколькихооетое

Еслипопытатьсязаписатьпиксельбуферстаймстемпом,нижечемупоследнегозаписанноое-товсёв

Давайтетогданезаписыватьновыйбуфердотехпор,покапредыдущаязаписьнезакончится。

Хм,сталозначительнолучше。 Новсёравно,почемулагипоявилисьизначально?

Оказывается,функция.snapshot(),спомощьюкотороймыполучаемизображениесэкрана,накаждыйвызовсоздаётновыйрендерер,рисуеткадрснуля,ивозвращаетего,анетоизображение,котороеприсутствуетнаэкране。 Этоприводиткзабавнымэффектам,например,физическаясимуляцияпроисходитв2разабыстрее。

Нопогодите。 Зачеммыкаждыйразпытаемсяотрендеритьновыйкадр? Наверняка,где-томожнонайтитотбуфер,которыйвыводитсянаэкран。 Идействительно,доступктакомубуферуесть,ноонвесьманетривиален,идляэтогонамнужнеининининининиетель。

Ксожалению,напрямуюизSCNViewдобратьсядоMetal’анетакпросто,подовольнопростойпричине – вSceneKit’етипAPIможновыбратьсамому,ноеслизаглянутьподкапотипосмотретьна层,томожноувидеть,чтовкачественеговыступает, Metal’ом,— CAMetalLayer。

Ноитутнасждётнеудача:在CAMetalLayer中 Подразумевается,чтовывнегозапишетеданные,ивызоветеунегофункцию当前,котораяиотобразит。

Решение,насамомделе,существует。 Деловтом,чтопослеисчезаниясэкрананедеаллоцируется,以及лишьпомещаетсяобратновпул。 Действительно,зачемкаждыйразвыделятьпамять,еслидостаточно2х-3хбуферов:один,которыйпоказаннаэкране,второйдлярендеринга,итретий,например,дляпостпроцессинга,еслионувасесть。

Получается,послеотображениябуфера,данныеизнегоникуданепропадают,икнимооноспооо

И,еслимывнаследникеначнёмнакаждыйвызовnextDrawable()сохранятьего,мыполучимпочтито,чтонамнужн。 Проблемавтом,чтосохраненныйCAMetalDrawable —对的,是которыйпрямосейчасрисуетсяизображение。

Прыжоккреальномурешениюоченьпрост—мысохраняемитекущийдроуабл,ипредыдущий。

Ивотоно,готово,прямойдоступкпамятичерезCAMetalDrawable。

Чтоже,всеэтитрюкирадижутковатогофильтра?

Нуужнет! ВстатьепроARKitможнонайтиупоминаниетого,чтоизображениескамерыиспользуетнестандартноецветовоепространство,арасширенное,идажепредставиломатрицутрансформациицветовогопространства。 Нозачемзаниматьсятрансформацией,еслиможнопопробоватьзаписатьпрямовэтомформате。 Осталосьузнать—какойэтоформатиз60доступных…

Итутязанялсяперебором,изаписывалпо3видеовразныепотокисразнымиформатамисменяии。

Врезультате,примернонасороковомформатемыполучаемегоназвание。 Оказывается,этониктоиной,какkCVPixelFormatType_30RGBLEPackedWideGamut。 Какжеядоэтогонедогадался?

Номоярадостьпродолжаласьдопервоготестера。 Уменянебылослов。 Как? жжетолькочтопотратилкучувременинапоискправильногоформата。 Хорошо,чтопроблемалокализоваласьбыстро—图库照片6sи6s plus。 Практическисразупослеэвспомнил,чтодисплеисподдержкой广色域началиставитьтолькос7х。

ПоменявWideGamut在32RGBA和получаюработающуюзапись! Осталосьпонять,какопределять,чтодевайсподдерживает宽色域,таккакбываютещеайпадысразличнымивидамидисплея,ияподумал,чтонавернякаможноизсистемыдостатьэнамтипадисплея。 Покопавшисьвдокументациияегонашёл—在displayGamut或UITraitCollection’е中。

Отдавсборкутестерам,яполучилотнихприятныеновости—矢量图片ваникакакихлиболабелдажена

Вкачествезаключения,хочетсявамсказать—занимайтесь3Dграфикой! Унасвприложении,длякоторогодополненнаяреальностьнеявляетсяосновнымкейсомиспользования,людизавыходныеднягородапрошлиболее2000километров,посмотрелиболее3тысячобъектов,изаписалиболее1000видеосними! Представьтесебе,чтовысможетесделать,еслизаймётесьэтимсами。