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

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法线到RG,B为PrecomputedShadowFactors.x。

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

A为PerObjectGBufferData(bit1:CastContactShadow,bit2:HasDynamicIndirectShadowCasterRepresentation)

**GBufferB**
RGBA8888
金属,高光,粗糙,ShadingModelID+SelectiveOutputMask(各占4bit,Shading 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通道上)

**GBufferC(BaseColor)**
RGBA8888
RGB储存Lit物体的BaseColor,A在有静态光照时候储存随机抖动过的IndirectIrradiance * Material AO,否则直接储存Material AO。

**GBufferD(自定义数据)**

**GBufferE(静态阴影)**

**GBufferVelocity(速度)**


## 实用函数
LightingPass中的调用:
```c++
uint PixelShadingModelID = GetScreenSpaceData(ScreenUV).GBuffer.ShadingModelID;
```
最终:
```c++
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);