回覆列表
  • 1 # 虎牙雲圖小冰

    不對的,還是大神指證。

    渲染模組是遊戲引擎中最重要的模組,也是最基礎的模組。

    這個模組的任務就是實現各個平臺的渲染任務。

    我們先說渲染,再說平臺。

    渲染就是圖形學的知識,拋開硬體,只談演算法。

    現在的實現光陰的3d實時渲染演算法,最通用的還是poly網格模型表達,與blinn和phong演算法

    先了解3d的模型資料就是頂點與三角面,再讀明白後面兩個演算法。

    你自己可以在cpu上寫出基礎的渲染器。

    演算法的簡單說明是這樣的

    模型亮暗是透過計算點的法線與光線的夾角來實現燈光亮度的。

    模型的顏色是由模型的uv資料與貼圖來實現的

    模型的高光,透過計算點到攝像機向量與光源的方向的向量和求與點法向量的夾角來近似模擬。

    高光之所以用模擬是為了節約效能,高光的亮度應該是光源的反射光與攝像機到點的方向差距。但其實兩種計算誤差視覺看不出來,效能卻可以少算幾排。

    算出來每個點的明暗與本來顏色後,在用插值,線性填充或者漸變填充一個三角面所有點的顏色。

    這樣一個基礎的模型就渲染完了。

    上面說的流程,完全可以自己手寫實現在cpu上。運算速度嘛,模型面少應該還行,面多估計一秒1幀吧。

    上古時期的大神們,為了解決這個渲染速度問題,就專門搞了一個硬體包裝了這些演算法,加快計算這些東西。這個硬體就叫顯示卡。

    自從出了顯示卡後,遊戲的程式們工作變簡單了,只用把模型的資料按要求發給顯示卡,顯示卡就會反饋渲染好的資料。

    這個資料主要就是模型所有點,和三角面的點序號,再加貼圖,與渲染模式。

    就能直接渲染出結果,顯示卡處理的部分我們就叫渲染管線。

    但後來遊戲發展的需求越來越變態,遊戲渲染要求越來越多,顯示卡廠商推出了自定義渲染管線,

    於是就有了shader這種東西,應用在顯示卡上面的。用來控制顯示卡渲染的程式碼,一開始也就定義一下幾張貼圖,每個貼圖幹什麼,渲染明暗演算法自己最佳化一下,實現一些特殊的風格化。

    再後來顯示卡就越來越開放,程式設計師們定製化的渲染方式也越來越多。

    然後由於現在顯示卡有n卡和a卡兩家,所以自然肯定就有兩套驅動,你開發的的遊戲有可能用的n卡,也可能用到a卡。

    這就說到平臺了,所以一般遊戲引擎至少要實現,兩套渲染邏輯,用來防止遊戲出現平臺不相容。

    所謂的兩套驅動,就是著名的direct x和opengl了。

    然後由於顯示卡版本又眾多,顯示卡各種功能都不統一,比如曲面細分,還有drawInstance。新顯示卡有,舊顯示卡沒有,你遊戲引擎就得做處理,是要閹割功能,還是直接告訴使用者硬體不支援。就很麻煩,畢竟那麼多硬體呢

  • 2 # 銅青

    前排跑題警告,想借著這個題交流一下最近搗鼓的一套渲染器的介面流程,而不是單純侷限於Unity的時鐘處理。下面提到的這套介面流程還沒有經過任何驗證,所以如果有大佬能指出缺陷,將會是十分珍貴的。

    我的目標就是使用原生的DirectX 12開發獨立渲染模組,而這個模組要做到的是可以打包成動態庫給其他遊戲引擎使用,因此要做到本身只做純渲染的工作,輸入和輸出都相對乾淨,同時還要儘可能繞開C++標準中沒有的部分,防止踩坑,此為前提。

    首先,我將整體框架解耦成:視窗,渲染器兩個部分,視窗可以是最簡單的Winmain + WNDCLASS,也可以是Unity或者Unreal那種豐富到極致的花裡胡哨的GUI,而我認為這些視窗無論怎麼千奇百怪也離不開Backbuffer, Swapchain等等,因此,我把視窗部分向渲染部分傳遞的資料整理下來:

    有些操作是不同視窗不同做法的,這就意味著這些操作的事件需要經過視窗層傳遞到渲染層,這就多開一個單獨儲存函式指標的型別:

    因為呼叫的主動權一直是在視窗層,而渲染層只有被呼叫權,因此視窗層將會持有渲染層的“引用”,這個引用將會拆解成一個void*指向類的地址,和一個儲存所有渲染層應有的邏輯的函式指標列表:

    這裡Initialize也就是包括了整個渲染器的構造,並且返回指標,Dispose自然就是解構函式,其他兩個則是視窗大小改變和每幀的繪製函式,最後,渲染層的動態庫將會提供一個生成這個IRendererBase的裸函式,拼上最後一塊磚:

    這樣如果要解耦合渲染器部分,比如打包DLL,基本只需要將GetRendererFunction函式標記為DLL匯出格式,視窗層的設計就比較隨意,只要保證讓渲染器在視窗初始化之後再構造,在視窗銷燬之前被銷燬,並且每幀呼叫一下,就可以了。

    在最原始的windows app裡(忽略Debug部分)呼叫過程就幾行,其中D3DApp是視窗:

    Run內部的邏輯比較簡單粗暴,就是while迴圈呼叫Draw,外加一些更新時間等操作。因為渲染器是一個多執行緒並行的多幀非同步渲染模式,因此Draw函式邏輯很簡單並不會有什麼開銷,唯一的阻塞就是需要等待兩幀之前的GPU的渲染結果,當然這也是沒有辦法的事情。

    透過這套系統,把可能的邏輯和渲染層的溝通都涵蓋住了,如果邏輯需要更新,則透過DataPack傳遞進去,渲染器因為只負責把結果輸出到螢幕,所以可以不設計任何資料上和邏輯上的回撥。

  • 中秋節和大豐收的關聯?
  • 和田玉中的翠青料,你怎麼理解?