iOS で SceneKit を試す(Swift 3) その53 - SceneKit の Point Of View
これまで紹介した SceneKit のカメラは、コードで設定するか、scn ファイル内のカメラで設定していた。
SceneKit の SCNView(SCNSceneRenderer)には pointOfView というプロパティがあり、 これに SCNCamera を設定しているノードを設定するとカメラに設定することができる。
わかりやすい例だと、SCNView で allowsCameraControl を true に設定した時。
画面の操作が行われると pointOfView がコントロール可能なカメラに変更される。
ちなみに iOS 11 では SCNCameraController で allowsCameraControl の振る舞いを変更できる。
利用用途
allowsCameraControl = true の際、ダブルタップで初期位置へスムースにアニメーションが行われる。
これと同様に複数のカメラ間での移動や回転のアニメーションを pointOfView を使用して行うことができる。
動作例
コードを書いてみる
方法としては、異なる SCNCamera のノードを2つ作成し、pointOfView に設定したものをアニメーションさせる。
いつも通り iOS の Game テンプレートでプロジェクトを作成し、 GameViewController.swift のカメラの記述を削除。
シーン上にカメラを配置し、タッチイベントで pointOfView をアニメーションしている。
GameViewController.swift
import UIKit import QuartzCore import SceneKit class GameViewController: UIViewController { let cameraNode1: SCNNode = SCNNode() let cameraNode2: SCNNode = SCNNode() override func viewDidLoad() { super.viewDidLoad() // create a new scene let scene = SCNScene(named: "art.scnassets/ship.scn")! // create and add a light to the scene let lightNode = SCNNode() lightNode.light = SCNLight() lightNode.light!.type = .omni lightNode.position = SCNVector3(x: 0, y: 10, z: 10) scene.rootNode.addChildNode(lightNode) // create and add an ambient light to the scene let ambientLightNode = SCNNode() ambientLightNode.light = SCNLight() ambientLightNode.light!.type = .ambient ambientLightNode.light!.color = UIColor.darkGray scene.rootNode.addChildNode(ambientLightNode) // retrieve the ship node let ship = scene.rootNode.childNode(withName: "ship", recursively: true)! // animate the 3d object ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1))) let scnView = self.view as! SCNView // set the scene to the view scnView.scene = scene // allows the user to manipulate the camera scnView.allowsCameraControl = true // show statistics such as fps and timing information scnView.showsStatistics = true // configure the view scnView.backgroundColor = UIColor.black // --- 追加分 --- cameraNode1.name = "camera1" cameraNode1.camera = SCNCamera() cameraNode1.position = SCNVector3(x: 0, y: 0, z: 15) scene.rootNode.addChildNode(cameraNode1) cameraNode2.name = "camera2" cameraNode2.camera = SCNCamera() cameraNode2.position = SCNVector3(x: 0, y: 20, z: 0) cameraNode2.eulerAngles = SCNVector3(x: Float.pi * -0.5, y: 0, z: 0) scene.rootNode.addChildNode(cameraNode2) scnView.pointOfView = cameraNode1 // add a tap gesture recognizer let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:))) scnView.addGestureRecognizer(tapGesture) } func handleTap(_ gestureRecognize: UIGestureRecognizer) { // retrieve the SCNView let scnView = self.view as! SCNView let cameraNode:SCNNode! if scnView.pointOfView?.name == "camera1" { cameraNode = scnView.scene?.rootNode.childNode(withName: "camera2", recursively: true) } else { cameraNode = scnView.scene?.rootNode.childNode(withName: "camera1", recursively: true) } SCNTransaction.begin() SCNTransaction.animationDuration = 4.0 scnView.pointOfView = cameraNode SCNTransaction.commit() } override var shouldAutorotate: Bool { return true } override var prefersStatusBarHidden: Bool { return true } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { return .allButUpsideDown } else { return .all } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Release any cached data, images, etc that aren't in use. } }
注意点
シーン上にカメラを配置していないとアニメーションは行われず、瞬時にカメラが変わる。
また、iOS シミュレーターではアニメーションが微妙な動きをする場合があるので注意。
今回はここまで
iOS で SceneKit を試す(Swift 3) その53 - SCNLight の Gobo と Category BitMask
シーン上でキャストシャドウを行うと基本的にはシャドウマップが作成される。
もし、ジオメトリの影を落とす際、細かなフォルムが必要なければ
事前にテクスチャ画像を作成したものを使用し、シャドウマップを生成させないことでライド使用時の負荷を減らすことができる。
Gobo に設定したライトは影を落とすためのもので光沢や色等のライティング効果は出ない。
Gobo って何?
ライブや舞台等で、ライトの前に光の当てたい部分を削ったプレートを置いて照明を照らすことで、
壁面に絵や文字を投影することができ、そのプレートや効果を指すとのこと。
ひとまず書いてみる
Scene Editor では設定できないためコードで書いていく。
いつも通り iOS の Game テンプレートでプロジェクトを作成。
Gobo 用の画像をプロジェクトに追加し、
Gobo 用のライトと落とした影を確認するために SCNFloor を設定する。
影となる画像 gabo1.png
GameViewController.swift の「let scene = SCNScene(named: “art.scnassets/ship.scn”)!」より下に以下のコードを書く。
// --- 追加分 --- let goboNode = SCNNode() let light = SCNLight() light.type = .directional light.gobo?.contents = UIImage(named: "gobo1.png") light.gobo?.intensity = 0.8 light.orthographicScale = 5 light.shadowMode = SCNShadowMode.modulated light.castsShadow = false goboNode.position = SCNVector3(x: 0, y: 5, z: 0) goboNode.eulerAngles = SCNVector3(x: -Float.pi * 0.5, y: 0, z: 0) goboNode.light = light scene.rootNode.addChildNode(goboNode) let floorNode = SCNNode(geometry: SCNFloor()) floorNode.position = SCNVector3(x: 0.0, y: -4.0, z: 0.0) scene.rootNode.addChildNode(floorNode)
内容的には Y の値が 5 で下に向いた普通のライトを設定をして、 gobo の contents で画像設定、intensity で影の透過を決める。
そして、SCNLight の shadowMode を modulated にしている。
影の大きさを変更するため orthographicScale でサイズを変更している。
ちなみにドキュメントではスポットライトで使用できるとは書いてあるが、ディレクショナルライトでも動作する。
ビルドするとこのような感じになる。
ジオメトリにも影が落ちているので落ちないようにしたい
Category BitMask を使って適応範囲を変更する。
以下のように合わせると、下の床のノード部分だけに影を落とすことができる
light.categoryBitMask = 2 floorNode.categoryBitMask = 2
注意点
画像が適応できるものはモノクロが画像。
透過が含まれていると表示されない。
スポットライトと同等であるため、ライトの設置上限がある。
そのため、8個ライトが設定されていて Gobo のライトを追加すると
シーン内のいずれかのライトが消える。
Gobo はライトの向きで投影される画像が固定される。
そのため、方向の決まった影の画像を適応し、ジオメトリが回転すると問題が起きる。
画像
動作
今回修正した GameViewController.swift のコード
hitTest 部分が必要ないので省いている。
import UIKit import QuartzCore import SceneKit class GameViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // create a new scene let scene = SCNScene(named: "art.scnassets/ship.scn")! // create and add a camera to the scene let cameraNode = SCNNode() cameraNode.camera = SCNCamera() scene.rootNode.addChildNode(cameraNode) // place the camera cameraNode.position = SCNVector3(x: 0, y: 0, z: 15) // create and add a light to the scene let lightNode = SCNNode() lightNode.light = SCNLight() lightNode.light!.type = .omni lightNode.position = SCNVector3(x: 0, y: 10, z: 10) scene.rootNode.addChildNode(lightNode) // create and add an ambient light to the scene let ambientLightNode = SCNNode() ambientLightNode.light = SCNLight() ambientLightNode.light!.type = .ambient ambientLightNode.light!.color = UIColor.darkGray scene.rootNode.addChildNode(ambientLightNode) // --- 追加分 --- let goboNode = SCNNode() let light = SCNLight() light.type = .directional light.gobo?.contents = UIImage(named: "gobo1.png") light.gobo?.intensity = 0.8 light.orthographicScale = 5 light.shadowMode = .modulated light.castsShadow = false light.categoryBitMask = 2 goboNode.position = SCNVector3(x: 0, y: 5, z: 0) goboNode.eulerAngles = SCNVector3(x: -Float.pi * 0.5, y: 0, z: 0) goboNode.light = light scene.rootNode.addChildNode(goboNode) let floorNode = SCNNode(geometry: SCNFloor()) floorNode.position = SCNVector3(x: 0.0, y: -4.0, z: 0.0) floorNode.categoryBitMask = 2 scene.rootNode.addChildNode(floorNode) // retrieve the ship node let ship = scene.rootNode.childNode(withName: "ship", recursively: true)! // animate the 3d object ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1))) // retrieve the SCNView let scnView = self.view as! SCNView // set the scene to the view scnView.scene = scene // allows the user to manipulate the camera scnView.allowsCameraControl = true // show statistics such as fps and timing information scnView.showsStatistics = true // configure the view scnView.backgroundColor = UIColor.black } override var shouldAutorotate: Bool { return true } override var prefersStatusBarHidden: Bool { return true } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { return .allButUpsideDown } else { return .all } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Release any cached data, images, etc that aren't in use. } }
今回はここまで
iOS で SceneKit を試す(Swift 3) その52 - Scene Editor の Light Probe
シーンで動かない物体にはライトマップでテクスチャに焼き付けると綺麗な見た目となるが、 キャラクターなど動くもがあった場合、光は反映されない。
Light Probe はシーンの色の変化とすべての方向から受け取る照明の強度を球体で設定し、
有効範囲にある Physically Based のライティングモデルの Emission の値を光の情報として使用する。
そのため適応させたいキャラクターなどのジオメトリが動作する周辺にいくつか設置する必要がある。
Light Probe の制限
- 事前に計算させておく必要がある。
- ライトとなるジオメトリとそれを適応させるジオメトリは Physically Based のライティングモデルである必要がある
- 以前の記事で書いたが Light Probe は自体がライトになるわけではなく、ジオメトリの Emission の値がライトになる
- Emission の光を反映させたいジオメトリは Movabililty を true にする必要がある
- キャストシャドウは落とせないので他のライトと併用する。
シーン設定
Game (SceneKit) のテンプレートでプロジェクトを作成するか既存のファイルから ship.scn ファイルを選択。
中身はいらないので Scene Graph View か、Scene Editor 上にあるものを全て削除。
Object Library (Command + Control + Option + 3) から Plane と、Sphere、Light Probe を以下のように設定する。
Plane
Node Inspector (Command + Option + 3) で以下に変更。
Material Inspector (Command + Option + 5) で Physically Based に変更し、 Emission の色を赤に変更する。
両面描画のチェックを外す。
Sphere
原点に設置。
Node Inspector (Command + Option + 3) で Movabililty の is movable チェックをオンにする。
Light Probe
今回は下からしか照らされないので、球の真上に置く。
Light Probe の Attrubutes Inspector
名前以外では Probe の Near Clipping と Far Clipping。 Light Probe の計算を行う Compute のボタンにのみ。
Near Clipping と Far Clipping
適応範囲を Near Clipping と Far Clipping で設定する。
基本デフォルトのままでも良いと思われる。
(Apple のサンプルもデフォルト値を使用している)
Compute
ボタンを押すと Probe の計算が始まりジオメトリに結果が反映される。
今回のシーン設定でこのボタンを押すと以下のようになり、球の底の部分が赤く照らされているのがわかる。
もし、何も問題がなく、ジオメトリに変化がない場合は Movabililty のチェックボタンをオン/オフすると反映される場合がある。
複数 Light Probe があって、いくつも Compute ボタンを押すのが面倒
Scene Inspector (Command + Option + 7) に、「Compute all probes」というボタンがあるのでこれを押す。 計算していない Probe 量が多いと終わるまで結構時間がかかるので注意。
状況によっては複数の Light Probe を設置する必要がある。
四隅に Light Probe を設置してみた。
中央にも置いてみた。天井の照明が適応されている。
今回はここまで
iOS で SceneKit を試す(Swift 3) その51 - Scene Editor の IES Light
IES Light はテキストデータのファイルを使用し照明のシミュレーションを行い陰や光を与える。
Directional Light とほぼ同じで、Scale のパラメーターがなく、IES ファイルの選択がある。
基本的にはライトからのシャドウマップで表現しているため、アーティファクトが出る(データのエラーやノイズの出現する)場合がある。
その場合は、Casts Shadow の チェックをオンにして Shadow のパラメーター群で調整する。
IES ファイル
テキスト情報で光がどのように与えるか記述されている。
試しに、以下のコードを入れて .ies の拡張子でプロジェクトに保存してみる。
TILT=NONE 1 13172.61 1 37 1 1 2 0 0 0 1 1 0 0.00 2.50 5.00 7.50 9.11 10.00 10.80 12.50 15.83 22.50 25.00 27.50 32.50 34.28 35.00 42.50 47.02 47.50 47.81 50.00 50.78 52.50 55.00 57.50 60.00 62.50 65.00 67.50 70.00 72.50 75.00 77.50 80.00 82.50 85.00 87.50 90.00 0.00 8379.00 8409.00 8528.00 8126.65 8500.00 8564.00 8301.00 8158.61 8411.98 8036.59 7865.61 7283.76 5209.38 6038.93 4533.49 3091.00 3665.38 2996.97 3625.45 2194.62 3170.85 1115.28 651.00 450.00 244.00 102.00 80.00 43.00 5.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
今回コードを書いているが、基本的には自分で作成することはないと思われるので、 照明メーカーなどで配布されているものを使用した方が良いと思われる。
シーン設定
Game (SceneKit) のテンプレートでプロジェクトを作成するか既存のファイルから ship.scn ファイルを選択。
(設定が面倒である場合は、下にサンプルファイルをダウンロード)
中身はいらないので Scene Graph View か、Scene Editor 上にあるものを全て削除。
Object Library (Command + Control + Option + 3) から Plane を2つ、Sphere、IES Light を以下のように設定する。
Plane
2つの座標
Attributes Inspector (Command + Control + Option + 4) で両方とも大きさを変更。
Material Inspector (Command + Control + Option + 4) で両面描画のチェックを外す。
Sphere
座標値変更
Attributes Inspector で大きさを変更。
IES Light
IES Light の Attrubutes Inspector
以前紹介した共通の設定に IES Profile の読み込みと、キャストシャドウを追加したもの。
キャストシャドウは Spot Light で紹介しているのでこちらを参照。
IES Parameters
IES Profile のファイルを選択する。 Scene Editor ではフォルダのマークを選択して、上の方でつくったものか、ダウンロードした IES ファイルを選ぶ。
照明が適応されたのがわかる。
試しに Casts shadows のチェックを入れると背面にアーティファクトができる。
Shadow のパラメーターを調整したもの
注意点
- コードではライトの種類を選択後 IES ファイルの読み込みが呼ばれると Omni、Spot など他のライトを選択していても IES に変更される
- モバイルの GPU で再現するため記述されている IES が意図通りに表示されない可能性がある
- Scene Editor で IES Profile に適合していないファイル(特にバイナリ)を読み込むと Xcode が落ちたり scn が壊れる可能性があるので慎重に
- Scene Editor で IES Lgiht を使用した場合は、必ず IES ファイルをプロジェクトの中にあるものから読み込む。プロジクト外でも Scene Editor では読み込めるが、ビルドした環境では IES ファイルが読み込めなくなるため
サンプル
今回は scn がそこそこ複雑なのでファイルを用意。
- IES.scn
- iesprofile.ies
コード
let light = SCNLight() light.name = "IES" light.type = .IES light.intensity = 1000 light.castsShadow = true let iesPath:String = Bundle.main.path(forResource: "iesprofile", ofType: "ies")! let fileURL:URL = URL(fileURLWithPath: iesPath) light.iesProfileURL = fileURL let lightNode = SCNNode() lightNode.light = light lightNode.position = SCNVector3(x: 0, y: 10, z: 10) scene.rootNode.addChildNode(lightNode)
今回はここまで
iOS で SceneKit を試す(Swift 3) その50 - Scene Editor の Directional Light
太陽光のように一定の方向に光を放つ Directional Light のご紹介。
設置位置に関わらず一定で光の影響を与える。 遮るジオメトリがあった場合に影を与えるキャストシャドウを設定することができる。
以下の画像は、ライトの位置を変更しても、光沢と影が変わらない例。
ハンドラの薄い赤の矢印がライトの光の方向を表している。
シーン設定
Omni Light で作成したシーンをそのまま使用する。
適当なシーンに Object Library から Directional Light をドラッグ&ドロップしても可。
Floor や Plane を下に敷いておくとわかりやすいと思われる。
Scene Editor 上で動作を見ていくが、実機で動かす場合は GameViewController.swift にあるライトの記述をすべて消す。
Directional Light の設定
Scene Graph View から Omni Light を選択し、Attributes Inspector (Command + Option + 4) を開く。
Type が Omni になっているので Directional に変更する
Directional Light の Attrubutes Inspector
以前紹介した共通の設定にキャストシャドウと Scale の項目を追加したもの。
キャストシャドウは Spot Light で紹介しているのでこちらを参照。
Scale
キャストシャドウの大きさを設定する。 デフォルト値は 1。
そのままだと宇宙船の影が小さい四角になっているのがわかる。
Directional Light は影の大きさを指定する必要があり、試しに 20 にしてみると影が現れる。
現状はこのように手動で設定しているが、
iOS 11 では自動で Scale を決める設定と、距離に応じてシャドウマップの質を決めるカスケードが追加されている。
コード
let light = SCNLight() light.name = "directional" light.type = .directional light.intensity = 1000 light.castsShadow = true light.orthographicScale = 20 let lightNode = SCNNode() lightNode.light = light lightNode.position = SCNVector3(x: 0, y: 10, z: 10) scene.rootNode.addChildNode(lightNode)
今回はここまで
iOS で SceneKit を試す(Swift 3) その49 - Scene Editor の Spot Light と Cast Shadow (Shadow Mapping)
舞台照明で使用されているスポットライトを模した Spot Light のご紹介。
設置位置から円錐状に光の影響を与え、任意で遮るジオメトリがあった場合に影を与えるキャストシャドウが使用できる。
その前にキャストシャドウとは?
シャドウマップというライトから影の情報を持ったテクスチャを作成し、
シーンにあるジオメトリにそれ適応させることで、物体に影が落ちている表現する。
さっくり説明すると、
ライトをカメラにしてジオメトリを映しベタ塗をする。
(下の画像では、ライトはジオメトリの上、X方向-90度に回転)
ライトから照射される光の方向に他のジオメトリがあった場合、先ほどのベタ塗りをテクスチャをライトから影として適応するとディテールを持った影ができる。
ジオメトリと他のジオメトリが遠い場合は、
ベタ塗りをテクスチャのサイズを変更したり、薄くしたり、ぼかしたりすることで遠くから影が落ちていることを表現する。
影の演算処理はマシンパワーを使用するる為、リアルタイムの CG ではこのような工夫がされている。
シーン設定
Omni Light で作成したシーンをそのまま使用する。
適当なシーンに Object Library から Spot Light をドラッグ&ドロップしても可。
Floor や Plane を下に敷いておくとわかりやすいと思われる。
Scene Editor 上で動作を見ていくが、実機で動かす場合は GameViewController.swift にあるライトの記述をすべて消す。
Spot Light の設定
Scene Graph View から Omni Light を選択し、Attributes Inspector (Command + Option + 4) を開く。
Type が Omni になっているので Spot に変更する
照明が宇宙船に当たるよう X 軸を -90 度傾ける。
Spot Light の Attrubutes Inspector
以前紹介した共通の設定以外では以下のもの。
Spot Parameters
円錐の円の大きさと光の減衰設定。
Outer angle
円錐の円の大きさを決める。
デフォルト値は 45 度。
65 度に設定したもの
Inner angle
内側の円を決めることで光の減退を設定する デフォルト値は 0 度。
55 度に設定したもの。
Inner angle、Outer angle の値が同じ場合は減退が起きない。
Attenuation
スポットライトの始点から終点間での光の減衰を設定する。
(円錐の尖ったところから底の円の部分まで)
設定方法は Omni Light で紹介しているので割愛。
Shadow
ジオメトリに影を与えるキャストシャドウの設定を行う。
Casts Shadows
チェックを入れると、スポットライトの光の進行方向にジオメトリがあった場合に影が落ちる。
デフォルト値は false でチェックが入っていない。
Color
影に色をつける。
半透明も使用でき、デフォルト値は黒で、アルファは 1 の不透明になっている。
後ほど説明する Mode で「Deferred」を選択しないと設定した色は反映されず、影は黒になる。
Sample radius
影の輪郭のシャープさを設定する。
値を小さくするとシャープになり、大きくすると輪郭がぼやける。
デフォルト値は 3.0。
Near clipping, Far clipping
影の適応範囲。 デフォルト値は Near が 1.0、Far が 100.0。
例えば Far で 10 を設定するとそれ以降は影が乗り、 Near で 10 を設定するとスポットライトから 10 離れたジオメトリの影を描画し始める
Far: 10.0
Near: 10.0
Sample count
シャドウマップに重み付けを行い複数か処理しソフトエッジのシャドウを生成する。 サンプル数が多くなれば影はソフトになるが、処理が重くなる。
デフォルト値は 1。(macOS は 16) Scene Editor では表示上は 0。
Sample count: 1
Sample count: 4
Bias
複雑な形状の物体ではシャドウマップがうまく表示されない可能性がある。
それを補正するためのパラメーター。
デフォルト値は 1.0。
Map Size (width, height)
シャドウマップの画像の大きさ。
小さな画像にすると処理が軽くなるがそのぶん画像が荒くなる。
デフォルト値は縦横共に 0.0 で自動的サイズが調整される。
試しにかなり粗めの 100 x 100 px 描画したもの。
Baking
Light Map 焼き込み時に、直接的な照明 Direct Light や間接的な照明 Indirect Light を使用するか設定する。
Scene Editor 上のパラメーターであるため、SCNLight のクラスでこのプロパティは存在しない。
Mode
影をつける処理のモード
値 | 説明 |
---|---|
Forward | デフォルト値。そのままシャドウマップを表示する。color で設定しても色は適応されないが透明度は適応される。 |
Deferred | 最終画像をレンダリングした後に color で設定している影の色を適応する |
Modulated | 任意の画像の影(gobo)を使用し影を描画するモード。画像設定はコードから行う |
コード
let light = SCNLight() light.name = "spot" light.type = .spot light.intensity = 1000 light.castsShadow = true light.shadowRadius = 3.0 light.color = UIColor(red: 1.0, green: 0.0, blue: 0.502, alpha: 1.0) light.zNear = 1.0 light.zFar = 100.0 light.shadowSampleCount = 1 light.shadowBias = 1 light.shadowMapSize = CGSize(width: 0.0, height: 0.0) light.shadowMode = .forward let lightNode = SCNNode() lightNode.light = light lightNode.position = SCNVector3(x: 0, y: 10, z: 10) scene.rootNode.addChildNode(lightNode)
今回はここまで
iOS で SceneKit を試す(Swift 3) その48 - Scene Editor の Ambient Light
シーン全体に光を与える Ambient Light のご紹介。
設置位置に関係なく光の影響を与え、ジオメトリの暗部である陰の色を薄めたりできる。
シーン設定
iOS SceneKit のテンプレートでプロジェクト作成。
今回は床が必要ないので、ship.scn を表示するだけ。
Scene Graph View から shipMesh を選択し、マテリアルを Physically Based に変更。
一応、わかりやすくする為、
宇宙船のマテリアルの Lighting Type を Physically Based に変更しておくが今回の場合は必要はない。
光の影響を受けないためジオメトリが黒くなる。
一旦、Omni Light を設定してみる
Object Library (Command + Option + Control + 3) から Omni Light をシーンにドラッグ。
Omni Light は距離影響を受けるので Node Inspector (Command + Option + 3) を開いて y の 10 に設定。
宇宙船にライトが当たると思われる、
Ambient Light の設定
Object Library から Ambient Light をシーンにドラッグ。
適切な位置へ移動しなくても場所に関場所に光が適応されており、 Omni Light で陰が出ていた宇宙船の下の部分が真っ黒ではなくなっていると思う。
Scene Editor 上で動作を見ていくが、実機で動かす場合は GameViewController.swift にあるライトの記述をすべて消す。
Ambient Light の Attrubutes Inspector
以前紹介した共通の設定のもの以外設定はない。
デフォルトではカラーが灰色、intensity が 1000 になっている。
intensity が高めに設定されている為、カラーの値を白に変更すると陰の黒い部分がほとんど飛んでしまうので注意が必要。
調整すると全体の光を変更することができる。
Omni Light を消してみる
Ambient Light はジオメトリへ陰をつけない為、Omni Light をシーン上から削除するとジオメトリは単色の色が重ねられただけでフラットな見た目になる。
以下の画像のように、宇宙船のテクスチャを取り除くとわかりやすい。
使い所
全体の色の変更し、シーン印象を変えることが主な使用用途だと思われる。
また、Ambient Light はジオメトリへの陰の描画処理がされない為、演算処理が少ない。
ジオメトリにライトマップやオクルージョンのテクスチャを使用し、
影が落ちる必要のないシーンで使用することでライティングの処理が軽くなり全体の負荷を下げることができる。
コード
let light = SCNLight() light.name = "ambient" light.type = .ambient light.intensity = 1000 let lightNode = SCNNode() lightNode.light = light lightNode.position = SCNVector3(x: 0, y: 10, z: 0) scene.rootNode.addChildNode(lightNode)
今回はここまで