<canvas id="glcanvas"></canvas>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec3 palette2(float t, float factor) {
vec3 a = vec3(0.5) + 0.3 * sin(vec3(0.1, 0.3, 0.5) * factor);
vec3 b = vec3(0.5) + 0.3 * cos(vec3(0.2, 0.4, 0.6) * factor);
vec3 c = vec3(1.0) + 0.5 * sin(vec3(0.3, 0.7, 0.9) * factor);
vec3 d = vec3(0.25, 0.4, 0.55) + 0.2 * cos(vec3(0.5, 0.6, 0.7) * factor);
return a + b * cos(6.28318 * (c * t + d));
}
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(mix(hash(i + vec2(0.0, 0.0)), hash(i + vec2(1.0, 0.0)), u.x),
mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x),
u.y);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 uv = (gl_FragCoord.xy * 2.0 - u_resolution.xy) / u_resolution.y;
uv.x = abs(uv.x);
//float breath = 1.0 + 2.0 * sin(u_time * 0.15) * smoothstep(0.2, 1.5, length(uv));
//uv *= breath;
uv *= 20.0;
for (int i = 0; i < 30; i++) {
float t = u_time * 0.01 - float(i);
uv *= mat2(cos(t), sin(t), -sin(t), cos(t));
uv += noise(sin(uv) * 0.6);
uv += noise(-cos(uv) * 0.6);
color += 0.002 / length(uv + sin(t));
float intensity = 0.1 / length(uv - (10.3) * sin(t)) * (length(uv) * sin(float(i) + u_time));
color += palette2(float(i) / u_time, u_time * 0.5) * intensity;
}
gl_FragColor = vec4(color, 1.0);
}
</script>
body {
height: 100vh;
margin: 0;
}
body,
html {
overflow: hidden;
}
const canvas = document.getElementById('glcanvas');
const gl = canvas.getContext('webgl');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function getShaderSource(id) {
return document.getElementById(id).textContent;
}
const vertexShaderSource = getShaderSource('vertex-shader');
const fragmentShaderSource = getShaderSource('fragment-shader');
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('An error occurred compiling the shaders:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function createProgram(gl, vertexShader, fragmentShader) {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Unable to initialize the shader program:', gl.getProgramInfoLog(program));
return null;
}
return program;
}
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
const program = createProgram(gl, vertexShader, fragmentShader);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.useProgram(program);
const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
const timeLocation = gl.getUniformLocation(program, 'u_time');
function render(time) {
const startOffset = 20.0;
gl.uniform2f(resolutionLocation, canvas.width, canvas.height);
gl.uniform1f(timeLocation, time * 0.001 + startOffset); // time in seconds + offset
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(render);
}
resize();
function resize() {
const devicePixelRatio = Math.min(window.devicePixelRatio || 1, 2);
canvas.width = Math.floor(window.innerWidth * devicePixelRatio);
canvas.height = Math.floor(window.innerHeight * devicePixelRatio);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
canvas.style.width = window.innerWidth + "px";
canvas.style.height = window.innerHeight + "px";
}
window.addEventListener('resize', resize);
requestAnimationFrame(render);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.