레이마칭에서 앰비언트 오클루전

16407 단어 GLSL
레이마칭에서 앰비언트 오클루전을 계산하려면 레이마치의 스텝수를 바탕으로 구하는 방법과 레이와 객체의 교점의 법선 방향의 근사점에서의 거리를 샘플링하여 구하는 방법의 두 가지가 있습니다. 아래 샘플 코드는 GLSL로 작성되었습니다.

단계 수를 기반으로 계산하는 방법



스텝수를 이용하는 방법에서는, 레이와 오브젝트의 교점을 구하는데 필요한 레이마치의 스텝수를 최대 스텝수로 나눈 값을 앰비언트 오클루전의 값으로 합니다.
이 방법은, 「스텝수가 많다」 => 「레이의 근처에 오브젝트가 많다」 => 「차폐되고 있다」 라고 하는 이굴입니다.

이하, 샘플 코드입니다.
#define TMAX 50.0
#define ITERATION 128
float raymarch(in vec3 origin, in vec3 direction, inout int steps) {
    float t = 0.0;
    for (int i = 0; i < ITERATION; i++) {
        steps = i;
        vec3 p = origin + t * direction;
        float d = map(p);
        if (d < 0.02 || t > TMAX) break;
        t += d;
    }
    return t;
}

vec3 render(in vec3 origin, in vec3 direction) {
    int steps;
    float t = raymarch(origin, direction, steps);

    vec3 c = vec3(0.0);
    if (t < TMAX) {
        float ao = 1.0 - float(steps) / float(ITERATION);
        c = vec3(ao);
    }   
    return c;
}

앰비언트 오클루전만으로 색칠한 것은 다음과 같습니다.



움직이는 것은 아래에서 확인할 수 있습니다.
h tp // glsl 씨 d보 x. 이 m/E #44291.0

법선 방향의 근사점에서 거리를 샘플링하는 방법



이 방법은 레이와 객체의 교차점의 법선 방향 근사점에서 거리를 샘플링하여 앰비언트 오클루전을 계산합니다.
근사점에서의 거리를 구하고 있는 개소는 ambientoculustion 함수내의 이하의 개소가 됩니다.
ao += amp * clamp(map(position) / distance, 0.0, 1.0);

만약, 근처에 교차한 오브젝트 밖에 없으면, map(position) = distance 가 됩니다. 그러나, 샘플링하고 있는 점의 근처에 다른 오브젝트가 있는 경우는 map(position) < distance 가 되어, 이 오브젝트에 교차점이 차폐되고 있다고 생각할 수가 있습니다.
#define TMAX 50.0
#define ITERATION 128
float raymarch(in vec3 origin, in vec3 direction, inout int steps) {
    float t = 0.0;
    for (int i = 0; i < ITERATION; i++) {
        steps = i;
        vec3 p = origin + t * direction;
        float d = map(p);
        if (d < 0.02 || t > TMAX) break;
        t += d;
    }
    return t;
}

float ambientoculusion(in vec3 position, in vec3 normal) {
    float ao = 0.0;
    float amp = 0.5;
    float distance = 0.02;
    for (int i = 0; i < 10; i++) {
        position = position + distance * normal;
        ao += amp * clamp(map(position) / distance, 0.0, 1.0);
        amp *= 0.5;
        distance += 0.02;
    }
    return ao;
}

vec3 render(in vec3 origin, in vec3 direction) {
    int steps;
    float t = raymarch(origin, direction, steps);

    vec3 c = vec3(0.0);
    if (t < TMAX) {
        vec3 p = origin + t * direction;
        vec3 n = normal(p);
        float ao = ambientoculusion(p + 0.01 * n, n);
        c = vec3(ao);
    }

    return c;
}

이 방법으로 구한 앰비언트 오클루전으로 컬러링한 경우는 다음과 같습니다.



움직이는 것은 아래에서 확인할 수 있습니다.
h tp // glsl씨 d보 x. 이 m/E #44290.0

두 가지 방법의 차이



스텝수를 기초로 계산하는 방법은 정밀도는 좋지 않지만 계산은 가볍고, 반대로 법선 방향의 근사점에서의 거리를 샘플링하는 방법은 정밀도는 좋지만 계산은 무겁습니다.

[여담] 빛나는 것 같은 효과



스텝수를 이용하면 빛나는 듯한 이펙트도 만들 수 있습니다.


vec3 render(in vec3 origin, in vec3 direction) {
    int steps;
    float t = raymarch(origin, direction, steps);

    vec3 c = vec3(0.0);
    if (t < TMAX) {
        float grow =  float(steps) / float(ITERATION);
        c += vec3(1.5, 1.0, 2.0) * grow;
    }   
    return c;
}

참고


  • htp : // bg. hゔぃdt 훗ldts. 네 t/그리고 x. php / 2011 / 08 / ぢ s tanse-e s chime d 3 df 등 c ls - 좋다 - gh chin g an d-ko rin g /
  • h tp // w w. 가자 → 에 s. 오 rg / w w / 마테리아 l / n vs 세네 2008 / r w t. pdf
  • 좋은 웹페이지 즐겨찾기