基於OpenGL編寫一個簡易的2D渲染框架-08 重構渲染器-整體架構


  事實上,前面編寫的渲染器 Renderer 非常簡陋,雖然能夠進行一些簡單的渲染,但是它並不能滿足我們的要求。

  當渲染粒子系統時,需要開啟混合模式,但渲染其他頂點時卻不需要開啟混合模式。所以同時渲染粒子系統和其他紋理時會得不到想要的結果,渲染器還存在許多的不足:

  1、當渲染許多透明圖形時,沒有對其進行排序,使得本應透明的圖形沒有透明。

  2、不能對不同的頂點使用不同的狀態進行渲染。

 

  渲染器要做的東西很簡單,就是

    1、傳遞數據到 GPU

    2、設置 OpenGL 狀態信息(Alpha測試、模板測試、深度測試、混合,裁剪測試等等)

    3、設置着色程序,綁定 Uniform 數據

    4、繪制頂點

 

  下面給出兩種方式實現上面的流程。

  第一種實現方式:

  

   DrawList 根據繪制的圖形填充頂點數據,VertexData 和 IndexData 分別指向一塊內存,分別儲存頂點數據和索引數據(傳遞數據到 GPU 時遞交這兩塊內存的數據)。

  CmdList 命令列表,儲存一些繪制的信息(Alpha測試、模板測試、深度測試、混合,裁剪測試等等)。值得注意的是,繪制命令有 BeginIndex 和 IndexCount 這兩個屬性數據,調用函數 glDrawElements 進行繪制時使用。

glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);

  即所有的繪制命令 Cmd 都對應着其唯一的頂點數據,只不過它們的數據都儲存在一起。這樣每次繪制只需要提交一次數據就可以了,提高的效率。

    這種渲染方式是在 ImGui 中看到的,但這次重寫渲染器用的不是這種方式。

 

  第二種實現方式:

  這次渲染器要實現的功能:

    1、對於不同的頂點可以設置不同的 OpenGL 狀態進行繪制。

    2、對半透明圖形進行排序渲染。

  這次重寫渲染器用的就是這種方式,渲染器構成的主要類:

  這里把着色器給做成一個單獨的類,繪制頂點時 OpenGL 狀態信息儲存在 Pass 中,對象分配器(來自於物理引擎 Box2D 的小型對象分配器源碼)分配內存空間儲存頂點數據。

 

  當繪制圖形並顯示在窗口上時,需要進行的流程:

 

  首先設置渲染器當前 Pass,然后設置頂點數據到渲染器中。在渲染時

    1、渲染器會迭代每一個 Pass

    2、對頂點數據進行排序

    3、設置 OpenGL 狀態

    4、合並頂點數據

    5、設置着色器

    6、綁定 Uniform 數據

    7、最后進行渲染。

 

  渲染器具體要做的就是如何管理好 Pass 和 VertexIndexData,又不失效率。下面是渲染器管理 Pass 和頂點數據的圖片介紹:

  

  半透明渲染是這次寫渲染器中遇到的一個難題,單兩個不透明圖形重疊時,進行深度測試時被遮擋部分的像素會被剔除或者先繪制被遮擋的圖形,然后繪制頂層的圖形。但是渲染半透明的圖形時,半透明的圖形能夠看到被遮擋的圖形,直接拋棄就露餡了,不顧深度測試也依然得不到正確的結果,因為 Alpha

混合顛倒順序會得到不一樣的結果。

  一個解決方法就是把透明的和半透明的圖形分開,先渲染不透明的圖形,然后對半透明的圖形進行排序(被遮擋的半透明的圖形先渲染),排序后進行渲染。但是這樣代價較高,這次渲染器用的是這種方式。

  渲染器中有兩個渲染列表,不透明的 Pass 列表和透明的 Pass 列表。Pass 和 RenderOperation 作為鍵值對儲存在 Map 中,頂點數據儲存在RenderOperation 中。VertexIndexData 數組用於對頂點數據進行排序,主要是解決半透明圖形的渲染問題。

  接下來將對完成渲染器的各個部分。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM