GBuffer LayoutGBuffer 布局

NeoX's deferred path uses a compact 3-RT GBuffer for the standard mode, or a 5-RT Single-Pass Deferred for mobile (TBDR) optimization. This is significantly simpler than UE5's 5+ RT layout.

NeoX 的延迟路径标准模式使用紧凑的 3-RT GBuffer,或为移动端(TBDR)优化使用 5-RT 单 Pass 延迟。这比 UE5 的 5+ RT 布局简单得多。

Standard Mode (3 Render Targets): +=================================================================+ | | | SV_Target0: AlbedoAO | | +----------+----------+----------+----------+ | | | R: Alb.R| G: Alb.G| B: Alb.B| A: AO | RGBA8/16 | | +----------+----------+----------+----------+ | | | | SV_Target1: NormalRoughness | | +----------+----------+----------+----------+ | | | R: N.x* | G: N.y* | B: N.z* | A: Rough | * = 0.5(n+1) | | +----------+----------+----------+----------+ | | | | SV_Target2: MetallicShadingModelFlags | | +----------+----------+----------+----------+ | | |R: Metalic| G: Flags | B: (free)| A: (free)| Flags/255 | | +----------+----------+----------+----------+ | | | +=================================================================+ Single-Pass Deferred Mode (5 Render Targets -- Mobile TBDR): +=================================================================+ | SV_Target0: FinalResult // direct emissive output | | SV_Target1: Depth // manual depth (for GLSL) | | SV_Target2: AlbedoAO // same as standard RT0 | | SV_Target3: NormalRoughness // same as standard RT1 | | SV_Target4: MetallicFlags // same as standard RT2 | +=================================================================+

GBuffer Write — ps_main()GBuffer 写入 — ps_main()

The GBuffer pixel shader is remarkably simple — it just fills the Material struct and packs it into render targets:

GBuffer 像素着色器非常简洁——只需填充 Material 结构体并打包到渲染目标:

struct GBuffer {
  float4 AlbedoAO               : SV_Target0;
  float4 NormalRoughness         : SV_Target1;
  float4 MetallicShadingModelFlags : SV_Target2;
};

GBuffer ps_main(Fragment input, bool is_front_face : SV_IsFrontFace) {
  RawData raw_data = GetRawData(input);
  Material mtl = (Material)0;
  SetupMaterial(input, raw_data, mtl);
  DeferredApplyNewDecal(input, mtl);  // apply decals

  GBuffer gbuffer;
  gbuffer.AlbedoAO = float4(mtl.albedo, mtl.occlusion);
  gbuffer.NormalRoughness = float4(0.5 * (mtl.normal + 1.0), mtl.roughness);

  // Encode flags into single byte
  uint flags = 0;
  flags = EncodeShadingModel(flags, mtl.shading_model);
  flags = EncodeReceiveShadow(flags);          // if SHADOW_MAP_ENABLE
  flags = EncodeClusteredShadingLightProbeVolumeEnable(flags);

  gbuffer.MetallicShadingModelFlags = float4(
    mtl.metalness,
    float(flags) / 255.0,
    0, 0
  );
  return gbuffer;
}

Single-Pass Deferred — Mobile Optimization单 Pass 延迟 — 移动端优化

On tile-based deferred rendering (TBDR) GPUs (iOS/Android), NeoX supports Single-Pass Deferred Shading. This writes both GBuffer data AND lighting result in one pass, avoiding the costly off-chip GBuffer readback that destroys TBDR benefits.

在基于 Tile 的延迟渲染(TBDR)GPU 上(iOS/Android),NeoX 支持单 Pass 延迟着色。在一个 Pass 中同时写入 GBuffer 数据和光照结果,避免了破坏 TBDR 优势的昂贵离片 GBuffer 回读。

// Single-pass mode: output emissive directly + manual depth
#if SINGLE_PASS_DEFERRED_SHADING_ENABLE
  gbuffer.FinalResult = float4(mtl.emissive, 1);
  #ifdef NEOX_GLSL
    gbuffer.Depth = input.position.z;           // single float
  #else
    gbuffer.Depth = float4(input.position.z);   // packed
  #endif
#endif

Flag Encoding System标志位编码系统

The G channel of MetallicShadingModelFlags packs multiple boolean flags into a single byte (0-255). Defined in flags.hlsl:

MetallicShadingModelFlags 的 G 通道将多个布尔标志打包到单个字节(0-255)中。定义在 flags.hlsl

Flag标志BitsPurpose用途
ShadingModelbit 0-3Which shading model (0=Isotropy, 1=Skin, 2=Hair...)哪个着色模型
ReceiveShadowbit 4Whether this pixel receives dynamic shadows此像素是否接收动态阴影
LightProbeVolumebit 5Clustered shading light probe active聚簇着色光照探针激活
BakedShadowbit 6Use baked shadow from light probe使用来自光照探针的烘焙阴影

NeoX vs UE5 GBuffer ComparisonNeoX vs UE5 GBuffer 对比

Aspect方面 NeoX UE5.6
RT CountRT 数量3 (standard) / 5 (single-pass)3(标准)/ 5(单 Pass)5-6 (SceneColor + GBuffer A/B/C/D + Velocity)5-6 个
Normal Encoding法线编码0.5*(normal+1) (RGB8/16)Octahedron encoding (2-channel)八面体编码(2 通道)
Shading Model ID着色模型 ID4-bit field in Flags byteFlags 字节中的 4 位4-bit in GBufferB.aGBufferB.a 中 4 位
Custom Data自定义数据None (limited by 3 RTs)无(受 3 RT 限制)GBufferD (full RGBA for SSS color, cloth, etc.)GBufferD(完整 RGBA 用于 SSS 颜色等)
Bandwidth带宽Lower (3 RT = less memory traffic)更低(3 RT = 更少内存流量)Higher (5+ RT = more flexibility)更高(5+ RT = 更多灵活性)
Design trade-off: NeoX sacrifices GBuffer flexibility for bandwidth efficiency. With only 3 RTs, there's no room for per-pixel custom data (e.g., subsurface color). This is why NeoX primarily uses forward shading for complex materials (skin, hair) and reserves deferred for simple opaque geometry. 设计取舍:NeoX 牺牲 GBuffer 灵活性换取带宽效率。只有 3 个 RT,没有空间放逐像素自定义数据(如次表面颜色)。这就是为什么 NeoX 主要对复杂材质(皮肤、头发)使用前向着色,将延迟留给简单不透明几何体。