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)
今回はここまで