Writing Unity Shaders Using Depth Textures

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
My name is Ben, and I teach you how to write Unity shaders from scratch. In today's video, we're going to go through this effect where you can see the objects behind it in this, you know, one colored or two colored format, right? This object can be scaled. It can be moved. It can also you can also change the colors if you want, you know, on the fly. Right. So, yeah, let's jump right into it. So in this particular lesson, there will be some techniques that are a little bit more advanced than what I've shown you so far. But do bear with me. Try to go through them and I will try to cover them more in depth in a future video. But also briefly explain what each one does. So the unity setup we have today is very simple. It's a game camera and a scene camera. The reason why I've separated these two showing you both is so that you can see the difference between the two, because especially when it comes to using depth textures, it looks a little different in both. The shader setup is very simple. Black is what we're outputting, and this shader is attached to this black sphere behind. We have all these objects that we can use that will show up in the depth texture. So this shader will take advantage of the depth texture. The depth texture is actually given to us by unity. When we sample it, it's actually free to sample because it's already created by unity. So we just need to grab it from unity and sample it as simple as that. Now in order to sample this depth texture, we need something called screen space uvs because the depth texture encompasses the entire screen. Okay. So let me show you how to get a screen space uvs float4 in the v2f we'll call it screen space. We'll put it in texcoord1 The math can be done here and the vertex and then we'll pass it over into the fragment. So we'll do o.screenspace Unity has a function for us already. Called Compute. ComputeScreenPos And what we need to do is pass in the vertex. We have to pass in the one that's already in clip position. Now, in order for us to view the screen space uvs, we'll do float float3 (float2) not 3, screen space uv. And what we need is i. i.screenSpace.xy which is the computed space for us. Divided by W So you can do your own research on why it's using divide by W. I believe it's to fix up the projection, especially when it comes to this camera. It's a projected camera. Yeah, perspective camera. So it does, I believe, some math to kind of fix it up. So let's display the UV here cool. So as you can see, it's, it's worked out. When we bring the circle to the bottom right here, you can see that it's getting to read to the top it's becoming yellow in this corner, green and the other corner. Oops, green in this corner and probably black at this bottom corner. Right. Can't quite see it very black here. So we can see that this sphere or the UVs is encompassing the entire screen. It's not based on the sphere itself. But it's based on the screen itself. So the screen space texture is sorry, the texture is already given to us. That's given to us by UnityCG.cginc So all we need to do is declare here and we should be able to access it. To declare it, it's sampler2D _CamperaDepthTexture Now, sampling this thing is a little bit different than sampling the texture. We cannot just use a tex 2D sample. Unity has its own way of sampling. It has another it's a kind of like transformed text has its own way to sample it because depending on the version of device you're using, it could be a projection sample you could sample only in the red channel. There's a bunch of different ways to do it. And so I always use the one that Unity gives us. So the one unit gives us is called Sample Depth Texture. I think it's as simple as that, actually. So we'll do for depth as equal to sample going depth. SAMPLE_DEPTH_TEXTURE right? And what we need is the depth texture given to us by unity, and we need the screen space. Let's put that to see what it looks like. Well, I'll put it just in the Red Oak Okay. So I think this has worked and there's no errors. So I believe this has worked, but we need to decode this. This is given this is coming to us in a way where we cannot even see the red. There might be a reddish tinge here, as you can kind of see a little bit right here, but it's quite invisible. So we need to decode it there's two ways to decode it. I think I remember it It's called LinearEyeDepth let's save that off. Yeah. So this is the first way to Decoded. And right now we're seeing just red and I think Unity actually uses this one to determine if objects should draw behind or in front of each other. But from our perspective, from our eye, we cannot see it. I think there are differences in this red up close and further away, right? You can kind of see it, but it's not it's not linear. So I guess it's kind of a naming issue. But if you want it to be linear between zero and one that is zero and one based on this camera instead of "eye" we put the 01 that that is probably what you guys were more expecting. Now you can see all of the objects behind it with this depth going on. And you can also see that it doesn't actually work in the scene. Scene camera doesn't does, but it's doesn't look the same as what is in the game camera. So you got to make sure the game camera is there for this to work. Now, keep in mind, linear, because this is a depth texture. It is based off of the camera is based off of the near and far plane. So if I change just one or I change the forward to say 100 will actually change this, the look of this, right? So I brought it to 15 wherever it is close to just enough to see this blue box so we can see the full effect here. Right. So make sure that when you are doing this effect, your near and far plane are set properly. So now that this is done. There's a couple of things we can do to make this more advanced. We can do two colors and lerp between the two. So let's go ahead and do that. Right. So create color one, color two, no errors. I'm good. So let's do a mixed version. Let's just do a new color float and what we'll do, floats, for now and maybe convert it to a fix later onto the mixed color will lerp between the first one, color one and color two lerp it based on the depth So now when we select this object, we can select different types of colors. Let's just say we want, oh, I don't know what the objects near us to be dark. And we want the further ones to be kind of this reddish tinge or even purple or blue so we can kind of, you know, we can do to do what we want here. So I think I'll leave it into this, this type of color. Cool. So as I was doing this object (shader), I thought, you know what, it would be really cool if we can make a drawn edge around it, right? And we're in 3D space. We have this sphere in 3D. So why don't we want to add a quick fresnel to this? For those of you that don't fresnel is a product between the normal and the view direction. So that means as as we see the grazing angles like of the edge of the sphere, it becomes white or it becomes hotter. And as the sphere is directly reflecting back at us or the normals of the sphere is looking back at us, we see this texture. So why don't we quickly add that I think I'll do a separate video on exactly how fresnel works, if this is a little bit confusing, but we'll just quickly put it in for now for that to work. We need the normal from the app data and from here we need to pass in two things. We need a view direction and we need the normal this will be texcoord2 texcoord3 for the view direction to get the normal from the from the vertex. It's o.normal to it's always in local space. So we need to make sure it is in world space. I think it's UnityObjectToWorldNormal I think that's it. If not, I'll Google it after and we need the v.normal save that off. See if it works. Yes. Okay. And the view direction is quite simple to, viewDir WorldSpaceViewDirection we just need the vertex position I believe of the V of the objects. So and because we are converting it to world space V direction, I think these are not normalized so we need to normalize it okay. Let's quickly display our fresnel, we'll do a separate value, we'll call it float fresnel. I know it looks like "Fresnel", but it's not. Let's do a quick dot product of i.viewdir and i.normal so see that quickly works yes it does cool to get the edges. We need to do a one minus on it. All right. And if we took our fresnel and we've multiplied it with our mixed color should get the effect we're looking for. Not quite. We don't need the one minus there. Okay. So now what if you wanted this edge to have, like, a bit of a color, right? So why don't we quickly do that or do maybe, you know what? We'll put the main texture We do that instead. So if we look at our for now, again, it's going from white or red to the edge dark. So what we want is we do want the one minus actually and so now the edges are white or red and if we want to use our col, what we can do is we can do a final color. float 3 final color to go to lerp between our mixed color, which is going to be the black to our col, which is the red times, you know lerp bit by Fresnel Cool. So now that is working and it's using this texture. So whenever you do frenels right some people like to do ramps to kind of make the edge brighter, right? So ramps, especially on the frensel itself, will cause it to brighten at the edges like kind of a like a multiplier but exponentially. So let's do a ramp on that fresnel So I'll call it ramp it's going to be a float default to one because it's a power and our fresnel can now have a power powered by the ramp and that should be it actually. Right. Going to make sure we use the ramp here so we can use it cool. Now a ramp is one if we set it to say, ten now that is too much Yeah, we can start to push it against this edge right and we can also have a multiplier we'll multiply it onto this fresnel yeah. We can also, you know, animate this if we want it to just quickly add it here. So yeah, in order for us to see this, I think we would have to play because it doesn't it doesn't properly animate here. (In the game camera) Yeah. And there you go. That's, that's the effect we were aiming for. So now you have this effect that can scale up looks like this. I don't know if this water texture is really the right type of texture for this, but yeah, you can do all sorts of cool things with this can change out this green, you can change out yeah. You can have a lot of fun with this one. So I went ahead and also did this a little bit more advanced version. It's called the Advanced Depth as opposed to the test that's that we were I was showing you guys earlier, but this advanced one, all it did is change the way I'm sampling the UVs to this rotational type effect. I just thought it would be pretty cool, especially with this sphere that we have. I don't think it'll work very well on all types of objects though, but it probably won't work well on cubes. And stuff like that. But it works well on, you know, spheres, mostly spheres, rounded objects, things like that as it relies on, the fresnel to work, right? So I'll post this in the description if you guys want, and if you really want an in-depth version of how this one works, I'm more than happy to do that, but it's just an adaptation of what we have here. I just change the way I was sampling the texture. So yeah, so if you guys like what you see, please, like subscribe and support my channel. I hope you guys learn something and I'll see you next time, bye now.
Info
Channel: Benjamin Swee - Custom Unity Shaders
Views: 9,920
Rating: undefined out of 5
Keywords: Unity, Unity3d, shaders, shader, 3d, code, cel, shading, toon shader, cel shader, cg, hlsl, programming, vert, frag, vertex, fragment, pixel, 2d, physics, tutorial, games, development, ben swee, swee, material, graphics, rendering, rendering engineer, tech art, technical artist, gpu, training, real, time, shader from scratch, normals, tangents, 3d modeling, what are shaders, theory and application, gpu explained, intro to shaders, unity shaders, unity materials, depth map, depth texture
Id: yUVrtPCsCb0
Channel Id: undefined
Length: 16min 13sec (973 seconds)
Published: Mon Apr 18 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.