slang-shaders/procedural/dr2-droplet.slang
2018-02-24 02:20:43 +01:00

269 lines
6.2 KiB
Plaintext

#version 450
// Droplet - dr2 - 2015-09-17
// https://www.shadertoy.com/view/4l2Szm
// Probably liquid mercury (change viewpoint using the mouse).
// "Droplet" by dr2 - 2015
// License: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
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;
const float pi = 3.14159;
const vec4 cHashA4 = vec4 (0., 1., 57., 58.);
const vec3 cHashA3 = vec3 (1., 57., 113.);
const float cHashM = 43758.54;
vec4 Hashv4f (float p)
{
return fract (sin (p + cHashA4) * cHashM);
}
float Noisefv2 (vec2 p)
{
vec2 i = floor (p);
vec2 f = fract (p);
f = f * f * (3. - 2. * f);
vec4 t = Hashv4f (dot (i, cHashA3.xy));
return mix (mix (t.x, t.y, f.x), mix (t.z, t.w, f.x), f.y);
}
float Fbm2 (vec2 p)
{
float f, a;
f = 0.;
a = 1.;
for (int i = 0; i < 5; i ++) {
f += a * Noisefv2 (p);
a *= 0.5;
p *= 2.;
}
return f;
}
float Fbmn (vec3 p, vec3 n)
{
vec3 s;
float a;
s = vec3 (0.);
a = 1.;
for (int i = 0; i < 5; i ++) {
s += a * vec3 (Noisefv2 (p.yz), Noisefv2 (p.zx), Noisefv2 (p.xy));
a *= 0.5;
p *= 2.;
}
return dot (s, abs (n));
}
vec3 VaryNf (vec3 p, vec3 n, float f)
{
vec3 g;
float s;
vec3 e = vec3 (0.1, 0., 0.);
s = Fbmn (p, n);
g = vec3 (Fbmn (p + e.xyy, n) - s,
Fbmn (p + e.yxy, n) - s, Fbmn (p + e.yyx, n) - s);
return normalize (n + f * (g - n * dot (n, g)));
}
float Length4 (vec2 p)
{
p *= p;
p *= p;
return pow (p.x + p.y, 1. / 4.);
}
float Length6 (vec2 p)
{
p *= p * p;
p *= p;
return pow (p.x + p.y, 1. / 6.);
}
float PrSphDf (vec3 p, float s)
{
return length (p) - s;
}
float PrCylDf (vec3 p, float r, float h)
{
return max (length (p.xy) - r, abs (p.z) - h);
}
float PrTorus4Df (vec3 p, float ri, float rc)
{
return Length4 (vec2 (length (p.xz) - rc, p.y)) - ri;
}
vec3 sunDir;
float tCur;
int idObj;
const float dstFar = 100.;
const int idRing = 1, idWat = 2;
vec3 BgCol (vec3 ro, vec3 rd)
{
vec3 col;
float sd, f;
if (rd.y > 0.) {
col = vec3 (0.1, 0.2, 0.4) + 0.2 * pow (1. - max (rd.y, 0.), 8.);
sd = max (dot (rd, sunDir), 0.);
ro.xz += 2. * tCur;
f = Fbm2 (0.1 * (rd.xz * (50. - ro.y) / rd.y + ro.xz));
col += 0.35 * pow (sd, 6.) + 0.65 * min (pow (sd, 256.), 0.3);
col = mix (col, vec3 (1.), clamp (0.8 * f * rd.y + 0.1, 0., 1.));
} else {
f = Fbm2 (0.4 * (ro.xz - ro.y * rd.xz / rd.y));
col = mix ((1. + min (f, 1.)) * vec3 (0.05, 0.1, 0.05),
vec3 (0.1, 0.15, 0.25), pow (1. + rd.y, 5.));
}
return col;
}
float StoneRingDf (vec3 p, float r, float w, float n)
{
return Length6 (vec2 (length (p.xz) - r, p.y)) -
w * (0.2 * pow (abs (sin (atan (p.x, p.z) * n)), 0.25) + 0.8);
}
float ObjDf (vec3 p)
{
vec3 q;
float dMin, d, db, r, s, t;
bool up;
dMin = dstFar;
t = mod (tCur, 10.);
r = abs (sin (2. * pi * 0.1 * t));
q = p;
up = (t < 5.);
q.y -= up ? 2.5 : 0.55;
d = PrTorus4Df (q, 1., r);
q.y -= up ? -0.5 : 0.5;
d = max (PrCylDf (q.xzy, r, 0.5), - d);
if (up) d = max (d, q.y);
q.y -= up ? -0.75 : 0.2;
s = length (q.xz);
q.y -= 0.02 * cos (15. * s - 7. * tCur) * clamp (1. - s / 2.5, 0., 1.) *
clamp (s, 0., 1.);
db = PrCylDf (q.xzy, 2.5, 0.25);
d = up ? min (db, d) : max (db, - d);
if (d < dMin) { dMin = d; idObj = idWat; }
q = p;
s = 1. - sqrt (max (1. - r * r, 0.));
q.y -= 1.2 + (up ? s : - s);
d = PrSphDf (q, 0.3);
d = max (d, 1. - p.y);
if (d < dMin) { dMin = d; idObj = idWat; }
q = p;
q.y -= 1.3;
d = StoneRingDf (q, 2.8, 0.3, 16.);
if (d < dMin) { dMin = d; idObj = idRing; }
return dMin;
}
float ObjRay (vec3 ro, vec3 rd)
{
float dHit, d;
dHit = 0.;
for (int j = 0; j < 100; j ++) {
d = ObjDf (ro + dHit * rd);
dHit += d;
if (d < 0.001 || dHit > dstFar) break;
}
return dHit;
}
vec3 ObjNf (vec3 p)
{
vec4 v;
const vec3 e = vec3 (0.001, -0.001, 0.);
v = vec4 (ObjDf (p + e.xxx), ObjDf (p + e.xyy),
ObjDf (p + e.yxy), ObjDf (p + e.yyx));
return normalize (vec3 (v.x - v.y - v.z - v.w) + 2. * v.yzw);
}
vec3 ShowScene (vec3 ro, vec3 rd)
{
vec3 objCol, col, vn;
float dstHit, dif, bk;
int idObjT;
const int nRefl = 3;
for (int k = 0; k < nRefl; k ++) {
idObj = -1;
dstHit = ObjRay (ro, rd);
if (dstHit < dstFar && idObj == idWat) {
ro += rd * dstHit;
rd = reflect (rd, VaryNf (ro, ObjNf (ro), 0.1));
ro += 0.02 * rd;
} else break;
}
if (dstHit < dstFar) {
ro += rd * dstHit;
idObjT = idObj;
vn = ObjNf (ro);
idObj = idObjT;
if (idObj == idRing) {
objCol = vec3 (0.8, 0.6, 0.2);
vn = VaryNf (40. * ro, vn, 2.);
}
bk = max (dot (vn, sunDir * vec3 (-1., 1., -1.)), 0.);
dif = max (dot (vn, sunDir), 0.);
col = objCol * (0.1 + 0.1 * bk + 0.8 * dif +
0.3 * pow (max (0., dot (sunDir, reflect (rd, vn))), 64.));
} else col = BgCol (ro, rd);
return clamp (col, 0., 1.);
}
void mainImage (out vec4 fragColor, in vec2 fragCoord)
{
vec2 canvas = iResolution.xy;
vec2 uv = 2. * fragCoord.xy / canvas - 1.;
uv.x *= canvas.x / canvas.y;
tCur = iGlobalTime;
sunDir = normalize (vec3 (1., 1., 1.));
float el = 0.6;
#ifdef MOUSE
vec4 mPtr = iMouse;
mPtr.xy = mPtr.xy / canvas - 0.5;
if (mPtr.z > 0.) el = clamp (el - mPtr.y, 0.25, 0.8);
#endif
float cEl = cos (el);
float sEl = sin (el);
mat3 vuMat = mat3 (1., 0., 0., 0., cEl, - sEl, 0., sEl, cEl);
vec3 rd = normalize (vec3 (uv, 4.)) * vuMat;
vec3 ro = vec3 (0., 0.7, -10.) * vuMat;
fragColor = vec4 (ShowScene (ro, rd), 1.);
}
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);
}