Skip to content

Instantly share code, notes, and snippets.

@lmotp
Created June 9, 2023 00:42
Show Gist options
  • Save lmotp/bca1291a235437c4f5b16aef4655b99c to your computer and use it in GitHub Desktop.
Save lmotp/bca1291a235437c4f5b16aef4655b99c to your computer and use it in GitHub Desktop.
fBM noise GLSL
<canvas id="canvas"></canvas>
<script id="vert-shader" type="x-shader/x-vertex">
// gets the current position
attribute vec4 a_position;
void main() {
// returns the position
gl_Position = a_position;
}
</script>
<script id="frag-shader" type="x-shader/x-fragment">
precision highp float;
uniform vec2 u_resolution;
uniform float time;
uniform vec2 u_mouse;
float map(float value, float min1, float max1, float min2, float max2) {
return ((value - min1) / (max1 - min1)) * (max2 - min2) + min2;
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
float random (in vec2 _st) {
return fract(sin(dot(_st.xy,
vec2(12.9898,78.233)))*
43758.5453123);
}
// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 _st) {
vec2 i = floor(_st);
vec2 f = fract(_st);
// Four corners in 2D of a tile
float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
#define NUM_OCTAVES 5
float fbm ( in vec2 _st) {
float v = 0.0;
float a = 0.5;
vec2 shift = vec2(100.0);
// Rotate to reduce axial bias
mat2 rot = mat2(cos(0.5), sin(0.5),
-sin(0.5), cos(0.50));
for (int i = 0; i < NUM_OCTAVES; ++i) {
v += a * noise(_st);
_st = rot * _st * 2.0 + shift;
a *= 0.5;
}
return v;
}
void main( void ) {
vec2 st = gl_FragCoord.xy/u_resolution.y;
vec2 mouse = u_mouse.xy/u_resolution.y;
//st += st * abs(sin(time*0.1)*3.0);
vec3 color = vec3(0.0);
vec3 darker = vec3(45.0/255.0,107.0/255.0,55.0/255.0);
vec3 lighter = vec3(255.0/255.0,255.0/255.0,250.0/255.0);
vec2 q = vec2(0.);
q.x = fbm( st + 0.02*time);
q.y = fbm( st + vec2(1.0));
vec2 r = vec2(0.);
r.x = fbm( st + 10.0*q + vec2(1.0*mouse.x,9.2*mouse.y)+ 0.15*time );
r.y = fbm( st + 25.0*q + vec2(5.0*mouse.x,2.8*mouse.y)+ 0.126*time);
float f = fbm(st+r);
color = mix(darker,
lighter,
clamp((f*f)*4.0,1.0,1.0));
color = mix(color,
darker,
clamp(length(q),1.0,1.0));
color = mix(color,
lighter,
clamp(length(r.x),1.0,1.0));
vec4 rgb = vec4 (vec4((f*f*f+.6*f*f+.5)*color,1.));
gl_FragColor = rgb;
}
</script>
let canvas = null;
let gl = null;
let lastUpdate = null;
let timer = 0.0;
let time = null;
let mouseLocation = null;
let resolutionLocation = null;
let mouse = {
x:0,
y:0
}
let vertexShader = null;
let fragmentShader = null;
const stats = new Stats();
const initialize = () => {
// initializeStats();
initialize3DCanvas();
initializeResize();
initializeShaders();
initializeProgram();
initializeModel();
animate();
}
const initializeStats = () => {
stats.showPanel( 0 );
document.body.appendChild( stats.domElement );
}
const initialize3DCanvas = () => {
canvas = document.getElementById("canvas");
gl = canvas.getContext("webgl") || canvas.getContext('experimental-webgl');
if(gl)
{
gl.viewport(0,0,canvas.width,canvas.height);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearColor(1.0,1.0,1.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
}
}
const initializeModel = () => {
// create rectangle
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
-1.0, 1.0,
1.0, -1.0,
1.0, 1.0]),
gl.STATIC_DRAW);
// vertex data
const positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
// passing resolution to the shader
gl.uniform2f(resolutionLocation, window.innerWidth, window.innerHeight);
// gl.uniform2f(mouseLocation, mouse.x, mouse.y);
//init time
time = gl.getUniformLocation(program, "time");
mouseLocation = gl.getUniformLocation(program, "u_mouse");
resolutionLocation = gl.getUniformLocation(program, "u_resolution");
lastUpdate = new Date().getTime();
gl.uniform2f(resolutionLocation, window.innerWidth, window.innerHeight);
}
const createShader = (gl,source,type) => {
const shader = gl.createShader(type);
source = document.getElementById(source).text;
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}
const initializeShaders = () => {
vertexShader = createShader(gl, 'vert-shader', gl.VERTEX_SHADER);
fragmentShader = createShader(gl, 'frag-shader', gl.FRAGMENT_SHADER);
}
let program = null;
const initializeProgram = () => {
program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
if ( !gl.getProgramParameter( program, gl.LINK_STATUS) ) {
const info = gl.getProgramInfoLog(program);
throw "Could not compile WebGL program. \n\n" + info;
} else {
gl.useProgram(program);
}
}
const animate = () => {
stats.begin();
const currentTime = new Date().getTime();
const timeSinceLastUpdate = currentTime - lastUpdate;
lastUpdate = currentTime;
render(timeSinceLastUpdate);
stats.end();
window.requestAnimationFrame(animate);
}
const render = (timeDelta) => {
timer += (timeDelta ? timeDelta / 500 : 0.05);
gl.uniform1fv(time, [timer]);
//const
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
const initializeResize = () => {
const height = document.body.clientHeight;
const width = document.body.clientWidth;
canvas.width = width * window.devicePixelRatio;
canvas.height = height * window.devicePixelRatio;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
gl.viewport(0,0,canvas.width,canvas.height);
// gl.uniform2f(resolutionLocation, window.innerWidth, window.innerHeight);
}
window.onresize = () => {
initializeResize();
}
window.onmousemove = (e) => {
let x = e.x - (window.innerWidth/2)
let y = e.y - (window.innerHeight/2)
// TweenLite.to(mouse, 2, { ease: Power3.easeOut, x: Math.abs(x) });
// TweenLite.to(mouse, 2, { ease: Power3.easeOut, y: Math.abs(y) });
mouse.x = e.x
mouse.y = e.y
gl.uniform2f(mouseLocation, mouse.x, mouse.y);
}
initialize();
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
#canvas {
position: absolute;
width: 100%;
height: 100%;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment