Do you hate it when you go to the movies and all films are in “super awesome and modern 3D!!!11!One!”? Fear not you can now look silly while using your PC as well! Here’s how cool you will not look like:
Nvidia launched a new product called Nvidia 3D Vision quite some time ago. It enables people with capable displays to play their beloved games in 3D with the help of a pair of shutter glasses like the guy in the image above wears. As a game developer all you need to do is make sure that your billboards and HUD elements adhere to some basic rules that you usually stick to already. The rest is done by the driver automatically. The shutter glasses are synchronized to the display via a small USB IR-station (i think it’s IR). Plug it in, “start” your glasses and enable 3D-Vision in the driver settings and you are ready to go. Unless…
Unless your game uses OpenGL. Nvidia cleverly decided that it would support DirectX on standard consumer graphics hardware. Want driver support for OpenGL as well? Well, well Sir, buy yourself a multiple thousand dollar Nvidia Quadro first! Then we’ll (maybe) grant you the proper drivers!
I’m a bit silly so i decided to make 3D Vision work with OpenGL on the desktop on consumer level graphics hardware. What would be needed is something that translates OpenGL (ES) to DirectX 9/10/11 calls. There are a couple of old projects that do just that. One of them is called GLDirect which i tried ages ago and never really worked satisfactory for me. It’s also no longer maintained so i chose not to use it.
I remembered a sort of child project of Google Chrome that delegates OpenGL ES 2.0 (or WebGL for that matter) calls to DirectX 9. Why do they do that? Generally non-gaming people don’t have OpenGL drivers installed on their Windows PC. However, Windows XP and newer all come with DirectX 9. So, to make sure everyone can experience those nice and shiny new WebGL demos in their Chrome some Google and Transgaming folks decided to writer a wrapper for DirectX 9 that implements the EGL 1.2 and OpenGL ES 2.0 standard. The project is called Angle, is BSD licensed and generally awesome! Exactly what i needed.
Upon closer inspection that had a little problem though: there’s no fullscreen suppport in Angle and 3D-Vision only runs in fullscreen. Given the clean source of the Angle project it was not a big deal to hack support for fullscreen in. The Angle folks also adopted the es-utils developed for the book “OpenGL ES 2.0 Programming Guide” (buy it today, it’s good!). This is basically a very thin wrapper around EGL and the Win32API (or in the books case the PowerVR emu lib afair). It sets up a window and performs the standard Win32 event dispatching. Give that this code base was also pretty neat i modified it as well: i added fullscreen support to the initialization routines of the es-utils along with some callback methods that will give you window and input events (e.g. resize, mouse drag, keyboard events etc.).
The end result is 2 dlls, one for EGL 1.2 and one for OpenGL ES 2.0 as well as a pretty lean es-utils framework which you can directly include in source form into your project (or make it a dll as well if you care). Here’s the main method of the HelloTriangle example from the book adopted to my Angle fork:
int main ( int argc, char *argv )
esInitContext ( &esContext );
esContext.userData = &userData;
esCreateWindow ( &esContext, TEXT("Hello Triangle"), 480, 320, ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_FULLSCREEN);
if ( !Init ( &esContext ) )
esRegisterDrawFunc ( &esContext, Draw );
esRegisterKeyFunc ( &esContext, OnKey );
esMainLoop ( &esContext );
Pretty slick eh? So, having that working i wanted to make it a backend for libgdx so we can have 3D-Vision out of the box for libgdx apps as well. Here’s what i did.
First i created a lightweight JNI bridge for the es-utils, with all things like callbacks and so on. This way we don’t care for things like handling EGL directly or creating a Win32 window + dispatch loop. The Java code looks almost exactly the same as the C code above. Next up was another problem: i needed a JNI bridge for the OpenGL ES 2.0 API as well. Luckily i had already written such a thing for Android earlier this year to compensate the non-existant support from the Android API on the Java side. I was able to reuse it without any major modifications so that took like 15 minutes to add. Awesome!
Now i have a fully working JNI wrapper for the Angle project that is insanely easy to use. It looks a little like Lwjgl from a usage perspective, just even leaner :). Based on this i started writting a libgdx backend which is already finished but i didn’t add it to SVN yet.
And that’s how that went. I’m extremely grateful to the fine folks over at Google and Transgaming for providing humanity with the Angle project. They actually did all the hard work, i just added some minor feature that was easy to include due to the well written code base. I already have a couple of ideas how to exploit Angle further so we’ll see.
I’ll let the new libgdx backend go live in a few days. Still needs some more testing. Also, if you paid attention you’ll have noticed that this will only work on Windows! Don’t complain if it blows up on Linux or your Mac! Nothing i can do about it!
You can find my fork at http://code.google.com/p/angle-fullscreen/. For the JNI wrapper i’ll setup another Google Code project. Have fun!