From aa9614e0ab8db7cd101868fb994e84d79d33addf Mon Sep 17 00:00:00 2001 From: BlueRose <378100977@qq.com> Date: Wed, 7 Feb 2024 21:19:35 +0800 Subject: [PATCH] vault backup: 2024-02-07 21:19:35 --- .../剖析虚幻渲染体系(09)- 材质体系.md | 276 +++++++++++++++++- 1 file changed, 275 insertions(+), 1 deletion(-) diff --git a/03-UnrealEngine/Rendering/RenderingPipeline/向往渲染系列文章阅读笔记/剖析虚幻渲染体系(09)- 材质体系.md b/03-UnrealEngine/Rendering/RenderingPipeline/向往渲染系列文章阅读笔记/剖析虚幻渲染体系(09)- 材质体系.md index 46e68ff..13b385c 100644 --- a/03-UnrealEngine/Rendering/RenderingPipeline/向往渲染系列文章阅读笔记/剖析虚幻渲染体系(09)- 材质体系.md +++ b/03-UnrealEngine/Rendering/RenderingPipeline/向往渲染系列文章阅读笔记/剖析虚幻渲染体系(09)- 材质体系.md @@ -76,6 +76,12 @@ void FBasePassMeshProcessor::AddMeshBatch(const FMeshBatch& RESTRICT MeshBatch, >其实应该说**FMaterial**与**FMaterialResource**从FMaterialRenderProxy中将**有多线程竞争风险的渲染所需数据进行剥离**。渲染器只需要拿到FMaterial就可以获取Shader数据并进行MeshBatch提交。 >在FMaterialRenderProxy中通过**GetMaterialXXX()** 系列函数获取FMaterial。如果Shader没有编译好会进行等待,并在等待完之后返回。GetMaterialFallbackXXX()系列函数会不断递归获取有效的FMaterial直到默认UMaterial::GetDefaultMaterial()。 >从UMaterial调用GetRenderProxy()获取**FDefaultMaterialInstance DefaultMaterialInstance**,而这个变量在**UMaterial::PostInitProperties()** 通过**DefaultMaterialInstance = new FDefaultMaterialInstance(this);** 初始化。 + +MaterialTemplate.ush: +- **FHLSLMaterialTranslator::Translate()** 转译材质蓝图的材质节点表达式,将所有材质属性的编译结果填充到格子的FShaderCodeChunk中。 +- **FHLSLMaterialTranslator::GetMaterialEnvironment()** 处理材质蓝图的编译环境(宏定义)。 +- **FHLSLMaterialTranslator::GetMaterialShaderCode()**:填充MaterialTemplate.ush的空缺代码,根据Translate编译的FShaderCodeChunk对应的材质属性接口,以及其它的宏定义、结构体、工具类接口。 + # UMaterial UMaterial是属于引擎层的概念,对应着我们在材质编辑器编辑的uasset资源文件,可以被应用到网格上,以便控制它在场景中的视觉效果。它继承自UMaterialInterface。 ```c++ @@ -1625,4 +1631,272 @@ protected: virtual int32 Fmod(int32 A, int32 B) override; (......) }; -``` \ No newline at end of file +``` +FHLSLMaterialTranslator实现了FMaterialCompiler的所有抽象接口,它的核心核心成员和接口如下: +- FMaterial* Material:编译的目标材质。 +- FMaterialCompilationOutput& MaterialCompilationOutput:编译后的结果。 +- FString MaterialTemplate:待填充或填充后的MaterialTemplate.ush字符串。 +- Translate():执行HLSL转译,将表达式转译成代码块保存到对应的属性槽中。 +- GetMaterialShaderCode():将材质的宏、属性、表达式等数据填充到MaterialTemplate.ush并返回结果。 + +## MaterialTemplate.ush +MaterialTemplate.usf是材质shader模板,内涵大量%s的空缺和待替换的宏,它们由FHLSLMaterialTranslator::GetMaterialShaderCode负责填充。 +```c++ +// Engine\Shaders\Private\MaterialTemplate.ush + +#include "/Engine/Private/SceneTexturesCommon.ush" +#include "/Engine/Private/EyeAdaptationCommon.ush" +#include "/Engine/Private/Random.ush" +#include "/Engine/Private/SobolRandom.ush" +#include "/Engine/Private/MonteCarlo.ush" +#include "/Engine/Generated/UniformBuffers/Material.ush" +#include "/Engine/Private/DepthOfFieldCommon.ush" +#include "/Engine/Private/CircleDOFCommon.ush" +#include "/Engine/Private/GlobalDistanceFieldShared.ush" +#include "/Engine/Private/SceneData.ush" +#include "/Engine/Private/HairShadingCommon.ush" + +////////////////////////////////////////////////////////////////////////// +//! Must match ESceneTextureId + +// 后处理属性宏. +#define PPI_SceneColor 0 +#define PPI_SceneDepth 1 +#define PPI_DiffuseColor 2 +#define PPI_SpecularColor 3 +#define PPI_SubsurfaceColor 4 +#define PPI_BaseColor 5 +#define PPI_Specular 6 +#define PPI_Metallic 7 +#define PPI_WorldNormal 8 +#define PPI_SeparateTranslucency 9 +#define PPI_Opacity 10 +#define PPI_Roughness 11 +#define PPI_MaterialAO 12 +#define PPI_CustomDepth 13 +(......) + +////////////////////////////////////////////////////////////////////////// + +// 待填充的宏定义. +#define NUM_MATERIAL_TEXCOORDS_VERTEX %s +#define NUM_MATERIAL_TEXCOORDS %s +#define NUM_CUSTOM_VERTEX_INTERPOLATORS %s +#define NUM_TEX_COORD_INTERPOLATORS %s + +// 顶点插值位置定义. +%s + +// 文件引用和宏定义. + +#include "/Engine/Private/PaniniProjection.ush" + +#ifndef USE_DITHERED_LOD_TRANSITION + #if USE_INSTANCING + #ifndef USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED + #error "USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED should have been defined" + #endif + #define USE_DITHERED_LOD_TRANSITION USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED + #else + #ifndef USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL + #error "USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL should have been defined" + #endif + #define USE_DITHERED_LOD_TRANSITION USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL + #endif +#endif + +#ifndef USE_STENCIL_LOD_DITHER + #define USE_STENCIL_LOD_DITHER USE_STENCIL_LOD_DITHER_DEFAULT +#endif + +#define MATERIALBLENDING_ANY_TRANSLUCENT (MATERIALBLENDING_TRANSLUCENT || MATERIALBLENDING_ADDITIVE || MATERIALBLENDING_MODULATE) + +(......) + +// 材质的各类结构体. +struct FMaterialAttributes +{ +%s +}; + +struct FPixelMaterialInputs +{ +%s +}; + +// 像素参数. +struct FMaterialPixelParameters +{ +#if NUM_TEX_COORD_INTERPOLATORS + float2 TexCoords[NUM_TEX_COORD_INTERPOLATORS]; +#endif + + half4 VertexColor; + half3 WorldNormal; + half3 WorldTangent; + half3 ReflectionVector; + half3 CameraVector; + half3 LightVector; + float4 SvPosition; + float4 ScreenPosition; + half UnMirrored; + half TwoSidedSign; + half3x3 TangentToWorld; + +#if USE_WORLDVERTEXNORMAL_CENTER_INTERPOLATION + half3 WorldVertexNormal_Center; +#endif + + float3 AbsoluteWorldPosition; + float3 WorldPosition_CamRelative; + float3 WorldPosition_NoOffsets; + float3 WorldPosition_NoOffsets_CamRelative; + half3 LightingPositionOffset; + float AOMaterialMask; + +#if LIGHTMAP_UV_ACCESS + float2 LightmapUVs; +#endif + +#if USE_INSTANCING + half4 PerInstanceParams; +#endif + + uint PrimitiveId; + +#if TEX_COORD_SCALE_ANALYSIS + FTexCoordScalesParams TexCoordScalesParams; +#endif + + (.....) +}; + +// 顶点参数. +struct FMaterialVertexParameters +{ + float3 WorldPosition; + half3x3 TangentToWorld; +#if USE_INSTANCING + float4x4 InstanceLocalToWorld; + float3 InstanceLocalPosition; + float4 PerInstanceParams; + uint InstanceId; + uint InstanceOffset; + +#elif IS_MESHPARTICLE_FACTORY + float4x4 InstanceLocalToWorld; +#endif + float4x4 PrevFrameLocalToWorld; + + float3 PreSkinnedPosition; + float3 PreSkinnedNormal; + +#if GPU_SKINNED_MESH_FACTORY + float3 PreSkinOffset; + float3 PostSkinOffset; +#endif + + half4 VertexColor; +#if NUM_MATERIAL_TEXCOORDS_VERTEX + float2 TexCoords[NUM_MATERIAL_TEXCOORDS_VERTEX]; + #if ES3_1_PROFILE + float2 TexCoordOffset; + #endif +#endif + + FMaterialParticleParameters Particle; + uint PrimitiveId; + + (......) +}; + +// 数据操作接口. +MaterialFloat3x3 GetLocalToWorld3x3(uint PrimitiveId); +MaterialFloat3x3 GetLocalToWorld3x3(); +float3 GetObjectWorldPosition(FMaterialPixelParameters Parameters); +float3 GetObjectWorldPosition(FMaterialTessellationParameters Parameters); +(......) + +// 材质表达式接口. +float MaterialExpressionDepthOfFieldFunction(float SceneDepth, int FunctionValueIndex); +float2 MaterialExpressionGetAtlasUVs(FMaterialPixelParameters Parameters); +float4 MaterialExpressionGetHairAuxilaryData(FMaterialPixelParameters Parameters); +float3 MaterialExpressionGetHairColorFromMelanin(float Melanin, float Redness, float3 DyeColor); +(......) + +// 材质属性查找. +MaterialFloat4 ProcessMaterialColorTextureLookup(MaterialFloat4 TextureValue); +MaterialFloat4 ProcessMaterialVirtualColorTextureLookup(MaterialFloat4 TextureValue); +MaterialFloat4 ProcessMaterialExternalTextureLookup(MaterialFloat4 TextureValue); +MaterialFloat4 ProcessMaterialLinearColorTextureLookup(MaterialFloat4 TextureValue); +MaterialFloat ProcessMaterialGreyscaleTextureLookup(MaterialFloat TextureValue); +(......) + +// 统一材质表达式. +%s + +// 材质属性获取接口. +half3 GetMaterialNormalRaw(FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialNormal(FMaterialPixelParameters Parameters, FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialTangentRaw(FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialTangent(FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialEmissiveRaw(FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialEmissive(FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialEmissiveForCS(FMaterialPixelParameters Parameters); +{ +%s; +} +uint GetMaterialShadingModel(FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialBaseColorRaw(FPixelMaterialInputs PixelMaterialInputs); +half3 GetMaterialBaseColor(FPixelMaterialInputs PixelMaterialInputs); +half GetMaterialCustomData0(FMaterialPixelParameters Parameters) +{ +%s; +} +half GetMaterialCustomData1(FMaterialPixelParameters Parameters) +{ +%s; +} +half GetMaterialAmbientOcclusionRaw(FPixelMaterialInputs PixelMaterialInputs); +half GetMaterialAmbientOcclusion(FPixelMaterialInputs PixelMaterialInputs); +half2 GetMaterialRefraction(FPixelMaterialInputs PixelMaterialInputs); +(......) + +// 计算材质参数接口. +void CalcMaterialParametersEx( + in out FMaterialPixelParameters Parameters, + in out FPixelMaterialInputs PixelMaterialInputs, + float4 SvPosition, + float4 ScreenPosition, + FIsFrontFace bIsFrontFace, + float3 TranslatedWorldPosition, + float3 TranslatedWorldPositionExcludingShaderOffsets); +void CalcMaterialParameters( + in out FMaterialPixelParameters Parameters, + in out FPixelMaterialInputs PixelMaterialInputs, + float4 SvPosition, + FIsFrontFace bIsFrontFace); +void CalcMaterialParametersPost( + in out FMaterialPixelParameters Parameters, + in out FPixelMaterialInputs PixelMaterialInputs, + float4 SvPosition, + FIsFrontFace bIsFrontFace); +float ApplyPixelDepthOffsetToMaterialParameters(inout FMaterialPixelParameters MaterialParameters, FPixelMaterialInputs PixelMaterialInputs, out float OutDepth); +(......) +``` +MaterialTemplate.ush包含了大量的数据和接口,主要有几类: +- 基础shader模块引用。 +- 待填充的宏定义。 +- 待填充的接口实现。 +- 顶点、像素、材质属性等结构体定义。部分结构体待填充。 +- 材质属性、数据处理、表达式、工具类接口定义。部分接口待填充。 + +# 材质编译流程 +材质ShaderMap的编译入口在FMaterial的以下两个接口: +- FMaterial::BeginCompileShaderMap +- FMaterial::GetMaterialExpressionSource + +**编译不同类型的shader时,需要的数据不完全一样**: +- GlobalShader:Shader_x.usf +- MaterialShader:Shader_x.usf + MaterialTemplate_x.usf +- MeshMaterialShader:Shader_x.usf + MaterialTemplate_x.usf + VertexFactory_x.usf \ No newline at end of file