Files
game_engine/docs/superpowers/specs/2026-03-26-ssgi-quality-design.md
2026-03-26 15:25:26 +09:00

3.5 KiB

SSGI Quality Improvement Design (Bilateral Blur + Temporal Accumulation)

Overview

SSGI 출력의 노이즈를 줄이기 위해 bilateral blur와 temporal accumulation 필터를 추가한다.

Scope

  • Bilateral blur 셰이더: depth/normal 기반 edge-aware blur
  • Temporal accumulation: 이전 프레임 SSGI와 현재 프레임을 블렌딩
  • 각각 독립적 풀스크린 패스

Bilateral Blur

Depth와 normal 차이를 가중치로 사용하여 edge를 보존하면서 노이즈를 줄이는 블러.

셰이더 (bilateral_blur.wgsl)

@group(0) @binding(0) var input_tex: texture_2d<f32>;     // SSGI 출력
@group(0) @binding(1) var depth_tex: texture_2d<f32>;     // G-Buffer depth
@group(0) @binding(2) var normal_tex: texture_2d<f32>;    // G-Buffer normal
@group(0) @binding(3) var output_tex: texture_storage_2d<rgba16float, write>;

// 5x5 bilateral kernel
// weight = gaussian(spatial_dist) * exp(-|depth_diff|/sigma_d) * max(dot(n1,n2),0)^sigma_n

컴퓨트 셰이더로 구현. 워크그룹 16x16.

BilateralBlur 구조체

pub struct BilateralBlur {
    pipeline: wgpu::ComputePipeline,
    bind_group_layout: wgpu::BindGroupLayout,
}
  • new(device) — 파이프라인 생성
  • dispatch(encoder, ssgi_view, depth_view, normal_view, output_view, width, height) — 실행

파라미터

  • kernel_size: 5 (하드코딩)
  • sigma_spatial: 2.0
  • sigma_depth: 0.1
  • sigma_normal: 16.0

Temporal Accumulation

이전 프레임의 결과와 현재 프레임을 블렌딩하여 시간에 따라 노이즈를 줄임.

셰이더 (temporal_accum.wgsl)

@group(0) @binding(0) var current_tex: texture_2d<f32>;   // 현재 프레임 (blurred SSGI)
@group(0) @binding(1) var history_tex: texture_2d<f32>;   // 이전 프레임 결과
@group(0) @binding(2) var output_tex: texture_storage_2d<rgba16float, write>;

// blend_factor = 0.1 (10% 새 프레임, 90% 히스토리)
// output = mix(history, current, blend_factor)

TemporalAccumulation 구조체

pub struct TemporalAccumulation {
    pipeline: wgpu::ComputePipeline,
    bind_group_layout: wgpu::BindGroupLayout,
    history_texture: wgpu::Texture,  // 이전 프레임 저장
    history_view: wgpu::TextureView,
    pub blend_factor: f32,           // 0.1
}
  • new(device, width, height) — 히스토리 텍스처 + 파이프라인
  • dispatch(encoder, current_view, output_view, width, height) — 블렌딩 실행
  • swap_history(new_view) — 출력을 히스토리로 복사 (또는 ping-pong)

Ping-Pong 패턴

텍스처 2개를 교대로 사용:

  • Frame N: read history_A, write history_B → output = history_B
  • Frame N+1: read history_B, write history_A → output = history_A

적용 순서

SSGI Pass → [Bilateral Blur] → [Temporal Accumulation] → Lighting Pass (기존 SSGI 텍스처 대체)

File Structure

  • crates/voltex_renderer/src/bilateral_blur.rs — BilateralBlur
  • crates/voltex_renderer/src/bilateral_blur.wgsl — 컴퓨트 셰이더
  • crates/voltex_renderer/src/temporal_accum.rs — TemporalAccumulation
  • crates/voltex_renderer/src/temporal_accum.wgsl — 컴퓨트 셰이더
  • crates/voltex_renderer/src/lib.rs — 모듈 추가

Testing

Bilateral Blur (순수 수학)

  • gaussian weight 계산 검증
  • bilateral weight: depth 차이 클수록 weight 작아지는지

Temporal Accumulation (순수 수학)

  • blend: factor=0.0 → history 그대로, factor=1.0 → current 그대로
  • factor=0.1 → 90% history + 10% current