2011-07-05 59 views
1

我在窗口中設置了SlimDX中的Direct3D11場景。渲染是在一個單獨的線程中完成的。防止Direct3D視口圖像縮放(SlimDX)

當繪製到調整大小的控件時,有沒有辦法讓渲染器不會拉伸圖像?我試過ModeDescription.Scaling = DisplayModeScaling.Centered,它似乎沒有任何影響。有什麼我失蹤?我之所以會問這個問題,是因爲當我調整控件的大小時,它會在渲染目標被更新爲新的尺寸之前,延長圖像以便在瞬間完成控件的填充。結果是,當我調整它的大小時,它會非常閃爍,如果我可以稍微快速地重置渲染目標,它可以消除閃爍。保持圖像在角落而不縮放它是完全正確的,因爲最終它不會)

解決方法1:可以將渲染目標放入控件中。當窗口調整大小時,只會通過首先停止渲染的特殊方法調整控件的大小,然後更新緩衝區並再次開始渲染。不過,這有點破解。我必須等待渲染週期完成,然後阻止它,然後調整大小,然後解除阻止。

解決方法2:一個類似的解決方法是檢查渲染循環中的調整大小標誌,而不是中斷它。渲染器應該能夠直接繪製而不縮放。這在性能上更可接受。但是,必須阻止對UI線程的調用才能執行實際的調整大小。

解決方案3:根本不是調整控件的大小,而是可以使其大小盡可能大,但可以剪裁(在窗口內)。沒有必要調整大小,但剪刀矩形必須以類似於上述解決方法的方式進行維護,除非您不介意渲染大量的屏外像素。渲染二十左右像素的多行和多列確實具有在窗口被調整大一些的時候在邊緣提供即時圖像的有利效果。

理想情況下調整大小應該直接從UI線程完成(無需拖延它,並從渲染線程重新進入UI線程)。這不是渲染線程的責任,它會降低渲染速度。同樣,緩衝區調整大小應該在渲染線程中完成以獲得最佳性能(不要等待/阻止/調整大小/解除阻塞)。這不起作用的唯一原因是如果在調整緩衝區大小之前調整大小,渲染線程就會縮放。

所以我的問題仍然存在:有沒有一種不縮放的渲染方式?

回答

0

我會建議強制窗口到一個固定的大小(這似乎很常見)或不重繪D3D控件,直到完成更改(或簡單地將其清除爲黑色)。

似乎有辦法做到你想做的事,因爲我已經看到遊戲能夠改變大小而沒有閃爍,但我不知道如何做到這一點,不幸的是。鎖定窗口大小並提供菜單是舊的解決方案。

1

我打算用所涉及的原始Win32 API來回答這個問題,這可能需要一些技巧來轉換到託管的.NET環境& SlimDX。

當您拖動窗口或調整窗口大小時,Windows基本上會劫持您的消息泵並創建一個專門用於有效調整大小調整邏輯的新窗口。該操作在完成之前或多或少是模態的。在調整大小或拖動完成之前,您通常會收到的許多消息都會被完全封鎖。在應用程序中,當此行爲開始時,您將獲得WM_ENTERSIZEMOVE,並在結束時獲取WM_EXITSIZEMOVE或WM_CAPTURECHANGED。你需要檢查這兩條消息,比如當做一個拖拽的時候會發送WM_CAPTURECHANGED,而不會發送WM_EXITSIZEMOVE!

所有這一切意味着當你得到一個WM_ENTERSIZEMOVE時,你可以設置一個標誌並且知道所有後來發生的WM_SIZE和WM_MOVE消息都是用於拖動操作的。通常調整rendertargets大小並追蹤和取消分配所有默認池資源是一個非常緩慢的操作,並且非常值得推遲,直到drag/resize完成。這會產生窗口拉伸的副作用,這與您在此描述的問題完全相同,並且您想解決這個問題。

應該可以在WM_SIZE,WM_MOVE或WM_SIZING中添加特殊處理程序,WM_MOVING在發生時通過SendMessage(而不是PostMessage)強制同步渲染並重新繪製,但是您需要確保只有在WM_ENTERSIZEMOVE擁有的模態循環內執行此操作。

+0

我瞭解低級別的東西。即使緩衝區大小和窗口大小不同,我的問題實際上也是如何防止擴展。我實際上不需要一個同步調整大小的解決方法(請參閱上文)。它會導致用戶界面不穩定。我只想能夠渲染到不同大小的窗口而不縮放。 – jnm2