Why would oDepth be divided by oPos.w automatically? It uses the TEXCOORD0 semantic, not SV_Position.
The position semantic is special -- it's used by the rasterizer to figure out how all the other values should be interpolated.
i.e. oDepth is divided by oPos.w automatically in-between the vertex and pixel shader, during rasterization/interpolation.
So if in the vertex shader you write "oDepth = oPos.z/oPos.w", then in the pixel shader, oDepth will equal oPos.z/oPos.w/oPos.w.
I had this slightly wrong; what happens in normal usage is that the PS receives:
PS.input.oDepth = interpolate(oPos.z/oPos.w)*interpolate(oPos.w)if in the vertex shader you write "oDepth = oPos.z/oPos.w", then in the pixel shader you get:
PS.input.oDepth = interpolate(oPos.z/oPos.w/oPos.w)*interpolate(oPos.w)Say you've got some regular code like this:
VS:
output.pos = mul(...);
output.texcoord = ...
PS:
float color = tex2D( input.texcoord );
The hardware will perform perspective correct interpolation of all your PS-inputs/VS-outputs.
It does this by:
1) At the end of the vertex shader, every interpolant is divided by
w.
2) An extra hidden interpolant is created, which holds the value of
1/w.
3) At the start of the pixel shader, every interpolant is divided by the interpolated value of
1/w.
Thanks to the GPU doing this behind the scenes, you get results like in
Image A here, otherwise if the GPU didn't do this, you'd get results like in
Image B, which looks like PS1 games did...
If you want to disable perspective-correction and see the PS1-esque results for yourself, then at the end of your vertex shader, perform the perspective division yourself (
which also sets w to 1, which disables the above 3 steps)
output.position /= output.position.w;//disable hardware perspective correction
If you want to verify that the above 3 steps are what actually happens, then create the hidden "
1/w" interpolant yourself and use it in the PS:
VS:
output.texcoord /= output.position.w; // step 1
output.hidden = 1/output.position.w; // step 2
output.position /= output.position.w;//disable hardware perspective correction
PS:
input.texcood /= input.hidden; // step 3
This code should give you the same results as the regular, built-in hardware version... except that doing "
output.position /= output.position.w" in the VS can cause the GPU to cause some clipping problems, etc...
However, none of this is necessary. Just use a depth-stencil target instead of a colour target, and don't do anything special to output depth besides just rasterizing triangles as usual and have the hardware write them to the depth buffer.
^This is worth repeating though. If you simply want to output
z/w to a texture, then use a depth-stencil target and just let the rasterizer do it all automatically.