Apple Engine

Apple, iPhone, iOS, その周辺のことについて

iOS で SceneKit を試す(Swift 3) その47 - Scene Editor の Omni Light と Attenuation

豆電球のような Omni Light の設定を見ていく。

Omni Light は設置位置によって光の影響を変化させるが、ジオメトリの影を落とすことはできない。

影は必要ないが光の影響を与えたい場合などで使用するのが良いかと思われる。

 

シーン設定

ひとまず、iOS SceneKit のテンプレートでプロジェクト作成。

ship.scn を開き Object Library (Command + Option + Control + 3) から Floor をシーンにドラッグ。

f:id:x67x6fx74x6f:20170801183844p:plain

 

Node Inspector (Command + Option + 3) を開いて y を -2 に設定。
Scene Graph View から shipMesh を選択し、マテリアルを Physically Based に変更。

光の影響を受けないためジオメトリが黒くなる。

f:id:x67x6fx74x6f:20170801183922p:plain

 

Omni Light の設定

Object Library から Omni Light をシーンにドラッグ。

f:id:x67x6fx74x6f:20170801183942p:plain

 

Omni Light は距離影響を受けるので Node Inspector (Command + Option + 3) を開いて y の 10 に設定。

宇宙船にライトが当たると思われる、

f:id:x67x6fx74x6f:20170801184001p:plain

 

今回は Scene Editor 上で動作を見ていくが、実機で動かす場合は GameViewController.swift にあるライトの記述をすべて消す。

 

Omni Light の Attrubutes Inspector

Attrubutes Inspector (Command + Option + 4) を開くと、 以下のようなパラメーターが現れ、
以前紹介した共通の設定以外では Attenuation がある。

f:id:x67x6fx74x6f:20170801184241p:plain

 

試しに Intensity を 500 にしてみたもの。

f:id:x67x6fx74x6f:20170801184331p:plain

 

Attenuation

直訳すると減衰となり、光がどう減退するかを設定する。

f:id:x67x6fx74x6f:20170801184208p:plain

 

Start

減衰の開始の距離。

デフォルト値は 0.0 でライトの設置場所から行われる。

   

End

減衰の終了距離。これ以降は光の影響を受けない。

デフォルト値が 0.0 で適応範囲は無限遠となりかなりなだらかな減衰となる。

 

30 に設定するとこの形

f:id:x67x6fx74x6f:20170801184426p:plain

 

Falloff

減衰の状態を表す。
デフォルト値が 2.0

値: 0 の場合は完全に減衰は行われない。

f:id:x67x6fx74x6f:20170801184448p:plain

 

値: 1 で開始から終了までを線形で光が減衰する。

f:id:x67x6fx74x6f:20170801184503p:plain

 

値: 2 デフォルト設定。2乗の曲線を描き光が減衰する。2以降はパラメーターの数の乗数で光が減衰する。

f:id:x67x6fx74x6f:20170801184516p:plain

 

値: 4 値を大きくしいくと全体の変化が少なくなる。

f:id:x67x6fx74x6f:20170801184541p:plain

 

また、減衰はシーンエディタで有効範囲が表示される。

f:id:x67x6fx74x6f:20170801184607p:plain

 

コード

let light = SCNLight()
light.name = "omni"
light.type = .omni
light.intensity = 1000
light.attenuationStartDistance = 0.0
light.attenuationEndDistance = 30.0
light.attenuationFalloffExponent = 2.0

let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3(x: 0, y: 10, z: 0)
scene.rootNode.addChildNode(lightNode)

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その46 - SCNLight の共通設定

前回の書き忘れがあったのでライトの種類の前にこちらの紹介。

ライトには種類があったが、Light Probe 以外でいくつかの共通設定があるので、まずはこちらから。 

f:id:x67x6fx74x6f:20170801173301p:plain

 

Name

コードで使用するための識別用の名前。
Light Probe でも使用可能。

 

Type

