6

Unity のレンダリング エンジンがよくわからないと思います。

RenderTexture を使用してスクリーンショットを生成します (後で管理する必要があります)。

    screenshotRenderTexture = new RenderTexture(screenshot.width, screenshot.height, depthBufferBits, RenderTextureFormat.Default);
    screenshotRenderTexture.Create();

    RenderTexture currentRenderTexture = RenderTexture.active;
    RenderTexture.active = screenshotRenderTexture;

    Camera[] cams = Camera.allCameras;

    System.Array.Sort(
            cams,
            delegate(Camera cam1, Camera cam2)
            {
                // It's easier than write float to int conversion that won't floor
                // depth deltas under 1 to zero and will correctly work with NaNs
                if (cam1.depth < cam2.depth)
                    return -1;
                else if (cam1.depth > cam2.depth)
                    return 1;
                else return 0;
            }
        );

    foreach(Camera cam in cams)
    {
        cam.targetTexture = screenshotRenderTexture;          
        cam.Render();
        cam.targetTexture = null;
    }

    screenshot.ReadPixels(new Rect(0, 0, textureWidth, textureHeight), 0, 0);
    screenshot.Apply();

    RenderTexture.active = currentRenderTexture;

ただし、depthBufferBits が 0 の場合、レンダリングの結果、あらゆる種類の z バッファ バグ (間違った順序でレンダリングされるもの) が発生します。

一般的な意味での深度バッファとは何かを理解しています。しかし、私が理解していないのは、RenderTexture を使用して個々のカメラのレンダリング結果を結合する場合、なぜ深度バッファーが必要なのですか? この抽象化は正確にはどのように機能しますか? カメラは独自に画像を作成し、それを RenderTexture に渡しますか、それともカメラは RenderTexture の深度バッファを使用しますか? 私が経験したバグのため、後者のようです(間違った順序のものはすべて同じカメラでレンダリングされるため、問題は1つのカメラ内のものを注文することであり、異なるカメラ間のものを注文することではありません)が、同時にこれらの抽象化が C# レベルでどのように構造化されているかという常識と矛盾する場合があります。

そして最後に、これで通常のレンダリングに使用されるデフォルトの深度バッファをどうにかして使用できますか? モバイル デバイスでの 16 ビット/ピクセルはかなり苦痛だからです。

アップデート:

これが私がやろうとしたことです:

    screenshotRenderTexture = new RenderTexture(
            screenshot.width,
            screenshot.height,
            0,
            RenderTextureFormat.Default
        );
    screenshotRenderTexture.Create();

    RenderBuffer currentColorBuffer = Graphics.activeColorBuffer;
    Graphics.SetRenderTarget(screenshotRenderTexture.colorBuffer, Graphics.activeDepthBuffer);
    yield return new WaitForEndOfFrame();
    Graphics.SetRenderTarget(currentColorBuffer, Graphics.activeDepthBuffer);

そして、ここに私が得たものがあります:

SetRenderTarget can only mix color & depth buffers from RenderTextures. You're trying to set depth buffer from the screen.
UnityEngine.Graphics:SetRenderTarget(RenderBuffer, RenderBuffer)
<ScreenshotTaking>c__Iterator21:MoveNext() (at Assets/Scripts/Managers/ScreenshotManager.cs:126)

画面の深度バッファと RenderTexture のカラー バッファを混合できないのはなぜですか?

4

1 に答える 1

5

Unity についてはよくわかりませんが、基本レイヤーは知っています。たとえば、D3D9、D3d10、OpenGL などにマッピングできる場合、それらの抽象化では共通の分母を使用する必要があります。

この場合、D3D10 が最も限定的であり、異なるサイズのレンダー ターゲット間で深度サーフェスを共有することはできません。同じサイズのスクリーンとレンダー ターゲットがいたるところにある場合、一意の深度バッファーを異なるレンダー ターゲットにバインドできます。

深度バッファなしでレンダリングできることを観察したように、深度バッファは厳密には必要ありませんが、結果は描画コマンドが発行された順序でレンダリングされます。(draw call = D3D の DrawPrimitive、または glDrawBuffers など) グラフィック カードが非常に並列である場合でも、仕様によって三角形レベルで順序が一貫していることが保証されています。 1 つの描画呼び出しの異なる実行による描画の一貫性のため。

深度バッファを使用すると、より低い深度で描画されたオブジェクトの後に描画呼び出しが発生したオブジェクトは、これらの近いオブジェクトを (ビュー空間で) 上書きし、間違った結果をもたらします。深度バッファは、ピクセルごとに破棄するのに役立ちます。 、以前にこのピクセルでレンダリングされたものよりも深い(ビュー空間で)深度を持つオブジェクトのピクセルですが、より近い深度です。

深度バッファーをバインドするとパフォーマンスも向上します。これは、1 つのブロック内のすべてのピクセルが特定の値の最小深度を持つ場合、プリミティブ ラスタライザーは、頂点バッファーの終了後に、プリミティブの全体がこのブロックで決してレンダリングされないことを認識し、破棄するためです。ブロック全体をまとめて。これは早期 Z カリングと呼ばれ、パフォーマンスに大きく役立ちます。そのため、深度バッファを差し込んだままにしておくことが非常に望ましいです。

カメラは、低レベルのグラフィックス理論には概念がありません。単一の頂点変換計算の一部としてワールド空間からビュー空間に世界をシフトするために、全世界に適用される逆変換であるビュー マトリックスによって表されます。そのため、従来の頂点シェーダーでは、オブジェクト空間 (頂点バッファー ストリーム内) から位置が取得され、オブジェクト マトリックス変換、ビュー マトリックス変換、射影マトリックス変換が乗算され、ラスタライザーによって分割されます。すべてを 'w' で囲み、パースペクティブを分割します。

それは、カメラの概念を「作成」するこのパイプライン動作を利用することです。Unity は、カメラ クラスを公開することで、これらすべてを抽象化する必要があります。カメラクラスには、このカメラからのレンダリングがどこに保存されるかを説明する「テクスチャターゲット」メンバーさえあるかもしれません。

はい、レンダリングは指定されたレンダリング テクスチャに対して直接行われます。中間のフロント バッファなどはありません。レンダー ターゲットはハードウェアでサポートされている機能であり、レンダリングの最後にコピーする必要はありません。

レンダー ターゲットはそれ自体が構成全体です。これは、ハードウェア マルチサンプリングにより、必要な解像度のサイズの複数のバッファーを実際にバインドする場合があるためです。

たとえば、MSAA4x の 4 つの RGBA サーフェスであるカラー バッファ、一般に固定小数点 24 ビット表現である深度バッファ、およびステンシル サーフェス用の 8 ビットがあります。これらのサーフェスはすべてレンダー ターゲットの構成を表し、レンダリングに必要です。

これが役立つことを願っています

于 2013-09-27T01:04:04.267 に答える