WebGL Scroll Spiral
Today we want to show you some shader art made with WebGL. The idea is to create a decorative background effect by twisting images and hexagonal grid patterns smoothly on page scroll. The effect aims to be as light as possible on desktops or mobile devices.
Basic HTML / CSS structure
Let’s have a quick look at some HTML and CSS we need to define. We’ll use a fixed canvas element that we’ll size to be fullscreen:
<body>
<canvas id="webgl"></canvas>
...
</body>
canvas#webgl {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1;
}
The WebGL part
We’ll be using the regl library which is a light-weight WebGL wrapper. If you are getting started with WebGL, it’s a great way to begin writing your own shaders and custom graphical effects using this fast library that has a functional data-driven style inspired by React. If you want to get started with shaders, check out this article by Paul Lewis: An Introduction to Shaders.
Let’s have a look at the interesting parts of the code that we use throughout the demos.
GLSL
<script src="js/regl.min.js"></script>
<script type="x-shader/x-fragment" id="fragmentShader">
#define TWO_PI 6.2831853072
#define PI 3.14159265359
// On iOS, specifying highp works more smoothly.
precision highp float;
uniform float globaltime;
uniform vec2 resolution;
uniform float aspect;
uniform float scroll;
uniform float velocity;
...
</script>
Initialize regl from a canvas element
var canvas = document.querySelector('#webgl');
var regl = createREGL({
canvas: canvas,
onDone: function(error, regl) {
if (error) { alert(error); }
}
});
Create a regl draw command
var draw = regl({
// Fragment Shader
frag: document.querySelector('#fragmentShader').textContent,
// Vertex Shader
vert: 'attribute vec2 position;
void main() {
gl_Position = vec4(3.0 * position, 0.0, 1.0);
}',
attributes: { position: [ [-1, 0], [0, -1], [1, 1] ] },
count: 3,
uniforms: {
globaltime: regl.prop('globaltime'),
resolution: regl.prop('resolution'),
aspect: regl.prop('aspect'),
scroll: regl.prop('scroll'),
velocity: regl.prop('velocity')
}
});
Our fragment shader is the GLSL code in the script element #fragmentShader
.
Hooking in a per-frame callback function
The code that runs the regl processes for each frame of requestAnimationFrame is defined in the callback function. In addition, we also define variables that store the scroll status.
// Scroll variables
var scroll = 0.0, velocity = 0.0, lastScroll = 0.0;
regl.frame(function(ctx) {
// Resize a canvas element with the aspect ratio (100vw, 100vh)
var aspect = canvas.scrollWidth / canvas.scrollHeight;
canvas.width = 512 * aspect;
canvas.height = 512;
// Scroll amount (0.0 to 1.0)
scroll = window.pageYOffset / (document.documentElement.scrollHeight - window.innerHeight);
// Scroll velocity
velocity = velocity * 0.99 + (scroll - lastScroll);
lastScroll = scroll;
// Clear the draw buffer
regl.clear({ color: [0, 0, 0, 0] });
// Execute a REGL draw command
draw({
globaltime: ctx.time,
resolution: [ctx.viewportWidth, ctx.viewportHeight],
aspect: aspect,
scroll: scroll,
velocity: velocity
});
});
The important thing is that the size of the canvas is set smaller than the display size (100vw, 100vh). This will make the actual drawing size up to width
x height
, which improves speed.
Scroll state variables
We have created three variables for storing the scroll state: scroll
, velocity
and lastScroll
. scroll
contains the scroll position which is usually in the range of 0.0 to 1.0 (sometimes this value might fall out of range by operations such as swiping down).
The velocity
variable holds the scrolling taking the law of inertia into account. When scrolling down this will be a positive value and when scrolling up, it will be a negative value. The factor 0.99
means keeping the speed in the previous frame to 99%. The acceleration is calculated from the difference between scroll
and lastScroll
.
Hope you enjoy this WebGL experiment!
References and Credits
- Official regl website
- Images copyright by RuleByArt. Purchase on Creative Market: Flight and Surface Shapes
WebGL Scroll Spiral was written by Xoihazard and published on Codrops.
LEAVE A REPLY
You must be logged in to post a comment.