WWDC Quick Look 💓 By SwiftGGTeam
Explore rendering for spatial computing

Explore rendering for spatial computing

元の動画を見る

ハイライト

visionOS の RealityKit はカスタム image-based lighting、グラウンディングシャドウ、トーンマッピング制御、動的コンテンツスケーリングを追加し、空間コンピューティングにおける 3D コンテンツの見た目とパフォーマンスを開発者が精密に制御できるようにします。

主要内容

iOS と macOS で RealityKit を使って 3D アプリを作ってきました。ライティング、マテリアル、シャドウ——これらの概念は馴染みがあります。しかし同じコンテンツを visionOS に置くと微妙な違いが現れます: システムデフォルトのライティングがシーンの雰囲気に合わない、3D オブジェクトが空中に浮いて根付き感がない、UI の色と 3D マテリアルの色が一致しない、端のモデルがちらつく。

このセッションは4つの次元でこれらの問題に対処します: ライティングとシャドウ、マテリアルとトーンマッピング、ラスタライゼーションレートマップのパフォーマンス最適化、動的コンテンツスケーリングによる鮮明さの保証。

カスタムライティング: Image-Based Lighting

RealityKit は image-based lighting(IBL)で 3D コンテンツをリアルに見せます。IBL は2つの部分から成ります: ARKit が提供する環境プローブテクスチャ(実際の部屋のライティングを反映)とシステム組み込みの IBL テクスチャ(どの環境でもコンテンツが美しく見えることを保証)。両者を加算して最終的な IBL を形成します。

(02:29) visionOS ではシステム IBL を上書きする機能が追加されました。カスタム環境リソースを読み込み、特定のライティング環境で 3D オブジェクトを照らせます。例えば太陽系展示アプリでは「日光」環境リソースで衛星モデルを恒星の光に浴びせられます。

シャドウ: Grounding Shadow

3D オブジェクトを平面上に置いてもシャドウがないと、ユーザーは相対的な高さを判断しにくくなります。平面中央に浮く花瓶は漂っているように見えます。

(04:16) GroundingShadowComponentcastsShadow: true で追加すると、オブジェクトは下方向にシャドウを投射します。このシャドウは 3D モデル上にも実環境の物体表面にも投射されます。ユーザーは一目で花瓶が平面上にあることがわかります。

マテリアルとトーンマッピング

visionOS の RealityKit は iOS/macOS のすべてのマテリアルタイプをサポートします: PhysicallyBasedMaterial、SimpleMaterial、UnlitMaterial、VideoMaterial、および新しい ShaderGraphMaterial。

(06:34) すべてのマテリアルのデフォルト出力はトーンマッピングを通過します。トーンマッピングは 1.0 を超える色値を可視範囲に再マッピングし、ハイライト領域の詳細をより多く保持します。例えばテレビ画面のテクスチャでは、トーンマッピング有効時に花弁の明部詳細がより鮮明になります。

しかし一部のシーンでは精密な色一致が必要です。信号機アプリでは 3D モデルの灯色が SwiftUI ボタンの色と完全に一致する必要があります。UnlitMaterial はライティングの影響を受けませんが、出力は依然としてトーンマッピングを通過し、SwiftUI の色との微妙な差が生じます。

(08:48) UnlitMaterialapplyPostProcessToneMap パラメータが追加され、false に設定するとトーンマッピングを無効にし、SwiftUI UI 要素との精密な色一致を実現できます。

ラスタライゼーションレートマップ

visionOS のディスプレイは高解像度で、システムは毎秒複数回更新する必要があります。パフォーマンス節約のため、システムはラスタライゼーションレートマップ技術を使用します: ユーザーが見ている視野中心では高解像度レンダリング、周辺部では低解像度。

(10:27) この最適化は RealityKit で自動的に有効ですが、一部のコンテンツは調整が必要な場合があります。発表者はヤシの葉モデルを示します。画面右側を見ているとき、左のヤシの葉がちらつきます。原因は多数の小さな三角形が低解像度の周辺領域でアンチエイリアシングを生じさせることです。

(12:14) 解決策は小さな三角形を大きくし、詳細を透明度テクスチャに格納することです。RealityKit はテクスチャの mipmap を自動生成し、低解像度領域で適切なレベルを使用してちらつきを除去します。

動的コンテンツスケーリング

visionOS の SwiftUI と UIKit アプリは動的コンテンツスケーリングの恩恵を自動的に受けます。システムは視線位置に基づいて UI コンテンツを異なる解像度でラスタライズします——ユーザーが見ている領域が最高解像度、周囲はやや低く、端は最低です。

