Advanced Creative Coding with WebGL & Shaders Custom Geometry
Transcript from the "Custom Geometry" Lesson
>> What we're gonna be now chatting a bit about, and I'll chat about it sort of through the context of glitch for these couple examples, is understanding a bit more about geometry and how these scenes are made up. Cuz eventually, we're gonna wanna get into to vertex shaders and fragment shaders.
[00:00:14] But before we can understand a vertex shader, we have to understand a little bit more about how the pipeline works and how vertices are declared. And so if we go into this 3 demo geometry, And we can just click show and show the output next to our code.
[00:00:34] And so the sort of framework of this sketch is very much just the same as our other demos. We've got perspective camera, orbit controls, we have grid helper here as well. And now we're getting into creating a custom geometry. And so this is a very simple, this is like the building block for everything we're gonna do today is a triangle.
[00:00:55] And so how would we do this? Maybe I'll edit this in a remix version so that I won't destroy or I won't mess up the original so I'm gonna just remix this project. So I'm gonna start by removing some of this stuff so that we can start from a sort of clean slate and sort of build this up again from scratch and walk it through.
[00:01:15] So let's say I wanted to draw something more interesting than just a sphere because right now we're just working with the built-in geometry. And so, we can't get very far with some of that, cuz we're just working with spheres or boxes. And we wanna start to understand, how do we actually manipulate these shapes and how do we eventually produce our own geometries?
[00:01:34] So the first thing we're gonna do is we're gonna say const geometry = new THREE.Geometry, and the geometry interface allows us to specify vertices, and faces an end up actually creating these shapes that are made up of triangles. And so remember, a quad is made up of two triangles.
[00:01:52] A sphere is made up of many, many triangles. And so in order to create, let's say a triangle, we're gonna have to first define a list of vertices which is an array. And each of these vertices is gonna be a vector THREE. And so we're gonna say maybe the triangle is going from -0.5 on the x and 0.5 on the y, and 0 and the z axis.
[00:02:22] And so quite often in WebGL, the y axis when we go up, it's actually positive, and when we go down it's negative. So, it's sort of inverted to what we are familiar with, with maybe 2D rendering or the screen itself, going up is actually positive quite often, going down is negative.
[00:02:42] And then, so that will be the first vertex. Another vertex will be, let's say if we think about this as the top left, maybe we can then place the bottom right so it'd be 0.5 along the x, -0.5 on the y and 0. And by the way, I usually don't memorize this stuff, and you probably will never really have to write this.
[00:03:10] I mean, you might have to write it occasionally, but this is not something that you need to really write very often. And so it's something that I always forget and I'm probably gonna make a mistake here, but this is more to show how it works under the hood.
[00:03:22] So that you understand a little bit more about how it all comes together, rather than something that you're actually gonna be using in your day to day. You're rarely gonna need to write triangles out manually. But it's good to know. So this third vertex of the triangle, let's say would be the bottom left triangle vertex.
[00:03:41] So that would be -0.5 on the x,and it would be -0.5 on the y, I think and then 0. And so we're not gonna see anything yet. And that's because we haven't defined the order of these verses. And so right now we have a set of vector threes, but geometry this geometry class also needs to know how do we connect the dots basically.
[00:04:09] So if we imagine these vertices on a piece of paper, just like we're doing a connected dots kind of game for kids. Now we want to start with one of the points, draw a line connected to the other one, and then draw a line connected to the other one, and eventually close that path to create a triangle.
[00:04:28] And so in order to do that we're gonna say geometry.faces. We're gonna specify a new face and so a face is a face three object. And face three is just a face that has three vertices that's kind of what it's saying or three indices. And we specify here the index into the vertex array, which is a bit of a complex idea.
[00:04:55] And already I seem to have made a mistake, which is classic with doing this kind of vertex stuff. It might be in the way I have placed these xyz coordinates, and this is just to show how little I actually write this manually. But I haven't created a mesh obviously.
[00:05:27] Well, this is probably correct so far, but I just haven't created a mesh. So I've got a geometry but I'm not wrapping it in a mesh, I'm not wrapping it with a material and I haven't added it to the scene. So I have to do those things. So now we've just created a geometry as a replacement maybe towards here I'm just gonna create a very simple mesh, THREE.Mesh geometry and I'll pass in here, maybe a mesh basic material.
[00:05:53] And maybe this will just be the color red or something like that. Almost there, haven't added to the scene yet. So, I'm gonna add that now. And now we have a red triangle. One of the things you might notice is as we spin around, we're gonna sort of lose the triangle.
[00:06:13] And this is an important thing with three JS and with webGL and just graphics programming in general is that generally speaking, only one side of a triangle is rendered. And that's for performance reasons. Because usually, when we have a sphere, we're only seeing the outside of the sphere.
[00:06:31] So we're only seeing one side of those triangles that defines the sphere, but in this case, we actually are seeing both sides, we wanna see both sides at least. And so in the material, we can say side is THREE.DoubleSides, so now it's a double-sided material, it will render both of these sides.
[00:06:48] The performance implications are very subtle. It's really only a big deal if you have hundreds of thousands of triangles. But this is why it's generally something that's default only on the outside because typically speaking, we're not rendering the inside faces. And so now we have this, we could also try different materials we could try mesh normal material.
[00:07:11] And all of a sudden, it's gonna be black. And you're gonna wonder, well, that's weird. It works for spheres, why does it not work for custom geometry? There's one other little thing we have to do, and that's we have to automatically compute all the normals, quote unquote for the mesh.
[00:07:29] So normals is this information that's held within each vertex that tells the system where the face, or the vertex itself, is pointing at, where it's in the world. That's kind of a simplified explanation of normals. We don't need to get too, too far into trying to wrap our heads around normals right now.
[00:07:49] But you will need to have this line that is compute vertex normals. And there's other types of normals as well. There's face normals and geometries interface. The class here allows us to compute face normals, but we don't need to worry too much about that right now. We just do compute for text normals.
[00:08:09] And now we've built a geometry that's just a single triangle. And if we wanted to turn this into a quad well we could take this and do the same thing to build up the opposite triangle, that would be placed right next to our acute triangle. We could have three more vertices so like, bottom left, top right, and then top left.
[00:08:31] And then together those things together would make up a quad. But instead of doing another three vertices, the whole point of doing faces is that we can reuse vertices to create a more complex shape. So I'm just gonna add one more vertex here and that's the remaining one to create our quad.
[00:08:51] So it should be 0.5, 0.5, which is the only other coordinate that I haven't really touched on. And then here, I'm gonna just try and figure out, okay, based on this, what are the indices into this array? So right now we're saying 0, 1, 2, so this is index 0, index 1, and index 2.
[00:09:11] That makes up the first triangle. The second triangle might be 0, 2, 3 or something like that and this is sort of where it gets a bit complicated. It's because you have to sorta think, okay, based on the coordinates, how do I draw these lines? So you might say 0, 2, 3.
[00:09:30] But this is, again, not something that you're gonna be doing on a regular basis. Or no it might be let's see, so we have the top left is 0. The one is the top, the bottom right, so we're gonna say from 0 to the top right. So it'd be 0, 3, 2, not even.
[00:09:55] So this is where it gets, [LAUGH] messy. Honestly, sometimes when I'm doing this, I will just choose randomly until it works. And it's worked for me so far. So, like that technique is sometimes acceptable, [LAUGH] and that works perfect. There's actually, once you put it down and think about this and you actually were to maybe sketch these vertices out on paper.
[00:10:20] You could actually get the correct numbers but, sometimes when I'm just hacking things together, I'll just hack it together. Because ultimately we are just trying to show something. But again, like I am saying we are not really doing this typically. More often we're just gonna use the 3 plane geometry, rather than actually defining things manually.
[00:10:40] And the nice thing is if we create a plane geometry and we subdivide it, then we can do plane geometry dot vertices, or plane geometry dot faces. And for example, if we had, let's say we had a grid, and we wanted to randomly take some of the faces out.
[00:10:55] We could just do geometry dot faces and then maybe faces is equal to some filter function, filter out some of those faces randomly. And all of a sudden we have a grid that has some randomly faces taken out of it.