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

113 lines
6.8 KiB
Markdown
Raw Permalink Normal View History

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法线到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中的调用
```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);