UNPKG

solution

Version:

An animation library for different types of liquids.

84 lines (58 loc) 5.43 kB
import THREE from "three"; const fragment = "#define LAVA\n\n#include <common>\n#include <logdepthbuf_pars_fragment>\n#include <fog_pars_fragment>\n\nuniform sampler2D noiseMap;\n\nuniform float time;\nuniform float timeScale;\n\nuniform float primarySpeed;\nuniform float secondarySpeed;\nuniform float displacement;\nuniform float advection;\nuniform float intensity;\n\nuniform vec2 octaveScale;\nuniform vec3 lavaColor;\n\nuniform float direction;\n\n//varying float vViewTheta;\nvarying vec2 vUv;\n\nfloat noise3(vec2 n) {\n\n\tfloat x = n.x * n.y * 1000.0;\n\tx = mod(x, 13.0) * mod(x, 123.0);\n\tx = mod(x, 0.01);\n\n\treturn clamp(0.1 + x * 100.0, 0.0, 1.0);\n\n\t//return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);\n\n}\n\nmat2 makem2(float theta) {\n\n\tfloat c = cos(theta);\n\tfloat s = sin(theta);\n\n\tfloat a = mix(c, s, direction);\n\tfloat b = mix(s, c, direction);\n\n\t//return mat2(c, -s, s, c);\n\treturn mat2(a, -b, b, a);\n\n}\n\nfloat noise(vec2 x) {\n\n\treturn texture2D(noiseMap, x * 0.01).x;\n\n}\n\nvec2 gradn(vec2 p) {\n\n\tfloat ep = 0.09;\n\tfloat gradx = noise(vec2(p.x + ep, p.y)) - noise(vec2(p.x - ep, p.y));\n\tfloat grady = noise(vec2(p.x, p.y + ep)) - noise(vec2(p.x, p.y - ep));\n\n\treturn vec2(gradx, grady);\n\n}\n\nfloat flow(vec2 p) {\n\n\tfloat t = time * timeScale;\n\tfloat t1 = t * primarySpeed;\n\tfloat t2 = t * secondarySpeed;\n\n\tfloat z = 2.0;\n\tfloat rz = 0.0;\n\tvec2 bp = p;\n\n\tfor(float i = 1.0; i < 7.0; ++i) {\n\n\t\tp += t1;\n\t\tbp += t2;\n\n\t\t// Displacement field.\n\t\tvec2 gr = gradn(i * p * 0.34 + t * displacement);\n\n\t\t// Rotation of the displacement field.\n\t\tgr *= makem2(t * 6.0 - (0.05 * p.x + 0.03 * p.y) * 40.0);\n\n\t\t// Displace the system.\n\t\tp += gr * 0.5;\n\n\t\t// Add noise octave.\n\t\trz += (sin(noise(p) * 7.0) * 0.5 + 0.5) / z;\n\n\t\t// Blend.\n\t\tp = mix(bp, p, advection);\n\n\t\t// Intensity scaling.\n\t\tz *= intensity;\n\n\t\t// Octave scaling.\n\t\tp *= octaveScale.x;\n\t\tbp *= octaveScale.y;\n\n\t}\n\n\treturn rz;\n\n}\n\nvoid main() {\n\n\t#include <logdepthbuf_fragment>\n\n\tfloat rz = flow(vUv);\n\n\tvec3 color = lavaColor / rz;\n\tcolor = pow(abs(color), vec3(1.4));\n\n\tgl_FragColor = vec4(color, 1.0);\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 LAVA\n\n#include <common>\n#include <logdepthbuf_pars_vertex>\n\nuniform float scale;\n\n//varying float vViewTheta;\nvarying vec2 vUv;\n\nvoid main() {\n\n\tvec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\n\n\t//vViewTheta = clamp((normalize(cameraPosition - position).z + 1.0) * 0.5, 0.0, 1.0);\n\tvUv = uv * scale;\n\n\tgl_Position = projectionMatrix * mvPosition;\n\n\t#include <logdepthbuf_vertex>\n\n}\n"; /** * A noise-based flowing lava material. * * Original shader code by: https://www.shadertoy.com/user/nimitz * * @class LavaMaterial * @constructor * @extends ShaderMaterial * @param {Object} [options] - The options. * @param {Number} [options.timeScale=0.1] - The time scale. * @param {Number} [options.primarySpeed=0.6] - The primary flow speed. * @param {Number} [options.secondarySpeed=1.9] - The secondary flow speed (speed of the perceived flow). * @param {Number} [options.displacement=1.0] - A time multiplier for the displacement field. * @param {Number} [options.advection=0.77] - Blend factor (blending displaced system with base system). 0.5 ~ low, 0.95 ~ high. * @param {Number} [options.intensity=1.4] - Overall intensity. * @param {Vector2} [options.octaveScale=(2.0, 1.9)] - Used to scale the noise octave. * @param {Vector2} [options.scale=(3.0, 3.0)] - The overall scale of the lava. */ export class LavaMaterial 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 : 0.1}, primarySpeed: {type: "1f", value: (options.primarySpeed !== undefined) ? options.primarySpeed : 0.6}, secondarySpeed: {type: "1f", value: (options.secondarySpeed !== undefined) ? options.secondarySpeed : 1.9}, displacement: {type: "1f", value: (options.displacement !== undefined) ? options.displacement : 1.0}, advection: {type: "1f", value: (options.advection !== undefined) ? options.advection : 0.77}, intensity: {type: "1f", value: (options.intensity !== undefined) ? options.intensity : 1.4}, octaveScale: {type: "v2", value: (options.octaveScale !== undefined) ? options.octaveScale : new THREE.Vector2(2.0, 1.9)}, lavaColor: {type: "c", value: (options.color !== undefined) ? options.color : new THREE.Color(0.2, 0.07, 0.01)}, direction: {type: "1f", value: (options.direction !== undefined) ? options.direction : 0.0}, noiseMap: {type: "t", value: null}, scale: {type: "1f", value: 75.0} } ]), fragmentShader: fragment, vertexShader: vertex, fog: true }); } /** * A noise map. * * @property noiseMap * @type Texture */ get noiseMap() { return this.uniforms.noiseMap.value; } set noiseMap(x) { this.uniforms.noiseMap.value = x; } }