Skip to content

Instantly share code, notes, and snippets.

@katai5plate
Last active April 17, 2020 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save katai5plate/c779d2a5a19f58aea3d22a8e65ab8ab1 to your computer and use it in GitHub Desktop.
Save katai5plate/c779d2a5a19f58aea3d22a8e65ab8ab1 to your computer and use it in GitHub Desktop.
GLSLノート

座標の正規化 P

  • 原点 0.0, 0.0 が真ん中になる。
vec2 P = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);

原点との距離、点と点の距離

length(vec2(1)) == distance(vec2(0), vec2(1))
length(vec3(1)) == distance(vec3(0), vec3(1))
length(vec4(1)) == distance(vec4(0), vec4(1))

点オーブ

  • 原点に近付くほど色が変化する。
  • 1. - を消すと背景白の黒オーブになる。
float x = 0., y = 0., size = .5;

gl_FragColor = vec4(vec3(
  1. - (length(vec2(x, y) - P) / size)
), 1.);

HSV カラー

  • 白になる部分に乗算して使う。
  • 色付けは基本、白黒を作ってから色を乗算し、条件に応じて分類する。
vec3 getHSV(float h, float s, float v){
  vec4 t = vec4(1., 2. / 3., 1. / 3., 3.);
  vec3 p = abs(fract(vec3(h) + t.xyz) * 6. - vec3(t.w));
  return v * mix(vec3(t.x), clamp(p - vec3(t.x), 0., 1.), s);
}

gl_FragColor = vec4(vec3(
  (1. - length(vec2(x, y) - P) / 1.) * getHSV(time, 1., 1.)
), 1.);

オーブ

  • size の半径までは白く、そこから外に向かって光が減衰する。
float x = 0., y = 0., size = .5;

gl_FragColor = vec4(vec3(
  size / length(vec2(x, y) - P)
), 1.);

リング

  • 半径と原点の距離差を計算し abs で外側にも同じような描画を行う。
float x = 0., y = 0., size = .5, lineWidth = .01;

gl_FragColor = vec4(vec3(
  lineWidth / abs(size - length(vec2(x, y) - P))
), 1.);

グラデーション

  • 原点から指定座標への方向に向かって、原点で収束する形で色が付く。
  • dot は内積。
float x = 0., y = 0., size = .5;

gl_FragColor = vec4(vec3(
  dot(vec2(x, y), P)
), 1.);

上から円錐を見たようなグラデーション

float x = 0., y = 0., size = .5;

gl_FragColor = vec4(vec3(
  dot(P, vec2(x, y)) / (length(P) * length(vec2(x, y)))
), 1.);

日章旗の集中線

  • count は線の数。
float x = 0., y = 0., count = 10., angle = time;

gl_FragColor = vec4(vec3(
  sin((atan(P.y - y, P.x - x) + angle) * count)
), 1.);

花のような集中線

float x = 0., y = 0., count = 10., angle = time, lineWith = .01;

gl_FragColor = vec4(vec3(
  (lineWith / abs(sin((atan(P.y - y, P.x - x) + angle) * count) - length(P - vec2(x, y))))
), 1.);

波打つリング

float x = 0., y = 0., count = 10., angle = time, lineWith = .01, wave = .2, twist = -1.;

float posLength = length(P - vec2(x, y));
gl_FragColor = vec4(vec3(
  lineWith / abs(size + abs(sin(count * (
    atan(P.y - y, P.x - x) - (posLength * twist) + time
  ))) * wave - posLength)
), 1.);

マンデルブロ集合

float getMandelbrot(vec2 P, float x, float y, float scale){
  #define REPEAT 360
  int counter = 0;
  vec2 temp = vec2(0, 0);
  for(int i = 0; i < REPEAT; i++){
    counter++;
    if(length(temp) > 2.0) break;
    temp = vec2(temp.x * temp.x - temp.y * temp.y, 2. * temp.x * temp.y) + (P - vec2(x, y)) / scale;
  }
  return float(counter / REPEAT);
}
gl_FragColor = vec4(vec3(
  getMandelbrot(P, x, y, scale)
), 1.);

ノイズ

