3D Programming Fundamentals [Pixel Shader] Tutorial 9

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everybody I'm chilly welcome back to 3d fundamentals tutorial 9 today I got a doozy for you because we are gonna be incorporating our first shader unit into our pipeline here and the one we're gonna start with is the pixel shader we're gonna start with the fun stuff pixel shader in my opinion is the most interesting shader to work with the most important shader to work with and the reason why is because it is the thing that determines the colors of all the pixels on the screen so it is the thing that ultimately determines your image now you might be wondering well surely I've heard a lot about this pixel shader but what is it anyways so let's take a look at our pipeline diagram here and specifically you want to look at the end of it so you've got the triangle rasterizer unit here and that corresponds to the draw triangle function in our pipeline class and it is being called from the perspective screen transformer which corresponds to post-process triangle so post-processed triangle processes the vertices then it passes that triangle on to draw triangle what draw triangle does is it scans over the entire triangle and screen space and calls put pixel with some determined colors now the the determination of the colors here is fixed right it is generally doing a texture lookup but I mean obviously that's not the only way that we want to draw triangles ever we want to draw triangles in a whole bunch of different ways so what we want to do is we want to make this color determination process here we want to make it configurable and the way we're gonna do that is in code we're gonna use basically a functor and templating but we'll get into that later but in general what we want to be doing here is we want to have a piece of code that we can plug in here and that code will determine the color of the pixel based on its input so turning our attention to the code here and in the pipeline you know you got post-process triangle vertices calls draw triangle draw triangle does calls a bunch of things and here is the ultimate drawer of the triangle draw flat triangle and here is where we are determining the color of the pixel so we basically want to replace this stuff here with a call to a shader object because if you think of the case of drawing a textured triangle with clamping as opposed to drawing out the wrapping or even drawing just a flat color the only part that really has to change is this all this stuff can remain the same and it'll work so we just need a way of being able to configure this part of our code so if we take a look at the commits here here I implemented the programmable pixel shader stage in the pipeline and I've added the first effect so let's take a look at how the pipeline changes when we add the the programmable pixel shader stage in there so first thing you know obviously I'm gonna change a little bit of comments here now it is saying drawing triangle pipeline with programmable pixel shading stage now the main thing here is we are now causing the pipeline to be a template class and we are templating it on an effect so now pipeline will be basically configured based on an effect class that we will define outside of the pipeline class and now instead of defining the single vertex class in the pipeline the vertex format is gonna change depending on what effect we're using different effects have different requirements textured effects require texture coordinates but untextured effects don't require those etc so instead of hard-coding the vertex type in the pipeline all we do is we type def effect vertex as vertex in the pipeline here so the the effect will define the type of vertex that it uses that's one that's the first part and then we just delete all of that vertex code now I'm also removing buying the texture because is specific to the pixel shader effect right some if an effect doesn't have a texture obviously buying texture is gonna make sense and the texture is going to be stored in the effect in the pixel shader not in the pipeline here so buying textures and making sense we delete that and then down here all the stuff is the same right and you would expect that because pixel shader only affects the rasterization at the very end of triangle drawing and here we go so before what we had here was we had texture lookup yeah clamping all that good stuff scaling by the screen dimensions or the texture dimensions I guess and we replace all that with just effect dot PS that's a pixel shading object and then we call the function operator on that object and we pass it the interpolated vertex data so we interpolate vertex data as normal and then we pass it to the pixel shader and the pixel shader will take that data and determine a color based on its input interpolated data it'll return that color and that is what we keep put on the screen so now the pipeline will have an effect object we removed that sir the texture from there but we now have an effect object and that the effect is gonna hold all of our shaders right now we only have pixel shader but later on we're gonna have other kinds of shaders and they are all going to be embedded in the effect so the effect object contains a bunch of shader objects and the shader objects are all just basically functors so let's take a look at an effect class shall we the first one is a texture effect that's what we're creating and here is the vertex which is the same vertex we had before and the pipeline just has a position and texture but now we are defining it in our texture effect class and here we have the pixel shader class this is the func tor it has obviously it has its function operator this is what is going to be you called - I do the actual shading and it does the texture look up just like we before there's no change there we also got the bind texture function and all that does is it loads a texture and then it just calculates or it stores the width the height and the clamping that is used in here to do the texture clamping so we store that we only calculate it once when we're loading the texture and then we just refer to it as member variables and of course we got the unique pointer for our texture here and that is the pixel shader class and then in the texture effect we just embed a pixel shader object pixel shader doesn't have a constructor or it just only has the default constructor so we don't have to do any construction shenanigans for effect all we do is we embed the pixel shader and is created when the effect is created and that's it it's that it's that goddamn simple and by the magic of templates we can just put this in our pipeline and it works put this in your pipe and smoke it my friends so how do we put it all together well let's take a look at the new and improved cube skins scene I can never see that correctly so we add a new type def we are type defining pipeline which is templated on texture effect as just pipeline and then we type define pipeline vertex as vertex so I like to use these type depths it makes my code a little sexier here and the main change here is going to be instead of calling pipeline bind texture with a file name we call pipeline dot effect pixel shader that bind texture so we bind a texture to the pixel shader so yeah it's all it's all the same after that this is really the only change we had to make in order to use our texture effect in the pipeline and if you run that you see that it is the same as before nothing changed still runs pretty much exactly the same only now our is configurable so let's take advantage of our configurable let's make another effect so the next effect I added and I'll just hit tab here is the color blend effect so here we give each vertex its own color and as we are drawing a triangle we blend between the colors of different vertices and this is what you get color blend effect from vertices and this is implemented in the pixel shader so how do we do that so to start off let's take a look at vertex color effect because that is where all the actions happening this is where it is determined how the effect works so again we define a vertex this vertex is going to be different than the vertex for the texture effect because now we're not gonna have a texture so I'm not gonna have texture coordinates but we are gonna have a color per vertex so we're gonna have a color member now you might be noticing Soniyo to say in chile this is weird it says color but it's a Veck 3 what what's up this effect here is gonna be blending colors between vertices so it has to interpolate the color member now interpolation doesn't really work too well for intz it's much easier to do interpolation math with floating point values so we're gonna encode our vertex colors as floating point because remember a color is just a collection of three numbers red green and blue right doesn't matter whether those numbers are unsigned car or whether they're int or whether they're float or double no it actually doesn't matter at all so we encode this as a vector E and the way I'm gonna encode it is basically same as for normal color 255 is full channel zero is none of that channel so 255 255 255 is white zero zero zero is black this is a little different I mean in hardware in hardware generally color is also dealt with as floating-point numbers that's one of the first things you realize when you start doing you know shaders in direct3d color is float until the very end when it is converted out into int and are drawn to the surface so that's the same but in hardware generally color is normalized so one is full zero is nothing but here we're using 255 because that makes it easier to convert so yeah that is a vertex type and the pixel shader itself couldn't be simpler because all we're doing is we're taking the interpolated input vertex and we are converting that to an integer color and the way the reason why we can do this is because in colors H here I include vector E and I've added a couple of conversion operators so converting constructor and a conversion operator to convert from color to Veck 3 and from Veck 3 to color and this is just gonna make our life easier a little a little bit of syntactic sugar there I mean yeah that's the whole effect cuz this pixel shader doesn't have any doesn't have any texture or anything doesn't need any bind function doesn't need any member variables no constructor just a very simple functor gets the job done now I made a little change to pipeline there shouldn't normally be need to be a change but it must have had to fix something and what I had to fix was before what we were doing was when we transform the vertices to create the output stream we were transforming applying the transformation to the position and just copying the the texture member but here off here as you notice we don't have a texture member anymore so depending on the effect some effects aren't gonna have a member T so this code is bad what we want to do is we want to touch the the position this is really pissing me off we want to transform the position but leave the rest of the vertex alone and the way we do that is we use a constructor of the vertex that allows us to set the position and it will copy the rest of the vertex members as they are and this allows the this allows this module to only touch the position and not have to know anything about the rest of the members so that constructor is here it takes position and it takes a vertex which is the source from which you copy all of the other members so here we set the position from the past in position but we set the color from the copy source color and it is that construe that allows this code to work without having to know what the other members are because remember we're passing in template this code doesn't exactly know what members vertices has read it doesn't know what members it has it only knows it only assumes that has a position that's the only thing it assumes everything else it doesn't know so it has to allow that type to copy its members itself now in cube dot h we add another getter to generate a different kind of cube this is a plain cube playing cube only has 8 vertices the minimum required and it's mapping them accordingly whereas the skin has more vertices because it has to do that whole you know skinning with the unfolded texture it has to make some vertices independent of other ones even though they are in the same space for texturing purposes but this one doesn't have that requirement so we can use the minimum amount of vertices and there you go that is all the stuff that was required the actual demo scene here it creates the index triangle lists cube get plain template that on vertex in here because get plane only sets the positions you've got to set the other stuff yourself so here we set the colors of the eight vertices and the rest this stuff is gonna be the same and that's all the same and you do that and you get this effect here yeah it looks pretty cool it's not bad not bad pretty standard effect when you're learning about shaders now the final effect I'm gonna show today is basic solid color effect and you might think that this one is the simplest of all but actually it's a little more complicated so imagine you've got a cube like this you've got eight vertices you want to give each face its own color how do you do that well you're gonna have to spoor those colors somewhere right where are you gonna store them generally you store your drawing information in the vertices so okay well I mean these two triangles here let's take a look at this triangle it is gonna be yeah so all we have to do to make it yellow is well with our with our previous color vertex if we make these three vertices yellow here and make this one yellow as well then it will interpolate between them they're all the same and it will draw this yellow that's great it'll draw that yellow except what about this verdict what about this triangle here now it's got two vertices that are yellow even if we make this one red it is gonna be also mostly yellow and that's terrible right we don't want that so well let's make this one let's make it red then I'll now this guy is red but we wanted this one yellow guess you can't do it and you can't really do it like this if they're all sharing vertices it's not gonna work for you that well so what you do is you split these vertices up you you make them independent so now these faces they aren't going to share vertices with each other the two triangles of the face here they can share these vertices that's fine but separate faces will not share any vertices with any other face this will increase the the size of your model it'll increase the number of vertices but it will allow us now to give you know these guys all red and then we can give these guys all green and then it'll just work and this would work with our previous interpolating shader as well but when you think about it do we really need to interpolate this color component because I mean it's all gonna be one color why ain't even interpolate it so let's create a new shader effect that doesn't interpolate and gets a little speed boost so here we have solid effect each its vertex is going to have a vector II for position and a color for color not a vector E and the reason for this is if you look through the vertex here you can see that all the operations here the addition the subtraction they're only affecting the position so these operations will affect the color the color will remain the same throughout interpolation because it doesn't need to be interpolated it's the same for all the vertices on the triangle you'll never have a triangle where one of the vertices has a different color so there's no sense in interpolating so don't interpolate it and when you get the input from the pixel shader it's just gonna be the input from one of the vertices and they're all the same doesn't matter for the color anyways and then you just draw that color out directly no need to even convert it from flow to the end and there you go there's a pixel shader now for this the main work here is gonna be done in cubed H because we're gonna have to have a different generator generate plane independent faces so this one generates it with independent faces meaning there's a lot more vertices you're gonna have 24 vertices I believe some are gonna be duplicates right because they have to be independent and this is gonna be you know the same the indices are gonna be different obviously because we've got more vertices now and then in your cube solid scene what have we got here well we're gonna pipeline we're gonna template that on solid effect obviously in here I have created an array of colors and then I just do a loop and assign those colors to the vertex and what I've done here so every four vertices are gonna have the same color so this is 0 1 2 3 they all have red then 4 5 6 7 are all gonna have green so that's the reason for the division in here and the keyboard input is the same and this stuff is all still the same this stuff is all still the same and there you go you've got your solid effect it looks pretty sweet and the code is sexy as if I do say so myself and there you go there's the idea of a pixel shader in a nutshell and there is our pixel shader implemented now I you can probably imagine here I've only scratched the surface of what you can do with a pixel shader the sky is the limit so I encourage you to experiment with this come up with your own ideas make some crazy shader effects and if you come up with something cool you know you can message on Twitter on discord make a forum post post an image of what you made and I'd like to see that maybe I'll even feature it in a future video now one last thing I'd like to say here is again I'm making this whole pipeline this programmable pipeline we're building it with the hopes of learning how 3d graphics hardware actually accomplishes its goals so that we'll be better Hardware 3d programmers and so I'm making it I'm modeling it fairly similar to how it actually works in you know like an API like direct3d or OpenGL but there are some differences I just like to go over a few of the differences I mean first of all a pipeline is templated right so that means that if we want to change the pixel shader we wanna change a vertex shader we want to change the effect we basically got to create a whole new pipeline and obviously that's not how it works in direct3d if you want to change a pixel shader you just bind a different shader if you want to change vertex shader you just buying a different shader whereas with us we've got to create a different pipeline for every different effect this gives this is an advantage for us in that using templates allows the compiler to optimize the code better to inline the code more aggressively but the downside is obviously we can't switch things out at runtime we've got to create a different pipeline for every different effect that we want to use for rendering but again working with actual hardware with direct3d you can buy in different shaders to the same pipeline dynamically at runtime another difference is for our shaders here for example if we've got a texturing shader the pixel shader object is going to contain the the texture right and is going to use its own custom code to access the texture but with a real hardware pipeline what you're gonna have is an object in your pipeline separate from the shader and it's a fixed object and it's a texturing unit and you will bind textures to slots in your pipeline that the texture unit will read and you will interface with the texture unit so for example if we look into the framework in the actual direct 3 the pixel shader here what you're doing is you're setting up a texture object and a sampler State sampler state basically represents the the texturing engine that is going to be sampling from the texture and the texture is the resource that is bound to the pipeline so sampler represents the texture and then when you want to read from the texture you go texture dot sample you pass in the sampler and you pass in the texture coordinate but obviously don't worry about this we'll get into this when we get into hardware 3d and that's about it for this video thanks for watching hope you liked the video if you did please click the like button it helps a lot and I will see you soon with some more 3d fundamentals [Music]
Info
Channel: ChiliTomatoNoodle
Views: 11,384
Rating: undefined out of 5
Keywords: perspective, 3D perspective, 3D projection, perspective divide, DirectX, Direct3D, D3D, opengl, 3d programming, 3d graphics, 3d game, lesson, how to, C++, guide, code, tutorial, coding, windows, visual studio, game development, chili, chilitomatonoodle, pixel shader, fragment shader
Id: pef2405M-os
Channel Id: undefined
Length: 23min 6sec (1386 seconds)
Published: Sat Sep 30 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.