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 .);
白になる部分に乗算して使う。
色付けは基本、白黒を作ってから色を乗算し、条件に応じて分類する。
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 .);
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