ライトの種類を SCNLight.LightType を使用し設定する。
以下、SCNLight.LightType のプロパティ

プロパティ 名前
.ambient アンビエントライト
.omni オムニライト
.directional ディレクショナルライト
.spot スポットライト
.IES IES ライト
.probe Light Probe

 

ちなみに、type の後に IES ライトのファイルを読み込む関数 iesProfileURL を使用すると、何が設定されていても IES ライトに変更される。

 

Mode

デフォルト値は Dynamic。
Static はライトマップのベイク作成時に使用。

この設定は Scene Editor 内でのベイクのためだけにあるようなので、SCNLight クラスにこのプロパティはない。
( 確か Model I/O の機能だったはず )

 

Color

ライトの色。この色と共にジオメトリなどのマテリアル設定に反映させ物体に色をつける。

 

Intensity

光の強さ。
値を上げると光沢の範囲が増えや形がシャープになる。

デフォルト値は 1000。

 

コードで使用可能な項目

temperature

色温度の単位、ケルビンでライトの設定を行う。
6500 K で白色となっており、低くすると赤みがかり、高くすると青くなる。

デフォルト値は 6500 になっており、設定できる値は 0 〜 40000

 

iOS SceneKit のテンプレートに SCNFloor を追加して、オムニライトに temperature を設定したもの。

// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .omni

// 追加箇所
lightNode.light!.temperature = 3000

lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)

f:id:x67x6fx74x6f:20170801124726p:plain

  

以下で intensity と色をつけたもの

lightNode.light!.color = UIColor.init(red: 1.0, green: 0.8, blue: 0.8, alpha: 1.0)

f:id:x67x6fx74x6f:20170801124113p:plain

 

categoryBitMask

ジオメトリのノードの categoryBitMask と ライトのビットマスクと AND 演算して 0 以外であった場合 このライトに適応させる。

デフォルトの値は -1 となっており、すべてのジオメトリに適応される。

注意:SCNLight をアタッチしている SCNNode ではなく、SCNLight の categoryBitMask を設定しないと変化しないので間違えないように。

注意2:アンビエントライトは categoryBitMask が無視されるため適応できない

 

init(mdlLight: MDLLight)

Model I/O で作成したライトを適応できる。
基本的には SceneKit で使用されているライトなので直接 MDLLight を設定することはないと思われる。

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その45 - Scene Editor の Light について

今回はシーンのライトについて軽くご紹介。

シーン上には必ずライトとなるものが1つ必要となり、
SCNNode で light プロパティに SCNLight を設定するか、
以前、紹介したシーン設定の Light Environment (Image Based Lighting) を設定することで、
ジオメトリのマテリアルに光を照らしカメラに物体を映すことができる。

 

SCNLight の種類

Directional と Ambient は設置場所に関係なく一定の光を設定する。

f:id:x67x6fx74x6f:20170728190912p:plain

 

ライトの種類 説明
Omni オムニライト。豆電球のように球状に光が広がるライト
Directional ディレクショナルライト。太陽のように一定方向の光を設定するライト
Spot スポットライト。現実のスポットライト同様に円錐状に光を設定するライト
Ambient アンビエントライト。シーン全体に光を与えるライト
IES IES ライト。照明設定が記述されたテキストファイルを読み込み設定するライト
Light Probe これ自体はライトではなく、Light Probe 内に SCNMaterial の Emision が設定されたジオメトリがあった場合、そのジオメトリをライトに設定する

  

SCNLight の制限

ドキュメントでは SCNLight はノードで使用できるの 8 つまでとのこと。

通常、ライトを 8 つ使用することはあまりないが、 軽く試したところ、アンビエントライトや 光の変更を行わないモードであるスタティックにしたライト、 ライトプローブを除くライトが 8 個以上あると 9個目からはライトが無視される。

 

SCNLight の注意点

3DCG はシーン内のライトの数と種類でレンダリングパフォーマンスが変化する。

SceneKit で効率的なレンダリングを行う場合、シーン内のライティング設定を見直す必要がある。

