dx12 龙书第五章学习笔记 -- 渲染流水线
1.模型的表示:
實體3D對象是借助三角形網(wǎng)絡(luò)來近似表示的,這些3D物體可以通過3D建模工具生成。
2.計算機色彩基礎(chǔ):
初學(xué)者以RGB值(r,g,b)來描述顏色,每款顯示器所能發(fā)出的紅綠藍三色光的強度都是有限的。為了描述光的強度,我們常將它量化為范圍為0~1歸一化區(qū)間的值。0表示無強度,1表示強度最大。
顏色計算:
混合兩種顏色:
加 減 標(biāo)量乘法 -- 適合?
顯然點積和叉積就不適合顏色向量了
顏色向量專屬的顏色運算,分量式乘法:
?這種運算主要運用于光照方程。如果有顏色(r, g,b)的入射光,照射到一個反射50%紅色光、75%綠色光、25%藍色光且吸收剩余光的表面:
由于顏色相加操作時,分量可能會超出1或者低于0,比如1.1我們看作和1強度一致,然后鉗制到0~1的范圍(1.1->1,-0.5->0)
alpha分量:
不透明度,在混合(blending)技術(shù)中起到了至關(guān)重要的作用,暫時設(shè)置為1
:XMVECTOR
DirectXMath提供顏色的分量式乘法計算函數(shù):
// 返回c1?c2 XMVECTOR XM_CALLCONV XMColorModulate(FXMVECTOR C1,FXMVECTOR C2 );128位顏色:每個分量使用浮點值
32位顏色:每個分量使用0~255(8個字節(jié))
DirectX::PackedVector命名空間提供以下結(jié)構(gòu)用于存儲32位顏色:
struct XMCOLOR {union {struct {uint8_t b; // 8個字節(jié) -- 所以cout是以char形式展示uint8_t g;uint8_t r;uint8_t a;};uint32_t c;};void XMCOLOR();void XMCOLOR(const XMCOLOR & unnamedParam1);XMCOLOR & operator=(const XMCOLOR & unnamedParam1);void XMCOLOR(XMCOLOR && unnamedParam1);XMCOLOR & operator=(XMCOLOR && unnamedParam1);void XMCOLOR(uint32_t Color) noexcept;void XMCOLOR(float _r,float _g,float _b,float _a) noexcept;void XMCOLOR(const float *pArray) noexcept;void operator uint32_t() noexcept;XMCOLOR & operator=(const uint32_t Color) noexcept; };可以看到union中,4個8位整數(shù),封裝成一個32位整數(shù)值。由于這種封裝關(guān)系,因此在32位顏色與128位顏色的互相轉(zhuǎn)換不單純的是乘上或除以255,還需要一些額外的位運算。
對此,DirectXMath庫提供了獲取XMCOLOR類型實例并返回相應(yīng)XMVECTOR類型值的函數(shù):
XMVECTOR XM_CALLCONV PackedVector::XMLoadColor(const XMCOLOR* pSource );XMCOLOR類中使用的格式為ARGB而不是RGBA??
XMVECTOR轉(zhuǎn)換到XMCOLOR的函數(shù):
void XM_CALLCONV PackedVector::XMStoreColor(XMCOLOR* pDestination,FXMVECTOR V );128位顏色值常用于高精度的顏色計算,但最終存儲在后臺緩沖區(qū)中的像素顏色數(shù)據(jù),卻往往是以32位顏色值來表示。目前的物理顯示設(shè)備不足以充分發(fā)揮出更高色彩分辨率的優(yōu)勢
3.渲染流水線:
渲染流水線 rendering pipeline是以攝像機為觀察視角而生成2D圖像的一系列完整步驟
輸入裝配器階段->頂點著色器階段->外殼著色器階段->曲面細(xì)分階段->域著色器階段->幾何著色器階段(->流輸出階段)->光柵化階段->像素著色器階段->輸出合并(器)階段
GPU資源:緩沖區(qū)、紋理
圖中典型的箭頭的意義:①GPU資源->輸入裝配器階段:可以訪問GPU資源并完成輸入②輸出合并器階段->GPU資源:把數(shù)據(jù)寫入后臺緩沖區(qū)和深度模板緩沖區(qū)這樣的紋理當(dāng)中
①輸入裝配器階段:
從顯存中讀取幾何數(shù)據(jù)(頂點和索引),再將他們裝配為幾何圖元
頂點:一種特殊點,其意義不止于此,為頂點添加法向量、紋理坐標(biāo)等
D3D為用戶自定義頂點格式提供了很高的靈活性
圖元拓?fù)?#xff1a;primitive topology
void ID3D12GraphicsCommandList::IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology);typedef enum D3D_PRIMITIVE_TOPOLOGY {D3D_PRIMITIVE_TOPOLOGY_UNDEFINED = 0,D3D_PRIMITIVE_TOPOLOGY_POINTLIST = 1,D3D_PRIMITIVE_TOPOLOGY_LINELIST = 2,D3D_PRIMITIVE_TOPOLOGY_LINESTRIP = 3,D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4,D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5,D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10,D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11,D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12,D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13,D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST = 33,D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST = 34,┆D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST = 64, } D3D_PRIMITIVE_TOPOLOGY;通過命令列表修改圖元拓?fù)?所有的繪制調(diào)用會沿用當(dāng)前設(shè)置的圖元拓?fù)浞绞?直到改變
mCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 三角形列表?圖元拓?fù)漕愋驼堊孕蟹瓡?P148~150)查閱,最常使用的圖元拓?fù)漕愋褪?span style="color:#956fe7;">三角形列表D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST
索引:
Vertex quad[6] = {v0, v1, v2, // 三角形0v0, v2, v3, // 三角形1 };為三角形指定頂點順序是一項十分重要的工作,我們稱這個順序為繞序
?繞序會遇到問題:DX12默認(rèn)背面剔除,繞序決定了三角形的法線朝向,后續(xù)討論
創(chuàng)建一個頂點列表和索引列表,在頂點列表中收錄一份所有獨立的頂點,并在索引列表中存儲頂點列表的索引值
每個圖形適配器具有特定大小的緩存,剛處理過的頂點數(shù)據(jù)可以被臨時存儲在緩存中,所以設(shè)計索引順序時,優(yōu)先引用需要復(fù)用的頂點,就能快速引用
②頂點著色器階段:Vertex Shader stage (VS)
輸入和輸出都是單個頂點的函數(shù),每個要被繪制的頂點都經(jīng)過頂點著色器的處理再送往后續(xù)階段
// 我們可以認(rèn)為硬件中執(zhí)行的是下列過程 for(UINT i = 0; i < numVertices; ++i)outputVertex[i] = VertexShader( inputVertex[i]; )這一階段操作由GPU執(zhí)行,運行速度極快。可以用VS來實現(xiàn)許多特效,比如變換、光照和位移貼圖
在VS階段,不但可以訪問輸入的頂點數(shù)據(jù),還可以訪問GPU資源(紋理等)
局部空間和世界空間:
世界空間:全局場景坐標(biāo)系 world space
局部空間:局部坐標(biāo)系 local space -- 通常以目標(biāo)物體的中心為原點
3D美工在局部空間中繪制3D模型,再將其轉(zhuǎn)換到世界空間中
世界變換(world transform):局部空間->世界空間?-- 使用的變換矩陣為:世界矩陣
當(dāng)我們需要在場景中多次繪制同一個物體,我們保存一個頂點和索引數(shù)據(jù)的局部空間副本,然后按所需次數(shù)繪制此圖形,輔以不同的世界矩陣來指定物體在世界空間中的位置、方向、大小 -- 這種方法叫實例化
構(gòu)建世界矩陣的方法:(在第3章筆記中較為詳細(xì)的討論過了)
其中每一行分別存儲的是局部空間的x軸、y軸、z軸和原點相對于全局空間的齊次坐標(biāo)
我們也可以將世界矩陣視作一系列變換組合W,其中,分別是縮放矩陣、旋轉(zhuǎn)矩陣和平移矩陣
假設(shè)我們在局部空間定義了一個單位正方形,其最小點和最大點的坐標(biāo)分別為(-0.5,0,-0.5)與(0.5,0,0.5)。現(xiàn)要求出一個世界矩陣,使正方形在世界空間中的邊長為2,并在世界空間xz平面內(nèi)順時針旋轉(zhuǎn)45°,且中心位于世界空間坐標(biāo)(10,0,10)處。據(jù)此我們構(gòu)造S/R/T矩陣,并求得世界矩陣W:
??
?????這種方法比考慮Qw,Uw,Vw,Ww求取世界矩陣的方法簡單的多,只需要了解物體在世界空間中的大小、朝向和位置即可
思考,假設(shè)兩種情況:
①局部坐標(biāo)系原點在(0,0,0)處,且坐標(biāo)軸與世界坐標(biāo)軸平行;
②也是局部坐標(biāo)軸原點在(10,0,10)處,但局部x軸y軸z軸相對于世界坐標(biāo)軸的坐標(biāo)為???就是W的前3行分量;
對于①而言,在局部坐標(biāo)系中的物體通過SRT變換到世界空間,那么得到的最終物體是一個傾斜45°的正方形且平移到(10,0,10);
對于②而言,從世界空間觀察局部空間,正方形已經(jīng)在最終位置,只是將其局部坐標(biāo)通過QUVW的分量構(gòu)造的世界矩陣轉(zhuǎn)換為世界坐標(biāo),物體并沒有移動
所以這兩種方式是等價的,最終物體都在目標(biāo)位置
這里有點繞,不知道自己有沒有想或?qū)懬宄?反正我們假設(shè)在原點建模(局部坐標(biāo)系),然后通過SRT矩陣轉(zhuǎn)換到特定位置即可
觀察空間:
攝像機空間,在此局部空間中,虛擬攝像機位于原點,沿z軸的正方向觀察,x軸指向攝像機的右側(cè),y軸指向攝像機的上方
由世界空間到觀察空間的坐標(biāo)變換叫做視圖變換(view transform),變換矩陣叫做觀察(視圖)矩陣view matrix
?回歸:兩個坐標(biāo)系之間的變換,假設(shè)坐標(biāo)系A(chǔ)的x、y、z軸及其原點相對于坐標(biāo)軸B的齊次坐標(biāo)為u,v,w,Q,那么從坐標(biāo)系A(chǔ)轉(zhuǎn)換到坐標(biāo)系B的坐標(biāo)轉(zhuǎn)換矩陣為:,則坐標(biāo)系B到坐標(biāo)系A(chǔ)的變換矩陣為W矩陣的逆,uvw部分3x3做轉(zhuǎn)置,Q部分1×3取反
從世界空間轉(zhuǎn)換到觀測空間,可以通過觀測空間的坐標(biāo)軸相對于世界空間來構(gòu)造,但DirectXMath庫為我們提供了計算觀察矩陣的函數(shù):
XMMATRIX XM_CALLCONV XMMatrixLookAtLH(FXMVECTOR EyePosition, // 虛擬攝像機位置QFXMVECTOR FocusPosition, // 攝像機觀測點 -- 用于計算攝像機正前方向量FXMVECTOR UpDirection // 一般是(0,0,1,0) 攝像頭向上方向 );使用示例:
XMVECTOR pos = XMVectorSet(5, 3, -10, 1.f); XMVECTOR target = XMVectorZero(); XMVECTOR up = XMVectorSet(0.f, 1.f, 0.f, 0.f);XMMATRIX v = XMMatrixLookAtLH(pos, target, up);投影和齊次裁剪空間:?
攝像機有一個關(guān)鍵組成要素:攝像機可觀察到的空間體積(volumn of space),此范圍可以由一個四棱錐截取的平截頭體(frustum,四棱臺)來表示
?下一個任務(wù)是,將四棱臺內(nèi)的3D幾何體投影到一個2D投影窗口之中
我們將由頂點到觀察點的連線稱為頂點的投影線,將3D頂點v變換至其投影線與2D投影平面交點v'的透視投影變換
?在觀察空間中,我們可以通過近平面n,遠(yuǎn)平面f,垂直視場角α以及縱橫比r這四個參數(shù)來定義一個:以原點作為投影的中心,并沿z軸正方向進行觀察的平截頭體
注意,近平面和遠(yuǎn)平面都平行于xy平面,所以能方便確定它們沿著z軸到原點的距離
縱橫比(長寬比) Aspect Ratio??投影窗口的寬度除以高度
因為投影窗口實質(zhì)上即為觀察空間中場景的2D圖像,由于該圖像被映射到后臺緩沖區(qū)中,所以我們希望投影窗口和后臺緩沖區(qū)兩者的縱橫比保持一致
接下來利用相似三角形的性質(zhì)來求取平截頭體中的點投影到投影窗口內(nèi)的位置
注意:投影窗口具體大小以及離攝像機多遠(yuǎn)是不重要的,因為其本身就是通過比率從視錐體投影到投影平面上,然后又會按比率縮放到屏幕上。我們只需要確定垂直視場角FovY以及寬高比r=AspectRatio。現(xiàn)在我們只需假設(shè)一個具體的值(比如高度),那么其他長度就可以表示出來。比如:假設(shè)高度為2,那么寬為2r,投影窗口到攝像機的距離為。在這種假設(shè)情況下:
這里遇到的問題,硬件會涉及一些改變投影窗口(后臺緩沖區(qū))大小有關(guān)的操作,所以縱橫比可能改變,如果我們能去除投影窗口對縱橫比的依賴,那么處理過程會更簡單 -- 我們的解決辦法:將x坐標(biāo)上的投影區(qū)間從[-r,r]縮放到歸一化區(qū)間[-1,1] -- x和y坐標(biāo)就成為了規(guī)格化設(shè)備坐標(biāo)(Normalized Device Coordinates,NDC)?-- 注意這里沒有對z坐標(biāo)進行歸一化處理
現(xiàn)在我們希望求出頂點(x,y,z)在投影平面z=d的投影(x',y',d),其中頂點是視錐體里的任意點。
因為:
所以:
假設(shè)原投影窗口的高為h,寬為2:(x是在平截頭體中的坐標(biāo) x'是投影在z=d的投影平面的坐標(biāo))
經(jīng)過歸一化處理后:
因此:在NDC坐標(biāo)中,投影窗口的高和寬都為2,所以它的大小是固定的,硬件無須知道縱橫比。
但是我們一定要將投影坐標(biāo)映射到NDC空間中,因為圖形硬件會假設(shè)我們完成此項工作
我們嘗試用矩陣來表示這種投影變換,但因為NDC下xy坐標(biāo)的公式中存在z,也就是說不是線性關(guān)系,所以構(gòu)造矩陣時分別處理非線性變換(除以z)和線性變換
我們構(gòu)造矩陣:
這里令元素P[2][3]=1 P[3][3]=0來實現(xiàn)
?我們設(shè)置了常量AB,利用它們來把輸入的z坐標(biāo)變換到歸一化范圍內(nèi) --?
因為我們需要執(zhí)行非線性部分除以z的操作,但此時沒有最初的z坐標(biāo)可用,所以我們將輸入的z坐標(biāo)輸出到w位置
我們得到:
再根據(jù)我們保存在w處的z值,對該坐標(biāo)每個分量除以這個z值:
?歸一化深度值的作用:
因為所有的投影點都會位于2D投影空間中,所以我們看似可以丟棄原始的3D z坐標(biāo)了。然而為了實現(xiàn)深度緩沖算法,我們?nèi)匀恍枰A暨@些3D深度信息。
深度坐標(biāo)也需要被映射到[0,1]以內(nèi)
我們構(gòu)建一個保序函數(shù)g(z),將z坐標(biāo)從[n,f]映射到[0,1]中
我們看到Projection矩陣中:,我們據(jù)此構(gòu)造保序函數(shù)
我們根據(jù)下列約束求出對應(yīng)的A和B:①條件1:g(n)=A+B/n=0 將近平面映射為0?②條件2:g(f)=A+B/f=1 將遠(yuǎn)平面映射為1
得到:?因此我們構(gòu)造出一個函數(shù)g(z),觀察其圖像可以看出其非線性的保序函數(shù)
所以實則沒有“投影”z,因為投影面已經(jīng)固定了投影后z坐標(biāo)。此矩陣只是在投影并歸一化xy坐標(biāo)的基礎(chǔ)上,順帶歸一化原z坐標(biāo),以便深度緩沖使用
-- 這里的理解可以結(jié)合games101一起理解
所以,我們得到了透視投影矩陣perspective projection matrix:
其中 r:橫縱比,α:垂直視場角,n:近平面,f:遠(yuǎn)平面
當(dāng)然,坐標(biāo)乘上投影矩陣后,坐標(biāo)處于齊次裁剪空間或投影空間中,還需要完成透視除法,使用NDC(規(guī)格化設(shè)備坐標(biāo))來表示幾何體
DirectXMath提供構(gòu)造透視投影矩陣的函數(shù):
XMMATRIX XM_CALLCONV XMMatrixPerspectiveForLH(float FovAngleY, // 弧度制表示的垂直視場角rfloat Aspect, // 縱橫比=寬度/高度float NearZ, // 原點到近平面的距離float FarZ // 原點到遠(yuǎn)平面的距離 );// Aspect: 需要與后臺緩沖區(qū)的縱橫比一致 = mClientWidth/mClientHeight③曲面細(xì)分階段:
曲面細(xì)分階段:利用鑲嵌化處理技術(shù)對網(wǎng)格中的三角形進行細(xì)分(subdivide),以此來增加物體表面的三角形數(shù)量,再將這些新增的三角形偏移到適當(dāng)?shù)奈恢?/strong>,使網(wǎng)格表現(xiàn)出更加細(xì)膩的細(xì)節(jié)
有點:①我們借此實現(xiàn)一種細(xì)節(jié)層次機制,對離攝像機近的三角形進行鑲嵌化處理,而對遠(yuǎn)的三角形不做任何更改②內(nèi)存中僅維護簡單的低模,為它動態(tài)地增添額外的三角形,節(jié)省內(nèi)存資源③處理動畫和物理模擬時使用低模,在渲染過程中經(jīng)鑲嵌化處理高模網(wǎng)絡(luò)????????
曲面細(xì)分是Direct3D 11中新引入的處理階段,它們?yōu)槲覀兲峁┝艘环N利用GPU即可對幾何體進行鑲嵌化處理的手段 -- 之前只能在CPU上實現(xiàn)鑲嵌化處理?
曲面細(xì)分是一個可選的渲染階段 -- 第十四章討論
④幾何著色器階段:Geometry Shader stage(GS)
幾何著色器是一個可選的渲染階段 -- 第十二章討論
幾何著色器接收的輸入應(yīng)當(dāng)是完整的圖元,比如圖元拓?fù)涫侨切瘟斜?則傳入的是定義三角形的三個頂點 -- 幾何著色器的優(yōu)點是可以創(chuàng)建或銷毀幾何體(比如創(chuàng)建新的頂點)
幾何著色器常用作:將一個點或一條線擴展為一個四邊形
注意:渲染流水線中“流輸出”階段的箭頭。幾何著色器可以將頂點數(shù)據(jù)流輸出至顯存中的某個緩沖區(qū)內(nèi)
⑤裁剪:
這里的裁剪指的是將跨越平截頭體(可觀察的視覺范圍)邊界線的幾何體進行裁剪操作,保留平截頭體以內(nèi)的部分
裁剪操作由硬件執(zhí)行,我們不展示過多的細(xì)節(jié)。作為了解,推薦一種比較流行的裁剪算法--蘇澤蘭(薩瑟蘭德)-霍奇曼裁剪算法 -- 總的來說,算法的整體思路是找到平面與多邊形的所有交點,將這些頂點按順序組織成新的裁剪多邊形
⑥光柵化階段:
計算出屏幕上對應(yīng)像素點的像素顏色
我們通過視口變換,已經(jīng)將3D空間中坐標(biāo)轉(zhuǎn)換到2D的NDC空間中
?背面剔除:
每個三角形都有兩個面,在默認(rèn)情況下我們采用以下約定對它們進行區(qū)分:-- 我們可以修改這個默認(rèn)情況
如果組成三角形的頂點順序為v0, v1, v2,那么我們通過下述方法來計算三角形的法線n:
我們通過公式可以看出,如果三角形三個頂點的繞序為順時針,則其正面豎直朝上(面向我們)
?法向量從正面射出,另一面是背面。如果觀察者看到的是三角形的正面,則稱此三角形為正面朝向。
背面剔除:將背面朝向的三角形從渲染流水線中去除。因為對于一個實體物體,正面朝向的三角形會擋住背面朝向的三角形。
頂點屬性插值:
我們?yōu)轫旤c附加顏色、法向量和紋理坐標(biāo)等屬性,經(jīng)過視口變換后,我們需要為求取三角形內(nèi)諸像素所附的屬性而進行插值(interpolate),除了上述頂點屬性外,還需要對頂點的深度值進行插值
為了得到屏幕空間中各個頂點的插值屬性,我們往往需要通過一種名為透視矯正插值的方法,對3D空間中三角形的屬性進行線性插值。
-- 從本質(zhì)上來講,插值法即利用三角形頂點的屬性值計算出其內(nèi)部像素的屬性值。
?我們無需了解透視矯正插值法的具體數(shù)學(xué)細(xì)節(jié),硬件會自動完成相應(yīng)的處理
通過下圖可以看出,從3D線段投影到投影窗口成為2D線段的過程,是非線性插值
⑦像素著色器階段:pixel shader(PS)?
GPU執(zhí)行的階段,針對每個像素片段(pixel fragment)進行處理,并根據(jù)頂點的插值屬性作為輸入來計算出對應(yīng)的像素顏色。
像素著色器既可以直接返回一種單一的恒定顏色,也可以實現(xiàn)逐像素光照、反射、陰影等復(fù)雜效果
⑧輸出合并階段:
通過像素著色器生成的像素片段會被送入輸出合并階段,在這個階段,一些像素片段可能會被丟棄(例如沒通過深度測試或模板測試的像素片段) -- blend混合操作也是在這個階段實現(xiàn)的(對后臺緩沖區(qū)的對應(yīng)像素融合而不是覆寫) 一些透視效果是通過混合技術(shù)實現(xiàn)的 -- 第10章詳細(xì)講解
?索引緩沖區(qū)的使用以及不使用:
①不使用索引緩沖區(qū):
繪制函數(shù):DrawInstanced()
void DrawInstanced(UINT VertexCountPerInstance, // 實例要繪制的頂點數(shù)UINT InstanceCount, // 實例數(shù) -- 未開啟實例化:1UINT StartVertexLocation, // 頂點緩沖區(qū)讀取的第一個頂點的位置UINT StartInstanceLocation // 從頂點緩沖區(qū)讀取每個實例數(shù)據(jù)之前添加到每個索引的值 -- 未開啟實例化:0 );②使用索引緩沖區(qū):
使用索引緩沖區(qū)的目的是,防止重復(fù)保存同一個Vertex結(jié)構(gòu),以免浪費空間,用索引代替了之前Vertex的排排坐
繪制函數(shù):DrawIndexedInstanced()
void DrawIndexedInstanced(UINT IndexCountPerInstance, // 從每個實例的索引緩沖區(qū)讀取的索引數(shù) -- 不開啟實例化:就是總索引個數(shù)UINT InstanceCount, // 實例數(shù):1UINT StartIndexLocation, // 從索引緩沖區(qū)讀取的第一個索引位置INT BaseVertexLocation, // 從頂點緩沖區(qū)讀取頂點之前添加到每個索引的值UINT StartInstanceLocation // 從頂點緩沖區(qū)讀取每個實例數(shù)據(jù)之前添加到每個索引的值 -- 不開啟實例化:0 );示例:
mCommandList->IASetVertexBuffers(0, 1, &mBoxGeo->VertexBufferView()); mCommandList->IASetIndexBuffer(&mBoxGeo->IndexBufferView()); mCommandList->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);mCommandList->DrawIndexedInstanced(mBoxGeo->DrawArgs["box"].IndexCount, 1, 0, 0, 0);?三角形帶:D3D_PRIMATIVE_TOPOLOGY_TRIANGLESTRIP:
三角形條帶用于繪制👇這樣連續(xù)的三角形圖形,其中處于中間位置的頂點唄相鄰的三角形所共用,具體來說,利用n個頂點即可生成n-2個三角形。
我們可以不使用索引緩沖區(qū),直接利用頂點緩沖區(qū)(順序:01234567),然后直接DrawInstanced()即可繪制三角形帶。
注意:按照01234567的順序明顯不符合D3D的繞序規(guī)矩。但是其實,GPU內(nèi)部會對偶數(shù)三角形中兩個頂點的順序進行調(diào)換(比如123換成132),以保持繞序的一致性。-- DirectX置換的后兩個頂點的順序,OpenGL置換的前兩個頂點的順序。
三角形帶狀不同于三角形列表,三角形列表是每3個頂點繪制一個三角形,而三角形條帶是多個連續(xù)頂點(當(dāng)然大于等于3個),繪制條帶。注意如果三角形條帶的頂點個數(shù)是三個,其實就變成了三角形列表。 -- 后面幾何著色器中會涉及相關(guān)內(nèi)容
總結(jié)
以上是生活随笔為你收集整理的dx12 龙书第五章学习笔记 -- 渲染流水线的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 闪动的文字图片怎么制作?教你一招闪图在线
- 下一篇: 软件敏感性测试