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

113 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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法线到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);