mirror of
https://github.com/libretro/slang-shaders.git
synced 2024-11-23 08:19:54 +00:00
327 lines
7.2 KiB
Plaintext
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);
|
|
}
|