Uniform Buffer、FVertexFactory、FVertexFactoryType
按照惯例,先自淫一下,宣传下自己的书。
Uniform Buffer对应C++代码里面用BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT_WITH_CONSTRUCTOR或BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT两个宏生成的Shader Parameter,对应为Struct结构。
实现:
IMPLEMENT_GLOBAL_SHADER_PARAMETER_STRUCT(FSkyLightData, "SkyLight");
声明:
BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FSkyLightData, )
SHADER_PARAMETER(uint32, SamplesPerPixel)
SHADER_PARAMETER_TEXTURE(Texture2D, SceneColorTexture)
SHADER_PARAMETER(float, MaxRayDistance)
SHADER_PARAMETER(FVector, Color)
…
END_GLOBAL_SHADER_PARAMETER_STRUCT()
支持的数据类型
它里面可以存放任何类型的数据,资源类型则为指针类型。
加入普通数据类型:
SHADER_PARAMETER(FMatrix,LocalToWorld)
SHADER_PARAMETER_EX(float,DecalReceiverMask,EShaderPrecisionModifier::Half)
加入资源数据类型:
SHADER_PARAMETER_TEXTURE(Texture2D, SceneColorTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, SceneColorTextureSampler)
SHADER_PARAMETER_TEXTURE(Texture2D<float>, SceneDepthTextureNonMS)
SHADER_PARAMETER_TEXTURE(Texture2D<float4>, GBufferATextureNonMS)
SHADER_PARAMETER_SRV(Buffer<float4>, VertexFetch_PointColorBuffer)
SHADER_PARAMETER_SRV(Texture2D<uint2>, CustomStencilTexture)
加入数组类型:
SHADER_PARAMETER_TEXTURE_ARRAY(Texture2D, Textures, [GMaxLUTBlendCount])
SHADER_PARAMETER_SAMPLER_ARRAY(SamplerState, Samplers, [GMaxLUTBlendCount])
SHADER_PARAMETER_ARRAY(float, LUTWeights, [GMaxLUTBlendCount])
加入Struct类型
SHADER_PARAMETER_STRUCT_INCLUDE(FLightShaderParameters, LightParameters)
加入UniformBuffer索引
SHADER_PARAMETER_STRUCT_REF(FSkyLightData, SkyLight)
加入Unordered Access View
SHADER_PARAMETER_SRV(RaytracingAccelerationStructure, TLAS)
在Shader中,Uniform Buffer参数可按照Struct方式访问的。在任何一个Shader里面你就可以使用 “SKyLight.Color”。
实现原理
Uniform Buffer是Unreal自己引进的资源类型,没有对应的渲染API的资源。它里面保存的数据会在RHI层解析出来,然后设置到对应的渲染API Slot中。所以RHI层保存了每个Uniform Buffer数据分布情况。
C++层
每次都会创建对应的Struct,填写Struct数据,然后用Struct创建Uniform Buffer,无论成员数据在Shader中是否用到,都会赋值,资源类型为指针类型。
在宏声明中
BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FSkyLightData, )
会声明FSkyLightData类,下面接着是它的参数。
在宏实现中
#define IMPLEMENT_GLOBAL_SHADER_PARAMETER_STRUCT(StructTypeName,ShaderVariableName) \
FShaderParametersMetadata StructTypeName::StaticStructMetadata( \
FShaderParametersMetadata::EUseCase::GlobalShaderParameterStruct, \
FName(TEXT(#StructTypeName)), \
TEXT(#StructTypeName), \
TEXT(ShaderVariableName), \
sizeof(StructTypeName), \
StructTypeName::zzGetMembers())
会定义FSkyLightData类中FShaderParametersMetadata类型的静态全局变量。全局静态变量初始化会先于Main函数,被加入到全局GlobalListLink链表中。
FShaderParametersMetadata类保存着所有成员变量的细节和分布情况。
StructTypeName::zzGetMembers()会递归调用收集所有成员。
Shader层
在编译Shader前,GlobalListLink中保存所有类,生成Shader代码可用的结构体,因为不是所有数据都被用到,编译后,得到的占用Slot情况都是精简后的,数据分布情况保留在RHI层的Shader中。
RHI层
Uniform Buffer进入RHI层,会把Uniform Buffer数据分解出来,根据当前RHI层Shader数据分布情况,设置到对应Slot中。
FVertexFactory
可以得到Vertex Declaration 和Stream
每个Sub Mesh都会new Vertex Factory
FVertexFactoryType
全局唯一静态变量
包含所有和Vertex Shader有关的内容。
FMaterial遍历所有FVertexFactoryType生成所有的Vertex Shader。
通过FMaterial得到对应Vertex Shader。