「Unity Shader入門要旨」13章深さ法線とテクスチャノートの使用


深度法線とテクスチャの使用(Use Depth Normals and Texture)
深度と法線テクスチャの取得(Get Depth and Normal Texture)
げんり
深度テクスチャ(Depth Texture)
  • はレンダリングテクスチャで、格納されたピクセル値は高精度の深さ値です.
  • の範囲は[0,1]であり、通常は非線形分布である.
  • の深さ値は、頂点変換後に得る正規化されたデバイス座標
  • から生じる.
  • 頂点が整列剪断空間に変換されると、z座標はその深さ値になります.ただし、z成分の範囲は[-1,1]なので、画像に保存できるように、d=0.5*z+0.5を使用して[0,1]の範囲に変更します.
  • Unityの深度テクスチャは、レンダリングパスとハードウェアに応じて、真の深度キャッシュから取得することも、1つのPassレンダリングから取得することもできます.
  • 遅延レンダリングパスを使用すると、G-bufferから直接深度情報を取得できます.
  • デプスキャッシュを直接取得できない場合、デプスと法線テクスチャは別々のPassレンダリングによって取得されます.
  • 具体的には、Unityはシェーダ置換技術を使用して、レンダリングタイプがOpaqueの物体を選択し、使用するレンダリングキューが2500(Background、Geometry、AlphaTestを含む)未満であるかどうかを判断し、条件を満たすと深さおよび法線テクスチャにレンダリングする.
  • Unityでは、カメラに深度テクスチャを生成するか、深度+法線テクスチャを生成するかを選択できます.
  • 前者を選択すると、Unityは直接深度キャッシュを取得するか、前述したシェーダ置換技術に従って、物体がシャドウを投影するときに使用するPassを使用して深度テクスチャを取得します.shaderにこのようなpassが含まれていない場合、物体は深さテクスチャに現れません.深度テクスチャの精度は、通常、深度キャッシュの精度に応じて24ビットまたは16ビットです.
  • 深さ+法線テクスチャを生成する場合、Unityは画面解像度と同じ32ビットの精度のテクスチャを作成し、観察空間の法線情報がテクスチャのRおよびGチャネルに符号化され、深さ情報がBおよびAチャネルに符号化される.法線情報は、遅延レンダリングパスで簡単に取得できます.法線と深度キャッシュをマージすればいいです.順方向レンダリングでは、既定では法線キャッシュは作成されません.そのため、Unityの下部では、別のPassを使用してシーン全体を再レンダリングします.このPassはUnityに内蔵されたUnity Shaderに含まれており、builtin_shaders-xxx/DefaultResources/Camera-DepthNormalTexture.shaderファイルには、深さと法線情報をレンダリングするためのPassがあります.

  • 取得方法
  • 深さテクスチャを取得するのは簡単で、スクリプトにカメラのdepthTextureModeを設定して完成します:
  • camera.depthTextureMode = DepthTextureMode.Depth;
    
  • 以降shaderで宣言_CameraDepthTexture変数を使用してアクセスします.
  • と同様に、深さ+法線テクスチャを取得します.コードに設定するだけです.
  • camera.depthTextureMode = DepthTextureMode.DepthNormals;
    
  • 以降shaderで宣言_CameraDepthNormalTexture変数を使用してアクセスします.
  • 通常、tex 2 Dを直接使用してテクスチャをサンプリングすればよいが、PS 3やPS 2などのプラットフォームでは、いくつかの特殊な処理が必要である.Unityは、統合されたマクロ、SAMPLEを提供しています.DEPTH_TEXTUREは、これらのプラットフォームの違いを処理します.
  • float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv);
    
  • i.uvは、現在のピクセルのテクスチャ座標に対応するfloat 2タイプの変数です.
  • のようなマクロとSAMPLE_DEPTH_TEXTURE_PROJは、同じように2つのパラメータを受け入れ、2番目のパラメータは1つのfloat 3またはfloat 4タイプのテクスチャ座標であり、最初の2つの成分はuv座標であり、最初の2つの成分を3番目の成分で割ってサンプリングし、4番目の成分を提供すると、シャドウの実装で一般的に使用される再比較が行われます.例:
  • float d = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture,UNITY_PROJ_COORD(i.srcPos));
    
  • i.src Posは、頂点シェーダでComputerScreenPos(o.pos)を呼び出すことによって得られる画面座標です.
  • サンプリングにより得られたz成分は非線形であり、視角空間などの線形空間に変換する必要がある.
  • 整列剪断空間を画角空間に変換する方法は、画角空間から整列剪断空間への式から逆に推定することができる.
  • Unityは、上記の計算プロセス:LinearEyeDepthとLinear 01 Depthの2つの補助関数を提供します.
  • LinearEyeDepthは、サンプリングにより得る深さ値を観察空間の深さ値
  • に変換する役割を果たす.
  • Linear 01 Depthは、[0,1]の範囲の線形深さ値を返します.
  • の2つの関数には、組み込み変数が使用されています.ZBufferParams変数を用いて,遠近剪断面の距離を得た.
  • 深さ+法線テクスチャを得る必要がある場合はtex 2 D関数対_CameraDepthNormalTextureでサンプリングを行います.
  • Unityは、サンプリング結果を復号する補助関数DecodeDeothNormalを提供する:
  • inline void DecodeDepthNormal(float4 enc,out float depth,out float3 normal){
        depth = DecodeFloatRG(enc.zw);
        normal = DecodeViewNormalStereo(enc);
    }
    
  • の最初のパラメータは深さ法線テクスチャのサンプリング結果であり、この結果はUnityが深さ法線情報を符号化した結果であり、xy成分は視点空間下の法線情報を格納し、深さ情報はzw成分に符号化される.補助関数を呼び出すと復号後の深さと法線情報が得られる.この深さ値は[0,1]の範囲の線形深さ値(個別の深さテクスチャに格納されている深さ値とは異なる)であり、得られる法線は視点空間の法線方向である.同様に、DecodeFloatRGとDecodeViewNormalStereoを呼び出すことで、深さ+法線テクスチャの深さと法線情報を復号することもできます.

  • 深度と法線テクスチャの表示(View Depth and Normal Texture)
  • カメラレンダリング深度と法線テクスチャを設定した後、Frame Debugで確認できます.
  • 個々の深さテクスチャは、非線形空間における深さ値を示す.深さ加算線テクスチャは,符号化後の結果を示した.
  • 線形空間または復号後の結果を示すためにshaderを記述することができる.

  • モーションブラーについて
  • モーションブラーのより広範な技術は、速度マッピングマップを使用することである.速度マップは、各ピクセルの速度を格納し、この速度を使用してぼかしのサイズと方向を決定します.
  • 速度バッファ生成の方法は多い.1つは、シーン内のすべての物体の速度をテクスチャにレンダリングすることです.この方法の欠点は、シーン内のすべての物体のshaderコードを修正し、計算速度のコードを追加してレンダリングテクスチャに出力する必要があることです.
  • 『GPU Gems 3』では、速度マップを生成する方法が紹介されている.この方法は,現在の視野角*投影行列の逆行列を用いてNDC下の頂点座標を変換することによって,各画素について,深さテクスチャを用いて計算した.前のフレームの位置のNDC座標を同じ方法で得た.次に差分値を求め、その画素の速度を生成する.利点は、スクリーン後の処理時に効果全体のシミュレーションが完了したことです.欠点は、性能に影響を及ぼす2回のマトリクス乗算の操作を、メタシェーダで行う必要があることです.

  • グローバルフォグエフェクト(Global Fog Effect)
  • フォグ効果はゲームでよく使われる効果です.Unityに組み込まれたフォグ効果は、距離ベースの線形または指数的フォグ効果を生成します.自分で作成した頂点/チップシェーダでこれらのフォグ効果を実現するには、Shaderに#pragma multi_を追加する必要があります.compile_fogコマンドは、UNITY_などの関連する内蔵マクロも使用する必要があります.FOG_COORDS、UNITY_TRANSFER_FOGとUNITY_APPLY_FOGなど.
  • この方法の欠点は、シーン内のすべての物体に関連するレンダリングコードを追加するだけでなく、実現可能な効果も非常に限られていることである.
  • スクリーン後処理に基づくグローバルフォグ効果について学習します.この方法は種々のミスト効果を容易にシミュレートできる.
  • スクリーン後処理に基づくグローバルフォグ効果の鍵は、深さテクスチャに基づいて各ピクセルの世界空間下での位置を再構築することである.
  • 再構成方法:(モーションブラーよりも効率的に)画像空間下のテーパ線(カメラから画像上のある点を指す線)を補間し、この線はこの画素が世界空間下でカメラに向かう方向情報を格納する.次に,この放射線と線形化された視点空間における深さ値を乗算し,カメラの世界位置を加えると,この画素の世界空間における位置を得ることができる.世界座標を得ると,各式を用いてグローバルフォグ効果をシミュレートすることができる.

  • エッジ検出について
  • 以前はSobel演算子を用いていたが,色に応じてエッジ検出を行い,ストローク効果を実現した.しかし、私たちが望んでいないエッジ線がたくさん得られます.
  • 深さと法線テクスチャを使用してエッジ検出を行います.
  • このセクションでは、Roberts演算子を使用してエッジ検出を行います.
  • テクスチャサンプリングにより、現在のセルの左上と右下、左下と右上を比較するセルの法線と深さの値の差の大きさを取得し、閾値を超えるとエッジとみなされます.このような方法は、色ベースのエッジ検出よりも正確である.