Tutorial

WebGL 2.0 레이마칭 렌더링 원리

WebGL 2.0 레이마칭 기술을 깊이 있게 탐구하고, SDF 부호 거리 필드를 사용하여 실시간 볼륨 렌더링을 구현하는 방법과 이 기술이 GPU 성능을 한계까지 끌어올리는 방법을 배웁니다.

🚀 volumeshadertest
4일 전
10분 소요

WebGL 2.0 레이마칭, SDF, 실시간 볼륨 렌더링 심화 탐구

WebGL 2.0은 강력한 GPU 기능 세트를 해제하여 전통적으로 네이티브 API가 필요했던 고급 렌더링 기술을 가능하게 합니다. 그 중에서도 레이마칭은 최소한의 지오메트리로 복잡한 장면을 렌더링하는 가장 표현력이 풍부하고 수학적으로 우아한 방법 중 하나로 두각을 나타냅니다.

이 기사는 WebGL 2.0 레이마칭의 핵심 개념을 살펴보고, **부호 거리 필드(SDF)**가 어떻게 효율적인 렌더링을 가능하게 하는지 설명하며, 이 기술이 GPU에서 놀라운 성능을 끌어내는 방법을 보여줍니다.


1. 레이마칭이란?

레이마칭은 지오메트리를 화면에 투영하는 대신, 카메라에서 픽셀당 광선을 발사하고, 가상 장면을 단계적으로 이동하며, 광선이 표면에 닿거나 최대 범위에 도달할 때까지 거리를 평가하는 렌더링 방법입니다.

1.1 레이마칭 작동 방식 (시각적 다이어그램)

카메라
  |
  | 광선
  v
  +--------------------------------- 화면 픽셀
  |
  | 마칭 스텝 1      (거리 d1)
  |
  |---------> 마칭 스텝 2      (거리 d2)
  |
  |-----------------------> 마칭 스텝 3 ...
  |
거리 < ε 일 때 표면 도달

레이마칭은 본질적으로 루프입니다:

for (int i = 0; i < MAX_STEPS; i++) {
    float dist = sdf(currentPos);
    if (dist < EPSILON) hitSurface();
    currentPos += rayDir * dist;
}

마법의 요소는 우리가 전달하는 SDF 함수입니다.


2. 부호 거리 필드(SDF)란?

부호 거리 필드는 다음을 반환하는 함수입니다:

> 0  객체 외부 거리  
= 0  정확히 표면에  
< 0  객체 내부 거리  

2.1 SDF 다이어그램

            외부
        +------------+
        |   d = 0.5  |
        |            |
내부    |     SDF    | 표면 d = 0
d < 0   |            |
        |   d = -0.3 |
        +------------+

2.2 예제: 구 SDF

float sdSphere(vec3 p, float r) {
    return length(p) - r;
}

이러한 기본 모양을 부울 연산(합집합, 차집합, 교집합)과 결합하면, 전통적인 지오메트리 없이 복잡한 장면을 구축할 수 있습니다.


3. 왜 WebGL 2.0에서 SDF 레이마칭을 사용하는가?

3.1 장점

  • 정점 버퍼나 메시가 필요 없음 모든 것이 프래그먼트 셰이더에서 수학적으로 계산됩니다.

  • 무한한 기하학적 세부사항 SDF는 부드럽고 연속적인 표면을 정의합니다.

  • 동적이고 변형 가능한 객체 수학으로 모양을 쉽게 애니메이션화할 수 있습니다.

  • 컴팩트한 장면 완전한 3D 장면은 단 몇 줄의 GLSL로 정의될 수 있습니다.

3.2 이를 가능하게 하는 WebGL 2.0 기능

  • 고정밀도 부동소수점
  • 완전한 GLSL ES 3.0 셰이더 지원
  • UBO(유니폼 버퍼)
  • 부동소수점 텍스처
  • 더 유연한 루프 및 분기

이를 통해 WebGL 1.0에서 어려웠던 안정적이고 고성능 레이마칭이 가능해집니다.


4. WebGL 2.0 레이마처 단계별 구축

4.1 장면 광선 설정

각 픽셀에 대해 광선을 계산:

vec3 rayOrigin = cameraPos;
vec3 rayDir = normalize(uv.x * camRight + uv.y * camUp + camForward);

4.2 레이마칭 루프

float marchRay(vec3 ro, vec3 rd) {
    float totalDist = 0.0;

    for (int i = 0; i < MAX_STEPS; i++) {
        vec3 p = ro + rd * totalDist;
        float d = map(p);     // 당신의 SDF 함수

        if (d < EPSILON) break;    // 히트
        if (totalDist > MAX_DISTANCE) break;  // 미스

        totalDist += d;
    }
    return totalDist;
}

