Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SceneKitを使ってアプリのクオリティを劇的に上げる / Dramatically improve the quality of your apps with SceneKit

44f37c1fe3a6a56376bb41a338741355?s=47 ring
September 19, 2021

SceneKitを使ってアプリのクオリティを劇的に上げる / Dramatically improve the quality of your apps with SceneKit

SceneKitはUIViewやCALayerでは難しい3Dやパーティクルの表現を非常に簡単に使用できるフレームワークです。

「3Dモデルのレンダリングなどで使用するフレームワークだから私には関係ない」
「AR系のアプリ開発に携わっているわけではないので使用する機会はなさそう」

このように思っていませんか?

これは大きな間違いです。

SceneKitはUIKitと非常に親和性が高くUIKitにそのままViewとして統合できます。
そして何より、UIKitだけでは実現が難しいリッチな表現(アニメーション)がとても簡単に実装できるのです!

本トークでは「SceneKit × UIKitの導入事例を軸にアプリのクオリティを上げるtips」をご紹介します。

44f37c1fe3a6a56376bb41a338741355?s=128

ring

September 19, 2021
Tweet

Transcript

  1. 4DFOF,JUΛ࢖ͬͯΞϓϦͷΫΦϦςΟ Λܶతʹ্͛Δ J04%$+BQBO גࣜձࣾ;0;0ςΫϊϩδʔζ ;0;0ΞϓϦ෦J04νʔϜ Ϧʔμʔ ໊औ߂ฏ $PQZSJHIU˜;0;05FDIOPMPHJFT *OD

  2. © ZOZO Technologies, Inc. גࣜձࣾ;0;0ςΫϊϩδʔζ ;0;0ΞϓϦ෦J04νʔϜ Ϧʔμʔ ໊औ߂ฏ ೥݄c;0;0ςΫϊϩδʔζೖࣾ ೥݄c;0;0508/J04ΞϓϦ։ൃ

    ࠷ۙνʔϜϦʔμʔʹͳΓ·ͨ͠ɻ 2
  3. © ZOZO Technologies, Inc. IUUQT[P[PKQ 3 • ೔ຊ࠷େڃͷϑΝογϣϯ௨ൢαΠτ • 

    Ҏ্ͷγϣοϓɺ Ҏ্ͷϒϥϯυͷऔΓѻ͍ʢͱ΋ʹ೥ ݄຤࣌఺ʣ • ৗ࣌ສ఺Ҏ্ͷ঎඼ΞΠςϜ਺ͱຖ೔ฏۉ ఺Ҏ্ͷ৽ண঎඼Λ ܝࡌ • ίεϝઐ໳Ϟʔϧʮ;0;0$04.&ʯ΍ۺͷઐ໳Ϟʔϧ ʮ;0;04)0&4ʯɺϥάδϡΞϦʔˍσβΠφʔζκʔϯ ʮ;0;07*--"ʯΛల։ • ଈ೔഑ૹαʔϏε • ΪϑτϥοϐϯάαʔϏε • πέ෷͍ͳͲ
  4. © ZOZO Technologies, Inc. 4 ;0;0508/Ͱ࠷ۙങͬͨ΋ͷ

  5. © ZOZO Technologies, Inc. 5 ͜ͷηογϣϯͷओ୊

  6. © ZOZO Technologies, Inc. 6 4DFOF,JU͕ͲͷΑ͏ͳϑϨʔϜϫʔΫͳͷ͔ɺ ΞϓϦͷΫΦϦςΟΛ্͛ΔͨΊʹ4DFOF,JUͱ6*,JUͷซ༻ ʹΑ࣮ͬͯݱͰ͖Δදݱͱͦͷ࣮૷ྫ Λ͓࿩͠·͢ɻ

  7. © ZOZO Technologies, Inc. 7 ຊηογϣϯʹ͓͚ΔΞϓϦͷΫΦϦςΟ දݱͷ࣭ ΞϓϦͷදݱྗɾදݱͷ๛͔͞ ʹ

  8. © ZOZO Technologies, Inc. 8 ࠓ೔࿩͍ͨ͜͠ͱ ʁ 4DFOF,JUʷ6*,JUͷ දݱͱ࣮૷ྫ ʁ

    4DFOF,JUͬͯԿʁ ✖ 4DFOF,JUͱ6*,JUͷ਌࿨ੑ
  9. © ZOZO Technologies, Inc. 9 ݸਓ։ൃ͕޷͖͕ͩݸਓ։ൃͷΫΦϦςΟ͔Βൈ͚ग़͢͜ͱ͕ Ͱ͖ͣʹ೰ΜͰ͍ͨ ͍Δ Ϟνϕʔγϣϯ

  10. © ZOZO Technologies, Inc. 10 Ұͭͷख๏ͱͯ͠4DFOF,JU͕༗༻ͳͷͰ ಉ͡Α͏ʹ೰ΜͰ͍Δਓͷ͖͔͚ͬʹͳΕ͹خ͍͠ɻ Ϟνϕʔγϣϯ

  11. © ZOZO Technologies, Inc. 11 4DFOF,JUͬͯԿʁ $ ) " 1

    5 & 3  c   
  12. © ZOZO Technologies, Inc. $SFBUF%HBNFTBOEBEE%DPOUFOUUPBQQTVTJOHIJHIMFWFM TDFOFEFTDSJQUJPOT&BTJMZBEEBOJNBUJPOT QIZTJDTTJNVMBUJPO  QBSUJDMFFGGFDUT BOESFBMJTUJDQIZTJDBMMZCBTFESFOEFSJOH

    12 Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJU "QQMF%PDVNFOUBUJPO4DFOF,JU
  13. © ZOZO Technologies, Inc. ϋΠϨϕϧͳγʔϯهड़Λ༻͍ͯɺ%ήʔϜΛ࡞੒ͨ͠ΓɺΞϓϦʹ %ίϯςϯπΛ௥Ճ͢Δ͜ͱ͕Ͱ͖·͢ɻΞχϝʔγϣϯɺ෺ཧγ ϛϡϨʔγϣϯɺύʔςΟΫϧΤϑΣΫτɺϦΞϧͳ෺ཧϕʔεͷϨ ϯμϦϯάΛ؆୯ʹ௥ՃͰ͖·͢ɻ 13 Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJU

    "QQMF%PDVNFOUBUJPO4DFOF,JU
  14. © ZOZO Technologies, Inc. 4DFOF,JUDPNCJOFTBIJHIQFSGPSNBODFSFOEFSJOHFOHJOFXJUIBEFTDSJQUJWF"1*GPSJNQPSU  NBOJQVMBUJPO BOESFOEFSJOHPG%BTTFUT6OMJLFMPXFSMFWFM"1*TTVDIBT.FUBMBOE 0QFO(-UIBUSFRVJSFZPVUPJNQMFNFOUJOQSFDJTFEFUBJMUIFSFOEFSJOHBMHPSJUINTUIBU EJTQMBZBTDFOF

    4DFOF,JUSFRVJSFTPOMZEFTDSJQUJPOTPGZPVSTDFOF`TDPOUFOUTBOEUIF BDUJPOTPSBOJNBUJPOTZPVXBOUJUUPQFSGPSN 14 Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJU "QQMF%PDVNFOUBUJPO4DFOF,JU0WFSWJFX
  15. © ZOZO Technologies, Inc. 4DFOF,JU͸ɺߴੑೳͳϨϯμϦϯάΤϯδϯͱɺ%ΞηοτͷಡΈࠐΈɺૢ࡞ɺϨϯμϦϯ άͷͨΊͷهड़ࣜ"1*Λ૊Έ߹Θͤͨ΋ͷͰ͢ɻ.FUBM΍0QFO(-ͷΑ͏ͳ௿Ϩϕϧͷ"1*Ͱ ͸ɺγʔϯΛදࣔ͢ΔͨΊͷϨϯμϦϯάΞϧΰϦζϜΛৄࡉʹ࣮૷͢Δඞཁ͕͋Γ·͕͢ɺ 4DFOF,JUͰ͸ɺγʔϯͷίϯςϯπͱ࣮ߦ͍ͤͨ͞ΞΫγϣϯ΍ΞχϝʔγϣϯΛهड़͢Δ ͚ͩͰ0,Ͱ͢ɻ 15

    Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJU "QQMF%PDVNFOUBUJPO4DFOF,JU0WFSWJFX
  16. © ZOZO Technologies, Inc. 4DFOF,JU͸ɺߴੑೳͳϨϯμϦϯάΤϯδϯͱɺ%ΞηοτͷಡΈࠐΈɺૢ࡞ɺϨϯμϦϯ άͷͨΊͷهड़ࣜ"1*Λ૊Έ߹Θͤͨ΋ͷͰ͢ɻ.FUBM΍0QFO(-ͷΑ͏ͳ௿Ϩϕϧͷ"1*Ͱ ͸ɺγʔϯΛදࣔ͢ΔͨΊͷϨϯμϦϯάΞϧΰϦζϜΛৄࡉʹ࣮૷͢Δඞཁ͕͋Γ·͕͢ɺ 4DFOF,JUͰ͸ɺγʔϯͷίϯςϯπͱ࣮ߦ͍ͤͨ͞ΞΫγϣϯ΍ΞχϝʔγϣϯΛهड़͢Δ ͚ͩͰ0,Ͱ͢ɻ 16

    Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJU "QQMF%PDVNFOUBUJPO4DFOF,JU0WFSWJFX
  17. © ZOZO Technologies, Inc. 17 4DFOF,JUͱ͸ %ͷදݱΛ͢ΔͨΊͷϑϨʔϜϫʔΫ  ΞχϝʔγϣϯɺύʔςΟΫϧɺ෺ཧϨϯμϦϯά ͳͲ؆୯ʹ௥ՃՄೳ

     ίϯςϯπΛ௥Ճͯ͠ɺίʔυΛهड़͢Δ͚ͩͰ0, 
  18. © ZOZO Technologies, Inc. 18 %ίϯςϯπΛѻ͏ΞϓϦ։ൃ͸͍ͯ͠ͳ͍͠ ࢲʹ͸ؔ܎ͳͦ͞͏ͩͳ"

  19. © ZOZO Technologies, Inc. 19 %ίϯςϯπΛѻ͏ΞϓϦ։ൃ͸͍ͯ͠ͳ͍͠ ࢲʹ͸ؔ܎ͳͦ͞͏ͩͳ"

  20. © ZOZO Technologies, Inc. 20 4DFOF,JU͸ඇ%ܥͷΞϓϦͰ΋༗༻Ͱ͢#

  21. © ZOZO Technologies, Inc. 21 4DFOF,JUͱ6*,JUͷ਌࿨ੑ $ ) " 1

    5 & 3  c    ✖
  22. © ZOZO Technologies, Inc. 22 4DFOFͱ͸Կ͔ʁ

  23. © ZOZO Technologies, Inc. 23 4DFOF৔໘ ྫ͑͹ʮөըͷϥετγʔϯʯ

  24. © ZOZO Technologies, Inc. 24 4DFOFΛߏ੒͢Δཁૉ ͳͲ ͲΜͳਓɾ෺͕഑ஔ͞Ε͍ͯͨͷ͔ ໌Δ͍ͷ͔ɾ҉͍ͷ͔ ͲΜͳΞϯάϧͰඳࣸ͞Ε͍ͯΔ͔

    ͲͷΑ͏มԽɾҠಈ͕͋Δ͔
  25. © ZOZO Technologies, Inc. 25 4DFOFΛߏ੒͢Δཁૉ 4$/(FPNFUSZ 4$/-JHIU 4$/$BNFSB SCNActionɾSCNTransaction

    ͳͲ ͲΜͳਓɾ෺͕഑ஔ͞Ε͍ͯͨͷ͔ ໌Δ͍ͷ͔ɾ҉͍ͷ͔ ͲΜͳΞϯάϧͰඳࣸ͞Ε͍ͯΔ͔ ͲͷΑ͏มԽɾҠಈ͕͋Δ͔
  26. © ZOZO Technologies, Inc. 26 4DFOF,JUͰදݱՄೳ

  27. © ZOZO Technologies, Inc. 4$/7JFX 27 4DFOFΛߏ੒͢Δཁૉ ɾɾɾ 4$/(FPNFUSZ 4$/-JHIU

    4$/$BNFSB SCNActionɾSCNTransaction 4DFOFΛߏ੒͢Δཁૉ͸ 4$/7JFXͱ͍͏6*7JFXͷαϒΫϥε ্ͰऔΓѻ͏  1 0 * / 5
  28. © ZOZO Technologies, Inc. 28 Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJUTDOWJFX

  29. © ZOZO Technologies, Inc. 30 4$/7JFXͱ͸ 4DFOF,JUͰͭ͘Δʮγʔϯʯ͸4$/7JFX্ʹදࣔ  4$/7JFX͸6*7JFXͷαϒΫϥε 

    6*7JFXΛܧঝ͍ͯ͠ΔͷͰࢲͨͪʹೃછΈͷ͋Δૢ࡞΍ ѻ͍͕Մೳ 
  30. © ZOZO Technologies, Inc. 30 4DFOF,JU͸6*,JUͱ਌࿨ੑ͕ߴ͍ͷ͔΋͠Εͳ͍$

  31. © ZOZO Technologies, Inc. 31 4DFOF,JU͸6*,JUͱ਌࿨ੑ͕ߴ͍ͷ͔΋͠Εͳ͍$

  32. © ZOZO Technologies, Inc. 32 4DFOF,JUʷ6*,JUͷදݱͱ࣮૷ྫ 1BSJDMF4ZTUFN $ ) "

    1 5 & 3  c    ʁ
  33. © ZOZO Technologies, Inc. 33 4DFOFͱ͸Կ͔ʁ Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJUTDOQBSUJDMFTZTUFN

  34. © ZOZO Technologies, Inc. 35 4DFOF,JUΛར༻ͨ͠1BSUJDMF4ZTUFN 9DPEF্ͰύʔςΟΫϧͷڍಈΛ೺ѲͰ͖Δ  ඇৗʹγϯϓϧʹ࣮૷Ͱ͖Δ 

    ΤϑΣΫτΛ͚ͭΔ͚ͩͰΞϓϦͷදݱ͕ϦονʹͳΔ 
  35. © ZOZO Technologies, Inc. 36 ࢲ͕ͨͪ೔ʑ։ൃ͢ΔΞϓϦ΁Ͳ͏׆༻Ͱ͖Δͷ͔

  36. © ZOZO Technologies, Inc. 36 6*#VUUPOʹύʔςΟΫϧΛ͚ͭΔ 4DFOF,JU1BSUJDMF4ZTUFNͷϢʔεέʔε 6*#VUUPO

  37. © ZOZO Technologies, Inc. 37 Ξχϝʔγϣϯͳ͠ 4DFOF,JU1BSUJDMF4ZTUFNͷϢʔεέʔε ֦େॖখΞχϝʔγϣϯ ֦େॖখ ύʔςΟΫϧ

  38. © ZOZO Technologies, Inc. 38 ύʔςΟΫϧͷ࡞੒

  39. © ZOZO Technologies, Inc. 39 4DFOF,JU4DFOF'JMFΛ௥Ճ 9DPEFҎ߱4DFOF,JU1BSUJDMF4ZTUFN TDOQϑΝΠϧ ͷςϯϓϨʔτ͸ͳ͍ 4DFOF,JUΛར༻ͨ͠1BSUJDMF4ZTUFNͷ࣮૷ํ๏

  40. © ZOZO Technologies, Inc. 40 4DFOF,JUΛར༻ͨ͠1BSUJDMF4ZTUFNͷ࣮૷ํ๏ 1BSUJDMF4ZTUFNΛ௥Ճ

  41. © ZOZO Technologies, Inc. 41 4DFOF,JUΛར༻ͨ͠1BSUJDMF4ZTUFNͷ࣮૷ํ๏ 4DFOFʹυϥοάυϩοϓ

  42. © ZOZO Technologies, Inc. 42 ४උ׬ྃ%

  43. © ZOZO Technologies, Inc. 43 4DFOF,JUΛར༻ͨ͠1BSUJDMF4ZTUFNͷ࣮૷ํ๏ 1BSUJDMFʹؔ͢Δ֤छύϥϝʔλΛઃఆ

  44. © ZOZO Technologies, Inc. 44 4DFOF,JUΛར༻ͨ͠1BSUJDMF4ZTUFNͷ࣮૷ํ๏ ΠϯεϖΫλͰͷมߋ͸ଈ࣌൓ө͞ΕΔ

  45. © ZOZO Technologies, Inc. 45 ஋Λௐ੔͢Δͱઌ΄ͲͷύʔςΟΫϧ͕(6*Ͱ֬ೝՄೳ 4DFOF,JUΛར༻ͨ͠1BSUJDMF4ZTUFNͷ࣮૷ํ๏

  46. © ZOZO Technologies, Inc. 46 ࣮૷ํ๏

  47. © ZOZO Technologies, Inc. 47 private var scnView: SCNView? private

    var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } }
  48. © ZOZO Technologies, Inc. 48 TDOϑΝΠϧ͔ΒQBSUJDMFTΛಡΈࠐΉ private var scnView: SCNView?

    private var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } }
  49. © ZOZO Technologies, Inc. 49 private var scnView: SCNView? private

    var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } } TDFOFΛੜ੒
  50. © ZOZO Technologies, Inc. 50 private var scnView: SCNView? private

    var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } } 4$/$BNFSBΛ TDFOFͷSPPU/PEFʹ௥Ճ
  51. © ZOZO Technologies, Inc. 51 private var scnView: SCNView? private

    var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } } QBSUJDMFΛ TDFOFͷSPPU/PEFʹ௥Ճ
  52. © ZOZO Technologies, Inc. 52 private var scnView: SCNView? private

    var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } } TDO7JFXΛੜ੒͠ GBW#VUUPOʹJOTFSU͢Δ
  53. © ZOZO Technologies, Inc. 53 private var scnView: SCNView? private

    var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } } TDO7JFXͷTDFOFʹ ্ड़Ͱ࡞੒ͨ͠TDFOFΛ୅ೖ
  54. © ZOZO Technologies, Inc. 54 private var scnView: SCNView? private

    var favParticle: SCNParticleSystem? override func viewDidLoad() { super.viewDidLoad() guard let scene = SCNScene(named: "fav.scn", inDirectory: "./") else { return } let node: SCNNode = scene.rootNode.childNode(withName: "particles", recursively: true) favParticle = node.particleSystems?.first } private func addFavParticle() { let scene = SCNScene() let cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 10) scene.rootNode.addChildNode(cameraNode) scene.rootNode.addParticleSystem(favParticle) scnView = SCNView(frame: view.bounds) view.insertSubview(scnView!, belowSubview: favButton) scnView?.scene = scene } @IBAction private func favButtonTapped() { addFavParticle() UIView.animate(withDuration: 0.6) { [weak self] in self?.scnView!.alpha = 0 } completion: { [weak self] _ in self?.scnView?.removeFromSuperview() self?.scnView = nil } } Ϙλϯλοϓ࣌ʹύʔςΟΫϧΛੜ੒
  55. © ZOZO Technologies, Inc. 55 Ωϟϯϖʔϯ౰બ࣌ͷԋग़ͳͲͰ࢖͑Δࢴਧઇ΋ύʔςΟΫϧͰ؆୯ʹ࣮૷Մೳ 4DFOF,JU1BSUJDMF4ZTUFNͷϢʔεέʔε

  56. © ZOZO Technologies, Inc. 56 ݸਓ։ൃ͍ͯ͠ΔͳͧͳͧΞϓϦͰ΋ಋೖ 4DFOF,JU1BSUJDMF4ZTUFNͷݸਓ։ൃΞϓϦͰͷ࢖༻ྫ

  57. © ZOZO Technologies, Inc. 57 4DFOF,JUʷ6*,JUͷදݱͱ࣮૷ྫ γΣʔμʔͱෳ਺Ξχϝʔγϣϯ $ ) "

    1 5 & 3  c    ʁ
  58. © ZOZO Technologies, Inc. 58 4DFOF,JUΛར༻ͨ͠දݱ ը૾Λը໘தԝʹදࣔ ը૾ʹޫͷ൓ࣹΞχϝʔγϣϯΛ௥Ճ

  59. © ZOZO Technologies, Inc. 59 Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJUTDOTIBEBCMFTIBEFSNPEJGJFST

  60. © ZOZO Technologies, Inc. 60 4DFOF,JU͸(-4-γΣʔμʔϓϩάϥϛϯάΛαϙʔτ͓ͯ͠Γ 4IBEFS.PEJGJFSͰ؆қతʹ(-4-ͷεχϖοτΛదԠͤ͞Δ͜ͱ ͕Մೳɻ

  61. © ZOZO Technologies, Inc. 61 TIBEFS.PEJGJFST δΦϝτϦͷද໘ΛύϥϝτϦοΫʹมܗ  ෳࡶͳࡐྉಛੑΛ࣋ͭΦϒδΣΫτͷද໘ΛγϛϡϨʔτ 

    ඒ͍͠র໌ޮՌͳͲΛ௥ՃՄೳ  4DFOF,JUͷγΣʔσΟϯά͕׬ྃͨ͠ޙʹϐΫηϧΛ ޙॲཧͯ͠ಛघޮՌΛ࡞੒  Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJUTDOTIBEBCMF
  62. © ZOZO Technologies, Inc. 62 TIBEFS.PEJGJFST "QQMFͷެࣜυΩϡϝϯτ͕ॆ࣮͍ͯͯ͠෼͔Γ΍͍͢ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJUTDOTIBEBCMF

  63. © ZOZO Technologies, Inc. 63 TIBEFS.PEJGJFST Ҿ༻IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJUTDOTIBEBCMF

  64. © ZOZO Technologies, Inc. 64 ޫͷ൓ࣹͷ࣮૷

  65. © ZOZO Technologies, Inc. 65 public class GlitterView: SCNView {

    let glitter = SCNNode() public override func awakeFromNib() { super.awakeFromNib() let scene = SCNScene() self.scene = scene glitter.geometry = SCNPlane(width: frame.size.width, height: frame.size.height) glitter.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "iosdc") glitter.geometry?.firstMaterial?.shaderModifiers = [ .surface: surfaceShaderModifier ] glitter.geometry?.firstMaterial?.setValue(0.0, forKey: "glitter") scene.rootNode.addChildNode(glitter) } public func playAnimation() { let animation = CABasicAnimation(keyPath: "geometry.firstMaterial.glitter") animation.fromValue = 0.0 animation.toValue = 1.0 animation.duration = 0.8 glitter.addAnimation(animation, forKey: nil) } }
  66. © ZOZO Technologies, Inc. 66 public class GlitterView: SCNView {

    let glitter = SCNNode() public override func awakeFromNib() { super.awakeFromNib() let scene = SCNScene() self.scene = scene glitter.geometry = SCNPlane(width: frame.size.width, height: frame.size.height) glitter.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "iosdc") glitter.geometry?.firstMaterial?.shaderModifiers = [ .surface: surfaceShaderModifier ] glitter.geometry?.firstMaterial?.setValue(0.0, forKey: "glitter") scene.rootNode.addChildNode(glitter) } public func playAnimation() { let animation = CABasicAnimation(keyPath: "geometry.firstMaterial.glitter") animation.fromValue = 0.0 animation.toValue = 1.0 animation.duration = 0.8 glitter.addAnimation(animation, forKey: nil) } } 4$/7JFXΛαϒΫϥεʹ ΋ͭ7JFXΛ࡞੒ 7$ͳͲʹBEE4VC7JFX ͯ͠1MBZ"OJNBUJPOΛݺͿ
  67. © ZOZO Technologies, Inc. 67 public class GlitterView: SCNView {

    let glitter = SCNNode() public override func awakeFromNib() { super.awakeFromNib() let scene = SCNScene() self.scene = scene glitter.geometry = SCNPlane(width: frame.size.width, height: frame.size.height) glitter.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "iosdc") glitter.geometry?.firstMaterial?.shaderModifiers = [ .surface: surfaceShaderModifier ] glitter.geometry?.firstMaterial?.setValue(0.0, forKey: "glitter") scene.rootNode.addChildNode(glitter) } public func playAnimation() { let animation = CABasicAnimation(keyPath: "geometry.firstMaterial.glitter") animation.fromValue = 0.0 animation.toValue = 1.0 animation.duration = 0.8 glitter.addAnimation(animation, forKey: nil) } } ฏ໘ͷδΦϝτϦʹ ը૾Λදࣔ
  68. © ZOZO Technologies, Inc. 68 public class GlitterView: SCNView {

    let glitter = SCNNode() public override func awakeFromNib() { super.awakeFromNib() let scene = SCNScene() self.scene = scene glitter.geometry = SCNPlane(width: frame.size.width, height: frame.size.height) glitter.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "iosdc") glitter.geometry?.firstMaterial?.shaderModifiers = [ .surface: surfaceShaderModifier ] glitter.geometry?.firstMaterial?.setValue(0.0, forKey: "glitter") scene.rootNode.addChildNode(glitter) } public func playAnimation() { let animation = CABasicAnimation(keyPath: "geometry.firstMaterial.glitter") animation.fromValue = 0.0 animation.toValue = 1.0 animation.duration = 0.8 glitter.addAnimation(animation, forKey: nil) } } (-4-ͷεχϖοτΛ 4USJOHͰ౉͢
  69. © ZOZO Technologies, Inc. 69 public class GlitterView: SCNView {

    let glitter = SCNNode() public override func awakeFromNib() { super.awakeFromNib() let scene = SCNScene() self.scene = scene glitter.geometry = SCNPlane(width: frame.size.width, height: frame.size.height) glitter.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "iosdc") glitter.geometry?.firstMaterial?.shaderModifiers = [ .surface: surfaceShaderModifier ] glitter.geometry?.firstMaterial?.setValue(0.0, forKey: "glitter") scene.rootNode.addChildNode(glitter) } public func playAnimation() { let animation = CABasicAnimation(keyPath: "geometry.firstMaterial.glitter") animation.fromValue = 0.0 animation.toValue = 1.0 animation.duration = 0.8 glitter.addAnimation(animation, forKey: nil) } } surfaceShaderModifier
  70. © ZOZO Technologies, Inc. 70 let surfaceShaderModifier = """ #pragma

    arguments float glitter; #pragma transparent #pragma body float t = 2 * clamp(glitter - _surface.diffuseTexcoord.y / 2, 0.0, 0.5); _surface.diffuse.rgb += float3(pow(sin(3.14159 * t), 12) / 6.0); """ (-4-εχϖοτޫͷ൓ࣹ (-4-4BOECPY IUUQTHMTMTBOECPYDPN ͔ΒҠ২ (-4-4BOECPYʹ͸ૉ੖Β͍͠γΣʔμʔͷαϯϓϧ͕ଟ਺
  71. © ZOZO Technologies, Inc. 71 public class GlitterView: SCNView {

    let glitter = SCNNode() public override func awakeFromNib() { super.awakeFromNib() let scene = SCNScene() self.scene = scene glitter.geometry = SCNPlane(width: frame.size.width, height: frame.size.height) glitter.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "iosdc") glitter.geometry?.firstMaterial?.shaderModifiers = [ .surface: surfaceShaderModifier ] glitter.geometry?.firstMaterial?.setValue(0.0, forKey: "glitter") scene.rootNode.addChildNode(glitter) } public func playAnimation() { let animation = CABasicAnimation(keyPath: "geometry.firstMaterial.glitter") animation.fromValue = 0.0 animation.toValue = 1.0 animation.duration = 0.8 glitter.addAnimation(animation, forKey: nil) } } OPEFʹ$""OJNBUJPOΛ Ճ͑ͯ׬੒
  72. © ZOZO Technologies, Inc. 72 ଞʹ΋ʂ

  73. © ZOZO Technologies, Inc. 73 4DFOF,JUΛར༻ͨ͠දݱ TIBEFS.PEJGJFSTΛ࢖ཱͬͯମతʹ֦େɾॖখ͢ΔΞχϝʔγϣϯ

  74. © ZOZO Technologies, Inc. 74 ͜ΕΒෳ਺ΞχϝʔγϣϯΛ૊Έ߹ΘͤΔͱʜ

  75. © ZOZO Technologies, Inc. 75 ෳ਺ͷγΣʔμʔ΍ΞχϝʔγϣϯΛ૊Έ߹ΘͤΔ "QQMFެࣜͷ.FNPKJεςοΧʔ 4DFOF,JUΛ࢖ͬͨ.FNPKJεςοΧʔ ͬΆ͍Ξχϝʔγϣϯ

  76. © ZOZO Technologies, Inc. 77 ຊ೔ൃදͨ͠಺༰ͷαϯϓϧιʔείʔυ͸(JUʹ͋Γ·͢ IUUQTHJUIVCDPNOBUPSJOH4DFOF,JU6*4BNQMF

  77. © ZOZO Technologies, Inc. 78 ·ͱΊ

  78. © ZOZO Technologies, Inc. 79 4DFOF,JU͸%Λදݱ͢ΔͨΊͷϑϨʔϜϫʔΫͰ͋Γɺ ΞχϝʔγϣϯɺύʔςΟΫϧɺ෺ཧϨϯμϦϯάͳͲΛ ؆୯ʹ࣮૷Ͱ͖Δɻ

  79. © ZOZO Technologies, Inc. 80 4DFOF,JUͱ6*,JUͷ਌࿨ੑ͸ߴ͘ɺ %ίϯςϯπΛѻΘͳ͍ΞϓϦͰ΋࢖༻༻్͸ଟʑ͋Δɻ

  80. © ZOZO Technologies, Inc. 81 4DFOF,JUΛ࢖༻͢Δ͜ͱͰ6*,JU͚ͩͰ͸࣮ݱ͕೉͍͠දݱ͕ ՄೳͱͳΓɺΞϓϦͷΫΦϦςΟ දݱͷ࣭ ͕άοͱߴ͘ͳΔɻ

  81. © ZOZO Technologies, Inc. 82 ຊ೔͝঺հͨ͠4DFOF,JUͷ࿩͸ɺ΄ΜͷҰ෦ʹա͗·ͤΜɻ 4DFOF,JUͷ͓΋͠Ζ͍࢖͍ํ͕͋Γ·ͨ͠Βڭ͍͑ͯͩ͘͞ʂ

  82. © ZOZO Technologies, Inc. 83 IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJU IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTDFOFLJUTDOTIBEBCMF IUUQTHMTMTBOECPYDPN IUUQTHJUIVCDPNNBYYGSB[FS4$/4IBEFS.PEJGJFS&YBNQMFT IUUQTNBYYGSB[FSNFEJVNDPNBSLJUTDFOFLJUTIBEFSTJOUSPEG

    IUUQTHJUIVCDPNEFVSFMM4IBEFS.PEJGJFS-BC IUUQTEFVSFMMHJUIVCJPQPTUTTDFOFLJUTFUVQ 4XJGUJ1IPOF94ϛχήʔϜΞϓϦ։ൃೖ໳cதࢁໜ ࢀߟจݙ
  83. © ZOZO Technologies, Inc. 84 ࠷ޙʹʂ

  84. © ZOZO Technologies, Inc. 85

  85. None