見出し画像

ARKitでネオンサインを作る方法

ネオンってかっこいいですよね。私はサイバーパンクものが大好きなんですけど、作中の街の風景で必ず出てくるのがネオンサイン。今回、このネオンサインをARで再現したい思います。

サイバーパンクな街並み

それでは、ARKitでネオンサインのようなオブジェクトを作る方法を解説したいと思います。シェーダーフレームワークMetalを使わずに標準APIのみで作れます。出来栄えは以下の通りです。

解説なんていらねーから、githubのリンクを貼れという方はこちらをどうぞ
ソースをアップロードしておきました


1.光の瞬きを表現する
光の瞬きはCIFilterのCIBloomを使用します。
オブジェクトに設定するフィルターを返す関数を用意します。
inputIntensityは光の強さ、inputRadiusはぼやかす半径です

func addBloom() -> [CIFilter]? {
    let bloomFilter = CIFilter(name:"CIBloom")!
    bloomFilter.setValue(6.0, forKey: "inputIntensity")
    bloomFilter.setValue(15.0, forKey: "inputRadius")
    return [bloomFilter]
}

オブジェクト対して、フィルターをかけるにはMetalを使わなければいけないと思ってましたが、ライブラリがあるんですね。下記のstackOverflowで存在を知りました。

これだけでも、光ってる感じ出ますが、ネオンサイン感はない

テキストオブジェクトにCIFilterを適用した状態

実際のネオンは光の色に対して彩度をかなり白に近づけた蛍光灯の部分があります。これがない

実際のネオン

2.蛍光灯の部分を表現する
まず、蛍光灯部分のオブジェクトの色のsaturation(彩度)をかなり白め(0.1)に設定します。その後蛍光灯オブジェクトをcloneしてフィルターを設定する光オブジェクトを作成します。光オブジェクトは蛍光灯に重ねますので、alpha(透明度)を少し落としておきます(0.8に設定)
最後に操作しやすいように、適当なnodeを用意して、それらの子要素として蛍光灯と光を重ねます。

let text = "MASAO"

// 蛍光灯
let textGeo1 = SCNText(string: text,extrusionDepth: 1)
textGeo1.firstMaterial?.diffuse.contents = UIColor(hue: 0.5, saturation: 0.1, brightness: 1, alpha: 1)
let textNode1 = SCNNode()
textNode1.geometry = textGeo1
textNode1.position = SCNVector3(0, 0, 0)
textNode1.scale = SCNVector3(0.05,0.05,0.99);
let (min1, max1) = (textNode1.boundingBox)
let w1 = Float(max1.x - min1.x)
let h1 = Float(max1.y - min1.y)
textNode1.pivot = SCNMatrix4MakeTranslation(w1/2 + min1.x, h1/2 + min1.y, 0)
textNode1.scale = SCNVector3(0.01,0.01,0.01)

// 光
let textGeo2 = SCNText(string: text,extrusionDepth: 1)
textGeo2.firstMaterial?.diffuse.contents = UIColor(hue: 0.5, saturation: 1, brightness: 1, alpha: 0.8)
let textNode2 = textNode1.clone()
textNode2.geometry = textGeo2
textNode2.filters = addBloom()

// 重ねる
let node = SCNNode()
node.position = SCNVector3(0, 0, -0.7)
node.addChildNode(textNode1)
node.addChildNode(textNode2)
sceneView.scene.rootNode.addChildNode(node)

この状態がこれ

蛍光灯部分を足した状態

だいぶ良い感じになりましたが、テキストを押し出してオブジェクトを作成しているので角ばりが気になる。そこで光源設定をfalseにします。

sceneView.autoenablesDefaultLighting = false

その結果が最終系のこちら、陰影がなくなって蛍光灯のような丸みが出ました。 いい感じ!!

光源設定をfalseにした状態

解説は以上となります。
最後まで読んでいただきありがとうございました。


この記事が気に入ったらサポートをしてみませんか?