Check out a free preview of the full Advanced Creative Coding with WebGL & Shaders course

The "Circular Mask Pattern" Lesson is part of the full, Advanced Creative Coding with WebGL & Shaders course featured in this preview video. Here's what you'd learn in this lesson:

Students are instructed to add a recursive circle mask pattern with animation to a shader within the box geometry.

Preview
Close

Transcript from the "Circular Mask Pattern" Lesson

[00:00:00]
>> The first thing you wanna try and do, and you might wanna actually copy and paste your whole file. You might want to just go into your folder on the desktop. You have a shader.js. You might wanna duplicate that, and leave this as a backup, because maybe what you're creating, you're gonna wanna come back to this cube at some point.

[00:00:17]
We're gonna change it, and we're gonna start to produce something more like this. What we're gonna do is we're gonna go back to our fragment shader. And the first thing we need to do is we need to define just 1 circle. Before we start to get a pattern of many circles, let's figure out how do we just draw 1 circle within this cube.

[00:00:42]
So remember, coordinates here. So I'm gonna clear this a little bit, just clean it up, make it a vec4. That's just taking in the texture coordinates, the x, and it's just taking this x value. And what we actually wanna do is we want to create a image that is gonna be, let's say, white for a circle, and then black outside of the edges of the circle.

[00:01:12]
And so in order to do that, we're gonna say, okay, for each pixel in this surface, what is the distance of that pixel to the center of this coordinate system that we have here, this little two-dimensional radiant? What is this current pixels value, the distance to the center?

[00:01:30]
And then based on that distance, if it's over a certain limit, let's make it black, or make it white. So we're gonna say we have a vec2 called center. And center is gonna be 0.5 0.5, because remember, our texture coordinates are going from 0 to 1. And so if we were to consider 0.5 0.5, that's gonna be the center of that two-dimensional space between 0 and 1.

[00:02:01]
And then we're gonna say what is the distance between the vUv and center? So distance is a built-in function, part of GLSL, and it gives us the distance between these two coordinates. So it's a Euclidean distance, That basically just gives us how far away 1 coordinate is from the other.

[00:02:31]
Now we have this float. We have float d. And so we can pass d in as our vec3 color, instead of using vUv.x. And we've kinda created something interesting, actually. We've created a gradient, a radial gradient that goes from the center outwards. And what's happening is we're saying what is the the current pixels coordinates?

[00:02:54]
So remember, this is getting run on every single pixel of this surface. And every pixel has a slightly different coordinate here as vUv. So it's saying, let's say for this current pixel here, what's the distance of this pixel to the center? And it's gonna say well, the distance is maybe somewhere between 0 1 is somewhere in the middle.

[00:03:13]
It's like a greyish 0.5 type of thing. The closer we get to the center, the more likely this value's gonna get down to 0. So at the very center point, if we say the distance from the very center point to the center the distance is gonna be 0, because it's right on the center.

[00:03:29]
And the further away we get from the center, the higher that value's gonna go towards 1. So now we just say let's make another thing called mask. It's gonna be masking whether it's inside or out. We're gonna say if d > 0.25, make it 1. Otherwise, make it 0.

[00:03:51]
It's just the ternary. And then we're gonna output mask by putting that into our FragColor. So it's pretty hard to conceptualize the whole current coordinate, current pixel thing, because this is probably not a paradigm you've ever had to think about, until you start start to work with shaders, but yeah.

[00:04:16]
Okay, so now we have this mask value, and all of the sudden, now we have, something that's giving us a circle on each side. Maybe we want it the other way around. So instead of it being a black circle and a white outside, we want it to be white on the inside, and black on the outside.

[00:04:32]
So we'll just do this. We'll just invert the mass. So we'll say mass = 1- mass. That will just invert the color, or invert the value. Okay, so we're pretty close to getting towards this, at least this simple version here, just some circles. We're not quite there yet.

[00:04:57]
But what we're gonna do is we're gonna use a modulo operator to multiply this coordinate to make it repeat. And so instead of using vUv, we're gonna create another vec2, call it pos, short for position. And we'll put pos inside of distance. So it's now the same thing, but now we're using pos, instead of vUv.

[00:05:28]
And here we're gonna use some sort of wraparound, some sort of modulo to make it so that we can repeat this by some sort of multiple. So we're gonna say mod vUv times, let's say 8, and then 1. So in JavaScript, we have, let's say a mod b.

[00:05:52]
So this is how it looks in JavaScript, is you just have 1 number, modulo, another number. Well, in GLSL, it's actually mod function, which is a built-in a and b, so that's why we have it like this. We have the first parameter, which is the a, the second parameter, which is the b.

[00:06:10]
We're saying modulo around 1. So what this is doing is saying multiply the vUv by 8. And so it goes from 0 to 1, and then we multiply it by 8, so it goes from 0 to 8. But then we wanna wrap it around, so that it's always actually within 0 to 1.

[00:06:26]
And that's what this module is doing. And what ends up happening is that we have many circles, depending on how many times we repeat it. So if we repeat it by twice, we have 2 and 2. And now the next thing we're gonna do is we're gonna do two things.

[00:06:49]
One, if we're gonna use a built in function instead of this thing. So this thing is a ternary, where we're saying if it's greater than some threshold, use 1. If it's less than or equal some threshold, use 0. But we can replace this with a built-in function called step.

[00:07:06]
In step, it takes in a threshold. So let's say this is the size of the circle, and then it takes in a distance value. And it will do the same thing as well we just wrotel. And we'll do it in a little bit more of an optimized way, because it's generally better to use these built-in functions in GLSL.

[00:07:26]
Because then it can take advantage of some of the hardware inside of our GPU for these specific operations. And so just by changing this 0.25, we're gonna change the size of the circles. So how about we try doing this? We're gonna try making it so that instead of all the circles being the same size, we're going to make them increase based on the vUv.x And so what I'm doing now is I'm saying the circles are gonna start at some value.

[00:08:05]
Let's say they start at 0.25, so this is this first number here. And then I'm gonna increase the circle size, or the threshold here that we're doing. I'm gonna increase that by vUv.x times 0.25. So if I didn't have this times 0.25, the circles would get really large very quickly.

[00:08:25]
So I'm just gonna scale that down, so that we're only increasing them gradually. But maybe instead of just increasing it like this, let's introduce some time. Let's introduce some animation. So I'm gonna say sine of time, + vUv.x times some value. This is now using time to modulate the size of these little circles.

[00:08:55]
Let's try increasing the the number here, just playing around with some of these values, maybe. That looks pretty cool, it's like a lava lamp. But just by changing these values, we can start to get some different and interesting results.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now