180 lines
4.8 KiB
GLSL
180 lines
4.8 KiB
GLSL
#version 300 es
|
|
precision highp float;
|
|
|
|
const float CAM_FAR = 20.0;
|
|
const vec3 BACKGROUND = vec3(0.0, 0.0, 0.0);
|
|
|
|
uniform float time;
|
|
uniform vec2 resolution;
|
|
uniform bool layer_snow;
|
|
|
|
in vec4 vColor;
|
|
layout (location = 0) out vec4 fragColor;
|
|
|
|
vec3 artifactOffset;
|
|
mat3 artifactRotation;
|
|
vec3 artifactAxis;
|
|
vec3 camFwd;
|
|
vec3 camUp;
|
|
|
|
float rand(float n) {
|
|
return fract(sin(n) * 43758.5453);
|
|
}
|
|
|
|
float noise(float x) {
|
|
float i = floor(x);
|
|
float f = fract(x);
|
|
return mix(rand(i), rand(i + 1.0), f * f * (3.0 - 2.0 * f));
|
|
}
|
|
|
|
mat4 viewMatrix(vec3 dir, vec3 up) {
|
|
vec3 f = normalize(dir);
|
|
vec3 s = normalize(cross(f, up));
|
|
vec3 u = cross(s, f);
|
|
|
|
return mat4(
|
|
vec4(s, 0.0),
|
|
vec4(u, 0.0),
|
|
vec4(-f, 0.0),
|
|
vec4(0.0, 0.0, 0.0, 1.0)
|
|
);
|
|
}
|
|
|
|
mat3 rotationAlign(vec3 d, vec3 z) {
|
|
vec3 v = cross(z, d);
|
|
float c = dot(z, d);
|
|
float k = 1.0 / (1.0 + c);
|
|
|
|
float k_vx = v.x * k;
|
|
float k_vy = v.y * k;
|
|
float k_vz = v.z * k;
|
|
|
|
return mat3(
|
|
k_vx * v.x + c, k_vx * v.y - v.z, k_vx * v.z + v.y,
|
|
k_vy * v.x + v.z, k_vy * v.y + c, k_vy * v.z - v.x,
|
|
k_vz * v.x - v.y, k_vz * v.y + v.x, k_vz * v.z + c
|
|
);
|
|
}
|
|
|
|
float intersectPlane(vec3 origin, vec3 direction, vec3 point, vec3 normal) {
|
|
return clamp(dot(point - origin, normal) / dot(direction, normal), -1.0, 9991999.0);
|
|
}
|
|
|
|
vec3 calcRay(vec2 uv, float fov, float aspect) {
|
|
uv = uv * 2.0 - 1.0;
|
|
float d = 1.0 / tan(radians(fov) * 0.5);
|
|
return normalize(vec3(aspect * uv.x, uv.y, d));
|
|
}
|
|
|
|
float octahedron(vec3 p, float s) {
|
|
const float factor = 0.57735027;
|
|
p = abs(p);
|
|
return (p.x + p.y + p.z - s) * factor;
|
|
}
|
|
|
|
void artifact(vec3 p, inout float currDist, inout vec3 glowColor, inout int id) {
|
|
p -= artifactOffset;
|
|
p = artifactRotation * p;
|
|
float dist = octahedron(p, 0.8);
|
|
const float glowDist = 4.8;
|
|
if (dist < glowDist) {
|
|
float d = dist + rand(dist) * 1.7;
|
|
glowColor += vec3(0.75, 0.55, 0.45) * clamp(1.0 - pow((d * (1.0 / glowDist)), 5.0), 0.0, 1.0) * 0.035;
|
|
}
|
|
if (dist < currDist) {
|
|
currDist = dist;
|
|
id = 1;
|
|
}
|
|
}
|
|
|
|
float objects(vec3 p, inout vec3 glowColor, inout int objId) {
|
|
float dist = CAM_FAR;
|
|
artifact(p, dist, glowColor, objId);
|
|
return dist;
|
|
}
|
|
|
|
float artifactDist(vec3 p) {
|
|
p -= artifactOffset;
|
|
p = artifactRotation * p;
|
|
return octahedron(p, 1.2);
|
|
}
|
|
|
|
vec3 objectsNormal(vec3 p, float eps) {
|
|
vec2 h = vec2(eps, 0);
|
|
return normalize(vec3(artifactDist(p + h.xyy) - artifactDist(p - h.xyy), eps * 2.0, artifactDist(p + h.yyx) - artifactDist(p - h.yyx)));
|
|
}
|
|
|
|
vec3 objectsColor(int id, vec3 normal, vec3 ray) {
|
|
return id == 1 ? vec3(0.85, 0.65, 0.55) * mix(0.8, 1.5, dot(normal, normalize(vec3(0.0, 1.0, 0.5))) * 0.5 + 0.5) :
|
|
id == 2 ? vec3(0.85, 0.65, 0.55) * 1.5 :
|
|
vec3(1.0, 1.0, 0.0);
|
|
}
|
|
|
|
void marchObjects(vec3 eye, vec3 ray, float wDepth, inout vec4 color) {
|
|
float dist = 0.0;
|
|
int id;
|
|
vec3 rayPos = eye;
|
|
float depth = CAM_FAR;
|
|
for (int i = 0; i < 30; i++) {
|
|
dist = objects(rayPos, color.rgb, id);
|
|
depth = distance(rayPos, eye);
|
|
if (depth > wDepth || dist < 0.01) break;
|
|
rayPos += ray * dist;
|
|
}
|
|
color = dist < 0.01 ? vec4(objectsColor(id, objectsNormal(rayPos, 0.01), ray), depth) : color;
|
|
}
|
|
|
|
|
|
vec3 march(vec2 uv, vec3 camPos) {
|
|
mat4 vm = viewMatrix(camFwd, camUp);
|
|
vec3 ray = (vm * vec4(calcRay(uv, 80.0, resolution.x / resolution.y), 1.0)).xyz;
|
|
vec4 color = vec4(BACKGROUND, CAM_FAR);
|
|
marchObjects(camPos, ray, color.w, color);
|
|
return color.rgb;
|
|
}
|
|
|
|
float snow(vec2 uv, float scale) {
|
|
float w = smoothstep(1.0, 0.0, -uv.y * (scale * 0.01));
|
|
if (w < 0.1) return 0.0;
|
|
|
|
float timeScale = time / scale;
|
|
uv += vec2(timeScale, timeScale);
|
|
uv.x += sin(uv.y + time * 0.125) / scale;
|
|
uv *= scale;
|
|
|
|
vec2 s = floor(uv);
|
|
vec2 f = fract(uv);
|
|
|
|
float sinValueX = sin((s.x + scale) * 7.0) * 5.0;
|
|
float sinValueY = sin((s.y + scale) * 5.0) * 5.0;
|
|
float combinedSinValue = sinValueX + sinValueY;
|
|
|
|
float lengthValue = length(0.5 + 0.5 * sin(11.0 * fract(combinedSinValue)) - f);
|
|
|
|
return smoothstep(0.0, min(lengthValue, 3.0), sin(f.x + f.y) * 0.01) * w;
|
|
}
|
|
|
|
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
vec2 uv = fragCoord / resolution.xy;
|
|
float s = sin(time);
|
|
float c = cos(time);
|
|
|
|
artifactRotation = mat3(c, 0, s, 0, 1, 0, -s, 0, c) * rotationAlign(vec3(0.0, 1.0, 0.0), vec3(s * 0.2, 1.0, c * 0.2 + 0.3));
|
|
artifactOffset = vec3(s * 0.4, c * 0.3 - 1.7, -6.0);
|
|
|
|
camFwd = vec3(0.0, 0.7 + noise(time * 0.8 + 4.0) * 0.08 - 0.04, 1.0);
|
|
camUp = vec3(noise(time * 1.2) * 0.02 - 0.01, 1.0, 0.0);
|
|
|
|
fragColor = vec4(march(uv, vec3(0.0, 1.9, 1.0)) - (length(uv - 0.5) - 0.3) * 0.05, 1.0);
|
|
|
|
if (layer_snow) {
|
|
vec2 uvSnow = (fragCoord * 2.0 - resolution.xy) / min(resolution.x, resolution.y);
|
|
fragColor += vec4(vec3(snow(uvSnow, 4.0)), 0.5) * 0.7;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
fragColor = vColor;
|
|
mainImage(fragColor, gl_FragCoord.xy);
|
|
}
|