The Direct3D rendering pipeline

20-Dec-1998

I mean here, Direct3D Immediate mode, of course. And also, I'll be considering the pipeline of DirectX 6 only.

This page is dedicated to the Direct3D rendering pipeline. I'll try to document it as well as I can, and hopefully other people will be able to fill in the gaps of my ignorance.

The reason for writing this page is so that I can try to make some sense of all the available information about the pipeline, and to put it together in a way that will allow me (and any other reader) to understand how that pipeline works, and also, to pinpoint any deviation from this encountered in any particular imlpementation. So far, I haven't seen any literature that clearly describes this pipeline in detail.

Note that I'm not interested in the actual, real implementation of this pipeline. There can, in fact, be many different implementations (imagine different involvements of hardware in different implementations, and you'll see what I mean). The pipeline steps don't even need to be distinct, and sometimes, they can even be out of order in a particular implementation. What matters are the results. They must match the results of the documented pipeline.

For starters, there's a geometry stage in the pipeline that is, as far as I understand, simplicity itself. It can be viewed as a black-box that gets a list of vertices in an input format, and outputs the same vertices in an output format. The output formats are Transformed, Lit vertices (TLvertices), of varying amount of UV-coordinate sets. The input formats are many (considering the combinations of Flexible Vertex Format flags), but they fall into two categories: Untransformed, unlit vertices (ULvertices) and Untransformed, lit vertices (Lvertices).

The geometry pipeline, then, can be viewed as a two-stage pipeline:

It's important to note that all these geometry calculations are done without regard to the state of the texture pipeline, the blending modes, the filtering modes, etc... The only states that are used here are the LightStates and the Fog states.

When the time comes to actually render a primitive, Direct3D checks for clipping issues, and rearranges and reconstructs the vertices of the primitive as appropriate in order to have vertices that lay within the clipping region. It then passes the clipped TLvertices to the rasterizer. The rasterizer will then interpolate all values (coords, Z-buf, colors, ooW, UV coord sets...) throughout the primitive. That yields a full set of such values for each pixel (screen coordinates, z, oow, diffuse, alpha, sepcular, fog and U-V sets, maybe mip-map value) which are input into the pixel pipeline. This pipeline seems to have the following stages (and I say again: the order of operations doesn't necesarily have to match the one I describe here. Instead, the results must match those of the pipeline I portray):

And that's it. It looks a lot clearer to me after writing all this, actually. There are still a few dark spots, like, for example, what's the color-key involvement in this, alpha testing and so on.

Also this view here has revealed a few places where the pipeline could be improved. For example, if you want to do the specular color as an environment-map, and you want the polygon to be alpha-blended, it's impossible to render it in one pass. Of course, current hardware doesn't allow that, anyway, but maybe future hardware would.

This would be accomplished by specifying four new arguments for the texture stages:

With those arguments available, we could build up the following pipeline state, which would resolve that situation appropriately, and would also implement the blend, specular and fog within the texture pipeline:

SetTextureColorStage(dev, 0, D3DTA_DIFFUSE, D3DTOP_MODULATE, D3DTA_TEXTURE);
SetTextureColorStage(dev, 1, D3DTA_CURRENT, D3DTOP_BLENDTEXTUREALPHA, D3DTA_FBUFFER);
SetTextureColorStage(dev, 2, D3DTA_SPECULAR, D3DTOP_MODULATE, D3DTA_TEXTURE);
SetTextureColorStage(dev, 3, D3DTA_CURRENT, D3DTOP_ADD, D3DTA_CURRENT2);
SetTextureColorStage(dev, 4, D3DTA_CURRENT, D3DTOP_BLENDTEXTUREALPHA, D3DTA_FOGCOLOR);

SetTextureAlphaStage(dev, 0, D3DTA_DIFFUSE, D3DTOP_MODULATE, D3DTA_TEXTURE); // I know it's not so normal to modulate them, but I like it this way.
SetTextureAlphaStage(dev, 1, D3DTA_CURRENT, D3DTOP_SELECTARG1, D3DTA_CURRENT);
SetTextureAlphaStage(dev, 2, D3DTA_SPECULAR, D3DTOP_SELECTARG1, D3DTA_CURRENT);
SetTextureAlphaStage(dev, 3, D3DTA_CURRENT, D3DTOP_SELECTARG1, D3DTA_CURRENT);
SetTextureAlphaStage(dev, 4, D3DTA_CURRENT, D3DTOP_SELECTARG1, D3DTA_CURRENT);

Ok. This is enough. I want ideas, comments, suggestions, clarifications, corrections, jokes, or any other kind of feedback about all this. Except flames, of course.

All trademarked things I mention here are TM by their respective owners. If you are one of those owners and want to be specifically mentioned, please, contact me and I'll include it.

Go back to the main index of JCAB's Rumblings

Wow! Very large number here... :) hits and increasing...

To contact JCAB: jcab@JCABs-Rumblings.com

Last updated: [an error occurred while processing this directive]


Did you like this page? Did you dislike it? Do you have any comments or questions? This is your chance! Just type some text in the box below and click on the "send" button.

Your name:

Your email:

Subject: