2009-07-11 99 views
1

我正在寫在D3D9一個3D建模應用程序,我想使盡可能廣泛的兼容性。這意味着使用少數依賴於硬件的功能,即多重採樣。然而,雖然實時渲染不需要完美無瑕,但我確實需要提供漂亮的屏幕捕捉,而沒有多重採樣,看起來很粗糙和很差。抗鋸齒/多重採樣在D3D9

爲了製造我的截屏,我在內存中創建一個臨時的表面,使現場一次,然後將其保存到一個文件中。我的,我怎麼能實現抗鋸齒捕獲的第一個想法是創造我的屏幕外的stencilsurface作爲多次採樣,但當然DX不允許,由於設備本身已經與D3DMULTISAMPLE_NONE初始化。

要開始了,下面是我究竟如何創建一個抓屏樣品。我知道它會更簡單,只是保存已渲染幀的後備緩衝,但我需要保存不同尺寸的影像比實際的渲染窗口的能力 - 這就是爲什麼我做這種方式。爲簡潔起見,錯誤檢查,恢復狀態的代碼和釋放資源在此處省略。 m_d3ddev是我的LPDIRECT3DDEVICE9。

//Get the current pp 
LPDIRECT3DSWAPCHAIN9 sc; 
D3DPRESENT_PARAMETERS pp; 
m_d3ddev->GetSwapChain(0, &sc); 
sc->GetPresentParameters(&pp); 

//Create a new surface to which we'll render 
LPDIRECT3DSURFACE9 ScreenShotSurface= NULL; 
LPDIRECT3DSURFACE9 newDepthStencil = NULL; 
LPDIRECT3DTEXTURE9 pRenderTexture = NULL; 
m_d3ddev->CreateDepthStencilSurface(_Width, _Height, pp.AutoDepthStencilFormat, pp.MultiSampleType, pp.MultiSampleQuality, FALSE, &newDepthStencil, NULL); 
m_d3ddev->SetDepthStencilSurface(newDepthStencil); 
m_d3ddev->CreateTexture(_Width, _Height, 1, D3DUSAGE_RENDERTARGET, pp.BackBufferFormat, D3DPOOL_DEFAULT, &pRenderTexture, NULL); 
pRenderTexture->GetSurfaceLevel(0,&ScreenShotSurface); 

//Render the scene to the new surface 
m_d3ddev->SetRenderTarget(0, ScreenShotSurface); 
RenderFrame(); 

//Save the surface to a file 
D3DXSaveSurfaceToFile(_OutFile, D3DXIFF_JPG, ScreenShotSurface, NULL, NULL); 

你可以看到調用CreateDepthStencilSurface(),這是我希望我能有即D3DMULTISAMPLE_4_SAMPLES取代pp.MultiSampleType,但沒有奏效。

我的下一個想法是創建一個完全不同的LPDIRECT3DDEVICE9作爲D3DDEVTYPE_REF,它始終支持D3DMULTISAMPLE_4_SAMPLES(不管視頻卡)。然而,我所有的資源(網格,紋理)的已加載到m_d3ddev,我HAL設備,因此,我無法將它們用於REF設備下渲染場景。請注意,資源可以在Direct3d9ex(Vista)下的設備之間共享,但我正在使用XP。由於存在相當多的資源,重新加載所有內容以渲染這一幀,然後卸載它們對於我的應用程序而言效率太低。

我看了看其他的選擇抗鋸齒的圖像捕捉後(即3×3模糊濾鏡),但它們都產生很糟糕的結果,所以我很想嘗試,並得到一個反鋸齒場景右出D3D,如果可能的....

任何智慧或指針將不勝感激......

謝謝!

+0

爲什麼不檢測多采樣能力,只是在可用的情況下使用(可能需要禁用性能選項)?我的意思是,這不像你通過做你想做的事來提高兼容性。 – U62 2009-07-11 18:39:10

+0

那麼,這是我最後的選擇......但我真正想做的是能夠提供antialiased圖像,無論視頻卡的能力。我沒有那麼在乎實時的質量呈現 (是的,這肯定會提高兼容性 - 因爲_always_支持多重採樣,所以如果我可以使用該類型設備的參考設備來呈現的截圖,它應該冷靜但仍有上述問題,所以我希望一些其他的解決辦法...) – Metal450 2009-07-11 22:37:27

回答

3

通過渲染到更大的緩衝區和縮小或組合抖動緩衝區的超採樣可能是您最好的選擇。組合多個抖動緩衝區應該爲給定數量的樣本提供最佳質量(比簡單渲染等分樣本數量多倍的分辨率和縮小比常規網格更好),但是會產生額外的多次渲染通道開銷。它的優點是不受你渲染目標支持的最大尺寸的限制,並且允許你選擇幾乎任意級別的AA(儘管如果組合了許多抖動緩衝區,你將不得不關注精度問題)。

opengl.org上的文章「用積累緩衝區進行抗鋸齒」介紹瞭如何修改用於抖動採樣(OpenGL,但數學基本相同)的投影矩陣。亞歷山大·凱勒和沃爾夫岡·海德里奇的論文「Interleaved Sampling」談到了技術的擴展,它會以更多的渲染過程爲代價提供更好的採樣模式。對不起,不提供鏈接 - 作爲一個新用戶,我只能爲每個答案發佈一個鏈接。谷歌應該爲你找到它們。

如果您想要將渲染路線轉換爲較大的緩衝區並降低採樣率,但不希望受限於允許的最大渲染目標尺寸,那麼您可以使用偏心投影矩陣生成平鋪圖像,如here

1

您可以始終呈現寬度和高度兩倍(即4倍大小)的紋理,然後對其進行超級取樣。

誠然,你仍然會得到問題如果卡不能創建一個紋理4倍後緩衝區的大小...

編輯:有想到的另一種方式。

如果您重複使用視圖矩陣中的微小抖動n次,您將能夠生成儘可能多的圖像,然後再將它們相加,形成一個非常抗鋸齒的圖像。獎金是,它可以在任何可以渲染圖像的機器上運行。儘管如此,它顯然比較慢。當你這樣做時,仍然是256xAA真的看起來不錯!

+0

+1:超級採樣是在我腦海中,這是可以做到的w/o GPU支持的唯一的事情。我不確定要改變視圖矩陣。我認爲你會因透視變化而得到其他的文物。看看會發生什麼會很有趣。我想這取決於正在渲染的場景。 – gatorfax 2009-07-15 15:31:47

+0

是的......我也想到了這一點,看起來這可能是我必須走的路。不知怎的,它只是似乎不可思議,它沒有內置設施得到更廣泛的多重採樣的支持,這是不可用的一半以上我已經試過了筆記本電腦! – Metal450 2009-07-22 17:19:50

0

這篇文章http://msdn.microsoft.com/en-us/library/bb172266(VS.85).aspx似乎暗示你可以使用渲染狀態標誌D3DRS_MULTISAMPLEANTIALIAS來控制這個。您是否可以在啓用了抗鋸齒功能的情況下創建設備,但使用此渲染狀態標誌關閉屏幕渲染和關閉屏幕渲染?

雖然我沒有嘗試過。