3.5 KiB
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— BilateralBlurcrates/voltex_renderer/src/bilateral_blur.wgsl— 컴퓨트 셰이더crates/voltex_renderer/src/temporal_accum.rs— TemporalAccumulationcrates/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