diff --git a/README.md b/README.md index 1d39d6f..ac2f97b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ GLSL shaders and projects for [SHADERed](https://github.com/dfranx/SHADERed). ## Gallery ![neon_pulse](/render/neon_pulse.gif) -![flame](/render/flame.gif) +![sdf_lavalamp](/render/sdf_lavalamp.gif) ![sun](/render/sun.gif) ![galaxy](/render/galaxy.gif) +![flame](/render/flame.gif) diff --git a/render/sdf_lavalamp.gif b/render/sdf_lavalamp.gif new file mode 100644 index 0000000..c46f0b7 Binary files /dev/null and b/render/sdf_lavalamp.gif differ diff --git a/sdf_lavalamp.sprj b/sdf_lavalamp.sprj new file mode 100644 index 0000000..854a970 --- /dev/null +++ b/sdf_lavalamp.sprj @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + Cube + 1 + 1 + 1 + 3 + TriangleList + + + + + + + + + + + + + + + + + + + 4 + 18 + 317 + 360 + + + + + + diff --git a/shaders/sdf_lavalamp_sdf_lavalampPS.glsl b/shaders/sdf_lavalamp_sdf_lavalampPS.glsl new file mode 100644 index 0000000..07dd975 --- /dev/null +++ b/shaders/sdf_lavalamp_sdf_lavalampPS.glsl @@ -0,0 +1,139 @@ +#version 330 + +uniform float uTime; +uniform vec3 vecCamPos; + +in vec3 vert_pos; + +out vec4 outColor; + +const int MAX_STEPS = 100; +const float MAX_DIST = 100.0; +const float SURF_DIST = 0.01; + +const int SHAPES = 6; +const float MAX_SPREAD_H = 0.1; +const float MAX_HEIGHT = 2.0; +const float RISE_SPEED = 0.4; +const float MIN_SPEED = 0.15; +const float LAVA_SMOOTHNESS = 0.5; + +const float HEIGHT_GRADIENT = 0.2; +const float RIM_GRADIENT = 0.6; + +// https://iquilezles.org/articles/palettes/ +// http://dev.thi.ng/gradients/ +vec3 palette(float t) { + vec3 a = vec3(0.500, 0.500, 0.000); + vec3 b = vec3(0.500, 0.500, 0.000); + vec3 c = vec3(0.100, 0.500, 0.000); + vec3 d = vec3(0.000, 0.000, 0.000); + + return a + b*cos(6.28318*(c*t+d)); +} + +float sdf_sphere(vec3 p, vec3 sp, float r) +{ + return length(sp - p) - r; +} + +float smooth_union(float d1, float d2, float k) +{ + float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0); + return mix(d2, d1, h) - k * h * (1.0 - h); +} + +float rand(vec2 co) +{ + return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453); +} + +float get_dist(vec3 p) +{ + float field = MAX_DIST; + + // random blobs + for (int i = 0; i < SHAPES; i++) + { + float seed1 = rand(vec2((i+1)*1.15)); + float seed2 = rand(vec2((i+1)*1.25)); + float seed3 = rand(vec2((i+1)*1.35)); + field = smooth_union( + field, + sdf_sphere( + p, + vec3( + (seed1 - 0.5) * MAX_SPREAD_H, + MAX_HEIGHT * sin(uTime * max(seed2, MIN_SPEED) * RISE_SPEED) - 0.5, + (seed3 - 0.5) * MAX_SPREAD_H + ), + 0.2 * (1.0 - pow(seed2, 4)) + ), + LAVA_SMOOTHNESS + ); + } + + // big blob at the bottom + field = smooth_union( + field, + sdf_sphere( + p, + vec3( + 0.0, + -MAX_HEIGHT, + 0.0 + ), + 0.8 + ), + LAVA_SMOOTHNESS + ); + + return field; +} + +vec3 get_normal(vec3 p) +{ + float d = get_dist(p); + vec2 e = vec2(0.01, 0.0); + vec3 norm = d - vec3( + get_dist(p - e.xyy), + get_dist(p - e.yxy), + get_dist(p - e.yyx) + ); + return normalize(norm); +} + +float ray_march(vec3 origin, vec3 direction) +{ + float d = 0.0; + for (int i = 0; i < MAX_STEPS; i++) + { + vec3 p = origin + direction * d; + float sd = get_dist(p); + d += sd; + if (d > MAX_DIST || sd < SURF_DIST) + { + break; + } + } + return d; +} + +void main() { + vec3 cam_dir = normalize(vert_pos - vecCamPos); + float d = ray_march(vecCamPos, cam_dir); + + float alpha = step(d, MAX_DIST); + + vec3 ray = vecCamPos + cam_dir * d; + vec3 n = get_normal(ray); + + // color gradient + float h = 1.0 - (ray.y * MAX_HEIGHT * HEIGHT_GRADIENT); + float f = dot(-cam_dir, n) * RIM_GRADIENT; + float g = f * h; + + vec3 col = palette(1.0 - g) * alpha; + + outColor = vec4(col, 1.0); +} \ No newline at end of file diff --git a/shaders/sdf_lavalamp_sdf_lavalampVS.glsl b/shaders/sdf_lavalamp_sdf_lavalampVS.glsl new file mode 100644 index 0000000..9dffeb5 --- /dev/null +++ b/shaders/sdf_lavalamp_sdf_lavalampVS.glsl @@ -0,0 +1,15 @@ +#version 330 + +uniform mat4 matVP; +uniform mat4 matGeo; + +layout (location = 0) in vec3 pos; +layout (location = 1) in vec3 normal; + +out vec3 vert_pos; + +void main() { + vec4 vert = (matGeo * vec4(pos, 1.0)); + vert_pos = vert.xyz; + gl_Position = matVP * vert; +}