Intro to Graphics 08 - WebGL

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello hi everyone uh get your popcorns ready we're starting another lecture okay well thank you all for joining and uh tuning in i don't i don't even know what dirt to use for this thank you for for coming i guess to another introduction to computer graphics lecture all right so um last time if you'll remember we were talking about the gpu pipeline right so that was that was our thing last time and then you know we went through this this whole process and i would like to repeat that go over that again because we're going to complete this this whole thing today that's the plan for today so we said that our cpu application sits here and our cpu application uses a graphics api in our case it's going to be webgl but you know it could be a different api if we're using a different programming language because we're using javascript to write our cpu application that runs on a browser we're going to be using webgl as our graphics api and our graphics api will allow us to control the gpu for all sorts of rendering related stuff and this this involves quite a bit of uh setup right so we need to specify what scene we're rendering that is we created the buffers and put our vertices that define our triangles there and then we said that we're going to have a vertex shader and fragment shader we're going to write the programs related to that that will be running on those shaders and and then we're going to set their parameters these are the uniform variables over here and now we're going to initiate the whole rendering process and the gpu will take all this data and spit out an image that we would like to produce right so that's the that's the pipeline that's the simplified view of the pipeline as i see it i'm going to show you a slightly more complicated pipeline uh towards the end but this is i think this is a very good um this is my mental diagram of what's going on and that's what i would recommend that you you you have in your head when you're programming something on to run on the gpu okay so last time we started talking about webgl so let's let's uh briefly go over the stuff that we covered last time uh and now we're gonna add more more stuff to it so because we're using javascript we're gonna be using javascript graphics api that is webgl um so the first thing to do is to create a canvas because um our gpu is going to render an image what are we going to do with that image we're going to put it on what we need someplace to put it and on our web pages that's going to be the canvas right so that doesn't mean that you know canvas is just a html container right you can control it just like any other html container just like it it's the dev or whatever you you can hide it if you want you can put it wherever you want on the page it's completely under your control you can have multiple canvases too uh but yeah a canvas would look something like this and then when when we have a canvas we said i'll get this canvas whatever that was and and get context so this is creating a webgl context inside the canvas and we're getting this variable as our access to the webgl context context so it's just a variable name that i said i call it gl i didn't have to call it gl calling it gl so it kind of makes sense that that's what people typically do okay uh next thing to do would be to set the the output resolution if you don't set this you're just going to get the default whatever default resolution is it's it's a good idea to to set it and we set it to the the width and height of the canvas as it appeared on the web page we also said that you know if you have phone scaling then this width and height is not going to give you the actual pixel values on the screen if you want to get the actual pixel values you kind of need to multiply it by this device pixel ratio and that's what we did to get the actual with knight we set away the knight so that would be the the resolution that our gpu will render and the final thing to do here is that we set our viewport to cover that entire canvas so we talked about this when you're rendering an image on the gpu you don't have to render it to the entire canvas you can just render it to a part of it and actually you can render multiple times through multiple different places on on the cameras there are places where this is needed but most of the time we're going to render it to the entire camera so that's the most difficult thing to do so that's what we're doing zero zero is the bottom left corner and then the width and height let's specify where it is located anyhow before we did this we can also do some other kind of all sorts of initializations now uh it's a good idea to think about webgl and opengl also and you know many graphics apis the gpu in general as a state machine you set certain states and then you tell it to render it just uses that state to to do stuff so for example in this case i'm setting the background color to be white now this did not create an image that was white it didn't do anything actually it just said that my background color is going to be white and nothing else like 1 1 1 0 white with 0 alpha so that's invisible white as i call it so this means that this is the state that i'm saying so whenever i tell my gpu to just clear the screen it's going to use this background color to clean the screen all right so it's this compound itself is not doing anything other than the fact that it's just setting that state this is going to be useful only when i'm actually clearing the screen and we're going to get to that i'll i'll show you how to do it and when we call that command it's going to use this color to clear the screen right so it's very much like this so in this case i'm setting the the thickness of a line so when i'm drawing lines i'm saying that the line width is going to be this one pixel webgl actually implementations won't allow thicker than one pixel unfortunately but in opengl it's possible to have thicker lines anyhow if i'm drawing lines i'm saying that this is going to be the thickness of the line that i want on the screen one one pixel is going to be the thickness of the the lines i haven't drawn any lines yet i haven't done anything right um this is just setting that state maybe maybe in my application i'm going to be modifying things maybe sometimes i'm going to change the background color maybe sometimes i'm going to change the thickness of my lines and i can do that i can call these functions as many times as i want to to set the state to something else if i want to but a lot of times i you know this is the background color i want it's always going to be the same background color this is the thickness of the lines that i want it's always going to be the same thickness i said it once and then i'm down with them i don't ever call i have to call them ever again okay so a lot of these kind of things things that you're going to call only once and you won't have to modify again you would typically call these functions you will typically set that state right after you generate your canvas you generate your canvas and you set that state and then you don't have to worry about it again now some of these things will be the will have default values there's gonna be a default background clear color so if i don't set it uh it's just gonna use the default value whatever that is uh the line width i'm pretty sure it's it's one by default so this this function call is really not doing anything at all because the default value is already one and actually i'm not 100 sure that implementations support anything other than one here so never mind but yeah there are all sorts of things that you can you could set and and you can do it right here now this guy this guy is is a little bit different uh depending on how my web page is set up maybe i set my canvas such that the size of my canvas depends on the size of the window that's that's containing it right if i extend my vehicle if i make it larger my canvas grows in which case maybe i want to adjust the resolution again i want to change the resolution again so i might want to do this repeatedly as needed like i don't want to do it every time if it's not needed if i'm going to keep setting it to the same width and height i should probably do it once and stick with it but if the user is allowed to change the window size and i want to you know adjust things accordingly i might want to do that right so in a on resize callback instead of on load callback here i can have an own resize callback and on resize callback i can set these values another another thing here is that you know these opengl these webgl calls over here uh i can only do that after i create canvas obviously but because i am using this gl dots and like calling using this as an object and calling its functions right so this is sort of uh forcing me to to do this uh like you you first call this and get the get the context and then you're calling the functions and the very important thing here is that we can do this after our canvas is generated that is we need to call this an onload function inside an onload callback uh that that's very important so we don't want this we don't want this function to run as the browser is still loading our web page from from the web wherever where it's hosted okay moving on now that we initialized our webgl canvas and we set the output image resolution and all that stuff uh the next thing to do would be setting our scene putting data on the gpu memory that will be used for for rendering this this final image so what's that going to be it's going to be a certain set of primitives and these are the types of primitives that are supported by webgl um we can have points lines blind strip line loop uh triangles triangle strip and triangle fan but i'll i'll go over them a little bit later so let's say that we're dealing with triangles as our primitives so we're going to of course we're going to have the primitive type we're going to have the list of vertices and lists of our disease means and a number of attributes per vertex right so all these are possible vertex attributes and we said like let's use two to attributes as examples we said that we can have positions x y z x y z x y z or we can have colors uh what's important here is that the size of these two areas in terms of the the number of vertices they have to be the same but these are both 1d arrays one of them is containing this one is containing six times three elements this one is containing six times four elements so if you look at the size of these arrays this one is larger than that one right but conceptually they they actually contain the data for the same number of vertices and that's going to be important because you know index 0 will be associated with you know this color will be associated with this position and we're going to we're going to talk about how to set it up in a little bit but we first generate our data just like that in the previous slide we would generate our data on on the cpu memory so this is the position data for defining a rectangle that looks like this formed by two triangles and this is the color data that's associated by that and this is how we were allocating the buffer on the gpu memory and basically creating a what we call a vertex buffer object so this is create buffer creates a vertex buffer object now i'm assigning it to a variable that i'm going to be using later on and then i bind it after i find it i can set its data i can set its contents now there was a question about this last time the question was can we send said this multiple times yes we can do that we can i can change this data as many times as i want as many times as i need to and gpu will do the memory allocation sort of automatically for me i'm not allocate i'm not directly allocating memory on the gpu i'm just saying hey here's my data to store it on your memory somewhere and because this is a javascript array you know this function knows the size of this data so it's allocating enough size on the gpu memory and just dumping that data on the gpu so this is where the transfer from the cpu memory to gpu memory happens all right uh so this has created the buffer basically just uh created a an id for the buffer that's about it nothing else and then using that id i can bind it and then i can set its contents right so actually you can think of these two functions as like a single function because you know these two together saying change the contents of of this buffer right now this may look a little odd to you it is a little bit odd actually and in the sense that you know why do i need this function at all i could just take this variable and sort of stick it in here somewhere right this function could just take the id of the buffer so like why would i have to have two function calls here when i could do the same thing with one better design function call right well there are reasons for this sort of clunky looking structure my explanation to you would be you you bind the buffer and then you can do all sorts of operations related to that buffer and you don't have to set the entire contents of a buffer at once you might want to modify a part of that buffer that would be a different function called and then modify a different part of the buffer a different part of the buffer and you don't want to keep specifying the same buffer this just uh um historically it made sense i'm not exactly 100 sure that it totally makes sense today but it's you know it's uh that that's how it's structured because of that i believe now i am seeing a question here does webgl use event listeners for these things such as resizing uh no webgl has nothing to do with listening to anything all of that stuff will be handled by javascript right so javascript is going to get all the handles and then inside our javascripts we can use webgl functions to set all sorts of stuff about the gpu but webgl is not going to do anything automatically and this is actually very very good question because um for the other types of graphics apis for example when you use opengl what do you do you kind of need to get you know i'm running a c plus plus program i need to get keyboard data i need to get mouse data i need to get some some input from the user how do i do that opengl won't help you there either right so it's strictly graphics api but there are libraries built on top of opengl that will help you design that user interface relatively easily the nice thing about webgl is that it runs it's a javascript api and javascript runs on a browser so it's it's basically a user interface machine right so you have your html you have your css and you have javascript that controls all of that stuff so uh you can easily get user input you can easily adjust any of the other elements you can put a form in there all these functionalities of javascript are completely available to you but webgl is not going to get in the way it's strictly about controlling the gpu and not nothing else really all right so this is how i set the position data and put it all on the gpu memory uh and this is how i set the the color data same thing uh different variables uh and i put it on the gpu memory now i haven't done anything with it yet right all i did was i took that data from the cpu memory and dumped it in the gpu memory i didn't even tell webgl what that data was for i called it positions right it was my variable name i didn't tell opengl or webgl that it was supposed to represent the position of vertices or anything so webgl has absolutely no idea i just gave it some data and told it to put it on the gpu memory that's it but it's not sufficient at some point i'm gonna have to tell webgl what to do with it and that's gonna come on later right so i'm gonna tell you how to tell webgl what to do with that buffer later on all right but for now before we get there i would like to talk about the the shader programs so basically how do we write a vertex shader how do we write a simple fragment shader and how do we put it all together okay so let's talk about that ah our vertex shader uh gets the it's gonna get our scene made up somehow we're gonna talk about how how to do that so we'll get our scene data instead of applying some transformations to it uh it's going to send it to the rasterizer and the rasterizer will take that and actually do the rasterization operation that will generate the actual pixels and then it will call our fragment here so let's move them up here all right good so vertex shader and then rasterizer so vertices are sending vertex positions in the canonical view volume and the rasterizer will just rasterize it into an image like this and then our fragment shader is going to compute the colors of those fragments very good so let me show you what a vertex shader might look like so here is a glsl code graphics library shading language this is not javascript this is glsl it's a different language it's a specific language for writing gpu shaders and opengl uses the same language i believe you can use it in vulcan as well so this is uh you know that's the language to use for programming your gpu uh gpu shaders so this language has a uh its own syntax but it kind of looks like c c plus plus or java javascript now this is similar type of looking language it's going to have its own specific things so what's important to understand here the first thing is that this is not javascript you will have absolutely no access to your javascript code at all we're going to write this code separately and then we're going to tell webgl and here's our source code compile it all right and uh webgl is going to compile this code compile this glsl code all right so this is our glsr code that's the first important thing to understand and i'm going to in these slides to separate json code from the javascript code i'm going to put json code in that in these yellow containers and i'll put glsl sign over here so don't ever mix json code with javascript code okay so this this because this is vertex shader this is vertex shader code it's going to run one time for each vertex so if i have one triangle like here one triangle will have three vertices that means the same code is going to run three times one for each vertex and it's going to run with different parameters there's a question what's the difference between glsl and hlsl syntax i think there's some minor syntax differences hlsl is the shading language what's like a high level shading language i think that's what it is anyhow hlsl it's glso and there there are it's it's another language for writing shaders and it's hlsl is directx version of direct3d version of shading language and they're very very similar they look really really similar not not exactly the same though they have their own minor differences but you know if you know glsl you can fairly easily figure out how to write hsl code and vice versa so okay again first important thing is this is glc second important thing is that this is going to run once per vertex right so this is how we're getting the the gpu parallelism that everybody likes to talk about so we're writing a parallel code but writing parallel code becomes really easy because we're looking at one vertex at a time so that's what makes it really really easy right so let's see what this code is doing actually what this code is doing is that it's taking over here it's taking a position and color so these are going to be the attributes that it's getting now i call so dec3 is a glsl type that is a vector a three-dimensional vector back four is a four-dimensional vector so uh so this is going to get probably xyz values and the other one is going to get rgba values right and i call one of them pause the other one learn so what this is doing is that it's just taking that 3d positioned attribute and it's converting it into a vector four it's converting into a four dimensional vector by adding one over here so it's converting this into into homogeneous coordinates right we talked about homogeneous coordinates i'm pretty sure you all remember remember it now so we set the fourth coordinate to one and it's saying that this is going to be my output position so this gl position you see here is a special glsl was that variable this is an output output of my vertex shader so i'm not saying return this position instead of saying gl position is equal to this and gl position is what my rasterizer over here is going to get okay so that's that's very important so i'm sending this position to my rasterizer just like by setting this gl position value the way i did this is that i just converted my position x y z i just add one and so this is supposed to be this is supposed to be a position in the canonical view volume that's what's important this is supposed to be a position in the canonical v volume but well this means that for this code to work the positions that i'm getting here as attributes they're supposed to be in the canonical view volume right because if they're not this is this is not going to be the correct position all right that's not that's not very convenient so you know maybe i need a transformation maybe i need to take some some positions in some other space like in the world space or object space and i need to transform them into this canonical view volume by multiplying it by a matrix right we talked about this these transformations will be four by four matrix multiplications so uh let's do that ready i am going to add a matrix here this is going to be my transformation matrix and i'm going to multiply my vertex position by that matrix and this is how i'm transforming my positions in whatever space to the canonical e volume good so just simple matrix multiplication uh there's a question here let me answer that first will the elements within back three and back four always be floats yes back three and back four are floats glsl also supports vectors of integers i believe they're called ivec3 and ivec for ivec2 so integers are also possible okay so this is more like what i would like to do right i would like to transform my vertices to the canonical v-volume and i'm going to do that using this transformation matrix i call it transceiver it's a 4x4 matrix so i called it max 4 matrix 4. that's the that's the tightening now here's a funny thing here we're gonna we're gonna get back to this later on but there's a there's a funny thing here that i would like you to to notice if you haven't already these two guys they were called attributes this guy is not called an attribute it's called uniform oh these are different kind of animals these attributes will come from those vertex buffer objects remember we created those vertex buffer objects and we set their contents and we put them in the gpu memory they're going to come from there i'm going to talk about how how we're going to make that connection this is going to be a parameter of our vertex shader that we're going to have to set and this is called uniform because it's uniformly applied to all of my vertices so the same matrix is going to be used for transforming all of my vertices that's why it's called uniform okay i'm going to talk about how to set those in just a little bit but i would like to complete this pipeline first and then i'll tell you how to set these you know in a little bit all right so um another thing that you might have noticed here is that i got these nice two attributes right and i got this transformation matrix and i use the one of the attributes to transform and set my output like what am i doing with the other guy over here this is not used anywhere right all right well this is a color so maybe i'm going to use it to set the color but set the color what i i i'm not i'm not here yet right i'm not here yet i don't have any fragments so what do i do with this so what i need to do with this guy is that because it's color and i'm going to need it in my fragment shader i'm going to need it so what i'm going to do is i'm going to pass it to my fragment shader i'm going to send that guy to my fragment shader here's what how i'm going to do is i'm going to create a variable as a varying vector4 and i call it v color and i am just setting this attribute to that uh i'm just writing that attribute value to that varying variable and this is called the varying variable and uh there's a reason for that i'll get to that in a little bit but this is how we pass data from our vertex shaders to our fragment shaders because remember our vertices is what's going to get the data to get our scene data so if you want to send anything to our fragment shooter that that has to pass through our vertex here and this is how we're going to do that i'm going to send something here that's going to be used by my fragment shader all right so this is a complete vertex shader code that actually runs i'm going to show you an example that uses this very shader uh it's a relatively simple shader it's not doing much but you know it's not atypical it's doing what it's supposed to do that is the transformation moving along to the fragment shader here's a complete fragment shader code uh the first line here says you know use this precision for setting the the color values uh you know this is good enough but you know we sometimes yeah i keep saying that the output of our gpu rendering is going to be an image but there are different ways of interpreting that image there are different ways of using that image you don't have to it might be just you can interpret that image as some data and use it for all sorts of different purposes uh in that case maybe you need more precision but you know for for most of our applications it won't matter so yeah you can just use this and it's fine now the important bit here is this line over here remember the very same line appeared in our vertex here this is the varying vector for b color so this is how my compiler will know that whatever that vertex shader was outputting it's going to have to appear here right so that output is effectively passed onto my fragment shader and i got the the color and the fragment shader and this simple fragment shader what it's doing is that it's setting the output color to that color it's not really doing anything fancy here is just outputting that color value and this is gl flat color is the the output of my fragment shader it's again a glsl variable that i the fragment shader must set right and and then my gpu is gonna get that color value and it's gonna do whatever it needs to do to that it's gonna use it as the color of the fragment and then it's going to do maybe alpha blending or whatever else it needs to do to set the color of the pixel in the end okay so this is a complete fragment shader all right i mean this sounds reasonable right so i set the i set my vertex shader and i set the colors of my vertices and and then i got the color over here in the fragment shader but there's something a little bit confusing here isn't there [Music] i have three vertices they all have different color values i set those color values over here and my fragment shader got a color like which which one did my fragment shader get like if i have a triangle like this with three different color values and these are going to be my so this this is my triangle and these are going to be my fragments that the rasterizer is going to produce so which color values am i getting out of these three so what this is going to do and the reason why this is called varying is that my gpu will automatically interpolate these three color values and pick a color value pick a corresponding value over here for each one of these pixels for each one of those fragments it's going to give me an interpolated value for that vertex attribute and this is very just something very very typical we're going to keep doing this we're going to set values per vertex and in our fragment shader we're going to get the interpolated value so there's a way to get there's a way to disable that interpolation and only get one of the values in here but that's not important that's there are use cases where it could be useful but almost always where this is how we're going to pass data to our fragment shader uh we're going to have per vertex data we're going to have vertex attributes and as our vertex attributes pass through the rasterizer they're going to appear in our fragment shader as interpolated values okay so when i do that my triangle will looks like something like this right so there's going to be rbg values so r b g so we're going to get the interpolated color value at any point along this triangle now i haven't talked about how to do this interpolation mathematically for for for this part we don't have to go into the details of that we're going to talk about that that stuff later on yeah i'm going to talk about it later on but at this point surprise it's sufficient to know that gpu will automatically do this interpolation for me and the the color value that i'm going to get here is going to be the corresponding color value on whatever the the fragment is good all right so enough about vertex and fragment shaders details so let's put them all together so to be able to run something on the jeep to render anything on the gpu i need a vertical and a fragment shader together i can't have just one maybe two i need both of them to form what is called a webgl program so a webgl program is a combination of a birthday cheater and a fragment shader if you look at opengl which is a c plus plus api that will require having a vertical and a fragment shader but it will also allow additional shaders here in between a vertex shader and a rasterizer i could have a tessellation shader more specifically tessellation control shader tesolation evaluation shader and then i can have a geometry shader so i can i can have more complicated stuff here those are optional opengl will require that i have a vertex shooter and a fragment shooter webgl only has a vertex shader and a fragment shader and it will require both of them because you know it doesn't make any sense that you can't do anything if you don't have a vertex shader or a fragment here you need to have both all right so that's going to be a webgl program i'm going to the way i'm going to form a program is that i'm going to take my shader code shader glsl code and i'm going to compile it using these webgl commands so first over here i'm creating a shader this is going to be a vertex shader i'm saying this is vertex shader type and i created i called it vs short for vertex shader that's just my variable name and then i'm saying that this is my vs source is my vertex shader source now this is a a text for javascript it's just some um some string that string contains my vertex shader code right it's just um it's just some text this is a a string variable and by calling this function i said that hey this is my vertex shader code and when i say compile it's going to compile that vertex here code okay so again i'm stressing this again glsl is not javascript so all my gsl code is written here as some text and i give it to my i should i give it to webgl and webgl will give it to the driver and the driver is going to compile it when i say compile over here of course whenever you try to compile something you need to check if it did compile right so this is what's happening here uh we're checking if the compilation was was successful so this is how we do this we get the gl shader get shader parameter and this is the compile status if it returns a compile status and i can get this log and this is going to be the error message that my compiler spit out over here and you know it's you can show it to yourself using an alert like this or you can uh put it on the the console you can write it on the console it's log it on the console probably let me know on console is a better idea but you know this is simpler and more obvious so that that's what i did over here and of course if if it didn't compile i probably don't need that vertex figure anymore i might as well delete it but yeah it's not too terribly important because if it didn't compile that i probably have something wrong i'm going to fix my code and you know hopefully this part of the javascript will never ever execute but you know it's a good idea to have it in there just just to make sure that everything is working because if i have any compilation errors here that's not going to be a javascript error right my javascript did what it's supposed to do it just told webgl to compile that code that's it my javascript is done there's no javascript ever if my code didn't compile so you know i'm not going to get any error messages automatically right because there's no javascript error that happened even if my shader did not compile that's why i need to specifically ask for that and see if it did compile and this is very important because if you don't do that you you're going to try to use that vertex shader to do something and it's just not going to work right because you don't actually have a vertical it didn't compile it's a very very very good idea to have something like this now i'm stressing this point in any code that i give you there's gonna be something like this maybe not an alert maybe maybe it's gonna be logging on the console but there's gonna be something that will tell you that there's gonna be a javascript error and whenever you write it sort of not javascript gls compilation error and whenever you're writing code make sure to put something in in here otherwise you're gonna you're gonna waste countless hours chasing a javascript problem when you just have a syntax error in your jl cell code and just didn't compile very important oh yeah so there's a question about this what is this vs source that is just some string just some texts that that contains the source code of my vertex shader the source code i showed you a few slides earlier that's the that's imagine that as a text and i i just kept it inside this variable and i'm going to pass it to my compiler i'm going to show you the complete code and you'll see one way of getting this from html containers all right let's move on so this is uh how i compile my vertex shader and this is how i'm compiling my fragment shader pretty much the only thing changed here is that i call it fragment shader and i called it fs and that the rest is our it's its source is different otherwise it's uh it's the same thing and i compile it using pretty much the same commands and after i compile them then i need to link them so i created my program the program is going to contain a vertex shader and a fragment shader right so i'm going to say this is i'm going to attach my vertex trigger i'm going to attach my fragment shader and i'm going to say link yeah again this looks a little bit clunky this whole thing could be just one function maybe maybe just two functions create and then compile link everything together but there are ways there are reasons for for this actually this kind of makes the future extensions a bit easier but you know this is how it's not and of course when you link again you need to check if it did think because then you can have linker errors right and you could have something like this for example when you have a when you have a vertical passing a variable to a fragment shader when the but the fragmentator did not does not use it or actually that probably going to be a warning but maybe my fragment shader required something that the vertices didn't have it or when i tried i tried the link but i didn't attach a vertex shader that would be a link or error so again check this just to be just to be sure one thing i want to say here is that it's it's very nice that we're compiling these things at runtime actually because then your jsl code can be compiled by your graphics driver into the most optimal form for your specific gpu so this compilation is not necessarily going to produce the same exact binary for every gpu it may produce a different binary and you know it's going to be specifically optimized for the device that it's running on so that's that's something pretty good here all right so this is this is all we needed for for handling this this component i i generated the shader program by compiling my vertex shader and my fragment shader so what's next what's next is the head i'm gonna you remember i told you that i'm going to tell you how to set the uh these uniform parameters so let's do that now that i created my vertex shader and fragment shader i can set their variables so let's do it so remember we have this uniform matrix i would like to set its value i would like to initialize it to whatever value that i would i needed to be so here's how i'm going to do this i'm going to get the position of that variable i'm putting the variable's name i call the trends in my code so that that's what it is and program is that compiled program compiled and linked program and i'm getting this this i'm getting the location of this variable so the location is you can think of it as wherever the compiler decided to put that data it's just it's gonna basically it's gonna assign an id to it in this case i'm pretty sure it's gonna be zero because i don't have any other uniform variable in my code but it didn't have to be like you can't just assume that it's going to be necessarily zero i'm not i'm not sure that specification guarantees that it's always going to be going to start from zero so always do this get this and i'm i'm reasonably sure that this is going to just return zero that's going to be the id of my or the location of my variable and i call it m here so this is the matrix that i want to pass let's say into my my uniform variable and this is an identity matrix as you can see but it's written in the transpose form here so the actual matrix is transposed of that because remember we keep using column major order right so these are actually columns so these are rows that's all this and i am setting so i get the location of my uniform variable and then i'm going to set the location of my variable using this uniform matrix for a b and then this is my variable data i'm saying no this is not in transpose form even though it is it looks like transpose form here it's in column major form and here's my matrix before i did that now this is very very important i need to set which program i'm using because i may have multiple programs in my rendering so i don't have to use the same shader for all of my objects in my scene i can use different shaders for different objects so i can have different programs so whatever this this variable is that i'm trying to modify i need to tell all the webgl which program it is that i'm trying to modify here so it's this program it's this variable of that program and this is the the data that is supposed to get okay so there's a little bit of funny naming convention here let's let's go with that real quick so that function you saw was setting a matrix this is setting some xyz values uh so geo uniform is actually the name of that function this is my webgl context and this is the name of the function now three means it's three dimensions so it's going to have x y z values f means it's going to be float if i'm setting integers i would call it i and xyz are the values that i'm setting now if i want to pass it a an array of values instead of individual values separated by commas like this then i'm going to write my function name is going to be in this form i'm going to have an extra v here uniform 3 f v means it's you're going to get an array of values so in this case p is an array of x y z values right and i specified how many values to get from that that area this way so this is a naming convention used by opengl and webgl so here are some examples it could be uniform 3f 2i 2d in that case it's going to expect double all right so i think we're pretty much done so we set our scene data we add our shader programs we set our uniform variables finally we're ready to render your things yeah almost we have couple more things to do so the way that this this thing is going to work is that you know i'm going to pass my vertex attributes there's my scene data into my vertex shooter and then it's going to go through this pipeline and i'll get my image right so let's see let's see how this is going to all come together so starting with this starting from the very end over here so my output is going to be this color value right in the that's coming out of my fragment shader and my gpu is going to take that output color value and put it into onto whatever pixel that it's supposed to go to it's the job of my gpu to handle that if it must do some awful blending or whatever it's going to do all of that stuff i don't have to worry about it okay my gp is handling all this stuff now my rasterizer is setting everything it was actually my rasterizer is generating that fragment and also doing the interpolation to get this varying v color right and this is coming from here right so i sent that data from my vertex shader to my fragment shader all good and this this vertex shader is setting the position that is used by the rasterizer and it's also outputting the varying variable here the color and its uniform uniform parameter is coming from our cpu code as as we said it just just as i showed you a minute ago so the missing part here is starting these guys these attributes now we put them on our gpu memory somewhere right now we can't need to tell tell webgl how to connect these two things like how to take a vertex buffer object and sort of split it into individual vertices with positions and colors appearing over here so we're going to do that all right let's let's just look at that part so remember my positions were specified as just some array this is how i generate it in my cpu memory uh i'm not showing you the colors just just positions and then i created the buffer uh that bind the buffer and i put that data so this is how my data i put this data in my gpu memory that's all i did now before i can use that data i need to tell webgl what to do with it and here's here's how we're going to do that so over here the first thing i'm doing is that i'm getting the location of the attribute that i'm going to use so i'm going to take say that this position and and i'm going to sense where that position is going to come from so i'm going to get its location just like we did for uniform variables and i set it to my local variable p over here right the next one is that i did bind that buffer remember before we use a buffer we kind of need to bind it i did bind the buffer this was my position buffer that i created earlier that exists in my gpu memory that's how i'm accessing that vertex buffer object and then i'm here is here's the trick here's the important bit this is this is the information that webgl needs i am telling webgl that this p that is my position attribute is going to be a 3d vector of xyz values each one of them are going to be floating point values and they're going to start from the beginning of the the buffer so this this additional parameters here allow you to have more complicated structure types so i'm skipping that for the time being you can just keep them as false 0 0 but you know if you want to have more complicated buffer structures these values here are going to be useful the important bit here is to say that this is going to be p that is my position it's going to be a vector of 3 floats all right and that's going to come from this buffer that i just did bind okay and then the last thing i need to do is that i need to tell webgl to use that attribute i need to enable that attribute now there's a there's a reason for that because um there's any reason for specifically enabling it on and off because i'm let's say i have a number of objects in my scene different objects may need to have different sets of attributes my one object has three attributes the other one has five attributes i can need to enable those attributes or the gpu gets the data another thing is that maybe i for for some for for some operations even if i'm running the same data code maybe the shader code just ignores the color attribute so i don't need that color as you use in that case i don't have to enable this this color area so over here i work at the top here i set the position and down here i did exactly the same thing for the color buffer to set the the color attribute in this case color attribute was a vector for again float all right so i i did this and i enabled them now when i say render is going to get my gpus automatically start grabbing data from those buffers all right so that's how gpus will start getting data from my c so let's do it we're ready to render the image are you excited all right let's start first thing to do first thing to do first thing to do always always always clear the screen first clear the screen i'm gonna make the screen invisible white how because remember early on when i was doing my visualization i set the clear color to be invisible white white with zero alpha so here's where that particular initialization actually got used i clear the screen i clear the canvas and then i said i am going to use this program that i created just buying that program remember if i have multiple objects i can have multiple programs for drawing them they could be using different shaders so i need to specify which shaders i'm supposed to use for rendering this object that i'm about to draw all right so this is i'm about to use this so i clear the screen and then i said this is my program that i'll be using and then i say render this is right this is this is just one line it says all right go for it everything is ready go for it yes this means we're actually going to finally render something so this gl draw erase call means we're going to start rendering the triangles we're rendering triangles so this is the call that will initiate this this whole rendering process shown up here everything else we've done before that was just that initialization to be able to call this very function and this function says we're going to be drawing triangles starting from zero starting from the very beginning of our vertex buffer arrays of vertex buffer objects and we're going to be drawing six vertices uh each triangle has three vertices that means i'm going to be drawing two triangles right so this is this is just what it means all right so we clear the screen um this is where we bind or we say that we're going to be using this shader program and then with that shader program we're going to be drawing two triangles right this is what it means uh so we could be using other things as well it doesn't have to be just triangles we uh look at them before it could be a bunch of points it could be lines it could be line straps could be line loop or it could be um just uh just regular triangles like this or triangle strip and triangle fan we're going to talk about these a little bit later when we're discussing triangular meshes right so all of these things could be used with gl draw arrays that tells us tells the gpu how to interpret the data that is in the vertex buffer objects right so let's take a look at an example here's a very simple example in this case um this is a canvas i'm i just drew a border around it so you can see the canvas and inside this canvas we're just drawing a quad by drawing two triangles so these are actually the the two triangles that we're drawing and of course when you draw them like this they appear as a quad right and the code to do this is very very simple that's actually what we've been looking at um so this is the html code for it so it's like all this html initialization that the title and inside the html body i only have this one canvas and nothing else right that canvas is is this guy of course i'm gonna have a a bunch of stuff here inside the header to actually tell um the browser how to draw this right so there's gonna be some stuff in here so there are three scripts as you can see that's one two three scripts and also a style description this style description is just saying how to place this canvas and where to put it and there's going to be a border around it and and whatnot so all that stuff is defined by the style the actual stuff is going on inside these three scripts now the first two are going to be the shader code so let's take a look at them so the top one is our vertex shader it's um this is a vertex shader and the bottom one is a fragment shader now this is not the kind of script that our browser will be able to read and execute so the browser will actually just ignore this we are keeping this here so we can read the contents of these scripts and then and then compile them and then use them as our shader programs right the actual webgl stuff is coming in this third script right below so inside this third script and just as i showed you earlier we're starting with with this call saying hey this this function is going to run after the whole web page is loaded and we're going to have our webgl initialization here it's attached to that that canvas cam my canvas object and then there's going to be a whole bunch of stuff here to do the initialization and and rendering so let's take a look at them real quick so for the initialization setting my vertex positions and the colors and i'm putting them in the vertex buffer objects um after that i am now i'm getting i'm reading the data the contents of the vertex shader code and the fragment shader code and compiling them into a program after that i'm going to be setting the uniform variable remember we've been using the transformation matrix this trans so i'm going to get its position and i update its its value set its value that's going to be an identity matrix in this case because actually the vertex positions that i'm providing are in the canonical view volume so there's no need for doing any transformation but you know in general we will need a transformation that's why i included this in this example even though it's really not necessary if you're just multiplying by an identity matrix which does nothing right but anyhow so this is how you send the matrix to the vertex shader as an example and then over here we're specifying how we're going to be using the vertex buffer objects as our array so one of them is going to be the attribute zero the attribute one and they're set to these attributes and finally we're ready to do to start rendering we clear the screen we're clear the canvas and then we say hey we're going to be using this this program and finally we're saying yeah go for it and drove everything right and this whole thing basically will draw this well we'll clear clear the canvas with white and then draw these two triangles inside the canvas right and this is the html code for doing that so you can you can download this this html code the html page from the course web page there's a link to that and you can find it the square.html i believe so you can download it and take a look at it and then play with it if you want to all right so this completes our discussion of the gpu pipeline as i described it so this is my view of how i see the gpu rendering pipeline in the context of webgl and we talked about all of its components but you might see you might see some more complicated representations of this this very pipeline people like showing things like like this this is a little bit more detailed so here the api is the webgl our webgl so we're providing our information to the primitive processing right and it goes into our vertex shader and then there's primitive assembly and rasterizer then we send the rasterizer sends the fragments to the fragment shooter and after the fragment shaded a whole bunch of operations to put the colors in the final frame buffer right so this is a more detailed pipeline but conceptually it's pretty much the same thing i i prefer thinking about it in a bit more simpler terms that i showed you earlier right but if you see something like this um yeah don't be surprised this is this is a bit more more more detailed overview of what goes on um in between different stages all right so this completes our discussion of webgl i'm happy that you could stick around till the end we're going to be using webgl for all of our projects in this course so we're going to be talking about a little bit of webgl but in this completes our general discussion of webgl i'm going to dive into more specific topics starting with curves next time so i'm happy to see you all until next time stay safe bye you
Info
Channel: Cem Yuksel
Views: 2,462
Rating: undefined out of 5
Keywords:
Id: je_PhVKJYng
Channel Id: undefined
Length: 62min 6sec (3726 seconds)
Published: Wed Feb 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.