跨越opengl和d3d的鴻溝(一) 開篇

2021-07-23 00:00:37 字數 1605 閱讀 4469

多年來,在論壇和各個**上不斷能看到拿opengl和d3d進行比較的帖子和文章。他們經常製造很多謎思,使得初學者和一些從業人員對opengl和d3d產生了各種各樣的流言。

有人說,opengl直接調到驅動,效能高於d3d。

有人說,shader都得寫兩套,很麻煩。

有人說,opengl和d3d在底層有很多區別,而且不可設定。

有人說,圖形引擎如果要相容兩者,就只能取其功能的交集,最後還不如任何一種api。

真的麼?

本文試圖:

本文不希望:

下面先從幾個比較基本的方面來**如何跨越兩個api的鴻溝。

opengl和d3d的架構基本上是這個樣子的:

在架構上其實兩者沒有什麼區別,只是d3d的runtime是在os裡,對於不同硬體來說都是一樣的。而opengl的runtime直接是和驅動合為一體的。但這並不會造成效能有所差別,破解了流言1。

opengl 的原生shading language是glsl,d3d的是hlsl。兩者語法相似,但細節上天差地別。好在,nvidia的cg在很大程度上類似於hlsl,而且可以編譯 出glsl來。所以,cg編譯器成了跨越這兩種shader的橋梁。當然,要真正實用起來,還需要不少工作。比如cg的geometry shader和hlsl 10+的有些許不同,需要通過#ifdef來分開。另外,cg編譯器生成的glsl需要一些調整才能在ati的驅動上工作,所以還需要多一次轉換。好在這 些事情都可以通過程式自動完成,而且速度很快。具體可以參考klayge的oglshaderobject::converttoglsl。實際上,klayge的所有shader都只寫了乙份(語法用hlsl 11的),在不同api上可以自動編譯成原生的shader使用(有opengl和opengl es的編譯器,曾經還有d3d9的)。這樣就沒有重寫的繁瑣,也沒有增加runtime開銷,破解了流言2。

當然,這裡還有另一種更好的選擇,把hlsl編譯器生成的bytecode轉換成glsl。ue3等引擎用了mojoshader來完成這件事情。優點是不需要多次編譯,缺點是不支援sm4+。

初學者經常 說,opengl用右手座標系,而d3d用左手;裁剪空間裡opengl的z是[-1, 1],而d3d是[0, 1];不可調和。實際上,直接把左手的頂點和矩陣給opengl也是沒有問題的。畢竟如果在vs裡執行的都是mul(v, matrix),得到的會是同樣的結果。可能會造成麻煩的反而是viewport的z。假設乙個經過clip之後的頂點座標為(x, y, z, w),那麼在opengl上,該頂點經過viewport變換的z是(z/w + 1) / 2,而在d3d上則是z/w而已。這對於depth test不影響,但depth buffer裡的值就不同了。所以需要對project matrix做一些調整,才能讓他們寫到depth buffer中的數值相同。具體來說,如果要讓opengl流水線接受d3d的project matrix,就需要乘上

相當於把project space的頂點z都作了z = z * 2 – 1的操作,所以經過viewport變換就一致了。d3d到opengl的矩陣也可以依此類推。所以,在座標系上,很容易就能使兩者接受同樣的輸入,同時也沒有增加runtime開銷。

跨越OpenGL和D3D的鴻溝(一) 開篇

有人說,opengl直接調到驅動,效能高於d3d。有人說,shader都得寫兩套,很麻煩。有人說,opengl和d3d在底層有很多區別,而且不可設定。有人說,圖形引擎如果要相容兩者,就只能取其功能的交集,最後還不如任何一種api。真的麼?下面先從幾個比較基本的方面來 如何跨越兩個api的鴻溝。ope...

跨越opengl和d3d的鴻溝(三) 交集?並集?

d3d9的功能早已被opengl 2.0所覆蓋,網上可以找到很多資料,這裡就不提了。本文注重的是新的gpu特性。下表列出了d3d10 的新功能,以及實現該功能所需要的opengl擴充套件或核心。d3d 10的功能 opengl所對應的 geomrtry shader gl arb geometry ...

OpenGL和D3D的區別

1 世界座標系 opengl為右手座標系d3d為左手座標系 2 裁剪空間 opengl中z的範圍 1.0,1.0 d3d為 0.0,1.0 3 shader shader開始是以彙編的形式出現,在推出一段時間後,就出現如下幾種類c的高階語言 注 這些高階語言會被編譯成顯示卡識別的彙編 opengl的...