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

108 lines
3.5 KiB
Markdown

# 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)
```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 구조체
```rust
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)
```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 구조체
```rust
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