Sticking to the Anti-Direct3D camp

(February 21, 2006)

As I already mentioned some time ago, the 3D API of my choice is OpenGL. There are two main reasons not to use Direct3D, the only alternative to GL. The first reason is of course platform-(in)dependence, because I develop stuff for both Windows and non-Windows systems. OK, platform-independence isn’t really a crucial issue for demos as Win32 is the main platform for new-school demoscene stuff nowadays. (Nevertheless, a multi-platform demo still gets some additional appreciation, but that’s nothing you’re going to win a compo with.)

Reason number two: Direct3D is said to be much more complex. I don’t have seen much Direct3D code yet, so this part is mostly prejudice. Today, after a brief IRC conversation with a friend who codes D3D stuff for a living, I decided to give the DirectX Sample Browser (which is part of the SDK) a try. I really wanted to rethink my attitude towards Direct3D. Alas, it ended in disaster — instead of curing me from my aversion for D3D, looking at the tutorials reinforced my anti-D3D opinion …

The Tutorials

The documentation of the tutorials is quite good: There’s a .chm file with detailed and interesting text, accompanied by a VC++ project with nicely commented code for each lesson.

Tutorial 1: Creating a Device made me somewhat optimistic. The amount of code needed to create a Direct3D device instance is roughly on par with an equivalent OpenGL render context creation. Having to wrap all rendering code into a pair of BeginScene()EndScene() calls is strange, but nothing I couldn’t live with.

Tutorial 2: Rendering Vertices already absorbed a bit of this optimism. All Rendering has to be done via vertex buffers, which is not a sign of good API design. (Remember »Keep simple things simple, but make complicated this possible«?) OK, Direct3D is a rather low-level API made for experienced programmers who want to get the maximum out of the hardware, so I let it pass.

The nice thing about Direct3D’s vertex buffers their array-of-flexible-structure organization (in contrast to OpenGL’s oddball structure-of-array approach). »Flexible« means that the contents of a vertex structure can be defined by the programmer. The structure members have to be in the correct order, but unneeded elements can easily be left out. For example, if a vertex structure like {float x,y,z,w; uint32_t color;} is desired, a Flexible Vertex Format (FVF) identifier of (D3DFVF_XYZRHW|D3DFVF_DIFFUSE) is passed to the CreateVertexBuffer() that create the IDirect3DVertexBuffer9 object.

However, filling the vertex buffer’s data area is quite cumbersome, just as with DirectSound buffers found elsewhere in the DirectX API. The buffer has to be Lock()ed to get a pointer to its data area, vertex data has to be memcpy()ed into it, and it has to be Unlock()ed again. This makes a total of 6 API calls (create – lock – copy – unlock – draw – destroy) to draw a bunch of triangles, 4 calls if the buffer instance can be kept global, or 3 calls if the vertex data can be generated in-place inside the locked buffer. Why can’t there just be a single-call function that draws a set of polygons from a buffer located somewhere in memory?
Edit: (2006-02-21) I figured out just now that there’s a method IDirect3DDevice9::DrawPrimitiveUP that does exactly what I wanted.

I finally stopped reading at Tutorial 3: Using Matrices. Direct3D uses three instead of OpenGL’s two transformation matrices, which basically is fine with me. The really, really, really bad thing is the complete absence of any matrix management functions. Oh wait, there’s IDirect3DDevice9::MultiplyTransform(), a more-or-less exact equivalent of glMultMatrix(). But there’s no direct way of doing any standard transformations like translation, rotation or scaling. A matrix stack? Forget it.


All this crucial core functionality is only available in D3DX, an external library that ships with the DirectX SDK. D3DX is for Direct3D what GLU is for OpenGL: an tool library with useful all-day functions. However, there are two huge differences. Firstly, GLU is really an addition for higher-level operations like drawing spheres, cylinders, disks or even NURBS. The only GLU functions that really offer functionality I’d consider as »basic« are gluLookAt and gluPerspective. The situation with D3DX is completely different: You can’t even do a simple rotation without it.

This would not be an issue if D3DX was an integral part of the Direct3D runtime, as GLU comes with every OpenGL implementation. But this isn’t the case. D3DX’ status is really hard to tell, mainly because it changes every year. It started its life as a static library that was linked into every program that used D3DX. Some time ago, Microsoft decided to make a DLL from it, which usually doesn’t pose a problem, unless it is not part of the DirectX end-user runtime package. This means no one with a clean Windows+DirectX installation has the library on the system and the developer has to ship the DLL together with the program. (Which is a no-go for me, because I absolutely don’t like depenencies on non-standard DLLs. That’s the reason why I don’t use GLUT any longer.) To make things worse, there’s not one DLL, there are many of them. Every new version of the DX SDK (there are about 3 releases a year) ships with another version of the library, of course with another name as well.

Rumor has it Microsoft is going to finally include the DLLs in the end-user runtime, but this isn’t a stable solution until they stop changing the DLL name with every SDK release. Requiring the user to have a newer DirectX sub-sub-sub-version than the developer is unacceptable. Thus, D3DX was and still is unbearable for a developer like me who wants to create small programs (read: intros) of 64k or even 4k total code size. And even with D3DX enabled, I think that there would be more overhead in the code than it would have been with OpenGL.

Now add the facts that DirectX isn’t really pleasant to use in plain C, I don’t even have modern (DX9) headers for my favorite compiler, I totally dislike C++ and I’m not comfortable with Managed DirectX, you’ll perhaps understand why I neither like nor use Direct3D.

Post a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>