If you haven’t been following my last couple of blog posts, I have been chronicling my progression through GLSL 4.0 Shading Language Cookbook. I started with chapter two where the fundamentals of GLSL were laid down. Last week I posted about chapter three which built on those fundamentals where more time was spent on lighting. This chapter focused heavily on textures.
All of this work is being done in my open-source game engine, the Derydoca Engine. The engine is available on GitHub so all of the source c++ and glsl code is available for you to explore and see how I made all of this come together.
The first shader in this chapter is a fairly simple one. The book has us applying a texture to a model. Fortunately for me, my pointy squirrel is fully textured so I had my source files ready to go. The book was pretty straight-forward here so I won’t go into much detail, but you can see a screenshot of it in action below. Also, notice the awesome new skybox! I picked up this skybox from OpenGameArt.com. The skybox is provided by Jockum Skoglund, and if you come across this, thanks for sharing your work!
What could be greater than a model with a texture? A model with two textures! You heard right! I decided here to go with a Splatoon style effect. I fired up a copy of Gimp (which seems to be much better than I remembered it last I used it) and created a simple splat texture by generating some noise and applying some filters and alpha mask. I was lucky enough for the texture to sit nicely on the model my first try!
Now we are going from more of a Splatoon effect to an Alien effect. It looks like that green goo has eaten through the flesh of our squirrel! That or we are using the same texture to discard fragments in the fragment shader. Okay, it was the latter, but it looks pretty neat! The discard function is the same GLSL function we used in chapter two to create our grid effect. It’s a simple, but effective addition to the shader.
Now, here comes the doozy. Normal maps actually took me a little bit of time to implement in the engine. This was partly because I needed to find a suitable model with a normal map to demo this, and also part because there were some bugs lurking in the shader that took me a while to figure out.
First things first, I brought in the crate model from Acorn Assault: Rodent Revolution. This crate has many texture maps including a normal map. You can also see I have a texture on the ground as well. It isn’t the prettiest texture, but it works for demoing the effect. I have been trying to avoid using obvious “programmer art” in my game engine because I think I should avoid it if I can, but I know that ground texture is venturing into that realm. I also want to stay away from “programmer art” because I modeled and textured all of the assets in Acorn Assault: Rodent Revolution so I think it would be inexcusable for me to not try to leverage my hard work, but I digress.
The other thing that surprised me is exactly how normal maps work. I already thought I knew the tricks in and out, but I was wrong! Well, not wrong, but I didn’t know everything. Normal maps are a texture that generally have a bluish purple color to them. This color is because the normal of the surface is encoded into the RGB channels of the image and the up vector is where normals generally point and that is the Z (or blue) component. The colors shift where the normal is pointing in a different direction. That is all stuff I knew. The part I didn’t know is that the normal is actually defined in tangent space. Tangent space is a space relative to the texture map. Originally I thought you took the normal from the surface and shift it by the sampled value in the normal map. You can read more about tangent space here. Once I got past all of that, I ended up with what you see below.
Here is the real reason why I opted to find a good looking environment map. I knew this chapter was going to get into creating a reflective and refractive material, and my blue gradient test skybox wasn’t going to cut it for me. This, and the refraction shaders are fairly simple because much of the actual math is hidden behind the GLSL functions reflect and refract respectively. For being so simple, they produce such a mesmerizing effect. If you run the code, you will see I have all of my models rotating. This is one of the more interesting ones to watch spin around because you can see the beautiful skybox slide and shimmer across the surface of the squirrel.
This is another favorite. Again, the GLSL function refract should get most of the praise here because it does most of the heavy lifting. I think this produces a pretty believable glass effect.
Here is another shader that took a while to implement. This one mainly came down to having to extend the engine to allow some of the variables to be passed from components to shaders. This is a projector shader that takes an image and projects it on top of some geometry. You can see the hero image of Acorn Assault: Rodent Revolution being cast over the squirrel and onto the ground. Of course, the engine does not support shadows right now, so you naturally (or unnaturally) see the floor behind the squirrel lit up as if he isn’t even there.
Ultimately I had to create a new game component ImageProjector that can be positioned anywhere in the scene and the scene file can define where it is pointed and how large the image should be.
And for the final “shader” we have render textures. I say “shader” with quotes because this doesn’t do much in GLSL. You actually render to a separate buffer and then use that buffer as a texture in another shader.
I actually had render textures working prior to working through this book, so I simply created a scene to demo what I have already done. That allowed me to make up for lost time on the normal mapping and projection mapping sections!
Also, if you are also following along in the book, you will notice that I skipped the section on image based lighting. This is because the book relies heavily on a third-party software called HDRShop. At the time of the writing of the book, the software was free. Now, you have to contact the author to buy it and I was not up for buying a software I knew little about. I even looked up documentation to do what the book asks you to do and it didn’t look all that intuitive, nor was there much information out there about it. For those reasons, I skipped it. Hopefully future versions of the book address this section because it was disappointing to have to skip it.
As always, feel free to share links to your own work in the comments below. I would love to see what your versions of these shaders look like!