02. The-Forge 入门教程 - uniform & 纹理
我之前说过,我接下来会写一些简单的教程,通过在The-forge中实现learning opengl教程中的前几个Demo,来理解The-Forge API的设计。之前已经完成了三角形的绘制,这一次就来进行第二步,绘制纹理贴图。
目标
本教程要实现的目标
绘制方块并传送正确的纹理坐标
显示定点色
绑定texture,到Tex0和Tex1
显示Tex0,Tex1或者Tex0/Tex1进行blend
Shader
本节shader难度并不高,故把shader的实现提前,而且如果有shader文件,也可以更好的理解我前面所说的目标是要实现什么
vertex shader

相比绘制三角形的部分,多传了顶点UV变量
fragment shader

fragment shader相比绘制三角形的代码,变化就比较大了。
多了一个constantbuffer,有两个值,prog和mixWeight,prog代表程序功能,mixWeight代表在Tex0和Tex1混合模式下的混合系数
多了两个Texture2D,Tex0和Tex1
多了一个SamplerState,uSampler0
我这个shader写的比较随意,没有代码规范。合乎规范的代码应该让所uniform变量都加小写u开头
给只用过GLSL没用过HLSL的同学解释一下SamplerState。在GLSL下,Texture2D和SamplerState两个对象合二为一变为了sampler2D对象。如果同一张texture,但是同时需要点采样和线性插值采样就需要两个sampler2D,而HLSL中,只需要对同一个Texture对象使用不同的SamplerState即可
绘制方块并添加UV
points数据变化

每个顶点的数据从6个float增加到了8个float,顶点数量也增加到6个,因为一个方块由两个三角形构成,注意,dataSize也要随之发生变化
vertexLayout修改

vertex attribute增加了UV,数量从2变成了3
绘制命令变化
const uint32_t triangleVbStride = sizeof(float) * 8;
cmdDraw(cmd, 6, 0);
VbStride现在已经变成8了,绘制的点数也增加到6

现在绘制的话就可以得到这样了,当然你直接运行会报错,因为所有的uniform变量还都没传,所以接下来解决这个问题
uniform & DescriptorSet
首先添加全局变量

UniformBlock就是和shader中constantBuffer直接对于的结构
修改Init函数


descriptorSet和uniform变量之间相关,一般一组uniform变量使用一个descriptorSet。分组的依据,是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)
对于PER_FRAME更新的buffer,The-Forge的示例中都使用了三缓冲轮换使用的方式,为了和The-Forge的习惯统一
Tex0和Tex1不会更新,所以texture的descriptorSet的更新频率是NONE
cbuffer每帧刷新(不论prog和mixWeight的值是否发生修改),所以constantBuffer的descriptorSet更新频率为PER_FRAME


添加UI,prog添加下拉菜单,mixWeight添加滑条

descriptorSet是dx12/vulkan中非常重要的概念,为了后续学习,轻一定要理解透彻,descriptorSet本地相关的一些资料已经添加到文末参考中
在init函数中生成的对象别忘了在exit函数中删除,不然就内存泄漏了

draw函数修改

在draw函数中,更新uniformBufferData,并在绘制时绑定descriptorSet(即绑定uniform),就大功告成了。
结果




在Tex blend模式下,拉动滑条就可以改变两张图的混合比例
接下来该干什么
在此节完成后,推荐大家尝试自己重新实现The-Forge的第一个demo。需要:
自己实现一个camera
天空盒的绘制
习实例化渲染

相信这个demo对你来说并不会是难事
参考
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