개발/Shader / / 2023. 3. 1. 23:33

GLSL - cross translate 십자가 위치 변환

반응형

https://thebookofshaders.com/08/

 

The Book of Shaders

Gentle step-by-step guide through the abstract and complex universe of Fragment Shaders.

thebookofshaders.com

※ 다음 페이지를 참고하여 공부한 게시물입니다.

https://www.opentutorials.org/module/3659/24522

 

15. Translate - GLSL / Shader

15. Translate 2019-03-25 00:39:13

www.opentutorials.org

Translate

// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform float u_time;

float box(in vec2 _st, in vec2 _size){
    _size = vec2(0.5) - _size*0.5;
    vec2 uv = smoothstep(_size,
                        _size+vec2(0.001),
                        _st);
    uv *= smoothstep(_size,
                    _size+vec2(0.001),
                    vec2(1.0)-_st);
    return uv.x*uv.y;
}

float cross(in vec2 _st, float _size){
    return  box(_st, vec2(_size,_size/4.)) +
            box(_st, vec2(_size/4.,_size));
}

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    vec3 color = vec3(0.0);

    // To move the cross we move the space
    vec2 translate = vec2(cos(u_time),sin(u_time));
    st += translate*0.35;

    // Show the coordinates of the space on the background
    // color = vec3(st.x,st.y,0.0);

    // Add the shape on the foreground
    color += vec3(cross(st,0.25));

    gl_FragColor = vec4(color,1.0);
}

이렇게 십자가 모양이 둥글게 도는 형태의 코드를 만들어보려고 한다.

 

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

float bar(vec2 loc, vec2 size, vec2 coord){
    vec2 sw = loc - size/2.;
    vec2 ne = loc + size/2.;
    
    vec2 ret = step(sw, coord) - step(ne, coord);
    
    return ret.x * ret.y;
}

float cross(vec2 loc, vec2 size, vec2 coord){
    float b1 = bar(loc, size, coord);
    float b2 = bar(loc, vec2(size.y, size.x), coord);
    
    return max(b1, b2);
}

void main(){
    vec2 coord = gl_FragCoord.xy/u_resolution;
    coord.x *= u_resolution.x/u_resolution.y;
    
    vec3 col = vec3(cross(vec2(.5), vec2(0.650, 0.080), coord));
    
    gl_FragColor = vec4(col, 1.0);
}

우선 십자가 모양을 먼저 만든다.

 직사각형을 그리는 함수 bar()에서는 사각형을 그리는 sw, ne과 step을 이용하여 (1,1)로 나오는 부분들만을 흰색으로 칠했던 이전 포스팅의 square 로직으로 생성한다. 

 cross()에서 두 직사각형을 겹치는데, 가로로 긴 직사각형을 만들고 세로로 긴 직사각형을 만들 때는 size의 x,y좌표를 뒤바꾸어서 생성해준다. 각 좌표에 따라서 b1혹은 b2의 사각형이 그려지거나 그려지지 않는데, 그려지지 않으면 해당 좌표에 대해 0, 그려지면 1을 담고 있으므로 각 좌표에 대해 max(b1, b2)를 해주어야 사각형을 서로 겹칠 수 있다. 

 

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

float bar(vec2 loc, vec2 size, vec2 coord){
    vec2 sw = loc - size/2.;
    vec2 ne = loc + size/2.;
    
    vec2 ret = step(sw, coord) - step(ne, coord);
    
    return ret.x * ret.y;
}

float cross(vec2 loc, vec2 size, vec2 coord){
    float b1 = bar(loc, size, coord);
    float b2 = bar(loc, vec2(size.y, size.x), coord);
    
    return max(b1, b2);
}

void main(){
    vec2 coord = gl_FragCoord.xy/u_resolution;
    coord.x *= u_resolution.x/u_resolution.y;
    
    coord = coord * 2. - 1.;
    
    float rad = 0.5;
    vec2 loc = vec2(0.) + vec2(sin(u_time), cos(u_time)) * rad;
    vec3 col = vec3(cross(loc, vec2(0.30, 0.020), coord));
    
    gl_FragColor = vec4(col, 1.0);
}

이 십자가를 움직이는 방법에는 십자가 모양 자체의 위치를 옮기거나, 원점의 위치를 옮기는 방법이 있다.

위 코드는 십자가 자체의 위치를 옮기는 방법이다. 

화면에 표시되는 coord 좌표 범위를 x,y 2배로 늘린 후, 1을 빼서 원점이 중앙에 놓이도록 만들고,

loc 위치에 sin(), cos()으로 시간에 따라 원 모양으로 움직이도록 하였다. rad은 회전하는 원의 반지름을 적용한 것이다.

 

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

float bar(vec2 loc, vec2 size, vec2 coord){
    vec2 sw = loc - size/2.;
    vec2 ne = loc + size/2.;
    
    vec2 ret = step(sw, coord) - step(ne, coord);
    
    return ret.x * ret.y;
}

float cross(vec2 loc, vec2 size, vec2 coord){
    float b1 = bar(loc, size, coord);
    float b2 = bar(loc, vec2(size.y, size.x), coord);
    
    return max(b1, b2);
}

void main(){
    vec2 coord = gl_FragCoord.xy/u_resolution;
    coord.x *= u_resolution.x/u_resolution.y;
    
    coord = coord * 2. - 1.;
    
    float rad = 0.5;
    vec2 loc = vec2(0.) + vec2(sin(u_time), cos(u_time)) * rad;
    coord += loc;
    
    vec3 col = vec3(cross(vec2(.0), vec2(0.30, 0.020), coord));
    
    gl_FragColor = vec4(col, 1.0);
}

이번에는 원점을 이동시키는 방법의 코드이다.

coord 좌표에 vec2 값을 더하면 원점이 해당 위치로 이동하므로, 십자가가 해당축이 증가하는 만큼 반대방향으로 움직인다. 그랬을 때 cross() 십자가가 원점을 중심으로 생성되고, coord에 loc값을 더함으로써 원점이 회전하면서 십자가가 회전하는 것으로 보이게 된다.

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유