The position semantic is special -- it's used by the rasterizer to figure out how all the other values should be interpolated.
Why would oDepth be divided by oPos.w automatically? It uses the TEXCOORD0 semantic, not SV_Position.
I had this slightly wrong; what happens in normal usage is that the PS receives:
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.
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 correctionIf 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 3This 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...
^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.
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.