In my earlier article describing the design of Perl 5 and its suitability as a “glue language,” I discussed I had beforehand written OpenGL bindings for Bash. This was maybe too incredulous of an announcement to make with out some proof, so I went again into the dusty corners of my exhausting drive, dug it out, freshened it up a bit, improved the font help, wrote up documentation, and printed it on my site and on GitHub. (You’ll want a system with each Bash and OpenGL help to expertise it firsthand, however here’s a video.)
So now my confession: The Perl graphics within the DeLorean dashboard I described in My DeLorean runs Perl share a historical past with my OpenGL for Bash undertaking. In a enjoyable and ironic twist, I initially began the undertaking 13 years in the past after witnessing Frozen Bubble and having my technical sensibilities offended that somebody had written a real-time online game in Perl. Back then, my major language was C++, and I used to be learning OpenGL for online game functions. I declared to my associates that the one factor worse can be if it had been 3D and written in Bash. Having stated the thought out loud, it saved prodding me, and I finally determined to offer it a attempt to one-up the “awfulness” of utilizing Perl for real-time graphics.
The most direct means so as to add OpenGL help to Bash would have been to change the supply code and add every OpenGL operate as a shell “builtin”; nevertheless, the one individuals who would be capable to expertise it will be these prepared to put in a customized model of Bash, and possibly no one would need to try this. It additionally did not appear within the spirit of doing issues “the Bash way.”
I then got here up with the thought of a client-server, the place every OpenGL operate can be put in within the path and invoke a shopper that may hook up with an OpenGL server to ship a message to execute that operate. That would have been a delightfully “awful” resolution, however irrespective of how exhausting I optimized issues, it was nonetheless too gradual for me to say I had succeeded on the total objective.
Finally, I settled on a design the place I might have an “OpenGL Interpreter” course of that may learn OpenGL instructions on standard-in and write any consumer enter occasions to standard-out. Then a Bash script might begin this interpreter linked to pipes, and every OpenGL command may very well be a Bash operate that writes to the pipe. While I used to be at it, I made a decision to throw in my whole bag of effectivity tips and write the interpreter in plain C with some statically compiled hash tables and red-black trees.
OpenGL speedy mode
The OpenGL particulars are the place this undertaking begins to intersect with the DeLorean dashboard undertaking. First, I will take a step again and recap the OpenGL API.
OpenGL is all about writing a program that plans out its graphics by way of 3D coordinates and textures, then ships that knowledge over to the graphics card to be rendered to a 2D display screen. To be actually simplistic, there’s a set of math you employ to explain the area of the display screen being painted, and a set of math to explain the colour of every pixel in that area.
The commonest operation is to explain three corners of a triangle in a digital 3D house, let OpenGL work out the place that lands on a 2D display screen, then inform it to stretch a 2D picture throughout that space, possibly additionally mixed with one other picture or altered by some brightness calculations. The essential loop of this system generates one body of video by wiping the buffer, plotting each polygon that may be seen, and sending it to the display screen. If you pull off this whole stunt in 16 milliseconds or much less, you possibly can keep 60 frames per second and have good fluid graphics.
I am unable to converse with authority in regards to the origins of the OpenGL API, but it surely appears fairly clear that it’s constructed across the thought of streaming, most likely to be appropriate with the X11 show protocol, but in addition simply because it is a good suggestion. So, most OpenGL features do not need a return worth, versus different APIs the place every operate name returns a standing that tells you the result of the operation. If you visualize an OpenGL operate equivalent to
glVertex3f(1,2,three) as a print assertion that writes three numbers over a pipe, you’ve got received a fairly good thought the way it works behind the scenes. In reality, for the Bash bindings, I actually write
glVertex 1 2 three over the pipe when
glVertex 1 2 three is executed. The Bash script runs blind, with none thought whether or not its graphics instructions are doing something as supposed.
There have been a number of huge revisions to the OpenGL API through the years, and other people write whole chapters of their books about “retained” vs. “immediate” modes, but it surely all boils down to 2 ideas:
- It’s gradual to resend all that knowledge over the pipe every body, so let’s cache a few of it on the opposite finish.
- We can by no means fulfill everybody’s wants with the built-in math, so let’s give individuals a language to explain their very own customized math.
That stated, whereas the caching and customized math supplied by the brand new OpenGL APIs are rather more environment friendly and positively wanted for top-tier video video games, they’re additionally extra effort to arrange and work with (and study) and possibly do extra hurt than good to hobbyists. They’re additionally pointless until you are doing superior graphics results or high-detail fashions.
So, though the Bash OpenGL bindings solely cope with the “deprecated” API, I nonetheless encourage individuals to have a look at it for training and tinkering functions.
Luckily, the unique OpenGL API has some caching mechanisms, and so they’re straightforward to make use of. They work roughly alongside the sequence of:
“Hey OpenGL, I want you to create object 37 on the remote end”
“Here’s some data describing object 37”
“Use object 37 in the next rendering steps”
To make it even simpler, the Bash bindings allow you to use names as an alternative of numbers.
The first essential sort of object is the feel, the place you load a 2D picture into the graphics card after which “paint” polygons with it. The second is the “display list,” the place you file a sequence of OpenGL instructions, then play them again as in the event that they had been a single OpenGL command.
Display lists work nice for ad-hoc prototyping. You can plot out some factors describing your 3D (or 2D) mannequin utilizing easy vertex instructions, then file that sequence of factors as a show listing, and now you possibly can render that mannequin with a single command.
For an instance of this energy, try Robot.sh within the Examples directory. It creates one show listing for every phase of the robotic’s physique at startup, and whereas working, it solely emits 58 traces of textual content per body to render the robotic. Bash can fairly simply generate 58 traces of textual content in 16 milliseconds (it even might 12 years in the past), so the demo was in a position to run at full pace on widespread hardware.
Display lists are the first trick I carried over to the Perl graphics I am utilizing within the DeLorean dashboard software program. Perl operate calls are a bit costly in comparison with C, particularly for a function-heavy API like OpenGL 1.four, however by combining issues into show lists, Perl would not have a lot work to do per video body. If I hadn’t realized this trick for the Bash undertaking, the Perl undertaking would not have been practically as profitable.
Why did not I publish this 12 years in the past?
While I used to be in a position to create some fancy animation demos in Bash, my precise objective was to create an entire sport with it. I used to be aiming for a clone of the previous flight-sim sport Terminal Velocity, and I received so far as a spaceship that might fly via a subject of cubes (see Flight.sh within the Examples), however the subsequent downside was collision detection. The primitives out there in Bash are the worldwide “associative array” of variable names and array variables (though model four now has associate-array variables), and all math is integers. While I used to be in a position to pull off 3D matrix rotations in fixed-point integer math, implementing collision detection seemed like too giant of an impediment. I used to be additionally not glad with my font API. While pondering options for these issues, the undertaking regularly fell off my listing.
This is the place I concluded (as I wrote), “Bash is a horrible glue language.” While this undertaking began and ended as a joke (or training device, possibly), the identical program type in Perl turned out to be fairly helpful for actual purposes. If I would given Frozen Bubble extra severe consideration 13 years in the past, I may need been in a position to get a head begin on Perl, my now-favorite language.
I haven’t got any plans to boost this undertaking except for bug fixes, however I figured it might at the least be helpful to individuals eager to study the ideas of OpenGL or somebody with a bunch of free time and a powerful want to put in writing a Doom clone in M4.
Enjoy! And have enjoyable forwarding this hyperlink, in any other case, nobody will consider you.