Projection Matrices in OpenGL

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up guys my name is a turn-on welcome back to my OpenGL series so last time we talked about mass and we started getting into maths and all the math like topics that will come in the future in this in this OpenGL series and in your graphics programming journey today and we're going to be specifically focusing on one small part of that which is projection projection is one of the biggest actual things that we need to solve when it comes to rendering graphics on the screen is part of the transformation pipeline which we will continue to explore over the coming weeks but today I just want to focus on projection and this is not gonna be a super long episode because I don't want to over complicate this for you and have you scratching your head we're not going to talk too much about the technical details and how the maths works because that is completely relevant for 99% of cases I know they're probably bunch of you interested in how it actually works so that you can kind of write your own version of OpenGL from scratch or something well we might cover that in the future but today practically speaking what is projection in OpenGL how does it work and why do we use it so to put it simply projection is just how we go from having some kind of arbitrary coordinate system in our 3d world or 2d world doesn't matter I mean 2d worlds are really 3d anyway as far and looking gel is concerned it's how we go from having coordinates or vertex positions in that space to being able to somehow map them to our window where we're actually rendering on our computer screen so we have to project them somehow onto this 2d surface you might have this massive 3d world with Hills and terrain and characters and all of that which in the end obviously just balls down to a bunch of triangles which are made up of vertex positions but in the end that 3d world has to somehow be rendered onto our 2d monitor and into our window that is what projection is it is essentially the maths that converts all of those 3d points in space into something that is in a 2d kind of window that is what projection is so forget everything you know about projection or whatever that's all it is it is as simple as that now what do I mean by convert into positions what does that even mean the actual transformation that happens with a projection matrix which we kind of talked about last time in math we we will touch on today as well is we just convert all of those positions that we have into something called normalized device coordinates which is basically some kind of normalized space that we can then map to our window now a normalized space means that literally a coordinate system between negative 1 and 1 in every access XY and Z right so what I'm saying is the picture that you have a window does not matter evolution does not matter at this rate doesn't matter what size your window is all that we know is that the left side of our window let's just say we render in full-screen so the left side will be negative 1 the right side will be positive 1 the bottom will be negative 1 and the top will be positive 1 let's not worry too much about Z at this point because that's not as important to visualize as x and y so that's it we have our computer monitor we have our window open where we're actually rendering all of our graphics and that is between negative 1 and 1 that is how we that that is the space that we need to have all of our bird expositions in so that we can actually start rasterizing stuff onto the screen however what we have is like this 3d world or maybe this 2d object somewhere on our screen and we need to convert it into that space that's what a projection matrix does and in fact up until really last episode we've just we have not been using a projection matrix which is why you probably heard me say that our space is between negative 1 and 1 and in other words when we actually made that churner logo in the textures video as an example we plotted that geometry like the vertex positions that we actually use there had to be between a negative 1 and 1 and I think I wrote something like negative zero point 5 to positive 0.5 or something like that because without a projection matrix we have nothing to can we don't have an actual matrix to convert our vertex positions into that normalized device coordinates space so we have to provide it initially because if we don't if we're gonna be well outside of that that coordinate space then we're not going to see anything on the screen because as far as the Spirit is concerned as far as what actually gets rendered on to our window that has to be between negative 1 and 1 it has to be but it's a bit difficult for us to deal with something that's just constantly negative one to one I mean as an example let's just say we're entering a square but our window is not square is 4 by 3 or it's 16 by 9 we can't just I mean we could theoretically do all the maps every time we calculate vertex positions and I just keep doing the maths every time so that we do get a square but wouldn't it be easier to just kind of be able to say okay well how about the left side of our screen maybe is 0 the right side of our screen is width so maybe my my window is 1280 by 720 so let's just say that the left side is 0 right side is 1280 now I can render anywhere in between there and then we'll worry about the maths of actually converting that into negative 1 to 1 later so that is essentially what a projection can do for you it lets you decide what your coordinate space is so that you can render objects however you like whether they be inside the space maybe they are outside of the screen because we're dealing with some kind of camera system that only shows the same partially that's a projection let's let's do all that and for 3d it's especially important because if you think about what a 3d scene looks like it's not just as simple as kind of converting your projection from negative 1 to 1 and like wall scaling it rather from a value from a large kind of value into negative 1 to 1 so as that example that I just gave from 0 to 1280 is my kind of projection matrix I'm scaling that down into something that is negative 1 to 1 that's might seem to you like oh that's easy you know just divide this by like 1280 and like multiply but 2 or whatever subtract 1 you know easy right done but if you think about it perspective projection which is what is typically used in a 3d world if you just take a photo of something and you take a look at objects objects that are further away actually become smaller they'd be smaller than the photograph right and you don't even have to take a photo if it is you look with your own eyes and you can see hard that you know I can bet you know Mountain over there is really is this big from here because of the way that perspective works because objects that are further away tend to look smaller that is also a an actual projection needs to be applied if you're dealing with a 3d scene and that's what a projection matrix can do it will essentially look at the Z value and say okay well objects with the larger Z value if you use a coordinate system whereas positive Z is like far those objects are those vertices with a lower with a higher Z value will actually end up being closer to the middle of the camera which essentially will just make them smaller so that's really important as well and when we get into 3d stuff you'll see how important a perspective projection is but anyway if we just take a look at this little PowerPoint slide that I prepared here we have two different main types of projection here we have orthographic projection and perspective projection so orthographic projection is usually used for 2d rendering now when I say usually keep in mind first of all while orthographic is usually used for 2d it's not always used for 2d it's totally fine to use orthographic it's for 3d that's actually done quite commonly because it presents a slightly different view that might be useful to something like a level editor or a 3d modeling program perspective is usually used for 3d but I mean everything is 3d anyway because there is the concept of Z so if you're thinking of a 2d platformer that might actually be using a perspective projection because there might be elements further away if you look at a game such as Rayman like the new Rayman games they have that concept of depth even though you can really only move on what is mostly kind of a 2d plane a 2d axis so don't take these as like okay respective 3d lots of opportunity not true it can be used in both cases but usually when we think of an orthographic projection we think of rendering something like UI or something maybe a 2d game or something like that whereas when we think that when we think of perspective we think of like a first-person shooter or something like that what we actually have a 3d world that we're rendering but that's not necessarily all they're used for anyway while we say we here with this orthographic projection is that objects that are further away are not actually they don't get smaller like they do with perspective you can see these cubes they look like they're further away because they're small and our eyes are used to that because that's how we see in the real world whereas these two cubes here they're the same distance I mean for all intents and purposes what you see in these two diagrams that I just literally made in five seconds in PowerPoint using the shapes thing anyway they're awful I know these things that are further away let they have the same vertex positions as these ones here it's just that these are using orthographic projection and these are using perspective projection because you know these cubes do have the same width the same height the same depth all of that right they just happen to be at a further Z value and the perspective projection maps that actually goes on when we multiply these vertices with our projection matrix that is what makes them smaller because they have a high Z value but at the end of the day every single vertex position of all of these cubes gets mapped into a space that is between negative 1 and 1 and that's what the normalized device coordinates are they're a space that are between kind of negative 1 and 1 anything that is outside of that so for example if I have a vertex that ends up being calculated to be negative 2 that does not get rendered it gets cold because it's outside of our actual view it's outside of our frosting now we're definitely going to talk more about you know these projections as we start to use them but let's take a look at them in our card base if I go back to my opengl code over here I have this projection matrix that I'm creating so what I'm doing here is I'm saying I have an orthographic projection between negative 2 & 2 in X and negative 1 point 5 and positive 1.5 in Y and then this is just the Z the neuron far so we're not going to worry too much about that for now anything that I render any vertex position these are my vertex positions any vertex position that lies outside of this these bounds will not appear because this is the leftmost expound this is the rightmost expound so if I was to adjust any of these x coordinates to be say negative 2.5 or positive 5 or positive 100 they're not actually going to render because that is my view that is all that I say and at the end of the day this orthographic projection when multiplied with these vertex positions is going to convert them to be in that negative one to one space so as an example since we have chosen negative two to two that means that zero is in fact the center the middle of our actual screen if I have a vertex of negative 0.5 you can tell that that's kind of from the middle it's a quarter of the way towards the leftmost bound because 0.5 is a quarter of two so since this orthographic matrix is going to convert this position to be between negative one and one then what is a quarter between zero and negative one is 0.25 so we can just tell just by eyeballing this because this this projection matrix is so simple that this will become 0.25 on our actual screen and if we do hit f5 it'll be a little bit hard to tell because I believe we are actually rendering a texture which is like partially transparent but yeah I'm just going to get rid of that if I go to my shader I'm just going to make it so that we output instead of outputting the texture color we're just gonna output white so just back for 1 and if we look at this now you can see that if you kind of eyeball this you know this is the center of the screen here and this this leftmost kind of edge that we have from our square is a quarter of the way to the left because it becomes 0.25 where this or negative 0.25 where this is negative 1 hopefully this math is kind of making sense to you I don't really want to dive in and start drawing diagrams or anything because it's not really that useful to know this in practice you just have to know that what the projection matrix does is it converts it into that normalized kind of device coordinate space of negative 1 to 1 that's really all this happening it's just a simple maths operation there's nothing too fancy about projection matrices if we go over here and what I'm actually going to do is in my application I'm going to instead of drawn into a 640 by 480 I want to convert this to be 960 by 540 now what I'm going to do now well let's just hit f5 and see what happens remember we still have the same projection so it still kind of looks the same I mean it looks stretched out because we've changed the resolution of our window but kept the projection mastery the same it's no longer our square is no longer a square it's kind of a rectangle if we go back to our orthographic projection let's play a little bit around with this so what I'm going to do is what I mentioned earlier in my example which is just changing it to be basically in pixel space so one to one pixel mapping so to do that I'm going to make a zero in my leftmost edge 960 my rightmost edge because that's the horizontal resolution I'm then going to make 0 in my bottom and 540 my top and I guess I will have to make this a flirt because this is a bit sad ok cool so let's hit f5 all right cool so we don't see anything at all and that would be because well I mean we do it's just hard to see because of course if we are in pixel space then this square is one by one pixel which is obviously one pixel which is time so what we can do is just boost this so I might just set this to be like ten point five instead of 0.5 I'll just add a one here just to keep it simple still and if we hit at five you can now kind of begin to see it but it's over here in the bottom left because what we've done of course is we've made the bottom the like our zero comma zero coordinate to be the bottom left of our window so if we scroll back up what I'm going to do is just rewrite this so I was just going to modify it but let's just rewrite it let's make this a hundred by what will will start at 100 by 100 and then I think we go anti-clockwise it kinda looks like we are going clockwise give me a second yeah okay cool so we'll just say a hundred by hundred then we go anti-clockwise to the right so we'll say 200 by still 100 and all this gear to this point five and then we'll say 200 again 4x and 100 here and then we'll become 200 200 okay so if we head up five now with these new coordinates that we have here we should see a square somewhere and yes we do and if I go back to my shader and I change this to be a to be our actual texture then you can see if we get this rendering here so what we've done here as you can see this really we've just played with the coordinate system a little bit we've changed our projection matrix to be between 0 and 9 64 X 0 and 544 Y so essentially we've changed we've changed to be per pixel based on that on the resolution of our window and then because of that we've had to adjust the positions of our geometry to actually be in that space or rather than be like negative 0.5 positive 0.5 we've actually had to change them to be something a bit bigger like 100 and 200 and all of that because now we've redefined what space we actually define out that expositions in but at the end of the day what happens is these vertex positions get multiplied with our matrix and that is what converts them back into being negative 0.5 by 0.5 let's take a look at another example so just to make this absolutely clear we have this 100 by 100 what I'm going to do is I'll keep my projection matrix but I'll make a GLM back for I'll call this DP vertex position and I'll just create a vet for here that has the coordinate 100 by 100 and then 0 1 okay so we don't have a set coordinate and for one and for W what it's going to specify one what I'm going to do then is type in jail and vet full result equals proj times VP so I'm actually doing that multiplication myself right here on the CPU just to see what the result is so that we can actually see now remember what I said what we're doing here is this projection matrix is supposed to take our coordinate our vertex position and convert it into a space that is between negative 1 and 1 so if I hit f5 and I take a look at this if we look at our actual projection matrix it looks a bit wild I mean it's like 0.02 whatever what I really need to look at that our vertex position is of course 100 100 zero and one if I could have ten here to do this calculation take a look at our result now it might be a little bit hard to see I'll really tell if it's worked a month but you can see that at the X&Y is that of course was always 0 w 0 man 1 but x and y have changed from being a hundred 100 to negative zero point seven nine and negative zero point six two if we go to so remember those two values zero point negative zero point seven nine and negative zero point six two if we look at this and we take a look at the bottom left most coordinate that kind of makes sense doesn't it like this if we were to change our mapping to not use a projection matrix anymore and we had negative one to one you can kind of imagine this as being around seventy percent of the way to there from the middle right so what it's done clearly is it has converted our 100 by 100 to be in that negative one to one space and that is what projection does in both 2d and 3d so in other words orthographic or perspective again nothing to do with to your 3d it's just what people commonly associated with so in perspective and orthographic projection doesn't matter the same thing happens all you're doing is you're telling your computer how to convert from whatever space you're currently dealing it with which is something that you define yourself to that negative one to one normalized device coordinates space and that is all there is to projection in OpenGL anyway I hope you guys enjoyed this video if you did you can hit the like button you can also help support the series by going over to patreon icon force at the channel let me know what you think of these kind of more technical videos on one hand I really like making them because I think that like people like me probably would be interested to I wish like someone explained it as simple as I hope waited here today when I was learning this kind of stuff but on the other hand I know that some of you probably want to see more things on the screen and one see more progress I want to get to the fun stuff so let me know what your thoughts are on this if you're ok with this if you want me to do more practical things and maybe come back and do the theory later but either way you're not supposed to is we're gonna badger Anakin for such the churner huge thank you to all the patrons who make these videos possible we're not here without you guys so thank you so much I will see you guys next time goodbye [Music]
Info
Channel: The Cherno
Views: 63,553
Rating: 4.9007635 out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, opengl, projection, matrices, projection matrices
Id: xZs6K7VLM7A
Channel Id: undefined
Length: 20min 9sec (1209 seconds)
Published: Wed Mar 07 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.