4.3 SDF 장면 정의

float map(vec3 p) {
    float s = sdSphere(p, 1.0);
    float box = sdBox(p - vec3(2.0, 0.0, 0.0), vec3(0.7));
    return min(s, box); // 합집합
}

4.4 법선 계산

기울기 근사 사용:

vec3 calcNormal(vec3 p) {
    const vec2 e = vec2(0.001, 0.0);
    return normalize(vec3(
        map(p + e.xyy) - map(p - e.xyy),
        map(p + e.yxy) - map(p - e.yxy),
        map(p + e.yyx) - map(p - e.yyx)
    ));
}

4.5 조명 모델

간단한 확산 셰이딩:

float diffuse = max(dot(normal, lightDir), 0.0);

5. 볼륨 렌더링 (안개, 구름, 연기)

SDF 레이마칭은 볼륨 렌더링으로 확장될 수 있으며, 표면에서 멈추는 대신 각 단계가 색상과 밀도에 기여합니다.

5.1 볼륨 다이어그램

광선 →
[낮은 밀도] [중간] [높은 밀도] [불투명]
   +--------+---------+---------+-------+
   샘플1     샘플2      샘플3      샘플4

5.2 볼륨 누적 모델

vec3 color = vec3(0);
float absorption = 1.0;

for (int i = 0; i < STEPS; i++) {
    float density = computeDensity(p);
    vec3 sampleColor = density * vec3(0.6, 0.7, 1.0);

    color += sampleColor * absorption;
    absorption *= (1.0 - density * 0.1);

    p += rd * STEP_SIZE;
}

레이마칭 볼륨은 더 비용이 많이 들지만, WebGL 2.0의 성능 개선(특히 모바일 GPU에서)으로 실시간 구름, 안개, 성운이 가능해집니다.


6. 성능 최적화 기술

레이마칭은 무거울 수 있으므로 최적화가 필수적입니다.

6.1 주요 기술

  1. 거리 컬링 정확한 SDF 거리에 의존하여 큰 빈 영역을 건너뜁니다.

  2. 경계 볼륨 광선이 SDF가 존재하는 영역에 들어가는지 테스트합니다.

  3. 적응형 스텝 크기 표면 근처에서는 작은 스텝을 사용하고, 열린 공간에서는 큰 스텝을 사용합니다.

  4. 조기 종료 표면에 닿자마자 마칭을 중지합니다.

  5. MAX_STEPS 감소 실시간 렌더링의 일반적인 값은 64–128 범위입니다.

  6. WebGL 2.0 유니폼 및 버퍼 효율적 사용 변경되지 않는 값을 루프 밖으로 이동합니다.


7. WebGL 2.0 프로젝트의 코드 구조

디렉토리 레이아웃 예제:

shader/
  raymarch.vert
  raymarch.frag
src/
  webgl2-context.js
  camera.js
  renderer.js
index.html

일반적인 프래그먼트 셰이더 섹션:

// 1. 카메라/광선 설정
// 2. SDF 정의
// 3. 재질 및 조명 함수
// 4. 레이마칭 루프
// 5. 최종 색상 출력

8. 언제 레이마칭을 사용해야 하는가?

레이마칭은 다음에 뛰어납니다:

  • 무한한 부드러운 모양
  • 프랙탈
  • 공상과학 장면
  • 부호 거리 소프트 섀도우
  • 절차적 지오메트리
  • 볼륨 효과 (구름, 안개, 갓 레이)

레이마칭을 피해야 하는 경우:

  • 많은 상세한 복잡한 메시
  • 사실적인 스킨 캐릭터
  • 수천 개의 객체가 있는 대규모 동적 장면

레이마칭은 절차적 세계스타일화된 시각 효과에 가장 적합합니다.


9. 결론

WebGL 2.0 레이마칭은 수학과 GLSL만으로 고급 실시간 렌더링을 브라우저에 가져옵니다. SDF를 사용하면 단일 정점 버퍼 없이 복잡한 3D 장면을 만들 수 있습니다. 이 기술은 계산 집약적이지만, 신중한 최적화를 통해 네이티브 GPU 애플리케이션에 필적하는 표현력 있는 시각 효과가 가능합니다.

레이마칭은 수학, 예술, GPU 프로그래밍의 독특한 교차점을 나타내며, 현대 WebGL 개발에서 탐구할 가장 흥미진진한 기술 중 하나입니다.

Tags
WebGL레이마칭볼륨 렌더링GPU 성능

© 2025 Volume Shader BM Test. Original shader core algorithm by cznull.

Disclaimer: Heavy GPU usage may cause high power consumption.