When I first began building a DirectX graphics engine, I ran into an almost ironic problem. I couldn't find out how to implement the features I wanted to write in Direct3D. It was particularly bad with certain features such as BSP rendering; all the examples I found were in OpenGL. I've ported OpenGL code to Direct3D before, but problems arose when people decided to use the glVertex* family of commands. There just isn't anything like them in Direct3D. It got even worse when I needed to write some sort of culling or polygon reduction algorithm and the easiest way to do it was vertex by vertex, face by face. I never found any examples that had used OpenGL's vertex array commands, which have Direct3D counterparts. Recently, I came up with a rather clever idea. I figured that it should be possible to write the OpenGL vertex commands in Direct3D so that the vertices could be specified one by one, but they would still be sent down the graphics pipeline in a vertex buffer. The overhead incurred would be minimal, and it would be extremely useful. Porting code from OpenGL to Direct3D would be simplified greatly; it would be easier to write multi-API code.
It's important to realize that I am not going to develop a Direct3D wrapper using OpenGL commands. I am essentially implementing a new set of commands for the Direct3D API. We will follow the OpenGL naming conventions for our new commands and approximately the same argument format. In this particular article, I will show how to implement the following commands:
d3dBegin( D3DPRIMITIVETYPE Type, IDirect3DDevice8* pDevice ); d3dEnd(); d3dVertex3f( float x, float y, float z ); d3dNormal3f( float x, float y, float z ); d3dColor4f( float a, float r, float g, float b ); d3dTexCoord2f( float tu, float tv );
I decided that these were the core set of commands necessary for the implementation. Once you see the functions, it will be very easy to add more versions (e.g. d3dColor4ub) of these functions, as well as whole new functions. The next step, though, is to determine exactly what each of these functions should do.
I considered whether or not to write these as regular C functions, or to build a C++ class out of them. While a C++ class would have some advantages, primarily that it would allow multiple sets of vertices, it's not really all that useful. In addition, I'm trying to follow OpenGL's model as closely as possible, so we'll write them in regular C style. (NOTE: This code is C++, not C! We'll be using C++ to avoid the painfully long calls involved with coding DirectX in C.) In order to write these functions in C style, we will need a number of static variables in the CPP file along with the function implementations.
For the definitions of these functions, I've stayed as close as reasonably possible to the definitions for their OpenGL counterparts. There are only two changes. First of all, we need to get the device pointer somewhere; I decided to get it in the call to d3dBegin(). Second, OpenGL usually takes its colors in RGBA, but Direct3D likes them in ARGB format. I changed d3dColor4f() to use ARGB color order. It's not so important for that particular call, but it will become important if you ever write d3dColor4fv, which takes a pointer to the color locations.
d3dBegin( D3DPRIMITIVETYPE Type, IDirect3DDevice8* pDevice );
d3dVertex( float x, float y, float z );
d3dNormal3f( float x, float y, float z );
d3dColor4f( float a, float r, float g, float b );
d3dTexCoord2f( float tu, float tv );