const float SEED = 55.;
const int   oct  = 8;
const float per  = .5;
const float PI   = 3.14;
const float cCorners = 1. / 16.;
const float cSides   = 1. / 8.;
const float cCenter  = 1. / 4.;
// 補間関数
float inter(float a, float b, float x){
  float f = (1. - cos(x * PI)) * .5;
  return a * (1. - f) + b * f;
}
// 乱数生成
float rnd(vec2 p){
  return fract(sin(dot(p ,vec2(SEED, pow(SEED, 2.)))) * (SEED * 2.));
}
// 補間乱数
float irnd(vec2 p){
  vec2 i = floor(p), f = fract(p);
  vec4 v = vec4(
    rnd(vec2(i.x, i.y)), rnd(vec2(i.x + 1., i.y)),
    rnd(vec2(i.x, i.y + 1.)), rnd(vec2(i.x + 1., i.y + 1.))  
  );
  return inter(inter(v.x, v.y, f.x), inter(v.z, v.w, f.x), f.y);
}
// ノイズ生成
float noise(vec2 p){
  float t = 0.;
  for(int i = 0; i < oct; i++){
    float freq = pow(2., float(i));
    float amp  = pow(per, float(oct - i));
    t += irnd(vec2(p.xy) / freq) * amp;
  }
  return t;
}
// シームレスノイズ生成
float snoise(vec2 p, float map){
  vec2 t = mod(p, map), q = t / map, r = vec2(map);
  return (noise(vec2(t.x, t.y)) * q.x * q.y) +
    (noise(vec2(t.x, t.y + r.y)) * q.x * (1.0 - q.y)) +
    (noise(vec2(t.x + r.x, t.y)) * (1.0 - q.x) * q.y) +
    (noise(vec2(t.x + r.x, t.y + r.y)) * (1.0 - q.x) * (1.0 - q.y));
}
// 通常ノイズ
gl_FragColor = vec4(vec3(
  gl_FragCoord.xy + vec2(time * 10.0)
), 1.);
// シームレスノイズ
gl_FragColor = vec4(vec3(
  gl_FragCoord.xy + vec2(time * 10.0), 256.
), 1.);

レイマーチング

カメラ

  • レイは 横方向 * 横位置 + 上方向 * 高位置 + 向き * フォーカス深度
    • 視野角を使用する場合は sin(視野角) * 横位置, sin(視野角) * 高位置, -cos(視野角)
float getFov(float angle){
  return angle * .5 * 3.14 / 180.;
}
// 位置
vec3 cPos = vec3(0. + (x * 2.), 0, 2. + (y * 2.));
// 向きと上方向
vec3 cDir = vec3(0, 0,-1), cUp  = vec3(0, 1, 0);
// 横方向
vec3 cSide = cross(cDir, cUp);
// フォーカス深度
float targetDepth = 1.0;
// レイ計算
// vec3 ray = normalize(cSide * P.x + cUp * P.y + cDir * targetDepth);
float fov = getFov(60.);
vec3 ray = normalize(vec3(sin(fov) * P.x, sin(fov) * P.y, -cos(fov)));

マーチング・ループ

// 法線算出
vec3 getNormal(vec3 p){
  float d = 0.0001;
  return normalize(vec3(
    distanceFunc(p + vec3(d, 0, 0)) - distanceFunc(p + vec3(-d, 0, 0)),
    distanceFunc(p + vec3(0, d, 0)) - distanceFunc(p + vec3(0, -d, 0)),
    distanceFunc(p + vec3(0, 0, d)) - distanceFunc(p + vec3(0, 0, -d))
  ));
}
vec3 ray, cPos, lightDir = vec3(-.577, .577, .577);

// レイとオブジェクト間の最短距離
float distanceResult = 0.;
// 初期のレイの長さ
float rayLength = 0.;
// レイの先端の位置 (cPos はカメラの向き)
vec3  rayPos = cPos;
for(int i = 0; i < 16; i++){
  distanceResult = distanceFunc(rPos);
  rayLength += distance;
  rayPos = cPos + ray * rayLength;
}
// 描画
if(abs(distance) < 0.001){
  // 判定あり
  vec3 normal = getNormal(rPos);
  float diff = clamp(dot(lightDir, normal), 0.1, 1.0);
  gl_FragColor = vec4(vec3(diff), 1.0);
}else{
  // 判定なし
  gl_FragColor = vec4(vec3(0.0), 1.0);
}

オブジェクト設定 distance function

球体

float distanceFunc(vec3 p){
  return length(p) - sphereSize;
}

大量複製

vec3 trans(vec3 p){
  return mod(p, 4.) - 2.;
}
  float distanceFunc(vec3 p){
-   return length(p) - sphereSize;
+   return length(trans(p)) - sphereSize;
  }

しおり

https://wgld.org/d/glsl/g013.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment