2023-06-29 11:55:02 +08:00
|
|
|
|
---
|
|
|
|
|
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
|
2023-12-19 15:13:51 +08:00
|
|
|
|
**[001] unallocated**
|
2023-06-29 11:55:02 +08:00
|
|
|
|
**[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);
|