Introducing

OpenGL Bindings for BASH

"What???"

A while back, I came accross a game called Frozen Bubble, which is a Snood clone written in Perl using the OpenGL bindings. I was rather offended by the whole concept, and said something like "Arg! Thats almost as bad as writing a 3D game in Bash!". So, this December during winter break, when I was trying to think of something to do for Mike's Abuse of Technology #6....

"Oh, God!  No!!"

  <-- (common actual quote)

But here it is! Bwa-Ha-Ha! All the normal languages have OpenGL support, and some scripting languages like Perl, Python, and PHP have OpenGL bindings, and now Bash does too!

"BUT WHY, DAMNIT? WHY??"

If you have to ask why, you are not a member of the intended audience. Please go on about your business and accept my apologies for this distraction.
(tribute to Bob Zimbinski [1])

"But how? Bash doesn't support modules..."

Right. So I gave it an interface just like all the others it uses: a simple command that can be given parameters and fed commands on standatd input.

When invoked, CmdlineGL starts a server which creates an OpenGL window, and then either reads input from a file or from standard-in. To deliver commands to it, a script can pipe standard-out to the program, or write to a fifo, or other creative methods. The script sends lines of text to the server that tell it to execute any of the supported OpenGL, GLU, or GLUT API calls. CmdlineGL supports textures, display lists, quadrics, and just about all of the usual gl calls.

"This sounds Bad and Wrong"

I'd argue for Bad and Right. Keep reading.

"So, how bad does the performance suck?"

Its definately slower than games written in C, but might not be as slow as you think: CmdlineGL is written in straight C with as little overhead as possible, to the point of doing all text operations on the same character buffer filled by the call to 'read', and sacraficing reusability for performance (and wow, was it ever liberating!). It also uses a statically defined hash table to map command names to function pointers. To top things off, it uses a Red/Black Tree to manage the names of objects like display lists, quadrics, textures, and fonts.

Because of the support for display lists, any part of your game that doesn't move can be compiled into the OpenGL end and replayed as a single line of text. And, in a 3D application, most of the time is spent drawing pixels and texturing them, and this is probably done by the graphics card, so there's plenty of CPU time left over for running data through a pipe and a socket, and running string-to-float conversions, and repeatedly forking hundreds of times per frame per second, especially with the speed of today's computers ;-)

"And you actually wrote a game using this kluge?"

Well, mostly just demos, but a game engine of sorts, yes.
(I never finished the flight simulator)

Lets review some of the obstacles involved with a real-time game, and our old friend/nemesis Bash:

"How much time did you waste on this??"

Less time than I wasted on World of Warcraft

"So, what can I do to... 'Repay' you for this?"

If you were thinking along the lines of thanks: bug fixes, implementing more of the OpenGL commands, bug reports, money, pizza, sending Morrowgrain to Zellin on Earthen Ring (if you don't know what that means, don't worry about it), etc.

If you were thinking more along the lines of revenge, you could try using CmdlineGL to write a multiplayer racing game (like a Mario Cart clone or something) in Prolog.

"Where's the Windows version?"

The Windows version is the same as the Linux version. You'll just need to edit the source code a little before you can run it. ;-)

At the moment, the unix-specific things in this code are the asynchronous IO, the fifo's, and the timing. If you replace all the 'open' and 'read' with CreateFile and ReadFile, comment out the fifo stuff, and replace gettimeofday and usleep with GetCurrentTime and Sleep (remember that it'll change microseconds to milliseconds), it just might work on Windows. Then all you need is bash, which can be gotten from Cygwin. You will still need some way of creating the stdin/stdout loop between the script and CmdlineGL, and I'm not going to even investigate that.

I really can't see any reason why you'd want to do this on Windows (unless perhaps your graphics card isn't accelerated under X). One alternative is to install Cygwin and then export the display of your script to the windows box. That only works of you have two machines, of course. Anyway, it's your time, but if you get a windows version working I'll gladly host it.

Credits