I have been working through the book OpenGL 4.0 Shading Language Cookbook lately to implement all of the shaders and features into the Derydoca Engine. I recommend this book to anyone who is trying to get a handle on GLSL and how it works. I do have some gripes with the e-book version that I have through Kindle because the code is formatted horribly, but if you understand the basic syntax of GLSL you can work around those issues.
If you are following along and want to see this in action, you will have to check out the branch ‘features/shader-cookbook’ from the engine’s git repo. The specific commit hash for the time of this writing is 9be9a97a689118f8a2286c85d186e151371c3bad if you want to see the code 1:1 to where it is now. The examples can be found under ./exampleProject/shader_cookbook/ and all chapter 2 examples are prefixed with “2_”, which, if you have this particular commit, that would be all of the folders.
Chapter 2 introduces you to different shading effects that the future chapters will indelibly build on. The first example has you write a simple diffuse shader that takes nothing but a diffuse color. It is one of the simplest and most efficient ways to simulate light reflecting off of an object, but it definitely leaves a lot to be desired. For one, there are no specular highlights on the model that can imply that the surface is smooth or wet. The second example quickly remedies this.
The book then introduces the Phong ADS model. ADS is an acronym for Ambient, Diffuse and Specular. In the real world it is very improbable to come across a surface that when it is not being lit by a light it is fully dark. This is because light will bounce an infinite number of times off of surrounding objects and a small amount will reach the dark side of the object. Because we still don’t have computers that can simulate an infinite number of light bounces (seriously, get on that scientists), we simulate it with a simple baseline called ambient light. The D part of the acronym is diffuse part is pretty simple. We already went over it in the last chapter so that formula copies over more-or-less. This just simulates light bouncing off of the surface in all directions equally. Lastly, the S is the specular highlight that we see on shiny or wet surfaces. The specular highlight is influenced by the light’s position, surface normal, and the camera’s viewing angle. Because of that, we get some interesting shimmering effects when we move the camera around the scene. Lastly, in order to render the final color of each pixel, we sum all three influences of light together to form the Phong ADS model. All other subsequent shaders in this chapter use this phong model and build on top of it.
After exploring the phong model, the book explores two-sided shading. I had to disable backface culling in the engine to allow this example to function for obvious reasons. I was doing it at a global level before. Perhaps in the future I will explore options that can enable this per model so that double-sided shaders can be used in the engine without negatively affecting the rendering performance of non-double-sided shaders. With that aside, I broke away from my trusty pointing squirrel model (from Acorn Assault fame) and went to Blender’s Suzanne model. I hope she forgives me because I had to split her head open to show the other side of her polygons!
This next shader is one of my favorites. It renders every polygon in the mesh with zero blending between vertices. This creates a faceted look, and paired with the specular highlights provided by the phong shading model, it creates some nice looking shimmering effects across the surface of the pointing squirrel.
Now for the most boring shader examples. Well, it is only boring from the outside looking in. For me, as a person who cares about application performance, this one was pretty cool. In the screenshot below you will see two squirrels both seeming like they are using two different shaders. The one in the front looks to be shaded using our Phong shader and the one in the back using just the diffuse model. Well, if that is what you thought, you would be wrong! They are both being rendered by the same shader program. The shader contains methods for both Phong and diffuse shaders and the program tells it at runtime which one to use on the GPU. I did have to extend the engine’s shader code to support this, but that just adds another feature which I am more than happy with!
ENHANCE! Or maybe dehance! This one is another favorite of mine because it reminds me of cheezy TV effects that renders any object with a grid pattern in 3D to show it is being analyzed. This shader combines the two sided shader with the discard functionality allowing us to effectively punch holes through our mesh! In this example, a grid pattern is used to distort over the mesh and discard all other fragments. Of course the backside faces are visible because of the techniques utilized in the previous two-sided example. No need to split heads over this one to see the inside of the mesh! In order to distort the grid pattern over the mesh, the mesh’s UV map is used. Since this model is fully textured, that was no problem.
Also, if you are following along in the book as well, you will notice one thing I forgot to mention I did here. I extended each example to support multiple point lights. These point lights are rendered as solid white spheres for now for visualization purposes (you can see them in some of the screenshots). The book only focuses on using a singular light source for simplicity’s sake. I already had multiple point lights working in the system and figured it would be a shame to introduce these new shaders without adding support for it… so then I did!
Now, as I understand it, chapter 3 touches on adding support for multiple light sources. I may have to modify the code in these examples to be consistent with the book. Who knows, I may have made less work for me on this next chapter which would be nice. If you are following the examples in the book, or are simply modifying my shaders, share the screenshots of your engine in the comments below!