Shader Programming, Volume 2
A Diffuse Surface Shader
Now that we have some sense of the vocabulary, let’s explore making the most basic of shaders: a diffuse shader. We’ll learn a bit more about the nuances of shader programming while we’re at it, too.
Chapter 2.1
Surface Shaders and Texture Mapping, Diffuse Shading
Starting again with a Standard Shader, we’re going to create a Diffuse shader by stripping out all the stuff we don’t need. It ends up looking like this:
“As this shader has been refitted from a Standard Shader, it will use physically-based rendering to simulate how light behaves on your models. If you are trying to achieve a non-photorealistic look, you can change the first #pragma directive so that it uses Lambert rather than Standard. If you do so, you should also replace SurfaceOutputStandard with SurfaceOutput.”
Let’s take a look at some of the Shader structs we’ve seen.
The SurfaceOutput struct has the following properties:
- fixed3 Albedo: the diffuse color of the material
- fixed3 Normal: the tangent space normal, if written
- fixed3 Emission: the color of the light emitted by the material
- fixed Alpha: the transparency of the material
- fixed Gloss: the specular intensity
The SurfaceOutputStandard struct has similar properties, with some differences:
- fixed3 Albedo: the base color of the material (whether it’s diffuse or specular)
- fixed3 Normal
- half3 Emission: note that this has been declared as half3 instead of fixed3.
- fixed3 Alpha
- half Occlusion: default 1
- half Smoothness: 0 = rough, 1 = smooth
- half Metallic: 0 = non-metallic, 1 = metallic
The SurfaceOutputStandardSpecular struct doesn’t have the Metallic property, but instead has the Specular property:
- fixed3 Albedo
- fixed3 Normal
- half3 Emission
- fixed Alpha
- half Occlusion
- half Smoothness
- fixed3 Specular: the specular color. This is very different from the Specular property in SurfaceOutput as it allows specifying a color rather than a single value.
Chapter 2.2
Surface Shaders and Texture Mapping, Using packed arrays
Here’s a cool thing: you can treat Cg’s packed arrays (such as float3 and fixed4) a little differently than you might be able to treat structs in C#.
For example, Cg is totally chill with you doing this thing called swizzling:
o.Albedo = _Color.rgb
instead of individually assigning the elements of the o.Albedo as you would in C# like
o.Albedo.r = _Color.r
o.Albedo.g = _Color.g
o.Albedo.b = _Color.b
which is a total buzzkill if you ask me. You can even do nutty things like reordering the elements of _Color when you pass it into Albedo.
o.Albedo = _Color.bgr
Note that this reads sort of like _Color.booger. Write that in your copybooks now.
Pass in as many or as few elements as you want. Go wild. (Within reason.)
o.Albedo.rg = _Color.rg;
The last trick the book reveals to us is that when you assign a single value to a packed array, it’s copied to all of its fields:
o.Albedo = 0; // Black = (0, 0, 0)
o.Albedo = 1; // White = (1, 1, 1)
This is referred to as smearing. How pleasant.
Next we’ll be adding a texture to our shader which will make us feel pretty good about ourselves, I bet.