以下、調整例

  • 光の当たり方が固定の場合は、あらかじめ 3DCG のオーサリングツールでライトをライトマップテクスチャにベイクし、SCNMaterial にそのテクスチャ適応して multiply で色等を調整する
  • 必要のないライトやジオメトリで影の描画を行わない
  • ゲームキャラクタなど正確な影の形が必要ない場合、影を輪郭がぼやけた丸などの画像にしてしまう
  • スポット、オムニ、ディレクショナルライト で attenuationEndDistance プロパティを設定し有効範囲を制限する
  • SCNLight の categoryBitmask 使用してライトを必要ないジオメトリにはライトを適応しない

 

今回はここまで。

次回、種類別に紹介していく。

iOS で SceneKit を試す(Swift 3) その44 - Scene Editor モーションブラー

実際のカメラでは速い動きを物体を撮る際、カメラ性能にもよりますが残像が出る場合があり、
それを SceneKit のカメラである SCNCamera でシミュレーション行う。

 

f:id:x67x6fx74x6f:20170727184303p:plain

 

Scene Editor の パラメーター

f:id:x67x6fx74x6f:20170727184242p:plain

プロパティは一つのみ。

 

Motion Blur - Intensity

最大値を 大きくした場合、効果は顕著になる。
デフォルト値は 0.0 で効果は出ない。

また、ドキュメントでは Wide-Gamut Color (Display P3) では使用できず、
Info.plist で SCNDisableWideGamut のキーを設定し Bool 値で YES (true) にしてオプトアウトする必要がある。

 

サンプル

わかりやすく、大きめの値 4 で設定。

f:id:x67x6fx74x6f:20170727190336g:plain

 

コード

let camera = SCNCamera()

camera.motionBlurIntensity = 4

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その42 - Scene Editor カメラのポストプロセス

カメラとなる SCNCamara では画面描画後に簡易的な画像処理を行うことができる。

使用できる処理は以下のもの。

  • 画面の周りを暗くするケラレ処理
  • ブラウン管のような色のにじみを出すカラーフリンジ
  • 簡易的な色の調整を行うカラーグレーディング

 

さらに複雑な処理をしたい場合は SCNTechnique を使用し、自前でシェーダーを書いて合成する。

 

Scene Editor の パラメーター

f:id:x67x6fx74x6f:20170726190154p:plain

 

元画像

f:id:x67x6fx74x6f:20170726191754p:plain

 

Vignetting

ケラレ処理を行う。
Power が適応範囲で、Intensity が適応度合い。
デフォルト値は Power が 0 で、Intensity が 1。

Power が 0 の場合は処理が行われない。

 

Power: 1 / Intensity: 1

f:id:x67x6fx74x6f:20170726191819p:plain

 

Color Fringe

フリンジの処理を行う

Strength の値を大きくするほどフリンジの色のシフトと広がりが顕著になり、Intensity が適応度合い。
デフォルト値は Strength が 0 で、Intensity が 1。

Strength が 0 の場合は処理が行われない。

 

Strength: 4 / Intensity: 1

f:id:x67x6fx74x6f:20170726191840p:plain

 

Color Grading

Saturation

画面の彩度を設定する。 デフォルト値は 1.0 で 0 にするとグレイスケールになる。

 

Saturation: 0

f:id:x67x6fx74x6f:20170726191913p:plain

 

Contrast

画面のコントラスト変更する。
デフォルト値は 0.0。

 

Contrast: 4

f:id:x67x6fx74x6f:20170726192016p:plain

  

コード

let camera = SCNCamera()

// Vignetting
camera.vignettingPower = 0.0
camera.vignettingIntensity = 1.0

// Color Fringe
camera.colorFringeStrength = 0.0
camera.colorFringeIntensity = 1.0

// Saturation
camera.saturation = 1.0
camera.contrast = 0.0

また、コードのみだがカラーグレーディング用のテクスチャを作成し、適応させると細かな色の調整ができる模様。

