ARDKにおけるレンダリング
アプリ内のカメラフィードのレンダリング方法をカスタマイズする。
概要
ARDKでは、設定可能なレンダリングパイプラインを利用できます。対象シーンに ARRenderingManager コンポーネントを追加することで(通常はシーンカメラオブジェクトに追加)、レンダリングパイプラインが画面に対してカメラフィードを確実にレンダリングできるようにします。
ARRenderingManagerコンポーネントは、ネイティブイメージがフレームごとに更新されて画面に継続的にレンダリングされる方法を設定および管理します。さらに、要求に応じてCPUまたはGPUメモリ内に(カメラ画像の)スナップショットテクスチャを生成することも可能です。
カスタムコマンドバッファを書く
ARDKのレンダリングパイプラインに加えて、Unityのカスタムグラフィックスコマンドバッファも使用できます。カスタムコマンドバッファは、Unityの CameraEvent.BeforeForwardOpaque
またはレンダラーのGPUFenceのあとに実行されるべきものです。
深度情報とレンダリングパイプライン
カメラフィードデータのレンダリングに加えて、セッションが深度データを生成するよう設定されている場合は、ARDKのレンダーパイプラインがzバッファデータの生成も行います。そのため、対象シーンで深度生成を有効化する場合は、 ARDepthManager
を使用するにしても、 ARSession
を IsDepthEnabled
に設定するにしても、シーンには ARRenderingManager
が必須となります。 ARDepthManager
を使う場合、 ARRenderingManager
を追加したのと同じオブジェクトに ARDepthManager
コンポーネントを追加する必要があります。
ARDepthManager
から深度情報を取得する方法の詳細は、 深度データの生成 をご参照ください。
アウェアネスバッファを画面に合わせて調整する
深度バッファとセマンティックバッファでは、パイプラインが生成・利用するバッファは必ずしもデバイスのカメラまたは画面と一致するものではありません。ARDKでは DepthBufferProcessor.CopyToAlignedTextureARGB32 、 DepthBufferProcessor.CopyToAlignedTextureRFloat 、 SemanticBufferProcessor.CopyToAlignedTextureARGB32 を使ってバッファを調整する手法が利用可能ですが、これらの手法はピクセルごとの処理を用いるため時間がかかる場合があります。
より高速な代替手段は、適切なAwarenessProcessorから SamplerTransform
を取得し、カスタムシェーダーで使用することです。たとえば次のARDepthManagerから SamplerTransform
を取得できます:
Matrix4x4 samplerTransform = depthManager.DepthBufferProcessor.SamplerTransform;
それから使用したい未調整のテクスチャを取得します。たとえば深度バッファのフロートテクスチャなどです:
Texture2D depthTexture; depthBuffer.CreateOrUpdateTextureRFloat(ref depthTexture);
未調整テクスチャとトランスフォームを使用して移行を垂直加工機能に適用するカスタムシェーダーを作成します:
Shader "Custom/DepthSh" { ... SubShader { // No culling or depth Cull Off ZWrite Off ZTest Always Pass { ... // Transforms used to sample the context awareness textures float4x4 _depthTransform; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; // Transform UVs for the context awareness textures o.depth_uv = mul(_depthTransform, float4(v.uv, 1.0f, 1.0f)).xyz; return o; } ...
最後に、必要に応じて対象シーン内のカスタム素材でこのシェーダーを使います。たとえば、調整した深度バッファテクスチャを画面へ転送するには OnRenderImage()
が有効かもしれません:
public Material _shaderMaterial; .... void OnRenderImage(RenderTexture source, RenderTexture destination) { //pass in our raw depth texture _shaderMaterial.SetTexture("_DepthTex", depthTexture); //pass in our transform _shaderMaterial.SetMatrix("_depthTransform", samplerTransform); //blit everything with our shader Graphics.Blit(source, destination, _shaderMaterial); }
深度バッファまたはセマンティックバッファの調整の各ステップ例は 中級チュートリアル: 深度テクスチャ と 中級チュートリアル: セマンティック セグメンテーションテクスチャ をご参照ください。
ARアップデートの取得
このステップはiOSプラットフォームでは不要ですが、Androidプラットフォームでは必要です。Androidの場合、ARアップデートは必ずコマンドバッファのコマンドから取得しなければなりません(このコマンドを実行しないと ARFrame
アップデートが表出しません)。カスタムコマンドを使用したい場合、次を呼び出します:
yourCommandBuffer.IssuePluginEventAndData(yourARSession);
このARSessionBuffersHelperメソッドは、ARアップデートを取得するためにバッファにコマンドを追加するだけです。そのバッファの実行を設定するものではありません。コマンドバッファがARアップデートを起動するため、レンダリングループの一部のように繰り返し実行する必要があります。 ARCore
は30fpsでアップデートするため、それ以上の数値を目指してください。