본문 바로가기
Shader CG

05. RayMarching - Camera move

by SimonLee 2024. 8. 5.

 

이전 챕터에서 다룬 Rotation 을 사용하여 카메라의 원점을 이동해보고

방향을 회전 시켜보자.

 

카메라 회전

 

카메라 원점을 값을 변경해보자.

계속 증가하는 iTime(시간)을 sin, cos 함수에 넣고 각각 x, y에 넣게 되면 ,

원을 그리면서 카메라가 이동을 하게 한다.

 

mouse x, y 좌표를 -0.5 ~ 0.5로 remap 한 뒤, 

그 값을 rotation 공식에 theta를 넣어 회전 행렬을 만들자.

회전 행렬을 vec3 rd에 곱해주게 되면 

카메라 광선 방향이 마우스의 좌표에 따라 회전을 하게 된다.

 

x의 값은 y 회전할 때 사용하게 하고, y 값은 x 회전할때 사용하게 한다.

아래 그림처럼 y 회전은 Yaw, x 회전은 Pitch로 정의 된다.

 

전체 코드 >

struct Surface {
    float d;
    vec3 col;
    int id;
};

// Rotation matrix around the X axis.
mat3 rotateX(float theta) {
    float c = cos(theta);
    float s = sin(theta);
    return mat3(
        vec3(1, 0, 0),
        vec3(0, c, -s),
        vec3(0, s, c)
    );
}

// Rotation matrix around the Y axis.
mat3 rotateY(float theta) {
    float c = cos(theta);
    float s = sin(theta);
    return mat3(
        vec3(c, 0, s),
        vec3(0, 1, 0),
        vec3(-s, 0, c)
    );
}

// Rotation matrix around the Z axis.
mat3 rotateZ(float theta) {
    float c = cos(theta);
    float s = sin(theta);
    return mat3(
        vec3(c, -s, 0),
        vec3(s, c, 0),
        vec3(0, 0, 1)
    );
}

// Identity matrix.
mat3 identity() {
    return mat3(
        vec3(1, 0, 0),
        vec3(0, 1, 0),
        vec3(0, 0, 1)
    );
}

Surface sdSphere(vec3 p, float r, vec3 offset, vec3 col, int id)
{
  Surface s;
  p -= offset;
  s.d = length(p) - r;
  s.col = col;
  s.id = id;
  return s;
}

Surface sdBox(vec3 p, vec3 b, vec3 offset, vec3 color, int id)
{
    Surface s;
    p -= offset;
    vec3 q = abs(p) - b;
    s.d = length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);
    s.col = color;
    s.id = id;
    return s;
}

Surface sdFloor(vec3 p, vec3 color, int id) {
    Surface s;
    s.d = length(vec3(0, p.y + 1., 0));
    s.col = vec3(.5 + mod(floor(p.x) + floor(p.z), 2.) * 0.7);
    s.id = id;
    return s;
}

Surface merge(Surface a, Surface b) {
    if (a.id == 0) return b;
    if (b.id == 0) return a;
    
    if (a.d < b.d) return a;
    return b;
}

Surface sdScene(vec3 p) {
    Surface box = sdBox(p, vec3(1.), vec3(-2,0,0), vec3(0.4,0.5,1.), 1);
    Surface floor = sdFloor(p, vec3(0), -1);
    Surface sphere = sdSphere(p, 1., vec3(2, 0, 0), vec3(1,0,0), 1);
    
    Surface rst;
    rst = merge(rst, floor);
    rst = merge(rst, box);
    rst = merge(rst, sphere);
    
    
    return rst;
}

Surface rayMarch(float start, float end, vec3 ro, vec3 rd) {
    float dist = start;
    Surface s;
    
    for (int i=0; i<255; i++) {
        vec3 p = ro + rd * dist;
        s = sdScene(p);
        dist += s.d;
        if (dist < 0.001 || dist > end) break;
    }
    s.d = dist;
    return s;
}


vec3 calcNormal(in vec3 p) {
    vec2 e = vec2(1.0, -1.0) * 0.0005; // epsilon
    return normalize(
      e.xyy * sdScene(p + e.xyy).d +
      e.yyx * sdScene(p + e.yyx).d +
      e.yxy * sdScene(p + e.yxy).d +
      e.xxx * sdScene(p + e.xxx).d);
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    vec2 mouse = iMouse.xy / iResolution.xy - 0.5;
    vec3 background = vec3(0.2);
    vec3 col = background;
    
    const float PI = 3.141592;

    vec3 ro = vec3(sin(iTime), cos(iTime)+ 3., 5);
    vec3 lightPos = vec3(0, 10, 0);
    
    vec3 rd = normalize(vec3(uv, -1));
    mat3 yrot = rotateY(-mouse.x);
    mat3 xrot = rotateX(mouse.y);
    rd *= xrot * yrot;
    
    float start = 0.; float end = 100.;
    Surface s = rayMarch(start, end, ro, rd);
    if (s.d < 100.) {
        if (s.id > 0) {
            vec3 p = ro + rd * s.d;
            vec3 normal = calcNormal(p);
            vec3 lightDi = normalize(lightPos - p);
            float diffuse = clamp(dot(normal, lightDi), 0.3, 1.);
            col = s.col * diffuse * 0.7 + background * 0.2;
        }
        else {
            col = s.col;
        }
    }
    fragColor = vec4(col,1.0);
}

 

Reference

https://inspirnathan.com/posts/55-shadertoy-tutorial-part-9

 

Shadertoy Tutorial Part 9 - Camera Movement

Learn how to pan and tilt/rotate the camera with a mouse!

inspirnathan.com

 

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

07. RayMarching - Frenel effect  (0) 2024.08.10
06. RayMarching - 퐁 라이팅 모델  (0) 2024.08.08
04. RayMarching - Rotation  (0) 2024.08.04
03. RayMarhcing - Rendering Many Object  (0) 2024.08.02
02. RayMarhcing - Shading Sphere  (0) 2024.08.01