Color Grading のドキュメント

colorGrading - SCNCamera | Apple Developer Documentation

 

上記の設定でテクスチャ画像を作成し、
レンダリング画像に対して 80% の適応度合いで試したもの。

f:id:x67x6fx74x6f:20170726192636p:plain

let camera = SCNCamera()

camera.colorGrading.contents = NSImage(named:"colorgrading.png")
camera.colorGrading.intensity = 0.8

 

カラーグレーディングの画像についてはまたいつか説明しようと思う。

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その41 - Scene Editor カメラの Depth of Field(被写界深度)

カメラとなる SCNCamara で被写界深度のシミュレーションを行う。

実際のカメラと同様に距離でオブジェクトにピントを合わせて、 他がボケるさせる効果の設定を行う。

ちなみに、今回紹介するすべてのプロパティが macOS, tvOS, watchOS でも廃止予定で、
iOS 11 など最新の OS からはカメラのシミュレーションに近い、焦点距離 (focusDistance) と F値 (fStop) で行う。

 

Scene Editor の パラメーター

f:id:x67x6fx74x6f:20170726180008p:plain

 

Blur Radius

ピントがあっていないもの(被写界深度の外のもの)に対してボケ具合の最大値を設定する。
0 以上にしないと被写界深度のシミュレーションが行われない。

デフォルト値は 0.0。

 

Distance

ピントを合わせたいものまでの距離。焦点距離。

デフォルト値は 10.0

 

Aperture

レンズの口径を表す。

値を大きくすると焦点距離から鮮明に映る範囲が狭くなりボケる割合が大きくなり、
値を小さくすると全体がシャープになっていく。

デフォルト値は 0.125。

 

Size

オブジェクトが鮮明に表示される距離の範囲の大きさ。

デフォルト値は 0.0。

 

サンプル

以下の値に設定し、手前、2番目、3番目にピントを合わせたもの。

プロパティ
Blur Radius 6
Aperture 0.125
Size 1

 

Distance: 1.2

f:id:x67x6fx74x6f:20170726180123p:plain

 

Distance: 3

f:id:x67x6fx74x6f:20170726180141p:plain

 

Distance: 6

f:id:x67x6fx74x6f:20170726180159p:plain

 

コード

let camera = SCNCamera()

camera.focalBlurRadius = 0.0
camera.focalDistance = 10.0
camera.aperture = 0.125
camera.focalSize = 0.0

 

今回はここまで。

iOS で SceneKit を試す(Swift 3) その40 - Scene Editor カメラの HDR 設定 Part2

引き続き HDR の説明。

カメラとなる SCNCamara の HDR とは、
トーンマッピング処理を行い、シーン全体の輝度値を、ディスプレイに表示できる狭い範囲の輝度値に変換するすること。 具体的には露出調整、Bloom 効果を表現する。

また、HDR は Scene Editor のカメラのプロパティにある HDR のチェックをオンにするか、
コードで SCNCamara の wantsHDR を true にしないと、どの機能プロパティを設定しても動作しない。

 

Scene Editor の パラメーター

f:id:x67x6fx74x6f:20170726152110p:plain

 

HDR

HDR

チェックをオンにすると HDR の機能を動作できるようにする。

f:id:x67x6fx74x6f:20170726152913p:plain

 

Average Gray

HDR を使用する際、Photoshop のトーンカーブのように光の情報をどのように LDR に適応するかトーンマッピングカーブを作成する。

Average Gray はトーンマッピングカーブの中間点として使用する輝度レベルを設定し、暗いまたは明るいコンテンツのシーンを調整することができる。

値を高くすると画面全体の輝度高くなり、 値を低くすると輝度低くなる。

デフォルト値は 0.18。

 

0.05

f:id:x67x6fx74x6f:20170726152536p:plain

 

0.5

f:id:x67x6fx74x6f:20170726152519p:plain

 

White Point

