当前位置 博文首页 > 0向往0:剖析虚幻渲染体系(05)- 光源和阴影

    0向往0:剖析虚幻渲染体系(05)- 光源和阴影

    作者:0向往0 时间:2021-05-27 18:25

    目录
    • 5.1 本篇概述
      • 5.1.1 本篇内容
      • 5.1.2 基础概念
    • 5.2 Shader体系
      • 5.2.1 Shader概览
      • 5.2.2 Shader模块层级
      • 5.2.3 Shader基础模块
        • 5.2.3.1 Platform.ush
        • 5.2.3.2 Common.ush
        • 5.2.3.3 Definitions.ush
        • 5.2.3.4 ShadingCommon.ush
        • 5.2.3.5 BasePassCommon.ush
        • 5.2.3.6 BRDF.ush
        • 5.2.3.7 VertexFactoryCommon.ush
        • 5.2.3.8 BasePassVertexCommon.ush
        • 5.2.3.9 ShadingModels.ush
        • 5.2.3.10 DeferredShadingCommon.ush
        • 5.2.3.11 DeferredLightingCommon.ush
        • 5.2.3.12 ShadingModelsMaterial.ush
        • 5.2.3.13 LocalVertexFactoryCommon.ush
        • 5.2.3.14 LocalVertexFactory.ush
    • 5.3 BasePass
      • 5.3.1 BasePass渲染流程
      • 5.3.2 BasePass渲染状态
      • 5.3.3 BasePass Shader
        • 5.3.3.1 BasePassVertexShader
        • 5.3.3.2 BasePassPixelShader
      • 5.3.4 BasePass总结
    • 5.4 UE的光源
      • 5.4.1 光源概述
      • 5.4.2 光源算法
        • 5.4.2.1 BRDF概述
        • 5.4.2.2 特殊光源
      • 5.4.3 光源分配和裁剪
        • 5.4.3.1 光源基础概念
        • 5.4.3.2 GatherAndSortLights
        • 5.4.3.3 ComputeLightGrid
    • 5.5 LightingPass
      • 5.5.1 LightingPass渲染流程
      • 5.5.2 LightingPass渲染状态
      • 5.5.3 LightingPass Shader
        • 5.5.3.1 DeferredLightVertexShader
        • 5.5.3.2 DeferredLightPixelShader
      • 5.5.4 LightingPass总结
    • 5.6 UE的阴影
      • 5.6.1 阴影概述
      • 5.6.2 阴影基础类型
      • 5.6.3 阴影初始化
        • 5.6.3.1 InitDynamicShadows
        • 5.6.3.2 CreateWholeSceneProjectedShadow
        • 5.6.3.3 AddViewDependentWholeSceneShadowsForView
        • 5.6.3.4 SetupInteractionShadows
        • 5.6.3.5 CreatePerObjectProjectedShadow
        • 5.6.3.6 InitProjectedShadowVisibility
        • 5.6.3.7 UpdatePreshadowCache
        • 5.6.3.8 GatherShadowPrimitives
        • 5.6.3.9 FGatherShadowPrimitivesPacket
        • 5.6.3.10 AllocateShadowDepthTargets
        • 5.6.3.11 GatherShadowDynamicMeshElements
        • 5.6.3.12 阴影初始化总结
      • 5.6.4 阴影渲染
        • 5.6.4.1 RenderShadowDepthMaps
        • 5.6.4.2 FProjectedShadowInfo::RenderDepth
        • 5.6.4.3 FProjectedShadowInfo::RenderTranslucencyDepths
        • 5.6.4.4 RenderShadowDepthMapAtlases
      • 5.6.5 阴影应用
        • 5.6.5.1 RenderLights
        • 5.6.5.2 RenderShadowProjections
        • 5.6.5.3 FProjectedShadowInfo::RenderProjection
        • 5.6.5.4 FShadowProjectionNoTransformVS和TShadowProjectionPS
        • 5.6.5.5 RenderLight
        • 5.6.5.6 阴影Shader逻辑
        • 5.6.5.7 阴影应用总结
      • 5.6.6 UE阴影总结
    • 5.7 本篇总结
      • 5.7.1 本篇思考
    • 特别说明
    • 参考文献

     

     

    5.1 本篇概述

    5.1.1 本篇内容

    本篇主要阐述UE的以下内容:

    • Shader代码及主要模块。
    • UE的光源。
    • UE的阴影。
    • BasePass的机制和实现,包含C++和Shader。
    • LightingPass的机制和实现,包含C++和Shader。

    其中BasePass和LightingPass在上一篇中已经粗略地浅析过,本篇继续深入地剖析。

    本篇文章将首次引入mermaid语法,它是类似于\(\LaTeX\)的以文本描述作为画图工具的语法,简单、轻便、小巧,高清无损画质,和Markdown搭配,浑然天成。

    graph TD A[Unreal Engine] --> B(Rendering System) B --> C{RHI} C -->|One| D[DirectX] C -->|Two| E[Metal] C -->|Three| F[Vulkan]

    利用mermaid语法做出的矢量图例,开启文本绘图新纪元。

    前方高能预警,本篇篇幅达到5万多字,是目前本系列文章最长的一篇,需做好心理准备。

    5.1.2 基础概念

    本篇涉及的部分渲染基础概念及解析如下表:

    概念 缩写 中文译名 解析
    Shader - 着色器、着色代码 用于GPU执行的代码片段,常见的类型有VS(顶点着色器)和PS(像素着色器),也泛指Shader代码文件。
    Vertex Shader VS 顶点着色器 在GPU的顶点处理阶段执行的代码片段,常用于处理顶点变换。
    Pixel Shader PS 像素着色器 OpenGL中叫片元着色(Fragment Shader),专门执行于像素处理阶段的代码片段,用于处理光栅化后的像素,如光照计算等。
    High Level Shading Language HLSL 高级着色语言 DirectX的专用Shader语言,Vulkan、OpenGL的被称为GLSL,Metal的被成为MSL。

     

    5.2 Shader体系

    由于后面的章节会直接进行shader代码分析,所以本章先对UE的Shader体系做个简洁的分析,以便大家能够很好地过度到后续章节。

    5.2.1 Shader概览

    UE的内置Shader文件在Engine\Shaders目录下:

    所有Shader文件总数超过了600个,其中Shader头文件的后缀是ush,可被其它Shader文件include,实现文件是usf,通常不可被其它Shader文件include。下面是Shader目录及部分模块一览:

    Shaders/
      Private/
        BasePassCommon.ush
        BasePassPixelShader.usf
        BasePassVertexCommon.ush
        BasePassVertexShader.usf
        BRDF.ush
        CapsuleLight.ush
        CapsuleLightIntegrate.ush
        CapsuleShadowShaders.usf
        Common.ush
        CommonViewUniformBuffer.ush
        DeferredLightingCommon.ush
        DeferredLightPixelShaders.usf
        DeferredLightVertexShaders.usf
        DeferredShadingCommon.ush
        Definitions.usf
        LightGridCommon.ush
        LightGridInjection.usf
        LocalVertexFactory.ush
        MaterialTemplate.ush
        RectLight.ush
        RectLightIntegrate.ush
        ShadingCommon.ush
        ShadingModels.ush
        ShadingModelsMaterial.ush
        ShadowDepthCommon.ush
        ShadowDepthPixelShader.usf
        ShadowDepthVertexShader.usf
        ShadowProjectionCommon.ush
        ShadowProjectionPixelShader.usf
        ShadowProjectionVertexShader.usf
        SHCommon.ush
        VertexFactoryCommon.ush
        (......)
      Public/
        FP16Math.ush
        Platform.ush
        ShaderVersion.ush
        Platform/
          D3D/
            D3DCommon.ush
          Metal/
            MetalCommon.ush
            MetalSubpassSupport.ush
          Vulkan/
            VulkanCommon.ush
            VulkanSubpassSupport.ush
      Shared/
        (......)
      StandaloneRenderer/
        D3D/
          GammaCorrectionCommon.hlsl
          SlateDefaultVertexShader.hlsl
          (......)
        OpenGL/
          SlateElementPixelShader.glsl
          SlateVertexShader.glsl
          (......)
    

    5.2.2 Shader模块层级

    第一梯队的shader模块是最底层最基础的模块,这些模块不会引用其它模块,但会被其它很多模块引用。这些模块主要有:

    • BasePassCommon.ush
    • BRDF.ush
    • CapsuleLight.ush
    • Common.ush
    • CommonViewUniformBuffer.ush
    • Definitions.usf
    • FP16Math.ush
    • Platform.ush
    • ShaderVersion.ush
    • LightGridCommon.ush
    • LocalVertexFactoryCommon.ush
    • ShadingCommon.ush
    • ShadowDepthCommon.ush
    • ShadowProjectionCommon.ush
    • SHCommon.ush
    • (......)

    第二梯队的重要或基础模块会引用第一梯队的基础模块,但也会被其它梯队或模块引用:

    • BasePassVertexCommon.ush
    • CapsuleLightIntegrate.ush
    • DeferredLightingCommon.ush
    • DeferredShadingCommon.ush
    • LocalVertexFactory.ush
    • MaterialTemplate.ush
    • RectLight.ush
    • RectLightIntegrate.ush
    • ShadingModels.ush
    • ShadingModelsMaterial.ush
    • VertexFactoryCommon.ush
    • (......)

    最后是第三梯队的模块,重要模块的实现,会引用第一、第二梯队的模块:

    • BasePassPixelShader.usf
    • BasePassVertexShader.usf
    • CapsuleShadowShaders.usf
    • DeferredLightPixelShaders.usf
    • DeferredLightVertexShaders.usf
    • ShadowProjectionPixelShader.usf
    • ShadowProjectionVertexShader.usf
    • (......)

    5.2.3 Shader基础模块

    本小节选取部分基础或重要的shader模块,分析它们的接口、类型、定义,以便让大家对UE的内置shader模块有个大致的理解,了解UE自带了哪些模块,拥有哪些内置接口,在面对后续的shader代码剖析时更加了然于胸。

    5.2.3.1 Platform.ush

    主要定义了跟图形API(DirectX、OpenGL、Vulkan、Metal)和FEATURE_LEVEL相关的宏、变量及工具类接口。部分代码如下:

    // FEATURE_LEVEL的宏定义
    #define FEATURE_LEVEL_ES2_REMOVED    1
    #define FEATURE_LEVEL_ES3_1            2
    #define FEATURE_LEVEL_SM3            3
    #define FEATURE_LEVEL_SM4            4
    #define FEATURE_LEVEL_SM5            5
    #define FEATURE_LEVEL_MAX            6
    
    // 初始化*台相关的宏.
    #ifndef COMPILER_HLSLCC
    #define COMPILER_HLSLCC 0
    #endif
    
    #ifndef COMPILER_HLSL
    #define COMPILER_HLSL 0
    #endif
    
    #ifndef COMPILER_GLSL
    #define COMPILER_GLSL 0
    #endif
    
    #ifndef COMPILER_GLSL_ES3_1
    #define COMPILER_GLSL_ES3_1 0
    #endif
    
    #ifndef COMPILER_METAL
    #define COMPILER_METAL 0
    #endif
    
    #ifndef SM5_PROFILE
    #define SM5_PROFILE 0
    #endif
    
    (......)
    
    // 浮点数精度
    #ifndef FORCE_FLOATS
    #define FORCE_FLOATS 0
    #endif
    
    #if (!(ES3_1_PROFILE || METAL_PROFILE) || FORCE_FLOATS)
        #define half float
        #define half1 float1
        #define half2 float2
        #define half3 float3
        #define half4 float4
        #define half3x3 float3x3
        #define half4x4 float4x4 
        #define half4x3 float4x3 
        #define fixed float
        #define fixed1 float1
        #define fixed2 float2
        #define fixed3 float3
        #define fixed4 float4
        #define fixed3x3 float3x3
        #define fixed4x4 float4x4
        #define fixed4x3 float4x3
    #endif
    
    // PROFILE宏定义
    #if PS4_PROFILE
        #define FEATURE_LEVEL FEATURE_LEVEL_SM5
    
    #elif SM5_PROFILE
        // SM5 = full dx11 features (high end UE4 rendering)
        #define FEATURE_LEVEL FEATURE_LEVEL_SM5
    
    #elif SM4_PROFILE
        #define FEATURE_LEVEL FEATURE_LEVEL_SM4
    
    (......)
    
    // 分支语句.
    #ifndef UNROLL
    #define UNROLL
    #endif
    
    #ifndef UNROLL_N
    #define UNROLL_N(N)
    #endif
    
    #ifndef LOOP
    #define LOOP
    #endif
    
    #ifndef BRANCH
    #define BRANCH
    #endif
    
    #ifndef FLATTEN
    #define FLATTEN
    #endif
    
    (......)
    
    // 工具类接口(编译不支持时)
    #if !COMPILER_SUPPORTS_MINMAX3
    
    float min3( float a, float b, float c );
    float max3( float a, float b, float c );
    float2 min3( float2 a, float2 b, float2 c );
    float2 max3( float2 a, float2 b, float2 c );
    
    (......)
    
    #endif
    
    // 解压数据.
    #if !defined(COMPILER_SUPPORTS_UNPACKBYTEN)
    float UnpackByte0(uint v) { return float(v & 0xff); }
    float UnpackByte1(uint v) { return float((v >> 8) & 0xff); }
    float UnpackByte2(uint v) { return float((v >> 16) & 0xff); }
    float UnpackByte3(uint v) { return float(v >> 24); }
    #endif // !COMPILER_SUPPORTS_UNPACKBYTEN
    
    // 封装部分宏.
    #ifndef SNORM
    #if COMPILER_HLSLCC || PS4_PROFILE
        #define SNORM 
        #define UNORM
    #else
        #define SNORM snorm
        #define UNORM unorm
    #endif
    #endif
    
    #ifndef INFINITE_FLOAT
        #if COMPILER_HLSLCC
            #define INFINITE_FLOAT 3.402823e+38
        #else
            #define INFINITE_FLOAT 1.#INF
        #endif
    #endif
    

    5.2.3.2 Common.ush

    此模块主要包含了图形API或Feature Level相关的宏、类型、局部变量、静态变量、基础工具接口等,具体如下:

    // 类型定义或封装
    #if PIXELSHADER
        #define MaterialFloat half
        #define MaterialFloat2 half2
        #define MaterialFloat3 half3
        #define MaterialFloat4 half4
        #define MaterialFloat3x3 half3x3
        #define MaterialFloat4x4 half4x4 
        #define MaterialFloat4x3 half4x3 
    #else
        // Material translated vertex shader code always uses floats, 
        // Because it's used for things like world position and UVs
        #define MaterialFloat float
        #define MaterialFloat2 float2
        #define MaterialFloat3 float3
        #define MaterialFloat4 float4
        #define MaterialFloat3x3 float3x3
        #define MaterialFloat4x4 float4x4 
        #define MaterialFloat4x3 float4x3 
    #endif
    
    #if POST_PROCESS_ALPHA
        #define SceneColorLayout float4
        #define CastFloat4ToSceneColorLayout(x) (x)
        #define SetSceneColorLayoutToFloat4(dest,value) dest = (value)
    #else
        #define SceneColorLayout float3
        #define CastFloat4ToSceneColorLayout(x) ((x).rgb)
        #define SetSceneColorLayoutToFloat4(dest,value) dest.rgb = (value).rgb
    #endif
    
    struct FScreenVertexOutput
    {
    #if METAL_PROFILE || COMPILER_GLSL_ES3_1
        noperspective float2 UV : TEXCOORD0;
    #else
        noperspective MaterialFloat2 UV : TEXCOORD0;
    #endif
        float4 Position : SV_POSITION;
    };
    
    struct FPixelShaderIn
    {
        float4 SvPosition;
        uint Coverage;
        bool bIsFrontFace;
    };
    
    struct FPixelShaderOut
    {
        float4 MRT[8];
        uint Coverage;
        float Depth;
    };
    
    // 宏、常量定义
    #define USE_GLOBAL_CLIP_PLANE (PLATFORM_SUPPORTS_GLOBAL_CLIP_PLANE && PROJECT_ALLOW_GLOBAL_CLIP_PLANE && !MATERIAL_DOMAIN_POSTPROCESS && !MATERIAL_DOMAIN_UI)
    
    #define POSITIVE_INFINITY (asfloat(0x7F800000))
    #define NEGATIVE_INFINITY (asfloat(0xFF800000))
    
    const static MaterialFloat PI = 3.1415926535897932f;
    const static float MaxHalfFloat = 65504.0f;
    const static float Max10BitsFloat = 64512.0f;
    
    #define POW_CLAMP 0.000001f
    
    // 通用变量定义
    Texture2D        LightAttenuationTexture;
    SamplerState    LightAttenuationTextureSampler;
    
    // 基础、工具接口
    float  ClampToHalfFloatRange(float  X);
    float2 ClampToHalfFloatRange(float2 X);
    float3 ClampToHalfFloatRange(float3 X);
    float4 ClampToHalfFloatRange(float4 X);
    float2 Tile1Dto2D(float xsize, float idx);
    MaterialFloat Luminance( MaterialFloat3 LinearColor );
    MaterialFloat length2(MaterialFloat2 v);
    MaterialFloat length2(MaterialFloat3 v);
    MaterialFloat length2(MaterialFloat4 v);
    uint Mod(uint a, uint b);
    uint2 Mod(uint2 a, uint2 b);
    uint3 Mod(uint3 a, uint3 b);
    MaterialFloat UnClampedPow(MaterialFloat X, MaterialFloat Y);
    MaterialFloat2 UnClampedPow(MaterialFloat2 X, MaterialFloat2 Y);
    MaterialFloat3 UnClampedPow(MaterialFloat3 X, MaterialFloat3 Y);
    MaterialFloat4 UnClampedPow(MaterialFloat4 X, MaterialFloat4 Y);
    MaterialFloat ClampedPow(MaterialFloat X,MaterialFloat Y);
    MaterialFloat2 ClampedPow(MaterialFloat2 X,MaterialFloat2 Y);
    MaterialFloat3 ClampedPow(MaterialFloat3 X,MaterialFloat3 Y);
    MaterialFloat4 ClampedPow(MaterialFloat4 X,MaterialFloat4 Y);
    MaterialFloat PositiveClampedPow(MaterialFloat X,MaterialFloat Y);
    MaterialFloat2 PositiveClampedPow(MaterialFloat2 X,MaterialFloat2 Y);
    MaterialFloat3 PositiveClampedPow(MaterialFloat3 X,MaterialFloat3 Y);
    MaterialFloat4 PositiveClampedPow(MaterialFloat4 X,MaterialFloat4 Y);
    uint ReverseBits32( uint bits );
    uint ReverseBitsN(uint Bitfield, const uint BitCount);
    
    // 数学
    float Square( float x );
    float2 Square( float2 x );
    float3 Square( float3 x );
    float4 Square( float4 x );
    float Pow2( float x );
    float2 Pow2( float2 x );
    float3 Pow2( float3 x );
    float4 Pow2( float4 x );
    float Pow3( float x );
    float2 Pow3( float2 x );
    float3 Pow3( float3 x );
    float4 Pow3( float4 x );
    float Pow4( float x );
    float2 Pow4( float2 x );
    float3 Pow4( float3 x );
    float4 Pow4( float4 x );
    float Pow5( float x );
    float2 Pow5( float2 x );
    float3 Pow5( float3 x );
    float4 Pow5( float4 x );
    float Pow6( float x );
    float2 Pow6( float2 x );
    float3 Pow6( float3 x );
    float4 Pow6( float4 x );
    MaterialFloat AtanFast( MaterialFloat x );
    
    // 求导
    float DDX(float Input);
    float2 DDX(float2 Input);
    float3 DDX(float3 Input);
    float4 DDX(float4 Input);
    float DDY(float Input);
    float2 DDY(float2 Input);
    float3 DDY(float3 Input);
    float4 DDY(float4 Input);
    
    // 数据编码解码
    MaterialFloat EncodeLightAttenuation(MaterialFloat InColor);
    MaterialFloat4 EncodeLightAttenuation(MaterialFloat4 InColor);
    MaterialFloat4 RGBTEncode(MaterialFloat3 Color);
    MaterialFloat3 RGBTDecode(MaterialFloat4 RGBT);
    MaterialFloat4 RGBMEncode( MaterialFloat3 Color );
    MaterialFloat4 RGBMEncodeFast( MaterialFloat3 Color );
    MaterialFloat3 RGBMDecode( MaterialFloat4 rgbm, MaterialFloat MaxValue );
    MaterialFloat3 RGBMDecode( MaterialFloat4 rgbm );
    MaterialFloat4 RGBTEncode8BPC(MaterialFloat3 Color, MaterialFloat Range);
    MaterialFloat3 RGBTDecode8BPC(MaterialFloat4 RGBT, MaterialFloat Range);
    uint DecodeRTWriteMask(float2 ScreenPos, Texture2D<uint> RTWriteMaskTexture, uint NumEncodedTextures);
    float2 EncodeVelocityToTexture(float2 In);
    float2 DecodeVelocityFromTexture(float2 In);
    float DecodePackedTwoChannelValue(float2 PackedHeight);
    float DecodeHeightValue(float InValue);
    float DecodePackedHeight(float2 PackedHeight);
    
    // 纹理采样
    aterialFloat4 Texture1DSample(Texture1D Tex, SamplerState Sampler, float UV);
    MaterialFloat4 Texture2DSample(Texture2D Tex, SamplerState Sampler, float2 UV);
    MaterialFloat Texture2DSample_A8(Texture2D Tex, SamplerState Sampler, float2 UV);
    MaterialFloat4 Texture3DSample(Texture3D Tex, SamplerState Sampler, float3 UV);
    MaterialFloat4 TextureCubeSample(TextureCube Tex, SamplerState Sampler, float3 UV);
    MaterialFloat4 Texture2DArraySample(Texture2DArray Tex, SamplerState Sampler, float3 UV);
    MaterialFloat4 Texture1DSampleLevel(Texture1D Tex, SamplerState Sampler, float UV, MaterialFloat Mip);
    MaterialFloat4 Texture2DSampleLevel(Texture2D Tex, SamplerState Sampler, float2 UV, MaterialFloat Mip);
    MaterialFloat4 Texture2DSampleBias(Texture2D Tex, SamplerState Sampler, float2 UV, MaterialFloat MipBias);
    MaterialFloat4 Texture2DSampleGrad(Texture2D Tex, SamplerState Sampler, float2 UV, MaterialFloat2 DDX, MaterialFloat2 DDY);
    MaterialFloat4 Texture3DSampleLevel(Texture3D Tex, SamplerState Sampler, float3 UV, MaterialFloat Mip);
    MaterialFloat4 Texture3DSampleBias(Texture3D Tex, SamplerState Sampler, float3 UV, MaterialFloat MipBias);
    MaterialFloat4 Texture3DSampleGrad(Texture3D Tex, SamplerState Sampler, float3 UV, MaterialFloat3 DDX, MaterialFloat3 DDY);
    MaterialFloat4 TextureCubeSampleLevel(TextureCube Tex, SamplerState Sampler, float3 UV, MaterialFloat Mip);
    MaterialFloat TextureCubeSampleDepthLevel(TextureCube TexDepth, SamplerState Sampler, float3 UV, MaterialFloat Mip);
    MaterialFloat4 TextureCubeSampleBias(TextureCube Tex, SamplerState Sampler, float3 UV, MaterialFloat MipBias);
    MaterialFloat4 TextureCubeSampleGrad(TextureCube Tex, SamplerState Sampler, float3 UV, MaterialFloat3 DDX, MaterialFloat3 DDY);
    MaterialFloat4 TextureExternalSample(TextureExternal Tex, SamplerState Sampler, float2 UV);
    MaterialFloat4 TextureExternalSampleGrad(TextureExternal Tex, SamplerState Sampler, float2 UV, ...);
    MaterialFloat4 TextureExternalSampleLevel(TextureExternal Tex, SamplerState Sampler, float2 UV, MaterialFloat Mip);
    MaterialFloat4 Texture1DSample_Decal(Texture1D Tex, SamplerState Sampler, float UV);
    MaterialFloat4 Texture2DSample_Decal(Texture2D Tex, SamplerState Sampler, float2 UV);
    MaterialFloat4 Texture3DSample_Decal(Texture3D Tex, SamplerState Sampler, float3 UV);
    MaterialFloat4 TextureCubeSample_Decal(TextureCube Tex, SamplerState Sampler, float3 UV);
    MaterialFloat4 TextureExternalSample_Decal(TextureExternal Tex, SamplerState Sampler, float2 UV);
    MaterialFloat4 Texture2DArraySampleLevel(Texture2DArray Tex, SamplerState Sampler, float3 UV, MaterialFloat Mip);
    MaterialFloat4 Texture2DArraySampleBias(Texture2DArray Tex, SamplerState Sampler, float3 UV, MaterialFloat MipBias);
    MaterialFloat4 Texture2DArraySampleGrad(Texture2DArray Tex, SamplerState Sampler, float3 UV, ...);
    
    // 特殊采样,噪点
    float4 PseudoVolumeTexture(Texture2D Tex, SamplerState TexSampler, float3 inPos, float2 xysize, float numframes, ...);
    float AntialiasedTextureMask( Texture2D Tex, SamplerState Sampler, float2 UV, float ThresholdConst, int Channel );
    float Noise3D_Multiplexer(int Function, float3 Position, int Quality, bool bTiling, float RepeatSize);
    MaterialFloat MaterialExpressionNoise(float3 Position, float Scale, int Quality, int Function, ...);
    MaterialFloat4 MaterialExpressionVectorNoise(MaterialFloat3 Position, int Quality, int Function, bool bTiling, float TileSize);
        
    // 光照计算
    MaterialFloat PhongShadingPow(MaterialFloat X, MaterialFloat Y);
    
    // 数据转换
    float ConvertTangentUnormToSnorm8(float Input);
    float2 ConvertTangentUnormToSnorm8(float2 Input);
    float3 ConvertTangentUnormToSnorm8(float3 Input);
    float4 ConvertTangentUnormToSnorm8(float4 Input);
    float ConvertTangentUnormToSnorm16(float Input);
    float2 ConvertTangentUnormToSnorm16(float2 Input);
    float3 ConvertTangentUnormToSnorm16(float3 Input);
    float4 ConvertTangentUnormToSnorm16(float4 Input);
    float ConvertTangentSnormToUnorm8(float Input);
    float2 ConvertTangentSnormToUnorm8(float2 Input);
    float3 ConvertTangentSnormToUnorm8(float3 Input);
    float4 ConvertTangentSnormToUnorm8(float4 Input);
    float ConvertTangentSnormToUnorm16(float Input);
    float2 ConvertTangentSnormToUnorm16(float2 Input);
    float3 ConvertTangentSnormToUnorm16(float3 Input);
    float4 ConvertTangentSnormToUnorm16(float4 Input);
    
    // 坐标、空间转换
    float2 CalcScreenUVFromOffsetFraction(float4 ScreenPosition, float2 OffsetFraction);
    float4 GetPerPixelLightAttenuation(float2 UV);
    float ConvertFromDeviceZ(float DeviceZ);
    float ConvertToDeviceZ(float SceneDepth);
    float2 ScreenPositionToBufferUV(float4 ScreenPosition);
    float2 SvPositionToBufferUV(float4 SvPosition);
    float3 SvPositionToTranslatedWorld(float4 SvPosition);
    float3 SvPositionToResolvedTranslatedWorld(float4 SvPosition);
    float3 SvPositionToWorld(float4 SvPosition);
    float4 SvPositionToScreenPosition(float4 SvPosition);
    float4 SvPositionToResolvedScreenPosition(float4 SvPosition);
    float2 SvPositionToViewportUV(float4 SvPosition);
    float2 BufferUVToViewportUV(float2 BufferUV);
    float2 ViewportUVToBufferUV(float2 ViewportUV);
    float2 ViewportUVToScreenPos(float2 ViewportUV);
    float2 ScreenPosToViewportUV(float2 ScreenPos);
    float3 ScreenToViewPos(float2 ViewportUV, float SceneDepth);
    MaterialFloat2 ScreenAlignedPosition( float4 ScreenPosition );
    MaterialFloat2 ScreenAlignedUV( MaterialFloat2 UV );
    MaterialFloat2 GetViewportCoordinates(MaterialFloat2 InFragmentCoordinates);
    
    MaterialFloat3 TransformTangentVectorToWorld(MaterialFloat3x3 TangentToWorld, MaterialFloat3 InTangentVector);
    MaterialFloat3 TransformWorldVectorToTangent(MaterialFloat3x3 TangentToWorld, MaterialFloat3 InWorldVector);
    float3 TransformWorldVectorToView(float3 InTangentVector);
    void GenerateCoordinateSystem(float3 ZAxis, out float3 XAxis, out float3 YAxis);
    
    // 几何体交互: 求交, 距离等.
    float2 LineBoxIntersect(float3 RayOrigin, float3 RayEnd, float3 BoxMin, float3 BoxMax);
    MaterialFloat ComputeDistanceFromBoxToPoint(MaterialFloat3 Mins, MaterialFloat3 Maxs, MaterialFloat3 InPoint);
    MaterialFloat ComputeSquaredDistanceFromBoxToPoint(MaterialFloat3 BoxCenter, MaterialFloat3 BoxExtent, MaterialFloat3 InPoint);
    float ComputeDistanceFromBoxToPointInside(float3 BoxCenter, float3 BoxExtent, float3 InPoint);
    bool RayHitSphere(float3 RayOrigin, float3 UnitRayDirection, float3 SphereCenter, float SphereRadius);
    bool RaySegmentHitSphere(float3 RayOrigin, float3 UnitRayDirection, float RayLength, float3 SphereCenter, float SphereRadius);
    float2 RayIntersectSphere(float3 RayOrigin, float3 RayDirection, float4 Sphere);
    MaterialFloat GetBoxPushout(MaterialFloat3 Normal,MaterialFloat3 Extent);
    
    // 绘制接口
    void DrawRectangle(in float4 InPosition, in float2 InTexCoord, out float4 OutPosition, out float2 OutTexCoord);
    void DrawRectangle(in float4 InPosition, in float2 InTexCoord, out float4 OutPosition, out float4 OutUVAndScreenPos);
    void DrawRectangle(in float4 InPosition, out float4 OutPosition);
    
    (.....)
    

    由此可知,common的shader模块封装了大量的基础类型、接口、变量等,以上只是展示了部分接口,而且为了简洁去掉了实现代码,如果想看实现的童鞋自行查阅UE的源码。

    5.2.3.3 Definitions.ush

    此模块主要是预先定义了一些常见的宏,防止其它模块引用时出现语法错误。部分宏如下:

    #ifndef MATERIAL_TWOSIDED
    #define    MATERIAL_TWOSIDED                                0
    #endif
    
    #ifndef MATERIAL_TANGENTSPACENORMAL
    #define    MATERIAL_TANGENTSPACENORMAL                        0
    #endif
    
    #ifndef MATERIAL_TWOSIDED_SEPARATE_PASS
    #define    MATERIAL_TWOSIDED_SEPARATE_PASS                    0
    #endif
    
    #ifndef MATERIALBLENDING_MASKED
    #define MATERIALBLENDING_MASKED                            0
    #endif
    
    #ifndef MATERIALBLENDING_TRANSLUCENT
    #define MATERIALBLENDING_TRANSLUCENT                    0
    #endif
    
    #ifndef TRANSLUCENT_SHADOW_WITH_MASKED_OPACITY
    #define TRANSLUCENT_SHADOW_WITH_MASKED_OPACITY            0
    #endif
    
    #ifndef MATERIAL_SHADINGMODEL_DEFAULT_LIT
    #define MATERIAL_SHADINGMODEL_DEFAULT_LIT                0
    #endif
    
    #ifndef MATERIAL_SHADINGMODEL_SUBSURFACE
    #define MATERIAL_SHADINGMODEL_SUBSURFACE                0
    #endif
    
    #ifndef MATERIAL_SHADINGMODEL_UNLIT
    #define    MATERIAL_SHADINGMODEL_UNLIT                        0
    #endif
    
    #ifndef MATERIAL_SINGLE_SHADINGMODEL
    #define    MATERIAL_SINGLE_SHADINGMODEL                    0
    #endif
    
    #ifndef HAS_PRIMITIVE_UNIFORM_BUFFER
    #define    HAS_PRIMITIVE_UNIFORM_BUFFER                    0
    #endif
    
    #ifndef GBUFFER_HAS_VELOCITY
    #define GBUFFER_HAS_VELOCITY                            0
    #endif
    
    #ifndef GBUFFER_HAS_TANGENT
    #define GBUFFER_HAS_TANGENT                                0
    #endif
    
    #define PC_D3D                                            SM5_PROFILE
    
    (......)
    

    5.2.3.4 ShadingCommon.ush

    此模块主要是定义了材质所有着色模型,并提供了少量相关的工具类接口:

    // 材质着色模型, 每种类型都有对应的光照算法和流程.
    #define SHADINGMODELID_UNLIT                0
    #define SHADINGMODELID_DEFAULT_LIT            1
    #define SHADINGMODELID_SUBSURFACE            2
    #define SHADINGMODELID_PREINTEGRATED_SKIN    3
    #define SHADINGMODELID_CLEAR_COAT            4
    #define SHADINGMODELID_SUBSURFACE_PROFILE    5
    #define SHADINGMODELID_TWOSIDED_FOLIAGE        6
    #define SHADINGMODELID_HAIR                    7
    #define SHADINGMODELID_CLOTH                8
    #define SHADINGMODELID_EYE                    9
    #define SHADINGMODELID_SINGLELAYERWATER        10
    #define SHADINGMODELID_THIN_TRANSLUCENT        11
    #define SHADINGMODELID_NUM                    12
    #define SHADINGMODELID_MASK                    0xF        // ShadingModelID只占用了GBuffer的4bit.
    
    // 除了ShadingsModelID之外的4bit用作其它用途.
    #define HAS_ANISOTROPY_MASK                (1 << 4)
    #define SKIP_PRECSHADOW_MASK            (1 << 5)
    #define ZERO_PRECSHADOW_MASK            (1 << 6)
    #define SKIP_VELOCITY_MASK                (1 << 7)
    
    // 头发反射组件(R, TT, TRT, Local Scattering, Global Scattering, Multi Scattering,...)
    #define HAIR_COMPONENT_R            0x1u
    #define HAIR_COMPONENT_TT            0x2u
    #define HAIR_COMPONENT_TRT            0x4u
    #define HAIR_COMPONENT_LS            0x8u 
    #define HAIR_COMPONENT_GS            0x10u
    #define HAIR_COMPONENT_MULTISCATTER    0x20u
    #define HAIR_COMPONENT_TT_MODEL      0x40u
    
    // 着色模型调试颜色.
    float3 GetShadingModelColor(uint ShadingModelID);
    
    // 非导体的反射F0.
    float DielectricSpecularToF0(float Specular)
    {
        return 0.08f * Specular;
    }
    
    // 非导体的F0转换到IOR(折射率).
    float DielectricF0ToIor(float F0)
    {
        return 2.0f / (1.0f - sqrt(F0)) - 1.0f;
    }
    
    // 非导体的IOR(折射率)转换到F0.
    float DielectricIorToF0(float Ior)
    {
        const float F0Sqrt = (Ior-1)/(Ior+1);
        const float F0 = F0Sqrt*F0Sqrt;
        return F0;
    }
    
    // 计算物体表面的F0.
    float3 ComputeF0(float Specular, float3 BaseColor, float Metallic)
    {
        return lerp(DielectricSpecularToF0(Specular).xxx, BaseColor, Metallic.xxx);
    }
    

    需要注意的是,UE默认的ShadingModelID只占用4bit,最多16个,而目前UE内置着色模型已占用了13个,意味着自定义的ShadingModel最多只能3个了。

    5.2.3.5 BasePassCommon.ush

    此模块定义了BasePass的一些变量、宏定义、插值结构体和工具类接口:

    // 透明物体BasePass的定义
    #if MATERIALBLENDING_ANY_TRANSLUCENT
        #define ForwardLightData TranslucentBasePass.Shared.Forward
        #define ReflectionStruct TranslucentBasePass.Shared.Reflection
        #define PlanarReflectionStruct TranslucentBasePass.Shared.PlanarReflection
        #define FogStruct TranslucentBasePass.Shared.Fog
        #define ActualSSProfilesTexture TranslucentBasePass.Shared.SSProfilesTexture
    // 不透明物体BasePass的定义
    #else
        #define ForwardLightData OpaqueBasePass.Shared.Forward
        #define ReflectionStruct OpaqueBasePass.Shared.Reflection
        #define PlanarReflectionStruct OpaqueBasePass.Shared.PlanarReflection
        #define FogStruct OpaqueBasePass.Shared.Fog
        #define ActualSSProfilesTexture OpaqueBasePass.Shared.SSProfilesTexture
    #endif 
    
    // BasePass相关的宏定义
    #undef NEEDS_LIGHTMAP_COORDINATE
    #define NEEDS_LIGHTMAP_COORDINATE        (HQ_TEXTURE_LIGHTMAP || LQ_TEXTURE_LIGHTMAP)
    #define TRANSLUCENCY_NEEDS_BASEPASS_FOGGING    (MATERIAL_ENABLE_TRANSLUCENCY_FOGGING && MATERIALBLENDING_ANY_TRANSLUCENT && !MATERIAL_USES_SCENE_COLOR_COPY)
    #define OPAQUE_NEEDS_BASEPASS_FOGGING        (!MATERIALBLENDING_ANY_TRANSLUCENT && FORWARD_SHADING)
    
    #define NEEDS_BASEPASS_VERTEX_FOGGING        (TRANSLUCENCY_NEEDS_BASEPASS_FOGGING && !MATERIAL_COMPUTE_FOG_PER_PIXEL || OPAQUE_NEEDS_BASEPASS_FOGGING && PROJECT_VERTEX_FOGGING_FOR_OPAQUE)
    #define NEEDS_BASEPASS_PIXEL_FOGGING        (TRANSLUCENCY_NEEDS_BASEPASS_FOGGING && MATERIAL_COMPUTE_FOG_PER_PIXEL || OPAQUE_NEEDS_BASEPASS_FOGGING && !PROJECT_VERTEX_FOGGING_FOR_OPAQUE)
    
    #define NEEDS_BASEPASS_PIXEL_VOLUMETRIC_FOGGING        (MATERIALBLENDING_ANY_TRANSLUCENT || FORWARD_SHADING)
    
    #define NEEDS_LIGHTMAP                        (NEEDS_LIGHTMAP_COORDINATE)
    
    #define USES_GBUFFER                        (FEATURE_LEVEL >= FEATURE_LEVEL_SM4 && (MATERIALBLENDING_SOLID || MATERIALBLENDING_MASKED) && !SIMPLE_FORWARD_SHADING && !FORWARD_SHADING)
    
    (......)
    
    // 插值结构体的父类.
    struct FSharedBasePassInterpolants
    {
        //for texture-lightmapped translucency we can pass the vertex fog in its own interpolator
    #if NEEDS_BASEPASS_VERTEX_FOGGING
        float4 VertexFog        : TEXCOORD7;
    #endif
    
    #if !TESSELLATION_SUPPORTED
        // Note: TEXCOORD8 is unused
    
        #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
        float3 PixelPositionExcludingWPO : TEXCOORD9;
        #endif
    #endif
    
    #if TRANSLUCENCY_PERVERTEX_LIGHTING_VOLUME
        float3 AmbientLightingVector : TEXCOORD12;
    #endif
    
    #if TRANSLUCENCY_PERVERTEX_LIGHTING_VOLUME && TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_DIRECTIONAL
        float3 DirectionalLightingVector : TEXCOORD13;
    #endif
    
    #if TRANSLUCENCY_PERVERTEX_FORWARD_SHADING
        float3 VertexDiffuseLighting : TEXCOORD12;
    #endif
    
    #if PRECOMPUTED_IRRADIANCE_VOLUME_LIGHTING
        #if TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_NONDIRECTIONAL
            float3 VertexIndirectAmbient : TEXCOORD14;
        #elif TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_DIRECTIONAL
            float4 VertexIndirectSH[3] : TEXCOORD14;
        #endif
    #endif
    
    #if WRITES_VELOCITY_TO_GBUFFER
        // .xy is clip position, pre divide by w; .w is clip W; .z is 0 or 1 to mask out the velocity output
        float4 VelocityPrevScreenPosition : VELOCITY_PREV_POS;
        #if WRITES_VELOCITY_TO_GBUFFER_USE_POS_INTERPOLATOR
            float4 VelocityScreenPosition : VELOCITY_POS;
        #endif
    #endif
    };
    
    #if TESSELLATION_SUPPORTED
        // VS -> PS的插值结构体.
        struct FBasePassInterpolantsVSToPS : FSharedBasePassInterpolants
        {
            // Note: TEXCOORD8 is unused
    
            #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
            float3 PixelPositionExcludingWPO : TEXCOORD9;
            #endif
        };
        // VS -> DS(domain shader)的插值结构体.
        struct FBasePassInterpolantsVSToDS : FSharedBasePassInterpolants
        {
            #if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
            float3 WorldPositionExcludingWPO : TEXCOORD9;
            #endif
        };
    #else
        #define FBasePassInterpolantsVSToPS FSharedBasePassInterpolants
    #endif
    
    // 采样器封装.
    #if SUPPORTS_INDEPENDENT_SAMPLERS
        #define SharedAmbientInnerSampler View.SharedBilinearClampedSampler
        #define SharedAmbientOuterSampler View.SharedBilinearClampedSampler
        #define SharedDirectionalInnerSampler View.SharedBilinearClampedSampler
        #define SharedDirectionalOuterSampler View.SharedBilinearClampedSampler
    #else
        #define SharedAmbientInnerSampler TranslucentBasePass.TranslucencyLightingVolumeAmbientInnerSampler
        #define SharedAmbientOuterSampler TranslucentBasePass.TranslucencyLightingVolumeAmbientOuterSampler
        #define SharedDirectionalInnerSampler TranslucentBasePass.TranslucencyLightingVolumeDirectionalInnerSampler
        #define SharedDirectionalOuterSampler TranslucentBasePass.TranslucencyLightingVolumeDirectionalOuterSampler
    #endif
    
    // 工具类接口.
    void ComputeVolumeUVs(float3 WorldPosition, float3 LightingPositionOffset, out float3 InnerVolumeUVs, out float3 OuterVolumeUVs, out float FinalLerpFactor);
    float4 GetAmbientLightingVectorFromTranslucentLightingVolume(float3 InnerVolumeUVs, float3 OuterVolumeUVs, float FinalLerpFactor);
    float3 GetDirectionalLightingVectorFromTranslucentLightingVolume(float3 InnerVolumeUVs, float3 OuterVolumeUVs, float FinalLerpFactor);