레이 마칭에서 안개

레이마칭이라고 하면 간단하게 오브젝트를 반복할 수 있습니다만, 먼 쪽은 반복이 도중에 끝나거나 앨리어스(alias)가 발생하거나 해 그림이 더러워지는 경향이 있습니다.

예를 들어, 아래의 장면에서는 구가 도중이 끊어지고 있거나, 지면의 체커 무늬가 안쪽에서 엉망이 되고 있습니다.



이러한 경우에는 카메라로부터의 거리에 따라 안개를 걸어 속이는 것이 좋을 것 같습니다.

투과율(포그가 걸리지 않는 상태)을 $f$로서 $[0, 1]$의 범위로 나타내면, 원의 색${\bf c_i}$와 포그의 색${\bf c_f}$를 $f $로 보간하여 안개를 걸 수 있습니다.
{\bf c} = (1 - f){\bf c_f} + f{\bf c_i}

GLSL로 작성하면 단순히 mix 함수로 구현할 수 있습니다.
vec3 color = mix(fogColor, sceneColor, fogIntensity);

문제는 $f$를 찾는 방법이지만 몇 가지 방법이 있습니다.

선형 안개



다음의 식으로 $f$를 구하면, $d_{start}$보다 앞에서는 $f=1$, $d_{end}$보다 안쪽에서는 $f=0$, $d_{start}$부터 $d_ {end}$ 사이에서는 $f$가 $1$에서 $0$로 선형으로 바뀝니다.
f = clamp(\frac{d_{end} - d}{d_{end} - d_{start}}, 0, 1)

GLSL로 구현하면 다음과 같습니다.
float linearFog(float d, float start, float end) {
    return clamp((end - d) / (end - start), 0.0, 1.0);
}

위의 장면에 선형 안개를 적용하면 다음과 같습니다. 선형 안개는 파라미터가 직관적이고 알기 쉽지만, 안개가 걸려있는 부분과 달려 있지 않은 부분이 선명하고 리얼하지 않을까라는 인상입니다.



지수 안개 1



지수를 이용하여 $f$를 구하는 방법입니다. $density$는 $0$와 $1$ 사이의 값을 지정합니다.
f = e^{-d \times density}

그래프로 하면 다음과 같이 되어, 거리에 따라 완만하게 $f$의 값이 변화하는 것을 알 수 있습니다.



GLSL로 구현하면 다음과 같습니다.
float expFog(float d, float density) {
    return exp(-d * density);
}

이 포그를 첫 장면에 적용하면 선형 포그 때보다 리얼리티가 늘어나지만, 앞의 객체에도 포그가 걸려 모아한 인상이 되었습니다.



지수 안개 2



앞서 소개한 방법과 식이 비슷하지만 지수 부분을 제곱하고 있습니다.
f = e^{-(d \times density)^2}

그래프로 하면 아래와 같이 되어, 앞 부분은 천천히 변화해, 안쪽에 가면서 급격하게 $f$가 0에 접근해 갑니다.



GLSL로 구현하면 다음과 같습니다.
float exp2Fog(float d, float density) {
    float dd = d * density;
    return exp(-dd * dd);
}

이 방법이라면 앞 부분이 선명하게 보이게 되면서, 포그의 리얼리티도 유지하고 있는 것 같은 느낌이 듭니다.



끝에



이번에는 안개에 대해 정리해 보았습니다. 안개 자체는 3D로 스테디셀러 이펙트이므로 새로운 것은 없습니다만, 반복 표현을 간단하게 실현할 수 있는 레이마칭에서도 유용할까라고 생각하고 있습니다.

이번 샘플로 만든 장면은 glslsandbox에 두었습니다. #define FOG_TYPE 를 변경하여 사용하는 안개를 변경할 수 있습니다.
h tp // glsl씨 d보 x. 이 m/E #50866.0

참고


  • 안개 공식
  • 01-10 : 안개 (안개) | #region OpenTK
  • 좋은 웹페이지 즐겨찾기