본문 바로가기
Shader CG

02. RayMarhcing - Shading Sphere

by SimonLee 2024. 8. 1.

이전 포스팅

https://graphicsimon.tistory.com/68?category=1119246

 

01. RayMarhcing - Rendering Sphere

위 그림은 2차원이 아닙니다. ^ ~ ^  3차원임 vec2 uv = ( fragCoord - 0.5 * iResolution.xy ) / iResolution.y;fragCoord 값은 해상도 값 기준 좌표이다.  ( 0 화면 중심이 원점이고 가로 세로 종횡비를 맞춰주는 코드

graphicsimon.tistory.com

 

퐁라이팅 모델을 적용해서 구에 음영 입히기

 

노말을 계산하는 함수는 calcNormal 이다.

두점 사이의 기울기를 법선 벡터 노멀로 사용할 수 가 있다.

아주 작은 두점 사이의 기울기는 :  x증가량 / y 증가량 이다.

- (x, y), (x1, y1) 의 기울기는 (x1 - x) / (y1 - y) 이다.

 

3차원 좌표로 생각하면 아주 작은 거리 (e)를 사용해서 아래 처럼 나타낼 수 있다.

노말 구하는 공식은 따로 정리해두고 써먹자.

 

 

해당 좌표에 노멀과 라이트 방향을 내적하게 되면 받을수 있는 빛의 양을 구할수 있다. ( n dot l )

벡터니 정규화 시켜주고, 음수 값은 버려야 하므로 clamp 해주면

빛의 방향과 노멀의 사이각도가 0도의 ndotl 값이 가장 크므로, 밝아지고 90도에 가까워 질수록 어두워 진다.

이해가 안간다면 아래 참고..

https://graphicsimon.tistory.com/28

 

2. 내적 ( Dot Product )

두 벡터의 내적 ( Dot Product )은 다음과 같이 정의합니다. 내적 연산자는 가운데 점 입니다. U, V는 벡터이기 때문에 2차원일수도 있고 3차원일수도 있습니다. | U | | V | 라고 되어있는 부분은 벡터의

graphicsimon.tistory.com

 

전체 코드 >>

float sdsphere(vec3 p, float r) {
    vec3 offset = vec3(0, 0, -3);// 원이 원점기준이기 때문에 카메라와 너무 가까워서 뒤로 좀 물러서게함
    return length(p - offset) - r;
}

vec3 calcNormal(vec3 p) {
  float e = 0.0005; // epsilon
  float r = 1.; // radius of sphere
  return normalize(vec3(
    sdsphere(vec3(p.x + e, p.y, p.z), r) - sdsphere(vec3(p.x - e, p.y, p.z), r),
    sdsphere(vec3(p.x, p.y + e, p.z), r) - sdsphere(vec3(p.x, p.y - e, p.z), r),
    sdsphere(vec3(p.x, p.y, p.z  + e), r) - sdsphere(vec3(p.x, p.y, p.z - e), r)
  ));
}

float rayMarch(float start, float end, vec3 ro, vec3 rd) {
    float depth = start;

    for (int i = 0; i < 255; i++) {
        vec3 p = ro + rd * depth;
        float d = sdsphere(p, 1.);
        depth += d;
        if (depth < 0.001 || depth > end) break;
    }
    return depth;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    vec3 background = vec3(0.2, 0.3, 0.2);
    vec3 circleCol = vec3(1., 0., 0.5);
    vec3 col = background;
    vec3 ro = vec3(0., 0, 5);
    vec3 rd = normalize(vec3(uv, -1));
    vec3 lightpos = vec3(15,10,0);
    
    float start = 0.;
    float end = 100.;
    float depth = rayMarch(start, end, ro, rd);
    
    if (depth < end) {
        vec3 p = ro + rd * depth;
        vec3 normal = calcNormal(p);
        vec3 lightdi = normalize(lightpos - p);
        float ndotl = clamp(dot(normal, lightdi), 0.2, 1.);
       
        vec3 diffuse = circleCol * ndotl;
        col = circleCol * diffuse + (0.2 * background);
    }
    fragColor = vec4(col,1.0);
}

 

Reference

https://inspirnathan.com/posts/52-shadertoy-tutorial-part-6#ray-marching

 

'Shader CG' 카테고리의 다른 글

04. RayMarching - Rotation  (0) 2024.08.04
03. RayMarhcing - Rendering Many Object  (0) 2024.08.02
01. RayMarhcing - Rendering Sphere  (0) 2024.07.31
3D Scenes With Ray Marching  (0) 2024.06.27
2.7 Noise - 영혼이 빠져나감  (0) 2023.08.28