HeadsUp NeHe Tutorials
Posted: April 16, 2012 Filed under: HeadsUp, Lua, LuaJIT, OpenGL Leave a commentSince time immemorial, I have learned from the NeHe OpenGL Tutorials. These tutorials have been great, particularly up through the 2.1 version of OpenGL. With the advent of more and more shader programming, WebGL, and other advancements, the old tutorials are now listed as “Legacy”.
These tutorials are still useful for a couple of reasons. Not everyone programs with shaders as yet, and they are a great way to flush out all the challenges with a new OpenGL interface, such as what is in HeadsUp. I have implemented tutorials 2-8, just for kicks. The picture here shows lesson8.lua, which is about blending, some lighting, and using texture objects. I’ve implemented an extremely simple brain dead Targa image viewer, just to get some images into texture objects. The rest is pure OpenGL.
The way I’ve done it is to grab the GLUT or C++ version of the code if it exists, and then just do some massaging of the code until it compiles. It’s typically a fairly simple straight forward process. I’ve even added some of the most common glxxx functions to the global namespace for convenience. One example is dealing with color. Of course, you can be very explicit:
gl.glColor4f(1,o,o,1)
And if you want to do that without the ‘gl.’ prefix, you can simply do:
glColor4f(1,0,0,1)
That allows your code to look exactly like the typical ‘C’ version of the code. But wait a minute, this is Lua, so convenience is the name of the game. We can do some overloading and get an even better effect:
function glColor(...) local arg={...}; if #arg == 3 then gl.glColor3d(arg[1], arg[2], arg[3]); elseif #arg == 4 then gl.glColor4d(arg[1], arg[2], arg[3], arg[4]); elseif #arg == 2 then gl.glColor4d(arg[1], arg[1], arg[1], arg[2]); elseif #arg == 1 then if type(arg[1] == "number") then gl.glColor3d(arg[1], arg[1], arg[1]); elseif type(arg[1]) == "table" then if #arg[1] == 3 then gl.glColor3d(arg[1], arg[2], arg[3]); elseif #arg[1] == 4 then gl.glColor4d(arg[1], arg[2], arg[3], arg[4]); end end end end
With this function, yoiu can use several calling conventions:
glColor(0.63) -- Set a grayscale value glColor(0.63, 0.5) -- Set a grayscale value with alpha glColor(0.25, 0.30, 0.30, 1) -- Set a full color value glColor({0.24, 0.30,0.30,1}) -- Set a full color, with alpha using a table glColor({0.24, 0.30, 0.30}) -- Set a full color using a table
The only one that is missing is:
glColor(vec3(0.24, 0.3,0.3)) -- Set color using a vec (float[3])
If you are familiar with using the processing environment, this flexibility in setting color values might seem more familiar. There is something nasty about the difference between counting from ‘0’ as is typical in C, and counting from ‘1’ which is standard for Lua tables. By using this sort of construct, you can get it both ways. If you want the typical C version, including passing array structures, then use the standard C looking functions. If you want to pass your Lua based tables around, then use the more generic versions of the function, and pass tables around.
The same is true for Vertex objects.
I find this to be a useful construct. Although the flexibility can be a bit much when you try to think about the many ways you can do something, really it just feels natural because you just do whatever feels natural to your programming style, and it will probably work. You can stick with copy/paste of code you find from elsewhere, or you can taylor it to the Lua environment as suits your needs.
Now, on to those shaders!