ハイライトとシャドウ間で光の情報の緩やかな遷移、または急な遷移を行う。
デフォルト値は 1.0

 

10.0

f:id:x67x6fx74x6f:20170726152640p:plain

 

0.3

f:id:x67x6fx74x6f:20170726152653p:plain

 

Adaptation

Auto Adapt

チェックを入れると、現在のカメラが映す輝度を自動的に測定し、それに応じて露出レベルを調整する。 さらに、遮蔽物などでシーンの輝度が変化すると、自動的に新しい露出レベルへ変更するアニメーションが行われる。

ドキュメントではデフォルトでオンとなっているが、値は false が返す。

Apple のコードサンプル Badger で洞窟から出る際、この効果が顕著に現れる。

developer.apple.com

 

Auto Adapt なし / あり

f:id:x67x6fx74x6f:20170726152740p:plain

 

Speed Factor

Brightening と Darkening の値があり、暗い領域から明るくなる領域、または明るいところから暗くなる際の持続時間。

デフォルト値では Brightening は 0.4、 Darkening 0.5 と変化が異なる。

 

Exposure

Minimum、Maximum

露光量と最小値を最大値。
最小値を下げると暗い部分が露出不足(均一に黒)になり、 最大値をあげると露出オーバー(均一に白)になる。

1.0 で 2 倍、 2.0 で 4 倍、-1.0 で 1/2。
差が大きいほど、コントラストが低くなる。

デフォルトでは Minimum が -15、Maximum が 15。

 

Minimum -15、Maximum -3。

f:id:x67x6fx74x6f:20170726153839p:plain

 

Minimum 1、Maximum -15。

f:id:x67x6fx74x6f:20170726154034p:plain

 

Offset

トーンマッピングカーブの明暗にオフセット(偏り)をつける。
プラス値を与えると画面全体の輝度が上がり、マイナス値を与えると下がる。

デフォルト値は 0.0

-3

f:id:x67x6fx74x6f:20170726154114p:plain

 

3

f:id:x67x6fx74x6f:20170726154130p:plain

 

Bloom

ブルームエフェクトを与える。
ブルームエフェクトとは、シーンのハイライト(明るい色の領域)にソフトグローを追加し、明るいハイライトを実際の人間の目や物理カメラに表示する方法をシミュレートする。

輝度によって処理が行われるため、設定によってはエフェクトが表示されないことがあるので注意。

 

Intensity

ブルームエフェクトの強さを設定する。
値を小さくすると微妙な効果を得られ、大きくすると非常に明るい輝きが発生する。

デフォルト値は 0.0 で効果は現れない。

 

Threshold

ブルームエフェクトをトリガするために必要な輝度レベルを設定する。 値を小さくするとシーンの広範囲に適応され、 値を大きくするとハイライトのみにエフェクトが適用される。

デフォルト値は 1.0。

 

Blur Radius

ブルームエフェクトでハイライトに適用されるソフトグローのぼかしのピクセル単位の半径。

値を大きくすると広範囲で柔らかいグローが表現され、0 で無効になる。

デフォルト値は 4.0 ピクセル。

 

以下の設定を設定したブルームエフェクト

プロパティ
Exposure Offset 2
Bloom Threshold 6
Bloom Blur Radius 18

f:id:x67x6fx74x6f:20170726160103p:plain

 

コード

let camera = SCNCamera()

// HDR
camera.wantsHDR = true
camera.averageGray = 0.18
camera.whitePoint = 1.0

// Adaptation
camera.wantsExposureAdaptation = true
camera.exposureAdaptationBrighteningSpeedFactor = 0.4
camera.exposureAdaptationDarkeningSpeedFactor = 0.6

// Exposure
camera.minimumExposure = -15.0
camera.maximumExposure = 15.0
camera.exposureOffset = 0.0

// Bloom
camera.bloomIntensity = 0.0
camera.bloomThreshold = 0.5
camera.bloomBlurRadius = 4.0

 

今回はここまで。