見出し画像

Reality Composer ProのShader Graph Materialで少しリッチの表現に

先日リリースしたApple Vision Pro向けの空間ゲームをアップデートしました!

Immersive Spaceのskyboxを複数から選択できるようになったことがメインですが、実はスペースシップが通過するチェックポイントのマテリアルをSimpleMaterialからShaderGraphMaterialに変更して、チェックポイントの表現を少しリッチにしました。今回はその方法について紹介します。

シンプルなチェックポイントの表現

今まではチェックポイントのEntityを生成する際に、SimpleMaterialを使ってカラーと透明度、粗さを指定していました。空間内に配置した時の見た目で値をある程度調整したとはいえ、やはり表現の単調っぽさが残っていたので、今回はShaderGraphMaterialを使ってもう少しリッチな表現にできないか試してみました。

func createCheckPoints(_ numberOfCheckPoints: Int, checkPointRadius: Float) async -> [Entity] {    
    var entities: [Entity] = []
    ...
    
    // シンプルなカラー指定・半透明のマテリアル
    let material = SimpleMaterial(color: .init(red: 1, green: 0, blue: 0, alpha: 0.5), roughness: 0.75, isMetallic: false)
    
    for (index, position) in positions.enumerated() {
        let entity = Entity()
        entity.name = "CheckPoint\\(index+1)"
        entity.components.set(ModelComponent(mesh: .generateSphere(radius: checkPointRadius), materials: [material]))
        ...
        let collisionShape = ShapeResource.generateSphere(radius: checkPointRadius)
        entity.components.set(CollisionComponent(shapes: [collisionShape]))
        
        entities.append(entity)
    }
    
    return entities
}

Shader Graphとは?

Shader GraphはReality Composer Proで3Dコンテンツ用のマテリアルやエフェクトをノードベースで構築できる機能で、たくさんの種類のノードを組み合わせると、時間経過でカラーを変化させたり、表面を模様が波打ったり、アニメ調にしたり、ディソルブなどの効果やアニメーションも作り出すことができます。

なお、Shader GraphはUnityでも以前から提供されていて、やり方や実装例が多く紹介されています。

Shader Graphでフレネル効果を表現

今回はこちらのリポジトリで紹介されているフレネル効果(Fresnel Effect)というエフェクトを参考に、少し時間経過による変化も加えて、チェックポイントの表現をリッチにしてみました。

フレネル効果とは、視線の角度によって表面上の反射率が変わり、入射角が平行に近いほど反射率が高くなる効果で、水面を真上から見ると底が見えるが水平から見ると景色を反射するイメージです。

フレネル効果は、3Dモデルの法線ベクトルとカメラの視線ベクトルの内積を使って表現することができ、Reality Composer Proでは以下のようにShader Graphで実現できます。なお、フレネルの式や反射係数の近似式はこちらを参照してください。

Shader Graphでフレネル効果を作る

また、Reality Composer Proで作成したマテリアルを取得するには、ShaderGraphMaterial(named:from:in:)を使えばよいのですが、nameは対象マテリアルへのフルパスである必要があり、ここで指定した文字列とReality Composer Pro上でのツリー構造がずれていると、正しくマテリアルが読み込まれないことに注意が必要です。

// nameは対象マテリアルへのフルパス
let material = try? await ShaderGraphMaterial(named: "/Root/UnvisitedCheckPoint/UnvisitedMaterial", from: "Materials/CheckPointMaterial", in: realityKitContentBundle) ?? SimpleMaterial(...)
entity.components.set(ModelComponent(mesh: .generateSphere(radius: checkPointRadius), materials: [material]))

これでShader Graphを使ってチェックポイントの表現を少しリッチにすることができました。冒頭での画像と比較してもおしゃれで動きのある表現になったのではないかと思います!

おわりに

今回はShader Graphを使って、フレネル効果でチェックポイントの表現を少しリッチにしてみましたが、Shader Graphの奥深さに触れることができ、もっと高度で複雑な表現もできそうという感触を掴むことができました。今後はいろいろな表現にチャレンジしてみようと思います!

いいなと思ったら応援しよう!