Check out a free preview of the full Advanced Creative Coding with WebGL & Shaders course
The "Basic GLSL Fragment Shader" 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:
Matt explains how a basic fragment shader is built to determine a single pixel, or fragment, across the surface of a face.
Transcript from the "Basic GLSL Fragment Shader" Lesson
[00:00:00]
>> Here's again another fragment shader and this one is just taking in the these two sliders here one of them is the color, which is a defined here as a hex code but in the shader, it has to be somehow turned into vec3. So when we use three js and we use color, we're using RGB which is between 0 and 1.
[00:00:22]
Well, it's the same thing here with color, so this is a 3D vector, which is between 0 and 1 for orange GNB and then we have opacity here. And so let's say we wanted to try and make the pixels of this quad a different color. So let's just try and edit it here.
[00:00:42]
The first thing we need to do is we need to use this gl_FragColor. This is the output of a fragment shader. The output is a vec4, so it's RGBA red, green, blue, alpha. And so we could just do vec4 is equal to some number. So now we have a FragColor that is 0.5 for all the components, for red, green, blue, and alpha.
[00:01:12]
So it's a bit semi-transparent because our alpha's 0.5, it's a bit gray because we're using 0.5. So maybe we wanna make it red. So we're gonna say inside, were gonna do 1.0, 0.0, 0.0 for the RGB and then pure opacity of one for the opacity. So now we've just made it red and if we were using properties from our JavaScript programs we would be using this thing called uniforms.
[00:01:43]
So uniform, this is a special type of property that we can't assign it a value here. So I can't just say, I want it to be right up here. You're gonna get an error. It's gonna say cannot initialize this type of qualifier. It's gonna say uniform can't be initialized, we can't initialize a uniform from the shader.
[00:02:03]
Instead, the uniforms are read only. They're coming in from the JavaScript somewhere. So the JavaScript is passing those down into the fragment shader and saying here's the value of color. But the the shader can't change this value. If you wanted to have a constant, you could say like const vec3.
[00:02:24]
MyColor = vec3, some values. So this is how you could do a constant but this value is not gonna change, right? And so we can't hook up like a slider to it, we can't hook up animations and stuff to it, it's always going to just be one. And so the purpose of uniforms is to get access of stuff from JavaScript.
[00:02:46]
So let's say from the dom, whether we're doing a slider, or maybe from something else, and to pass that information down to the fragment shader. And the reason it's called uniform is because because the value that we're getting is uniformly, the same across every single pixel in this fragment shader.
[00:03:03]
That's why it's called uniform. So it's not changing across the different pixels. So color let's say right now we have the color is set to this this red value here, which is 255420 or some similar value if we were to normalize that to 0 to 1. Well that color's not changing across the entire surface of this quad.
[00:03:22]
That's why it's called uniform. So uniform is one thing and then in vertex shaders, I'm just going back to mention this other thing. So we again see uniforms which means whenever you see uniforms just imagine is coming from JavaScript. So that stretch value is coming from JavaScript, and these sort of matrix transformations are coming from JavaScript as well.
[00:03:44]
And this is what's defining the camera and the way that the object is positioned as defining the way that the camera's actually projecting whether it's isometric or orthographic or perspective. So those things we don't really need to worry so much about what they mean other than the fact that they contain the data and they contain the information about how to transform this mesh.
[00:04:09]
But then there's this other thing that I haven't mentioned yet which is attribute. So attribute is different than uniform. It's not coming from like a slider or something like that, but it's actually coming from the vertex data that's contained in each of these vertices. So remember when I was talking before lunch about vertices and I'll just real quickly show you in this demo.
[00:04:40]
So let's say in the geometry demo or the buffer geometry demo we have these vector threes and each of these it's a position attribute so here we have a position attribute that's defining the Vertex positions. We could add other attributes like the colour, we could add texture coordinates, we could add random numbers if we wanted to create some random displacement in the geometry, and that's the attribute.
[00:05:09]
So it's coming from the actual geometry of the mesh that we're working with. And if we're doing buffer geometry, we can add in custom attributes. So you could have a new attribute that would say, myCord and it could be some vec3 or it could be a float or something like that.
[00:05:25]
You just have to declare it just in the way we've been declaring the position attribute in the buffer geometry example. Okay, one last little thing is to understand how shaders are different in three js, as opposed to in pure WebGL or pure OpenGL. So so far, these shader examples have been including a few things like precision highp float, and I've included a couple of uniform things like the transformations.
[00:05:54]
Well, when we write shaders in three js, we can simplify them a little bit. We don't specify precision highp float, we just go straight to the main function. And then we don't need to specify the transformation uniforms, we can just write our code. So this is a vertex shader now and it's a little bit simpler.
[00:06:13]
And this is the fragment shader. Once again no precision specifiers. So this is three js giving us some utility here, some convenience. Making it just a bit easier to right away start writing shaders, not having to worry about them. And so this code actually that you're seeing, you could copy and paste this into your scene that you have with the earth, and it would just create the same setup.
[00:06:37]
Because all of a sudden, we've created a shader material just by doing this these several lines of code here. We have the vertex shader as a string, we have the fragment shader as a string, and then we have the material which combines these two shaders, which says here's the vertex shader and here's the fragment shader, it's a shader material.
[00:06:56]
And then the third thing here is this idea of uniforms. I kept saying it's coming from JavaScript, and that's because this is where we define it. We define it in JavaScript as an object. And so if we wanted to say the opacity is 0.5 we can define this object here with the value, this is just this kind of weird syntax that three js enforces.
[00:07:18]
It's an object with value. And then now that we've defined it as a uniform, we can use that uniform in our fragment shader. And so I can start to use that maybe multiplying the color by opacity or something like that. And you'll see how changing the value in JavaScript in this JS object is gonna change the output.
[00:07:52]
And so really, you would actually want to use this opacity in the alpha component of a FragColor. But one thing you might notice is that if I use this. It looks pretty good actually. But sometimes what you'll need to do is, you'll need to also specify that your material is transparent by just saying transparent true.
[00:08:16]
It's just something to notice a bit of a gotcha is that in three js by default objects are opaque. And that's because it's a little bit more efficient to render opaque objects. But if you have an object that has some transparency, you're going to want to put in transparent true.
[00:08:32]
And there's one other thing I want to mention was this snippets, which is in the webgl glsl repo in the guides, or also in the links here. If you scroll down snippet using the workshop. So this kind of basic fragment and basic vertex shader, you can copy and paste this if you're forgetting what to write and you can use this as a base.
[00:08:57]
It includes the few things that I haven't talked about yet which we'll talk about later in the afternoon called varyings. But for now, you can just copy and paste it or you can copy and paste the ones from the guidebook that would also work.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops