slang-shaders/procedural/stellabialek-moonlight-sillyness.slang
2018-02-24 02:20:43 +01:00

327 lines
7.2 KiB
Plaintext

#version 450
// stellabialek - Moonlight Sillyness - 2018-02-22
// https://www.shadertoy.com/view/ld3czS
// having some fun
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
uint FrameCount;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
const vec2 madd = vec2(0.5, 0.5);
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = gl_Position.xy;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
float iGlobalTime = float(global.FrameCount)*0.025;
vec2 iResolution = global.OutputSize.xy;
#define CLOUDS_ON
const float STEPS = 120.0;
const float STEPSIZE = 0.05;
const float DRAWDIST = STEPS * STEPSIZE;
const float PI = 3.1415926535897932384626433832795;
const float TWOPI = 2.0 * PI;
const int OCTAVES = 3;
struct ray
{
vec3 o; //origin
vec3 d; //direction
};
vec3 calcCameraRayDir(float fov, vec2 fragCoord, vec2 resolution)
{
float fx = tan(radians(fov) / 2.0) / resolution.x;
vec2 d = fx * (fragCoord * 2.0 - resolution);
vec3 rayDir = normalize(vec3(d, 1.0));
return rayDir;
}
float hash(vec3 p)
{
p = fract( p*0.3183099 + .1 );
p *= 17.0;
return fract( p.x*p.y*p.z*(p.x+p.y+p.z) );
}
float rand(float seed)
{
return fract(sin(seed) * 1231534.9);
}
float rand(vec2 seed)
{
return rand(dot(seed, vec2(12.9898, 783.233)));
}
float noise( in vec3 x )
{
x *= 2.0;
vec3 p = floor(x);
vec3 f = fract(x);
f = f*f*(3.0-2.0*f);
return mix(mix(mix( hash(p+vec3(0,0,0)),
hash(p+vec3(1,0,0)),f.x),
mix( hash(p+vec3(0,1,0)),
hash(p+vec3(1,1,0)),f.x),f.y),
mix(mix( hash(p+vec3(0,0,1)),
hash(p+vec3(1,0,1)),f.x),
mix( hash(p+vec3(0,1,1)),
hash(p+vec3(1,1,1)),f.x),f.y),f.z);
}
float fbm(vec3 p)
{
p *= 1.4;
float f = 0.0;
float weight = 0.5;
for(int i = 0; i < OCTAVES; ++i)
{
f += weight * noise( p );
p.z -= iGlobalTime * float(i) * 0.5;
weight *= 0.5;
p *= 2.0;
}
return f;
}
float density(vec3 p)
{
p.y += 1.2;
p.y += cos(p.x*1.4) * 0.2;
p.y += cos(p.z)*0.1;
p *= 1.2;
p.z += iGlobalTime * 0.4;
float noise = fbm(p);
float clouds = noise*1.5 - p.y - 1.3;
return clamp(clouds, 0.0, 1.0);
}
vec3 clouds(vec3 p, float d, float l, vec3 bg)
{
vec3 lPos = vec3(0,0, DRAWDIST*1.75);
vec3 lDir = lPos - p;
float dL = density(p + normalize(lDir) * 0.2);
float dG = clamp(d - dL, 0.0, 1.0);
dG *= 1.0 - smoothstep(2.0,8.0, length(lDir));
dG *= 70.0;
vec3 cL = vec3(0, 0.1, 0.1) + vec3(1.0) * dG;
vec3 cA = mix( vec3(1.0, 1.0, 1.0), vec3(1.0)*0.01, d);
float a = 0.2;
float t = exp(-a * l);
return mix(bg, cL * cA, t);
}
float stars(vec2 uv, float amount, float radius)
{
uv = uv * amount;
vec2 gridID = floor(uv);
vec2 starPos = vec2(rand(gridID),rand(gridID+1.0));
starPos = (starPos - 0.5) * 2.0;
starPos = vec2(0.5) + starPos * (0.5 - radius * 2.0);
float stars = distance(fract(uv), starPos);
float size = rand(gridID)*radius;
stars = 1.0 - smoothstep(size, size + radius, stars);
return stars;
}
float gradient(vec2 uv)
{
uv.x *= 0.8;
uv *= 1.0 + sin(iGlobalTime*10.0) * 0.01;
float g = clamp(1.0 - length(uv), 0.0, 1.0);
return clamp(g, 0.0, 1.0);
}
float circle(vec2 uv, float r)
{
return length(uv)-r;
}
float smin(float a, float b, float k)
{
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
vec2 rotate(vec2 p, float angle)
{
mat2 mat = mat2(cos(angle),-sin(angle),
sin(angle),cos(angle));
return p * mat;
}
float timefunc(float scale, float k)
{
float var = sin(iGlobalTime * scale);
var = (var + 1.0)/2.0;
var = mix(var,smoothstep(0.0, 1.0, var),k);
var = (var - 0.5)*2.0;
return var;
}
float ghost1(vec2 uv)
{
float time = iGlobalTime * 6.0;
float t = timefunc(6.0, 0.5);
uv.x += 0.5;
uv = rotate(uv, t*max(0.0, uv.y)*0.2);
uv.y -= 0.4 + sin(time * 2.0) * 0.1 * smoothstep(-0.5, 1.5, uv.y);
vec2 originalUV = uv;
uv.x *= 1.0 + uv.y;
uv.y += max(0.0, -uv.y*0.8);
float body = circle(uv, 0.2);
uv = originalUV;
uv += vec2(-0.2, 0.2);
uv = rotate(uv, -PI/4.0 + t*0.8*uv.x);
uv *= vec2(0.4, 2.0);
float arms = circle(uv, 0.1);
uv = originalUV;
uv += vec2(0.2, 0.2);
uv = rotate(uv, PI/4.0 + t*0.8*(-uv.x));
uv *= vec2(0.4, 2.0);
arms = min(arms, circle(uv, 0.1));
uv = originalUV;
uv.x -= 0.01;
uv.y += 0.05;
uv.y *= 1.0 + cos(time*2.0)*0.4;
float mouth = circle(uv, 0.02);
uv = originalUV;
uv.x -= 0.11;
float eyeR = circle(uv, 0.02);
uv.x += 0.2;
float eyeL = circle(uv, 0.04);
float d = body;
d = smin(arms,body, 0.1);
d = max(d, -eyeR);
d = max(d, -eyeL);
d = max(d, -mouth);
float threshold = mix(0.04, 0.06, (0.5 +sin(iGlobalTime)*0.5));
d = 1.0 - smoothstep(-threshold, threshold, d);
return d;
}
float ghost2(vec2 uv)
{
uv.x -= 0.4;
uv.y += timefunc(6.0, 0.5)*0.2* smoothstep(-1.0, 0.0, uv.y);
vec2 originalUV = uv;
uv.x *= 1.0 + uv.y*0.4;
uv.y *= mix(0.0, 1.0, smoothstep(-0.1, 0.0, uv.y));
float body = circle(uv, 0.15);
uv = originalUV;
uv.x -= 0.06;
float eyeR = circle(uv, 0.03);
uv.x += 0.14;
float eyeL = circle(uv, 0.025);
float d = max(body,-eyeR);
d = max(d, -eyeL);
float threshold = mix(0.04, 0.06, (0.5 +sin(iGlobalTime)*0.5));
d = 1.0 - smoothstep(-threshold, threshold, d);
d *= 0.6;
return d;
}
float ghosts(vec2 uv)
{
float d = ghost1(uv) + ghost2(uv);
return clamp(d, 0.0, 1.0);
}
vec3 tonemapping(vec3 color, float exposure, float gamma)
{
color *= exposure/(1. + color / exposure);
color = pow(color, vec3(1. / gamma));
float lum = 0.3*color.r + 0.6*color.g + 0.1*color.b;
color = mix(color, color*color, 1.0 - smoothstep(0.0,0.4,lum));
return color;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 res = vec2(max(iResolution.x, iResolution.y));
vec2 uv = fragCoord.xy / res;
uv = (uv-vec2(0.5))*2.0;
uv.y += 0.5;
uv *= 1.3;
ray r;
r.o = vec3(0.0);
r.d = calcCameraRayDir(60.0, gl_FragCoord.xy, res);
float gradient = gradient(uv);
float moon = distance(uv, vec2(0.0,0.1));
moon = 1.0 - smoothstep(0.05, 0.08, moon);
vec3 bg = mix(vec3(0.0, 0.1, 0.1),vec3(0.1, 0.3, 0.5), min(1.0, gradient*2.0));
bg = mix(bg, vec3(0.6, 0.9, 1.0), (max(0.0, gradient - 0.5)) * 2.0);
bg += vec3(0.8) * moon;
bg += vec3(0.4) * stars(uv,5.0,0.01);
bg += vec3(0.4) * stars(uv, 100.0, 0.04);
bg += vec3(0.4) * ghosts(uv) * (uv.y+1.0)*0.5;
vec4 sum = vec4(0);
float t = 0.0;
#ifdef CLOUDS_ON
for(int i = 0; i < int(STEPS); i++)
{
vec3 p = r.o + r.d * t;
float d = density(p);
if(d > 0.01)
{
float a = d * (1.0 - smoothstep(DRAWDIST / 2.0, DRAWDIST, t))*0.4;
vec3 c = clouds(p, d, t, bg);
sum += vec4(c * a, a) * ( 1.0 - sum.a );
if(sum.a > 0.99) break;
}
t += STEPSIZE;
}
#endif
vec4 c;
c = vec4(bg, 1.0) * (1.0 - sum.a) + sum;
c.rgb = tonemapping(c.rgb, 1.5,1.2);
fragColor = c;
}
void main(void)
{
//just some shit to wrap shadertoy's stuff
vec2 FragmentCoord = vTexCoord.xy*global.OutputSize.xy;
FragmentCoord.y = -FragmentCoord.y;
mainImage(FragColor,FragmentCoord);
}