BlueRoseNote/03-UnrealEngine/Rendering/Shader/UE GBuffer存储数据.md

6.8 KiB
Raw Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
UE GBuffer存储数据 2022-10-11 13:07:27 Rendering

https://zhuanlan.zhihu.com/p/400677108

MRT R G B A
MRT0 SceneColor.r SceneColor.g SceneColor.b Alpha(Opacity?)
MRT1 GBufferA WorldNormal.r WorldNormal.g WorldNormal.b PerObjectGBufferData
MRT2 GBUfferB Metallic Specular Roughness ShadingModelId && SelectiveOutputMask
MRT3 GBUfferC BaseColor.r BaseColor.g BaseColor.b IndirectIrradiance
MRT4 GBUfferD(根据需求插入) Velocity.r Velocity.g Velocity.b Velocity.a
MRT5 GBUfferE(Velocity不渲染为D) CustomData.r CustomData.g CustomData.b CustomData.a
MRT6 GBUfferF(Velocity不渲染为E) PrecomputedShadowFactors.r PrecomputedShadowFactors.g PrecomputedShadowFactors.b PrecomputedShadowFactors.a
MRT7

Depth Stencil

[0] sandbox bit (bit to be use by any rendering passes, but must be properly reset to 0 after using) STENCIL LOD抖动过渡后处理贴花Local光源都有使用用来绘制临时Mask [001] unallocated [2] unallocated [3] Temporal AA mask for translucent object. 标记后TAA将不再读取History数据用来处理半透物体的TAA问题

1-3在移动延迟会被借用储存ShadingMode但小于ShadingMode总数量不清楚怎么处理的。但因为毕竟有重复使用不适合直接占用这两个值。 [4] Lighting channels [5] Lighting channels [6] Lighting channels [7] Primitive receive decal bit

GBuffer

SceneColorDeferred场景颜色 RGBAHalf移动默认R11G11B10 Emissive直接写入这里非自发光写入BaseColor。A通道正常储存Alpha值通常情况没用。

原神将其和BaseColor合并了由Alpha来标记自发光强度。这使得自发光颜色必须和BaseColor相同限制了其表达。在需要不同颜色的时候原神则用叠加半透材质的方法实现。
用这个方法需要给原本在BaseColor.a的IndirectIrradiance * AO 再找个位置。

GBufferA法线 R10G10B10A2 移动延迟用八面体Encode法线到RGB为PrecomputedShadowFactors.x。

PC直接储存法线到RGB禁用的分支里可以Encode法线到RG如果这样做了B可以空出一个10bit但移动没法使用。不如和移动一样把PrecomputedShadowFactors.x移到这来。不过PrecomputedShadowFactors.x其实也不需要10bit可以拆2bit做特殊用途

A为PerObjectGBufferDatabit1:CastContactShadowbit2:HasDynamicIndirectShadowCasterRepresentation

GBufferB RGBA8888 金属高光粗糙ShadingModelID+SelectiveOutputMask各占4bitShading Mode最大值16

SelectiveOutputMask记录了绘制时以下宏的开启结果

  • MATERIAL_USES_ANISOTROPY 禁止计算各向异性
  • !GBUFFER_HAS_PRECSHADOWFACTOR 禁止读取GBufferE数据作为预计算阴影
  • GBUFFER_HAS_PRECSHADOWFACTOR && WRITES_PRECSHADOWFACTOR_ZERO 当不读取GBufferE时若此值为1时预计算阴影设为0否则为1。
  • WRITES_VELOCITY_TO_GBUFFER 禁止从Gbuffer中读取速度值。

因为没写速度的时候Buffer里是0并不是零速度所以必须靠它来Mask但如果将速度图Clear为零速度按说可以不需要这个Mask就可以用在别处 并不觉得高光值得占用8bit的容量可以压缩其他数据到高光上。

常见的做法还有将F0储存至RGB让SSR无需采样BaseColor但这样一来粗糙度又需要另找地方储存可储存在法线B通道上

GBufferCBaseColor RGBA8888 RGB储存Lit物体的BaseColorA在有静态光照时候储存随机抖动过的IndirectIrradiance * Material AO否则直接储存Material AO。

GBufferD自定义数据

GBufferE静态阴影

GBufferVelocity速度

实用函数

LightingPass中的调用

uint PixelShadingModelID = GetScreenSpaceData(ScreenUV).GBuffer.ShadingModelID;

最终:

FGBufferData GetGBufferData(float2 UV, bool bGetNormalizedNormal = true)  
{  
   float4 GBufferA = Texture2DSampleLevel(SceneTexturesStruct.GBufferATexture, SceneTexturesStruct_GBufferATextureSampler, UV, 0);  
   float4 GBufferB = Texture2DSampleLevel(SceneTexturesStruct.GBufferBTexture, SceneTexturesStruct_GBufferBTextureSampler, UV, 0);  
   float4 GBufferC = Texture2DSampleLevel(SceneTexturesStruct.GBufferCTexture, SceneTexturesStruct_GBufferCTextureSampler, UV, 0);  
   float4 GBufferD = Texture2DSampleLevel(SceneTexturesStruct.GBufferDTexture, SceneTexturesStruct_GBufferDTextureSampler, UV, 0);  
   float4 ToonDataA = Texture2DSampleLevel(SceneTexturesStruct.ToonBufferATexture, SceneTexturesStruct_ToonBufferATextureSampler, UV, 0);  
   float CustomNativeDepth = Texture2DSampleLevel(SceneTexturesStruct.CustomDepthTexture, SceneTexturesStruct_CustomDepthTextureSampler, UV, 0).r;  
  
   int2 IntUV = (int2)trunc(UV * View.BufferSizeAndInvSize.xy);  
   uint CustomStencil = SceneTexturesStruct.CustomStencilTexture.Load(int3(IntUV, 0)) STENCIL_COMPONENT_SWIZZLE;  
  
#if ALLOW_STATIC_LIGHTING  
      float4 GBufferE = Texture2DSampleLevel(SceneTexturesStruct.GBufferETexture, SceneTexturesStruct_GBufferETextureSampler, UV, 0);  
   #else  
      float4 GBufferE = 1;  
   #endif  
  
   float4 GBufferF = Texture2DSampleLevel(SceneTexturesStruct.GBufferFTexture, SceneTexturesStruct_GBufferFTextureSampler, UV, 0);  
  
   #if WRITES_VELOCITY_TO_GBUFFER  
      float4 GBufferVelocity = Texture2DSampleLevel(SceneTexturesStruct.GBufferVelocityTexture, SceneTexturesStruct_GBufferVelocityTextureSampler, UV, 0);  
   #else  
      float4 GBufferVelocity = 0;  
   #endif  
  
   float SceneDepth = CalcSceneDepth(UV);  
   return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferF, GBufferVelocity, ToonDataA, CustomNativeDepth, CustomStencil, SceneDepth, bGetNormalizedNormal, CheckerFromSceneColorUV(UV));  
}

GBuffer.ShadingModelID = DecodeShadingModelId(InGBufferB.a);