Direct3D Transforms Applied To Vertex Bufer When?

Started by
6 comments, last by Muhammad Haggag 19 years, 7 months ago
I'm reading up on Direct3D. I understand about setting up the vertex buffer and even creating the transformation matrices (I think). But my question is, when is the vertex list transformed by the matrices (world, view, etc.)? Does Direct3D know which is which by the DTS_WORLD type tags and apply them in order when we ask it to draw a primitive? I hope I'm being clear. I would have expected that there would have to be a call that tells Direct3D to apply the transformation matrices we've set up to the vertex list. Or have I got it all wrong?
Advertisement
Direct3D will handle the transforms automatically during the processing of draw*primitive* calls - unless the vertex format has the rhw component indicating that the vertex data is pre-transformed.

Niko Suni

It is important to understand that the fixed-function-pipeline is just a collection of shaders that are supported on graphics hardware. The world, view, and projection transforms are applied to the vertices on a per-vertex basis, in the vertex shader. They are actually multiplied together, to form one final transform:

matFinalTransform = matWorld * matView * matProjection

Consider this:

float4 MyVertexShader( float4 positionIn ){   // This is our vertex shader.  Most vertex shaders start off like this   // matWorldViewProj is a constant.  It holds the (world * view * proj) matrix   float4 positionOut;   positionOut = mul( positionIn, matWorldViewProj );   return positionOut;}


If you don't know much (or anything) about shaders, then you probably won't really understand this.
Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )
In which Donavon tries to explain this using his admittedly creaky power of metaphor:

When you call one of the DrawPrimitive functions, you are basically pushing a button on a machine (the 3D hardware). The machine will take in the vertices (and possibly indices) that you've set up to be fed in on the input end. You've already configured the machine with transformation matrices and lighting/material values, plus a bunch of other crap. (Forget about shaders for in this discussion.) So the vertex and index conveyor belts start up, feeding raw materials into the machine.

After a number of stages, what the machine spits out are color values into the render target, depth values into the z-buffer, and stencil values into the stencil buffer, depending on what configuration of these outputs you've set it up for.

Note that there are no other outputs (at least not on DX8-class machines, and assuming I haven't overlooked anything in my tired state[smile]). The transformation of vertices that you're asking about occurs inside the machine. Nobody gets to see the results, not directly. They are not an output.

If you want access to the transformed (and/or lit) vertices, you have to forget about the machine down on the factory floor, because again, it is not designed to spit that sort of thing out. Instead you have to use your crack team of software vertex processors. They work in the CPU department, and the way to give them orders for this sort of job is with the ProcessVertices function. This is a function exclusively of the CPU department. They can take your vertices (and/or indices, etc.) and process them in the same way that the machine does, but sometimes slower, and eh, maybe sometimes even faster. And unlike the machine, they can give you back the results.

(Parenthetically, this metaphor helps explain why it's important to batch as many primitives as you can into Draw*Primitives calls: Because reconfiguring the machine involves stopping part or all of it for the reconfiguration process.)

I don't know, does that help? [smile]
Donavon KeithleyNo, Inky Death Vole!
Thanks all! That does help. I thought as much, but I wanted to make sure. It seemed to make sense given that we had to tag the transformation matrices we set up as WORLD, VIEW, etc...so DirectX knows which is which as we aren't applying them ourselves.

I read somewhere the DirectX will combine the 3 transforms into one matrix before it applies them. So, should we still do this in our code? Or is this a waste of time given that DirectX will try to do it again?

And yes, Donavon, your analogy is a good one. :)
Quote:Original post by Low Bias
I read somewhere the DirectX will combine the 3 transforms into one matrix before it applies them. So, should we still do this in our code? Or is this a waste of time given that DirectX will try to do it again?

Typically, the matrices are concatenated into one matrix before transforming the vertices.
However, when you're setting the matrices (IDirect3DDevice9::SetTransform), set each one separately - this gives you the ability to change just one at a time (Typically, the projection matrix is constant, world and view matrices change all the time).

However, when you're transforming the vertices on the CPU for some reason, concatenate the matrices first.

also as an optimization I employ:

proj = constant (set at init)
view = identity
world = (view * world)

because setting each of these matrices on the device is more costly than multiplying view * world and setting only 1.
DXSDK docs have an explanation and an example if u look under performance tips.
________________
"I'm starting to think that maybe it's wrong to put someone who thinks they're a Vietnamese prostitute on a bull"       -- Stan from South Park
Lab74 Entertainment | Project Razor Online: the Future of Racing (flashsite preview)
Quote:Original post by dhanji
proj = constant (set at init)
view = identity
world = (view * world)

You meant "world = world * view", right?
World transforms from model space to world space, view transforms from world space to camera space.

This topic is closed to new replies.

Advertisement