Last time we learned how to use GrabPass to make a glass shader. Now we're going to learn how to make a skybox!
A skybox is a background you put on your scene that doesn't get bigger or smaller no matter how you move the camera (which helps make it feel very far away.) It's perfect for - you guessed it - putting a sky on your scene, but you can also use it for things like faraway mountains or cities.
I think a lot of people find skyboxes a little intimidating because it seems like some behind-the-scenes magic.
In fact skyboxes are pretty darn simple, as you'll find out!
Make a new scene in Unity. In the hierarchy, add a plane and put its transform position at 0,0,0. Drag in your favorite models. I'll be using Claire as usual, and I also dragged in some junk from the Unity 3D Game Kit, which you can get for free here. (but you really don't need it, even cubes and capsules will do.)
Do not spend more than like 2 minutes on this, we just want stuff to see against the sky!
Now in your Shaders folder in your Assets, make a new folder called Skybox. In that folder, make a new material called GradientSkybox. Also in that folder, make a new Unlit shader called GradientSkybox.
Click the new material so that you see it in the Inspector, then click the shader dropdown and start typing GradientSkybox until you see Unlit/GradientSkybox. Click that entry to assign the shader to the material.
Go to the Lighting tab - it looks like this:
If you can't find the lighting tab, go to Window > Rendering > Lighting Settings to add it.
Once the lighting tab is open, drag the GradientSkybox material into the Skybox Material slot.
Cool, you made a skybox! Great job everybody, see you next time! jk jk
Making a Skybox Shader
Open the GradientSkybox shader in Visual Studio. Now it's time for our usual template cleanup. Change the name up top to "Xibanya/Skybox/GradientSkybox". Replace the existing tag with these
"Queue" = "Background"
"RenderType" = "Background"
"PreviewType" = "Skybox"
they do exactly what it sounds like.
Right after your tags, add
ZWrite Off means we're telling Unity not to write this to the depth buffer. This is gonna be behind everything else, we don't need to keep track of its depth at all. We're also turning culling off because this isn't for a normal mesh with backfaces we're trying to save render power by not drawing.
Then delete the fog stuff because we don't care about that.
You should have this
Now if we just saved and went back to Unity, we could put any random texture in the material and call it a day, but most people don't use skyboxes like that.
Nah let's make a skybox that we can use even if we don't have a sky texture lying around. Back to Visual Studio!
In your shader properties, delete _MainTex and instead add these:
Then inside the CGPROGRAM block, delete the _MainTex and _MainTex_ST declarations. In the vertex shader, get rid of the line with TRANSFORM_TEX and replace it with
o.uv = v.uv;
under the vertex shader, declare the colors
You'll note these are half3 and not half4 because transparency is sort of meaningless for a skybox since it's always the thing in the very back, so there's nothing to see through it anyway. And in fact we can make the return type of our frag function a half3 rather than a half4! Replace the existing frag function with this:
ALERT (2/17/2020): I recommend not returning a half3 if you plan to use your shaders anywhere except a Windows PC! You can read my full explanation here!
change the first line shown in the image above with
half4 frag(v2f i) : SV_Target
and replace the last line shown in the image above instead with
return half4(blend, 1);
What does this do? Well it makes a gradient between the bottom color and the top color, and the place on the gradient is determined by the Y UV coordinate. UVs go from 0 to 1, so as the UV value goes up, it'll make a linear blend from the bottom to top color.
Save and go back to Unity and you'll find yourself greeted by this:
Neat! If somewhat bleak. Let's put some nicer colors in there!
Oh yes, much better, thanks.
You may notice something interesting! Our lerp between the colors is mathematically linear, right? but that's a pretty sudden jump on the horizon. Where did we screw up? We didn't -- that's just how the UV coordinates are mapped to the skybox, presumably to better create the illusion of it being round. And conveniently it does make our gradient vaguely resemble some sort of actual atmospheric phenomenon. 'Course, there's no need to stay satisfied with what we're given. You know we have a long history of bending gradients to our will - if we treat this like our toon shading, we can control the blend here just like we have there.
Add _Offset and _Smoothness properties in your properties section and declare them down in the shader above the frag function.
(full disclosure, there's no special algorithm for coming up with what the range should be, I arrived at these numbers by experimenting and picking out what ranges looked best.)
Then change the frag function to this:
This should look familiar to all of you who have done toon shading. There is one difference here -- you'll note how we multiply the up/down position by two then subtract one. We are multiplying by two to increase the range so that it's between -1 and 1 rather than 0 and 1, then subtracting 1 so that despite doubling the range, the actual value remains proportionally the same. That means something that's 0.25 becomes -0.5, 0.5 becomes 0, and something that's 1 is still 1.
Also we are multiplying Smoothness by 5 because I found it looked best in a range between 0 and 5, but I wanted the user-facing slider to be between 0 and 1, lol.
Back in Unity, you should now have something like this!
And you can play with the sliders for fun variations like these
Ahhhh soothing, isn't it?
The code for the shader we made in this lesson is attached to this post as GradientSkybox.shader.
This tutorial is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. The code shared with this tutorial is licensed under a Creative Commons Attribution 4.0 International License.