vault backup: 2024-02-06 20:08:30

This commit is contained in:
BlueRose 2024-02-06 20:08:30 +08:00
parent 67a7f200b8
commit cb4b81260a

View File

@ -661,4 +661,236 @@ private:
上面展示了Vertex Factory的很多类型有好几个是核心类比如FVertexFactory、FVertexElement、FRHIVertexDeclaration、FRHIVertexBuffer、FVertexFactoryType、FVertexStreamComponent、FVertexInputStream、FVertexFactoryShaderParameters等。那么它们之间的关系是什么呢
为了更好地说明它们之间的关系以静态模型的FStaticMeshDataType为例
![[UE_VertexFactory_FStaticMeshDataType.jpg]]
![[UE_VertexFactory_FStaticMeshDataType.jpg]]
FStaticMeshDataType会包含若干个FVertexStreamComponent实例每个FVertexStreamComponent包含了一个在**FVertexDeclarationElementList**的**FVertexElement实例索引**和一个在**FVertexInputStreamArray**列表的**FVertexStream实例索引**。
此外FVertexFactory是个基类内置的子类主要有
- FGeometryCacheVertexVertexFactory几何缓存顶点的顶点工厂常用于预生成的布料、动作等网格类型。
- FGPUBaseSkinVertexFactoryGPU蒙皮骨骼网格的父类它的子类有
- TGPUSkinVertexFactory可指定骨骼权重方式的GPU蒙皮的顶点工厂。
- FLocalVertexFactory局部顶点工厂常用于**静态网格**,它拥有**数量较多的子类**
- FInstancedStaticMeshVertexFactory实例化的静态网格顶点工厂。
- FSplineMeshVertexFactory样条曲线网格顶点工厂。
- FGeometryCollectionVertexFactory几何收集顶点工厂。
- FGPUSkinPassthroughVertexFactory启用了Skin Cache模式的蒙皮骨骼顶点工厂。
- FSingleTriangleMeshVertexFactory单个三角形网格的顶点工厂用于体积云渲染。
- ......
- FParticleVertexFactoryBase用于粒子渲染的顶点工厂基类。
- FLandscapeVertexFactory用于渲染地形的顶点工厂。
除了以上继承自FVertexFactory还有一些不是继承自FVertexFactory的类型
- FGPUBaseSkinAPEXClothVertexFactory布料顶点工厂。
- TGPUSkinAPEXClothVertexFactory可带骨骼权重模式的布料顶点工厂。
除了FVertexFactory相应的其它核心类也有继承体系。比如FVertexFactoryShaderParameters的子类有
- FGeometryCacheVertexFactoryShaderParameters
- FGPUSkinVertexFactoryShaderParameters
- FMeshParticleVertexFactoryShaderParameters
- FParticleSpriteVertexFactoryShaderParameters
- FGPUSpriteVertexFactoryShaderParametersVS
- FGPUSpriteVertexFactoryShaderParametersPS
- FSplineMeshVertexFactoryShaderParameters
- FLocalVertexFactoryShaderParametersBase
- FLandscapeVertexFactoryVertexShaderParameters
- FLandscapeVertexFactoryPixelShaderParameters
- ......
另外有部分顶点工厂还会在内部派生FStaticMeshDataType的类型以复用静态网格相关的数据成员。为了更好地说明顶点工厂的使用方式下面就以最常见的FLocalVertexFactory和使用了FLocalVertexFactory的CableComponent为例
```c++
class ENGINE_API FLocalVertexFactory : public FVertexFactory
{
public:
FLocalVertexFactory(ERHIFeatureLevel::Type InFeatureLevel, const char* InDebugName)
// 派生自FStaticMeshDataType的数据类型.
struct FDataType : public FStaticMeshDataType
{
FRHIShaderResourceView* PreSkinPositionComponentSRV = nullptr;
};
// 环境变量更改和校验.
static bool ShouldCompilePermutation(const FVertexFactoryShaderPermutationParameters& Parameters);
static void ModifyCompilationEnvironment(const FVertexFactoryShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment);
static void ValidateCompiledResult(const FVertexFactoryType* Type, EShaderPlatform Platform, const FShaderParameterMap& ParameterMap, TArray<FString>& OutErrors);
// 由TSynchronizedResource从游戏线程更新而来的数据.
void SetData(const FDataType& InData);
// 从其它顶点工厂复制数据.
void Copy(const FLocalVertexFactory& Other);
// FRenderResource接口.
virtual void InitRHI() override;
virtual void ReleaseRHI() override
{
UniformBuffer.SafeRelease();
FVertexFactory::ReleaseRHI();
}
// 顶点颜色接口.
void SetColorOverrideStream(FRHICommandList& RHICmdList, const FVertexBuffer* ColorVertexBuffer) const;
void GetColorOverrideStream(const FVertexBuffer* ColorVertexBuffer, FVertexInputStreamArray& VertexStreams) const;
// 着色器参数和其它数据接口.
inline FRHIShaderResourceView* GetPositionsSRV() const;
inline FRHIShaderResourceView* GetPreSkinPositionSRV() const;
inline FRHIShaderResourceView* GetTangentsSRV() const;
inline FRHIShaderResourceView* GetTextureCoordinatesSRV() const;
inline FRHIShaderResourceView* GetColorComponentsSRV() const;
inline const uint32 GetColorIndexMask() const;
inline const int GetLightMapCoordinateIndex() const;
inline const int GetNumTexcoords() const;
FRHIUniformBuffer* GetUniformBuffer() const;
(......)
protected:
// 从游戏线程传入的数据. FDataType是FStaticMeshDataType的子类.
FDataType Data;
// 局部顶点工厂的着色器参数.
TUniformBufferRef<FLocalVertexFactoryUniformShaderParameters> UniformBuffer;
// 顶点颜色流索引.
int32 ColorStreamIndex;
(......)
};
// Engine\Source\Runtime\Engine\Public\LocalVertexFactory.cpp
void FLocalVertexFactory::InitRHI()
{
// 是否使用gpu场景.
const bool bCanUseGPUScene = UseGPUScene(GMaxRHIShaderPlatform, GMaxRHIFeatureLevel);
// 初始化位置流和位置声明.
if (Data.PositionComponent.VertexBuffer != Data.TangentBasisComponents[0].VertexBuffer)
{
// 增加顶点声明.
auto AddDeclaration = [this, bCanUseGPUScene](EVertexInputStreamType InputStreamType, bool bAddNormal)
{
// 顶点流元素.
FVertexDeclarationElementList StreamElements;
StreamElements.Add(AccessStreamComponent(Data.PositionComponent, 0, InputStreamType));
bAddNormal = bAddNormal && Data.TangentBasisComponents[1].VertexBuffer != NULL;
if (bAddNormal)
{
StreamElements.Add(AccessStreamComponent(Data.TangentBasisComponents[1], 2, InputStreamType));
}
const uint8 TypeIndex = static_cast<uint8>(InputStreamType);
PrimitiveIdStreamIndex[TypeIndex] = -1;
if (GetType()->SupportsPrimitiveIdStream() && bCanUseGPUScene)
{
// When the VF is used for rendering in normal mesh passes, this vertex buffer and offset will be overridden
StreamElements.Add(AccessStreamComponent(FVertexStreamComponent(&GPrimitiveIdDummy, 0, 0, sizeof(uint32), VET_UInt, EVertexStreamUsage::Instancing), 1, InputStreamType));
PrimitiveIdStreamIndex[TypeIndex] = StreamElements.Last().StreamIndex;
}
// 初始化声明.
InitDeclaration(StreamElements, InputStreamType);
};
// 增加PositionOnly和PositionAndNormalOnly两种顶点声明, 其中前者不需要法线.
AddDeclaration(EVertexInputStreamType::PositionOnly, false);
AddDeclaration(EVertexInputStreamType::PositionAndNormalOnly, true);
}
// 顶点声明元素列表.
FVertexDeclarationElementList Elements;
// 顶点位置
if(Data.PositionComponent.VertexBuffer != NULL)
{
Elements.Add(AccessStreamComponent(Data.PositionComponent,0));
}
// 图元id
{
const uint8 Index = static_cast<uint8>(EVertexInputStreamType::Default);
PrimitiveIdStreamIndex[Index] = -1;
if (GetType()->SupportsPrimitiveIdStream() && bCanUseGPUScene)
{
// When the VF is used for rendering in normal mesh passes, this vertex buffer and offset will be overridden
Elements.Add(AccessStreamComponent(FVertexStreamComponent(&GPrimitiveIdDummy, 0, 0, sizeof(uint32), VET_UInt, EVertexStreamUsage::Instancing), 13));
PrimitiveIdStreamIndex[Index] = Elements.Last().StreamIndex;
}
}
// 切线和法线, 切线法线才需要被顶点流使用, 副法线由shader生成.
uint8 TangentBasisAttributes[2] = { 1, 2 };
for(int32 AxisIndex = 0;AxisIndex < 2;AxisIndex++)
{
if(Data.TangentBasisComponents[AxisIndex].VertexBuffer != NULL)
{
Elements.Add(AccessStreamComponent(Data.TangentBasisComponents[AxisIndex],TangentBasisAttributes[AxisIndex]));
}
}
if (Data.ColorComponentsSRV == nullptr)
{
Data.ColorComponentsSRV = GNullColorVertexBuffer.VertexBufferSRV;
Data.ColorIndexMask = 0;
}
// 顶点颜色
ColorStreamIndex = -1;
if(Data.ColorComponent.VertexBuffer)
{
Elements.Add(AccessStreamComponent(Data.ColorComponent,3));
ColorStreamIndex = Elements.Last().StreamIndex;
}
else
{
FVertexStreamComponent NullColorComponent(&GNullColorVertexBuffer, 0, 0, VET_Color, EVertexStreamUsage::ManualFetch);
Elements.Add(AccessStreamComponent(NullColorComponent, 3));
ColorStreamIndex = Elements.Last().StreamIndex;
}
// 纹理坐标
if(Data.TextureCoordinates.Num())
{
const int32 BaseTexCoordAttribute = 4;
for(int32 CoordinateIndex = 0;CoordinateIndex < Data.TextureCoordinates.Num();CoordinateIndex++)
{
Elements.Add(AccessStreamComponent(
Data.TextureCoordinates[CoordinateIndex],
BaseTexCoordAttribute + CoordinateIndex
));
}
for (int32 CoordinateIndex = Data.TextureCoordinates.Num(); CoordinateIndex < MAX_STATIC_TEXCOORDS / 2; CoordinateIndex++)
{
Elements.Add(AccessStreamComponent(
Data.TextureCoordinates[Data.TextureCoordinates.Num() - 1],
BaseTexCoordAttribute + CoordinateIndex
));
}
}
// 光照图
if(Data.LightMapCoordinateComponent.VertexBuffer)
{
Elements.Add(AccessStreamComponent(Data.LightMapCoordinateComponent,15));
}
else if(Data.TextureCoordinates.Num())
{
Elements.Add(AccessStreamComponent(Data.TextureCoordinates[0],15));
}
// 初始化顶点声明
InitDeclaration(Elements);
const int32 DefaultBaseVertexIndex = 0;
const int32 DefaultPreSkinBaseVertexIndex = 0;
if (RHISupportsManualVertexFetch(GMaxRHIShaderPlatform) || bCanUseGPUScene)
{
SCOPED_LOADTIMER(FLocalVertexFactory_InitRHI_CreateLocalVFUniformBuffer);
UniformBuffer = CreateLocalVFUniformBuffer(this, Data.LODLightmapDataIndex, nullptr, DefaultBaseVertexIndex, DefaultPreSkinBaseVertexIndex);
}
}
// 实现FLocalVertexFactory的参数类型.
IMPLEMENT_VERTEX_FACTORY_PARAMETER_TYPE(FLocalVertexFactory, SF_Vertex, FLocalVertexFactoryShaderParameters);
// 实现FLocalVertexFactory.
IMPLEMENT_VERTEX_FACTORY_TYPE_EX(FLocalVertexFactory,"/Engine/Private/LocalVertexFactory.ush",true,true,true,true,true,true,true);
```