日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

个人的Directx9研究总结 (1)

發布時間:2023/12/9 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 个人的Directx9研究总结 (1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

自己最近在研究一個Directx9的小型游戲引擎,總結一下目前的成果以及遇到的各種問題的解決方法。
雖然是Directx9但是繪制全部使用Shader實現,現狀除了物理模擬外其他功能基本都有。
碰撞檢測有AABB,OBB和球體對球體。由于開發環境是日語環境所以UI說明用的日文,模型都來源自MMD模型。

1. ImGui介紹

IMGUI 全稱是immediate mode gui,這種實現方法的GUI非常適合作為實時程序輔助組件用來調試。
Dear Imgui是目前比較好用的一個開源Imgui項目,

下載: https://github.com/ocornut/imgui

下載后把必要文件包含到自己的工程并把對應函數加入到程序循環中即可使用。具體組入方法參考Demo。
IMGUI很合適實時項目使用,如果同樣是對Directx或者OpenGL進行研究的人來說,我強烈推薦使用Dear Imgui,可以大幅度縮短各種Debug時間。

2. 3D空間數學

3D空間表示一件物體的運動可以用縮放+旋轉+平移來描述。而矩陣則可以描述以上行為的總和

?

如圖,綠色部分表示物體的旋轉和縮放,紅色部分表示物體的平移。當無縮放時(也就是S = 1)。
綠色部分可以直接表示旋轉。而矩陣有了縮放的情況下乘法計算后狀況就變得比較復雜。
所以對于游戲制作等情況,我推薦使用兩套矩陣來記錄3D物體的運動,一個是s = 1,用來記錄物體平移和旋轉的矩陣,另外一個是縮放旋轉平移的矩陣,用來修正物體在空間里的原本大小和朝向,兩個矩陣相乘后便是最終矩陣。

?

3.關于3D場景管理的優化的意義

如上圖,這是3D空間一個物體最終位置的計算過程。從局部坐標系經過世界變換,視野變換,投影變換后得到在裁剪空間內的坐標,裁剪空間內會把視野外(觀察矩陣和投影矩陣構成的視錐體,在此之外的物體會被裁減掉不進行繪制。所以看不到的物體其實到最后沒有占用GPU。

那么諸如包圍球(BVH),2叉樹, n叉樹等場景算法是干什么用的呢?。

(1).程序如果本身存在大量物體,在世界>視野>投影變換時的矩陣計算已經會占用大量內存,而場景管理可以減少這部分的計算。也就是說通過場景管理使得后面的變換階段只計算必要的矩陣。

(2).物理計算與碰撞計算等,如果不進行管理時隨著物體的增多必然會消耗越來越多的內存,場景管理可以篩選出只存在可能碰撞的物體,減少計算量。

?

4. Directx9.0 下的一些Mesh處理

D3DXCreateBox,D3DXCerateSphere等系列函數可以創建自帶的簡單幾何圖形,不過這些圖形并沒有紋理坐標,那么如果想給這些默認圖形貼上紋理要怎么做呢?方法是:

(1).從D3DVERTEXELEMENT9數組定義一個包含紋理坐標的數據流。
(2).把Mesh下的LockVertexBuffer函數鎖定頂點緩存,傳入剛才定義的D3DVERTEXELEMENT9
(3).重新計算紋理坐標后再解鎖頂點緩存,再用CloneMesh克隆回去。

球型物體或者近似球型物體的紋理坐標有固定算法,像最初的圖中球和茶壺便是程序中重新計算紋理坐標后所得。這套方法可改變Mesh的所包含頂點信息。將來在做法線貼圖時需要切線。而給物體添加切線也是用這種方式:聲明頂點數據流>鎖定Mesh頂點緩存>傳入重構的數據>解鎖>克隆Mesh的方式重構Mesh包含的頂點信息

?

4.關于Lambert光照模型,Phong光照模型的光照方向:

(1).漫反射光照模型

Lambert光照模型是一種漫反射光照模型,計算其漫反射率方法為:

float Diff = max(dot(Object.Normal, Light.Dir), 0.0);

其中Object.Normal是物體的法線,而Light.Dir是光射出的方向。
注意是物體表面射出的方向而不是原本方向,如果光原本方向是L,則Light.Dir為-L。
如果直接用光原本方向L那么點乘結果肯定是負值,漫反射部分就會漆黑一片。順便說一下Lambert光照模型會導致物體沒受到光的部分比較暗,因此有了改良了Harf Lambert,其漫反射率方法為:

float Diff = max(0.5 + dot(Object.Normal, Light.Dir) * 0.5, 0.0);

原本的點乘結果由[-1,1]變成了[0,1],所以Harf Lambert在沒受光的部分也不會太黑。
而現在有一種更加便利的模型,叫Wrap Lighting,可以同時滿足以上情況并且能自己調整。其算法為:

float wrap_diff = max(wrap + dot(Object.Normal, Light.Dir) / (1 + wrap) , 0.0);

看出來了嗎?Lambert就是wrap=0的狀況,Half Lambert就是warp=1。改變wrap可以調整漫反射率。

(2). 高光光照模型

Phong和BlinnPhong光照模型是計算高光的光照模型,Phong的高光計算方法為:

float3 viewDir = normalize(Camera.ViewPos – Object.Pos); float3 reflectDir = reflect(Light.Dir, Object.Normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), Light.SpecPower);

?

Phong光照模型會在視線向量和反射向量大于90度情況下點乘為負數,于是高光就會突然消失沒有。
Blinn-Phong是Phong光照模型的改良版,Blinn-Phong的使用半程向量,不會有高光突然消失的情況,而且不需要使用reflect函數,性能消耗上也略低。

float3 viewDir = normalize(Camera.ViewPos – Object.Pos); float3 halfwayDir = normalize(LightDir + viewDir); float spec = pow(max(dot(Object.Normal, halfwayDir), 0.0), Light.SpecPower);

注意這里的Light.Dir是光射出方向。和上文的Lambert光照所用方向一致,和Phong的相反。下圖是各種光線方向總結

?

6.關于渲染到紋理

渲染到紋理可以說是非常重要的手段,后處理以及一系列需要屏幕空間的渲染方式都離不開他,Directx9中有兩種方式,一種是使用LPD3DXRENDERTOSURFACE接口,非常簡單易用,但是缺點是多重采樣會消失,也就是沒有多重采樣。而且如果需要各個表面有承接關系的話,這個接口很難用。

因此還是傳統方法自己建兩個Surface,一個負責RendeTarget一個負責DepthBuffer。在渲染前Get現在的RendeTarget和DepthBuffer,開始繪制時Set現在預定的表面,完畢后再Set回最初取得的的表面。這個方法結合LPDIRECT3DDEVICE9下的StretchRect函數可以把當前渲染具有多重采樣的表面綁回紋理所在的表面,最終結果就帶上了多重采樣效果。

總結

以上是生活随笔為你收集整理的个人的Directx9研究总结 (1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。