Sunday, July 25, 2010

OpenGL ES 2.0 Phong Shaders

I had a class during my last semester of school with a great professor who let us study just OpenGL ES 2.0 shaders. After mastering the basic programming concepts, the shader creation felt like painting with code. Pretty interesting. Here are a couple of pictures of models I made and wrote the shaders for.














Both shaders use the standard Phong shading equation. The die has a normal map applied to make the divets and slightly rough surface. There were two tricky concepts I had to learn to get the normal map to show up properly.

a. I had to put the view and light vectors into "tangent space" because that's the space the normals from the normal map are in. Tangent space is defined for each vertex by the normal, binormal, and tangent. This space is preferrable to world or view space because it preserves the normal map when transformations occur on the model. I defined tangent space with this line of code in the vertex shader: "mat3 tangentMatrix = mat3(a_tangent, a_binormal, a_normal)". Then I multipied the tangent matrix by the view and light vectors. Thus, in the fragment shader, all I had to do was grab the pertinent normal from the normal map and change the range from [0, 1] to [-1, 1] before performing the usual lighting calculations.

b. Some exporters and formats include the binormals and tangents, but the format I was using (3ds) did not so I needed to calculate them. The key is to use the vertex positions and texture coordinates. Both pieces of information are pertinent because you want to take into account significant changes in either one. I found a good website that describes how the calculations are derived: http://www.terathon.com/code/tangent.html. The code I ended up writing is below.