How to create a WebGL using Three.js, asscroll, and Midjourney AI

This simple WebGL demo utilizes the Three.js library to create a captivating waterline effect. It explores alternative mechanics for the native scroll bar, offering a unique and speculative approach.

Source Code

Table of Contents

Installing libraries

For this demo, we will be using the following libraries:

asscroll is used to create a custom scroll bar. It is a lightweight library that is easy to use and configure. Three.js will help us with adding a shader effect for the background and for the custom scroll bar.

Installing dependencies:

npm install @ashthornton/asscroll three

Adding custom scroll

The first step is to add the custom scroll bar. This is done by creating a new instance of asscroll and passing in the element that will be scrolled. In this case, we will be scrolling the entire page, so we will pass in the document.body  element.

export const asscroll = new ASScroll({ ease: 0.22, disableRaf: true, scroll barStyles: false, });

Note that we have disabled the requestAnimationFrame loop by setting the disableRaf option to true. This is because we will be using the Three.js requestAnimationFrame loop instead in index.webgl.js. That way, we can have more control over the animation and be sure that the custom scroll bar and the Three.js scene are in sync. We will also be using the ease option set to 0.22 to make the scroll animation smoother but not too smooth. Finally, we will be disabling the default scroll bar styles by setting the scroll barStyles option to false. This is because we will be creating our own custom scroll bar styles using WebGL.

Next, we need to add the custom scroll bar. This is done by calling the add() method on the asscroll instance. This method accepts an object of options. The only required option is the root property, which is the element that will be scrolled. In this case, we will pass in the document.body  element.

asscroll.add({ root: document.body });

You can find the source code for the custom scroll bar module here .

Creating the scene

Creating the scene for this project is similar to the typical Three.js setup. You can take a look at the code using this link .

Please note that I'm using a simple env module when creating the scene to get some of the environment variables like viewport resolution, viewport aspect ratio, etc.

Creating the background effect

The background effect is created using a shader. You can find the source code for the shader here .

The shader is applied to a plane geometry. The plane geometry is then added to the scene.

For the background texture I used a jpg image generated with Midjourney.

The shader is applied to a plane geometry. The plane geometry is then added to the scene.

Nothing too fancy, just a Perlin noise effect applied to the Three.js plane (Perlin noise is used very often in WebGL projects and 3D). The code of the fragment shader is here .

We are also increasing time for the noise by changing it via uniforms to the background material in the requestAnimationFrame loop in the main module index.webgl.js:

// index.webgl.js function animate() { requestAnimationFrame(animate); backgroundPlane.material.uniforms.u_time.value += 0.05; ... }

Creating the custom scroll bar effect

Now making the scrollbar effect is a bit more tricky. You can find the source code for the custom scroll bar effect in this file . I called it water.js because it looks like a waterline. The module contents is a trivial Plane and ShaderMaterial initialisation, all magic happens in the shader .

After taking a glance look at the shader you may notice that we are using a displacement texture.

// fragment.glsl float displacement = texture2D(u_displacementMap, vUv).r;

The displacement texture is a simple black and white image (also generated with Midjourney) that is used to displace the vertices of the plane geometry. We are passing it to the shader in water.js:

// water.js const uniforms = { // <..> other uniforms u_displacementMap: { type: 't', value: textureLoader.load('/images/water.jpg'), }, };

Now we can use the displacement in the shader to distort uv coordinates. That will enable a slight wave effect.

// fragment.glsl float displacement = texture2D(u_displacementMap, vUv).r; vec2 uv = gl_FragCoord.xy / u_resolution.xy; uv += displacement * 0.05;

Note that we only need to get one channel from the image (red in this example) in order the displacement take the effect, that's because the image is black and white. Displacement texture is an easy technique. You basically just need an image with a textured pattern you want to have for your animation.

Making the custom scroll bar draggable

asscroll scrollbar element is draggable by default. Let's just add cursor: grab; and cursor: grabbing; to its corresponding states.

// scrollbar.scss .asscrollbar { position: fixed; top: 0; right: 0; width: 3%; height: 100vh; &__handle { position: absolute; top: 0; left: 0; width: 100%; height: 100% !important; cursor: grab; transform: none !important; &:active { cursor: grabbing; } } }

Please also note the width is set to 3% to make it synced with the WebGL version. Also, I had to forcibly change some of the asscroll styles in order to make the scrollbar work wherever the user clicks within the scrollbar area and tries to drag.

Useful resources

Congratulations on completing this tutorial! Let's recap what we did:

  • Created a custom inertia scroll effect using asscroll .
  • Created a Three.js scene.
  • Added a shader effect to the background using Three.js.
  • Added a shader effect to the custom scroll bar.
  • Made the custom scroll bar draggable.

To continue your learning journey and enhance your skills, here are some valuable resources:

Bruno Simon's Three.js Journey Course

Bruno Simon's Three.js Journey is an in-depth online course that covers various aspects of Three.js, from basics to advanced techniques. The course provides practical examples and hands-on projects to help you become proficient in creating stunning 3D visuals for the web.

Three.js Examples

Explore the official Three.js examples collection. These examples demonstrate a wide range of Three.js features and concepts, serving as a valuable resource for learning and inspiration. You can dissect the code and modify the examples to suit your projects.

The Book of Shaders

The Book of Shaders is an excellent resource for gaining a deeper understanding of computer graphics and shaders. It covers fundamental concepts and provides interactive shader examples that you can experiment with directly in your browser. This knowledge can greatly enhance your ability to create custom visual effects.

asscroll Documentation

If you're interested in implementing smooth scroll animations, the asscroll documentation is a must-read. asscroll is a JavaScript library that enables advanced scroll animations with ease. By leveraging this library, you can add captivating scrolling effects to your Three.js projects.

Continue exploring, experimenting, and applying what you've learned to your own projects. The world of web 3D and interactive graphics is vast, so keep pushing your boundaries and honing your skills. Happy coding!