GLSL 퀵 레퍼런스

0 ~ 1 사이의 값을 갖는 간단한 노이즈 함수

float random (in vec2 st) {
    return fract(sin(dot(st.xy,
        vec2(12.9898,78.233)))*
        43758.5453123);
}

// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 st) {
    vec2 i = floor(st);
    vec2 f = fract(st);

    // Four corners in 2D of a tile
    float a = random(i);
    float b = random(i + vec2(1.0, 0.0));
    float c = random(i + vec2(0.0, 1.0));
    float d = random(i + vec2(1.0, 1.0));

    vec2 u = f * f * (3.0 - 2.0 * f);

    return mix(a, b, u.x) +
            (c - a)* u.y * (1.0 - u.x) +
            (d - b) * u.x * u.y;
}

-1 ~ 1 사이의 값을 갖는 Simplex 노이즈 함수

// Some useful functions
vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
vec3 permute(vec3 x) { return mod289(((x*34.0)+1.0)*x); }

//
// Description : GLSL 2D simplex noise function
//      Author : Ian McEwan, Ashima Arts
//  Maintainer : ijm
//     Lastmod : 20110822 (ijm)
//     License :
//  Copyright (C) 2011 Ashima Arts. All rights reserved.
//  Distributed under the MIT License. See LICENSE file.
//  https://github.com/ashima/webgl-noise
//
float snoise(vec2 v) {

    // Precompute values for skewed triangular grid
    const vec4 C = vec4(0.211324865405187,
                        // (3.0-sqrt(3.0))/6.0
                        0.366025403784439,
                        // 0.5*(sqrt(3.0)-1.0)
                        -0.577350269189626,
                        // -1.0 + 2.0 * C.x
                        0.024390243902439);
                        // 1.0 / 41.0

    // First corner (x0)
    vec2 i  = floor(v + dot(v, C.yy));
    vec2 x0 = v - i + dot(i, C.xx);

    // Other two corners (x1, x2)
    vec2 i1 = vec2(0.0);
    i1 = (x0.x > x0.y)? vec2(1.0, 0.0):vec2(0.0, 1.0);
    vec2 x1 = x0.xy + C.xx - i1;
    vec2 x2 = x0.xy + C.zz;

    // Do some permutations to avoid
    // truncation effects in permutation
    i = mod289(i);
    vec3 p = permute(
            permute( i.y + vec3(0.0, i1.y, 1.0))
                + i.x + vec3(0.0, i1.x, 1.0 ));

    vec3 m = max(0.5 - vec3(
                        dot(x0,x0),
                        dot(x1,x1),
                        dot(x2,x2)
                        ), 0.0);

    m = m*m ;
    m = m*m ;

    // Gradients:
    //  41 pts uniformly over a line, mapped onto a diamond
    //  The ring size 17*17 = 289 is close to a multiple
    //      of 41 (41*7 = 287)

    vec3 x = 2.0 * fract(p * C.www) - 1.0;
    vec3 h = abs(x) - 0.5;
    vec3 ox = floor(x + 0.5);
    vec3 a0 = x - ox;

    // Normalise gradients implicitly by scaling m
    // Approximation of: m *= inversesqrt(a0*a0 + h*h);
    m *= 1.79284291400159 - 0.85373472095314 * (a0*a0+h*h);

    // Compute final noise value at P
    vec3 g = vec3(0.0);
    g.x  = a0.x  * x0.x  + h.x  * x0.y;
    g.yz = a0.yz * vec2(x1.x,x2.x) + h.yz * vec2(x1.y,x2.y);
    return 130.0 * dot(m, g);
}

좀더 고른 분포의 랜던 hash

uvec2 murmurHash21(uint src) {
  const uint M = 0x5bd1e995u;
  uvec2 h = uvec2(1190494759u, 2147483647u);
  src *= M;
  src ^= src>>24u;
  src *= M;
  h *= M;
  h ^= src;
  h ^= h>>13u;
  h *= M;
  h ^= h>>15u;
  return h;
}

// 2 outputs, 1 input
vec2 hash21(float src) {
  uvec2 h = murmurHash21(floatBitsToUint(src));
  return uintBitsToFloat(h & 0x007fffffu | 0x3f800000u) - 1.0;
}

smoothstep의 보간식

아래의 a와 b는 동일한 값이다.

float f = uv.x;
float a = smoothstep(0., 1., f);
float b = f * f * (3. - 2. * f);

위의 보간식을 cubic Hermite curve(큐빅 헤르미트 곡선)라고 한다. 0~1 사이의 영역에서 시작과 끝을 좀더 편평하게 만들어주는 quintic interpolation cuver(퀸틱 보간 곡선)에 대한 코드는 다음과 같다.

float f = uv.x;
float b = f * f * f * (6. * f * f - 15. * f + 10.);

modelMatrix로 변환된 normal 얻기

varying vec3 vNormal;

...

vNormal = mat3(transpose(inverse(modelMatrix))) * normal;

프레그먼트 쉐이더에서는 받은 vNormal을 반드시 정규화(normalize)해야 한다.

3초 주기로 0 ~ 1 사이의 연속된 값 얻기

uniform float u_time; // 0, 1, 2, ...의 값이며 각각 0초, 1초, 2초, ...를 나타냄

...

float period = 3.; // 3초 주기
float t = mod(u_time, period) / period; // 0 ~ 1 사이의 연속된 값

// sin 함수에 3.1415를 곱하는 이유는 sin 함수의 한 주기가 360도이기 때문임
vec3 color = mix(vec3(0), vec3(1), abs(sin(3.1415 * t)));
// or
vec3 color = mix(vec3(0), vec3(1), sin(3.1415 * t) * .5 + .5); 

원하는 각도를 이루는 선

아래의 이미지는 45도를 이루는 선인데, 이처럼 원하는 각도를 이루는 선을 만들기 위한 코드이다.

uniform vec3 uResolution;
uniform float uTime;
uniform vec4 uMouse;

#define PI (3.141592)

void main() {
  vec2 st = gl_FragCoord.xy / uResolution.xy;
  st = (gl_FragCoord.xy - .5 * uResolution.xy) / uResolution.y;

  float w = fwidth(st.y);
  float a = (45.) * PI / 180.0;
  float d = dot(st, vec2(cos(a), sin(a)));
  d = smoothstep(-w, w, abs(d));

  gl_FragColor = vec4(vec3(1. - d), 1.);
}

다각형 그리기

uniform vec3 uResolution;
uniform float uTime;
uniform vec4 uMouse;

#define PI 3.14159265359
#define TWO_PI 6.28318530718

void main(){
  vec2 st = gl_FragCoord.xy/uResolution.xy * 2. - 1.; //-1-1
  st.x *= uResolution.x/uResolution.y;
  vec3 color = vec3(0.0);
  float d = 0.0;

  // Number of sides of your shape
  int N = 6;
  // int N = int(floor(mod(uTime * 10., 20.))) + 3;

  // Angle and radius from the current pixel
  float a = atan(st.x,st.y)+PI;
  float r = TWO_PI/float(N);

  // Shaping function that modulate the distance
  d = cos(floor(.5+a/r)*r-a)*length(st);

  // color = vec3(d); // Distance Field
  color = vec3(1.0-step(.5, d)); // Fill
  // color = vec3(step(.5,d) * step(d,.51)); // Only outline

  gl_FragColor = vec4(color,1.0);
}

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다