2013-09-26 117 views
4

我認爲我不太理解Unity渲染引擎。爲什麼我需要depthBuffer才能使用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緩存的bug(中呈現的東西結果錯誤的順序)。

我明白了什麼是一般意義上的深度緩衝。但是,我不明白的是 - 如果使用RenderTexture來合併單個相機的渲染結果,爲什麼需要深度緩衝區?這個抽象如何工作,確切地說 - 相機是否自己創建圖像,然後將其提供給RenderTexture,或者相機是否使用RenderTexture的深度緩衝區?它似乎是後者,因爲我遇到的錯誤(錯誤順序的東西都是用同一個相機渲染的,所以問題是在一個相機內部排序,而不是在不同相機之間排序),但是在相同的情況下這與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的顏色緩衝區?

回答

3

我不知道團結好,但我知道他們的底層,如果他們能映射在說,D3D9,D3D10和OpenGL那麼他們的抽象必須使用一個共同點。

在這種情況下,D3D10是最有限的,您不能共享不同尺寸的渲染目標之間的深度表面。如果屏幕尺寸相同,並且渲染目標遍佈整個地方,那麼您確實可以將獨特的深度緩衝區綁定到不同的渲染目標。

深度緩衝是沒有必要像你看到,你可以沒有深度緩衝渲染,但那麼結果只是其中的繪圖命令被下達的命令渲染狹義。 (在D3D中繪製call = DrawPrimitive,或者使用glDrawBuffers等等)甚至可以保證,在規範的三角形層次上該順序是一致的,即使圖形卡非常平行,他們也不會爲通過一次繪製調用的不同運行繪圖的一致性。

如果您使用深度緩衝區,那麼在深度較低的對象之後發生其繪圖調用的對象將覆蓋這些關閉的對象(在視圖空間中)並給出錯誤的結果,深度緩衝區有助於逐像素丟棄一個物體的像素,該物體的深度(在視圖空間中)的深度比之前在該像素處已經渲染的深度深,但深度更接近。

綁定深度緩衝區也有助於提高性能,因爲如果一個塊中的每個像素的最小深度都達到某個值,那麼原始柵格化器在退出頂點緩衝區後知道您的基元的整個部分將永遠不會渲染塊,並完全丟棄整個塊。這被稱爲Z早期撲殺,對性能有很大的幫助。所以最好保持深度緩衝區的插入。

相機在低級圖形理論中沒有概念,它只是一個視圖矩陣,它是一個應用於整個世界的逆向變換,將世界從世界空間轉移到視圖空間,作爲任何單個頂點的一部分變換計算。這就是爲什麼在經典的頂點着色器中,位置是從對象空間(在頂點緩衝流中)獲取的,然後乘以對象矩陣變換,然後通過視圖矩陣變換,然後進行投影矩陣變換,然後光柵化器分開'w'使所有視角分裂。

這是通過利用這種管道行爲,你「創造」了相機的概念。 Unity必須通過暴露相機類來抽象所有這些。也許相機類甚至有一個「紋理目標」成員來解釋這個相機的渲染將被存儲在哪裏。

是的,渲染是直接對指定的渲染紋理進行的,沒有中間前置緩衝區或其他,渲染目標是硬件支持的功能,並且在渲染結束時不需要複製。

渲染目標本身是一個完整的配置,因爲硬件多重採樣,它可能實際上綁定了所需分辨率大小的多個緩衝區。

存在顏色緩衝區,例如MSAA4x中的4個RGBA表面,深度緩衝區(通常是固定點24位表示)和8位模板表面。所有這些表面都表示渲染目標配置並且對渲染是必需的。

我希望這可以幫助

相關問題