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