(15:34) Core Animation で直接 UI を構築する場合は手動で有効化します: CALayer.wantsDynamicContentScaling = true を設定します。この技術は高解像度ラスタライズに依存し、ビットマップ主体のコンテンツには適しません。

詳細

カスタム Image-Based Lighting

RealityView { content in
    async let satellite = Entity(named: "Satellite", in: worldAssetsBundle)
    async let environment = EnvironmentResource(named: "Sunlight")

    if let satellite = try? await satellite, let environment = try? await environment {
        content.add(satellite)

        satellite.components.set(ImageBasedLightComponent(
           source: .single(environment)))

        satellite.components.set(ImageBasedLightReceiverComponent(
           imageBasedLight: satellite))
   }
}

キーポイント:

  • EnvironmentResource(named:) でカスタム環境ライティングリソースを読み込みます
  • ImageBasedLightComponent で IBL ソースを指定し、システムデフォルト IBL を置き換えます
  • ImageBasedLightReceiverComponent でエンティティがその IBL のライティングを受信します
  • 他のエンティティに receiver component を追加して同じライティングを共有できます

Grounding Shadow の追加

RealityView { content in
    if let vase = try? await Entity(named: "flower_tulip") {
        content.add(vase)

        vase.components.set(GroundingShadowComponent(castsShadow: true))
    }
}

キーポイント:

  • GroundingShadowComponent(castsShadow: true) でシャドウ投射を有効化します
  • シャドウは 3D モデルと実環境の物体に投射されます
  • 1行のコードで、光源やシャドウマップの手動設定は不要です

トーンマッピングを無効にして精密な色を実現

RealityView { content in
    if let trafficLight = try? await Entity(named: "traffic_light") {
        content.add(trafficLight)

        if let lamp = trafficLight.findEntity(named: "red_light") {
            if var model = lamp.components[ModelComponent.self] {
                let material = UnlitMaterial(
                    color: .init(color),
                    applyPostProcessToneMap: false  // トーンマッピングを無効化
                )

                model.materials = [material]
                lamp.components[ModelComponent.self] = model
            }
        }
    }
}

キーポイント:

  • applyPostProcessToneMap: false でマテリアルの後処理トーンマッピングを無効化します
  • SwiftUI UI との精密な色一致が必要なシーンに適しています
  • HUD、メニューなど精密な色表示が必要なシーンにも適しています
  • このパラメータは Reality Composer Pro のマテリアルエディタにも公開されています

Dynamic Content Scaling の有効化

// Core Animation の CALayer で有効化
layer.wantsDynamicContentScaling = true

キーポイント:

  • SwiftUI と UIKit アプリは自動的に有効で、追加操作は不要です
  • Core Animation で構築した UI は wantsDynamicContentScaling を手動設定する必要があります
  • 高解像度ラスタライズに依存し、ビットマップ主体のコンテンツには適しません
  • システムは視線位置に基づいて異なる領域のレンダリング解像度を自動調整します

重要ポイント

1. 3D 展示アプリにシーン専用ライティングを追加

アート作品、自動車、家具などの 3D モデルを表示するアプリでは、デフォルトのシステム IBL では製品の特徴を引き出せない場合があります。複数の環境ライティングリソース(スタジオ照明、自然光、暖色調)を用意し、ユーザーに切り替えさせます。入口: EnvironmentResource + ImageBasedLightComponent

2. 表面上のすべての 3D オブジェクトに Grounding Shadow を追加

シャドウのない 3D オブジェクトは不安定に見え、没入感を損ないます。仮想キーボード、3D アイコン、ゲームキャラクターなど、表面の上に立つものすべてに GroundingShadowComponent を追加します。入口: 1行 .set(GroundingShadowComponent(castsShadow: true))

3. 色が精密なデザインツールを構築

3D モデリング、マテリアルプレビュー、カラーツールなどのデザイン系アプリでは、ユーザーは「この赤がまさに #FF0000 である」ことを見る必要があります。トーンマッピングを無効にし、UnlitMaterial で精密な色を表示し、横に SwiftUI の Color ビューで対照します。入口: UnlitMaterial(color:applyPostProcessToneMap: false)

4. Rasterization Rate Map に合わせて 3D アセットを最適化

3D モデルが多数の微小三角形(1ピクセル未満)を使用しているか確認します。該当する場合は小さな三角形を統合し、切り抜き詳細を透明度テクスチャに移します。これにより視野端の低解像度領域でのちらつきを防げます。入口: Reality Composer Pro で三角形統計を確認し、「Rendering at Different Rasterization Rates」ドキュメントを参照します。

関連セッション

コメント

GitHub Issues · utterances