02. The-Forge 入門教程 - uniform & 紋理
我之前說過,我接下來會(huì)寫一些簡(jiǎn)單的教程,通過在The-forge中實(shí)現(xiàn)learning opengl教程中的前幾個(gè)Demo,來理解The-Forge API的設(shè)計(jì)。之前已經(jīng)完成了三角形的繪制,這一次就來進(jìn)行第二步,繪制紋理貼圖。
目標(biāo)
本教程要實(shí)現(xiàn)的目標(biāo)
繪制方塊并傳送正確的紋理坐標(biāo)
顯示定點(diǎn)色
綁定texture,到Tex0和Tex1
顯示Tex0,Tex1或者Tex0/Tex1進(jìn)行blend
Shader
本節(jié)shader難度并不高,故把shader的實(shí)現(xiàn)提前,而且如果有shader文件,也可以更好的理解我前面所說的目標(biāo)是要實(shí)現(xiàn)什么
vertex shader

相比繪制三角形的部分,多傳了頂點(diǎn)UV變量
fragment shader

fragment shader相比繪制三角形的代碼,變化就比較大了。
多了一個(gè)constantbuffer,有兩個(gè)值,prog和mixWeight,prog代表程序功能,mixWeight代表在Tex0和Tex1混合模式下的混合系數(shù)
多了兩個(gè)Texture2D,Tex0和Tex1
多了一個(gè)SamplerState,uSampler0
我這個(gè)shader寫的比較隨意,沒有代碼規(guī)范。合乎規(guī)范的代碼應(yīng)該讓所uniform變量都加小寫u開頭
給只用過GLSL沒用過HLSL的同學(xué)解釋一下SamplerState。在GLSL下,Texture2D和SamplerState兩個(gè)對(duì)象合二為一變?yōu)榱藄ampler2D對(duì)象。如果同一張texture,但是同時(shí)需要點(diǎn)采樣和線性插值采樣就需要兩個(gè)sampler2D,而HLSL中,只需要對(duì)同一個(gè)Texture對(duì)象使用不同的SamplerState即可
繪制方塊并添加UV
points數(shù)據(jù)變化

每個(gè)頂點(diǎn)的數(shù)據(jù)從6個(gè)float增加到了8個(gè)float,頂點(diǎn)數(shù)量也增加到6個(gè),因?yàn)橐粋€(gè)方塊由兩個(gè)三角形構(gòu)成,注意,dataSize也要隨之發(fā)生變化
vertexLayout修改

vertex attribute增加了UV,數(shù)量從2變成了3
繪制命令變化
const uint32_t triangleVbStride = sizeof(float) * 8;
cmdDraw(cmd, 6, 0);
VbStride現(xiàn)在已經(jīng)變成8了,繪制的點(diǎn)數(shù)也增加到6

現(xiàn)在繪制的話就可以得到這樣了,當(dāng)然你直接運(yùn)行會(huì)報(bào)錯(cuò),因?yàn)樗械膗niform變量還都沒傳,所以接下來解決這個(gè)問題
uniform &?DescriptorSet
首先添加全局變量

UniformBlock就是和shader中constantBuffer直接對(duì)于的結(jié)構(gòu)
修改Init函數(shù)


descriptorSet和uniform變量之間相關(guān),一般一組uniform變量使用一個(gè)descriptorSet。分組的依據(jù),是uniform更新的頻率。The-Forge提供了四種uniform更新模式:
UPDATE_FREQ_NONE?- Descriptor gets hardly updated in the lifetime of the application
UPDATE_FREQ_PER_FRAME?- Descriptor gets updated roughly once per frame
UPDATE_FREQ_PER_BATCH?- Descriptor gets updated per arbitrary batch (batch is application dependent. commonly this is per material)
UPDATE_FREQ_PER_DRAW?- Descriptor gets updated per draw call. (information which changes per draw call, ... usually with modern APIs, it is better to avoid this update frequency by using the bindless model and using push constants instead)
對(duì)于PER_FRAME更新的buffer,The-Forge的示例中都使用了三緩沖輪換使用的方式,為了和The-Forge的習(xí)慣統(tǒng)一
Tex0和Tex1不會(huì)更新,所以texture的descriptorSet的更新頻率是NONE
cbuffer每幀刷新(不論prog和mixWeight的值是否發(fā)生修改),所以constantBuffer的descriptorSet更新頻率為PER_FRAME


添加UI,prog添加下拉菜單,mixWeight添加滑條

descriptorSet是dx12/vulkan中非常重要的概念,為了后續(xù)學(xué)習(xí),輕一定要理解透徹,descriptorSet本地相關(guān)的一些資料已經(jīng)添加到文末參考中
在init函數(shù)中生成的對(duì)象別忘了在exit函數(shù)中刪除,不然就內(nèi)存泄漏了

draw函數(shù)修改

在draw函數(shù)中,更新uniformBufferData,并在繪制時(shí)綁定descriptorSet(即綁定uniform),就大功告成了。
結(jié)果




在Tex blend模式下,拉動(dòng)滑條就可以改變兩張圖的混合比例
接下來該干什么
在此節(jié)完成后,推薦大家嘗試自己重新實(shí)現(xiàn)The-Forge的第一個(gè)demo。需要:
自己實(shí)現(xiàn)一個(gè)camera
天空盒的繪制
習(xí)實(shí)例化渲染

相信這個(gè)demo對(duì)你來說并不會(huì)是難事
參考
https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/
https://docs.microsoft.com/en-us/windows/win32/direct3d12/resource-binding-in-hlsl
https://github.com/ConfettiFX/The-Forge/wiki/Descriptor-Binding-Interface