UNPKG

solution

Version:

An animation library for different types of liquids.

66 lines (46 loc) 5.41 kB
import THREE from "three"; const fragment = "#define WATERFALL\n\n#include <common>\n#include <logdepthbuf_pars_fragment>\n#include <fog_pars_fragment>\n\nuniform float time;\nuniform float timeScale;\n\nuniform float smoothness;\nuniform float fallAccel;\nuniform float spread;\nuniform float drops;\nuniform float shape;\nuniform float power;\nuniform float alpha;\nuniform float height;\nuniform float overflow;\nuniform vec2 scale;\nuniform vec2 strength;\nuniform vec3 tint;\n\nvarying vec2 vUv;\n\nconst float K1 = 0.366025404; // (sqrt(3) - 1) / 2\nconst float K2 = 0.211324865; // (3 - sqrt(3)) / 6\n\nvec2 hash(vec2 p) {\n\n\tp = vec2(\n\t\tdot(p, vec2(127.1, 311.7)),\n\t\tdot(p, vec2(269.5, 183.3))\n\t);\n\n\treturn -1.0 + 2.0 * fract(sin(p * smoothness) * 43758.5453123);\n\n}\n\nfloat noise(vec2 p) {\n\n\tvec2 i = floor(p + (p.x + p.y) * K1);\n\n\tvec2 a = p - i + (i.x + i.y) * K2;\n\tfloat z = clamp(ceil(a.x - a.y), 0.0, 1.0); // x > y = 1, else 0\n\tvec2 o = vec2(z, 1.0 - z);\n\tvec2 b = a - o + K2;\n\tvec2 c = a - 1.0 + 2.0 * K2;\n\n\tvec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0);\n\n\tvec3 n = h * h * h * h * vec3(\n\t\tdot(a, hash(i)),\n\t\tdot(b, hash(i + o)),\n\t\tdot(c, hash(i + 1.0))\n\t);\n\n\treturn dot(n, vec3(70.0));\n\n}\n\nfloat fbm(vec2 uv) {\n\n\tmat2 m = mat2(1.6, 1.2, -1.2, 1.6);\n\n\tfloat f = 0.5000 * noise(uv);\n\tuv = m * uv; f += 0.2500 * noise(uv);\n\tuv = m * uv; f += 0.1250 * noise(uv);\n\tuv = m * uv; f += 0.0625 * noise(uv);\n\n\treturn spread + 0.5 * f;\n\n}\n\nvoid main() {\n\n\t#include <logdepthbuf_fragment>\n\n\tvec2 q = -vec2(vUv);\n\n\tfloat t = time * timeScale;\n\n\tq.x *= scale.x;\n\tq.y *= scale.y;\n\n\tfloat T3 = max(3.0, 1.25 * strength.x) * t * 0.6 + pow(abs(q.y), fallAccel) * 2.0;\n\n\tfloat n = fbm(vec2(strength.x * q.x, strength.x * q.y) - vec2(0.0, T3));\n\n\tfloat T3B = max(3.0, 1.25 * strength.y) * t * 0.6 + pow(abs(q.y), fallAccel) * 2.0;\n\n\tn = n * 0.5 + (n * 0.5) / (0.001 + 1.5 * fbm(vec2(strength.y * q.x, strength.y * q.y) - vec2(0.0, T3B)));\n\n\tfloat intensity = abs(sin(t * overflow));\n\tn *= 1.0 + pow(intensity, 8.0) * 0.5;\n\n\tfloat c = 1.0 - (drops / abs(pow(q.y, 1.0) * 4.0 + 1.0)) * pow(max(0.0, length(q * vec2(1.8 + q.y * 1.5, 0.75)) - n * max(0.0, q.y + 0.25)), shape);\n\tfloat c1 = n * c * ((power + pow(intensity, height) * 0.9 - pow(intensity, 4.0) * 0.4) - pow(vUv.y, 2.0));\n\n\tc1 = c1 * 1.05 + sin(c1 * 3.4) * 0.4;\n\tc1 *= 0.95 - pow(q.y, 2.0);\n\tc1 = clamp(c1, 0.4, 1.0);\n\n\tfloat c4 = c1 * c1 * c1 * c1;\n\n\tvec3 color = vec3(\n\t\t(1.0 + tint.r) * c4,\n\t\t(1.0 + tint.g) * c4,\n\t\t(1.0 + tint.b) * c4 / c1\n\t);\n\n\tfloat a = c * (1.0 - pow(abs(vUv.y), alpha));\n\n\tgl_FragColor = vec4(color, a);\n\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\n}\n"; const vertex = "#define WATERFALL\n\n#include <common>\n#include <logdepthbuf_pars_vertex>\n\nuniform vec4 offsetRepeat;\n\nvarying vec2 vUv;\n\nvoid main() {\n\n\tvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n\n\t#include <logdepthbuf_vertex>\n\n}\n"; /** * A mod of xbe's "fire" that creates a fast, smooth falling water effect. * * Original shader code by: https://www.shadertoy.com/user/bbcollinsworth * * @class WaterfallMaterial * @constructor * @extends ShaderMaterial * @param {Object} [options] - The options. * @param {Number} [options.drops=16] - The sharpness of the water drops. The higher, the sharper. */ export class WaterfallMaterial extends THREE.ShaderMaterial { constructor(options) { if(options === undefined) { options = {}; } super({ uniforms: THREE.UniformsUtils.merge([ THREE.UniformsLib.fog, { time: {type: "1f", value: 0.0}, timeScale: {type: "1f", value: (options.timeScale !== undefined) ? options.timeScale : 1.0}, smoothness: {type: "1f", value: (options.smoothness !== undefined) ? options.smoothness : 0.0001}, fallAccel: {type: "1f", value: (options.fallAccel !== undefined) ? options.fallAccel : 1.25}, spread: {type: "1f", value: (options.spread !== undefined) ? options.spread : 0.6}, drops: {type: "1f", value: (options.drops !== undefined) ? options.drops : 16.0}, shape: {type: "1f", value: (options.shape !== undefined) ? options.shape : 1.2}, power: {type: "1f", value: (options.power !== undefined) ? options.power : 0.7}, alpha: {type: "1f", value: (options.alpha !== undefined) ? options.alpha : 10.0}, height: {type: "1f", value: (options.height !== undefined) ? options.height : 0.8}, overflow: {type: "1f", value: (options.overflow !== undefined) ? options.overflow : 0.2}, scale: {type: "v2", value: (options.scale !== undefined) ? options.scale : new THREE.Vector2(1.0, 1.0)}, strength: {type: "v2", value: (options.strength !== undefined) ? options.strength : new THREE.Vector2(6.0, 26.0)}, tint: {type: "c", value: (options.tint !== undefined) ? options.tint : new THREE.Color(0.25, 0.5, 0.5)}, offsetRepeat: {type: "v4", value: new THREE.Vector4(-0.5, -0.75, 1.0, 1.0)} } ]), fragmentShader: fragment, vertexShader: vertex, side: THREE.DoubleSide, transparent: true, fog: true }); } }