본문 바로가기
셰이더 (Shader)/The Art of Code

[GLSL] Starfield - 2 : 별 여러개 만들기 (1)

by Minkyu Lee 2023. 3. 30.

mat2 Rot(float a) {
    float s = sin(a), c = cos(a) ;
    return mat2(c, -s, s, c) ;
}

float Star(vec2 uv, float flare) { // flare = 섬광(밝기)
    float d = length(uv) ;
    float m = 0.02/d ; // 0.02까지는 완전히 1, 0.02 이후부터는 서서히 falloff
    
    // 십자 레이
    float rays = max(0.0, 1.0-abs(uv.x*uv.y*1000.0)) ;
    m += rays * flare ;
    
    // 대각선 레이
    uv *= Rot(3.1415/4.0) ;
    rays = max(0.0, 1.0-abs(uv.x*uv.y*1000.0)) ;
    m += rays * 0.3 * flare ;
    
    return m ;
}

float Hash21(vec2 p) // 랜덤
{
    p = fract(p * vec2(123.34, 456.21) ) ; // 0~1 범위 난수로 만들기
    p += dot(p, p + 45.32) ; // 더욱 더 난수로 만들기
    // dot은 성분별 곱한 후 더하기를 대신한다.
    
    return fract(p.x*p.y) ; // float으로 내보내기
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord-0.5*iResolution.xy)/iResolution.y ; 
    uv *= 3.0;
    
    // --- 랜덤 배치 별 만들기 ---
    vec3 col = vec3(0.0);
    vec2 gv = fract(uv)-0.5;
    // uv를 소수점으로 만들어 여러개의 노멀라이즈된 uv로 분할한다.
    // -0.5로 중심 uv로 만든다. 0 ~ 1 >> -0.5 ~ 0.5
    
    vec2 id = floor(uv) ; // gv별 id이다.
    float n = Hash21(id) ; // random 0~1
    col += Star( (gv-vec2(n, fract(n * 34.0))) + 0.5, 1.0) ;
    // 랜덤값으로 오프셋 한다. 

    if(gv.x > 0.48 || gv.y > 0.48) col.r = 1.0 ; // 디버깅용 빨간줄
    
    fragColor = vec4(col,1.0);
}

/*
https://www.youtube.com/@TheArtofCodeIsCool
*/

별이 잘리는 것은 다음 단계에서 해결한다.

uv를 fract로 분할하고 랜덤값을 만들어 offset하는 것이 핵심이다.

 

// Rot 함수

- 위키백과 공식

https://en.wikipedia.org/wiki/Rotation_matrix

 

// Hash21 함수

원형보다 많이 단순해졌다. 비용싸게 하려고 한듯하다.
    
- Hash21이란?
주어진 입력에서 21 비트 해시 값을 생성하는 함수이다.
각 픽셀에 대한 고유 식별자를 생성하는 데 사용된다.

랜덤이다.

 

- 참고링크
https://thebookofshaders.com/10/
https://shadertoyunofficial.wordpress.com/2019/01/02/programming-tricks-in-shadertoy-glsl/

 

댓글