dx9: the depth is the position's, as the chip has it

The Direct3D 9 renderer as the others (rend/depth_scale.h): the depth
is the vertex position's, by the fixed functions, and no pixel shader
writes DEPTH. transformVertex(), which places the vertices of both
vertex shaders, gives z = S instead of 0: a depth of S*z, the chip's 1/w
up to 1 at fZ_max, reversed, in the D24FS8 depth buffer where the device
has that format (it was already preferred) and D24S8 where not (a float
depth surface without stencil is no use here: the shadows need the
stencil); z is clamped to w, so a vertex beyond fZ_max is at depth 1 and
not clipped. S, 1/fZ_max, and the inverse of the matrix's z scale are
vertex constant register c3. Shader model 3 has no precise: the same
text in the two shaders is what there is, and a polygon drawn again for
its shadow (EQUAL) and the sorted depth prepass are placed by it.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-10-20 01:52:51 +02:00
1 parent 68ca18ffe2
commit b78383f9e4
4 files changed
+16 -14

No files matched your search

+2
View File
@@ -503,6 +503,8 @@ void DX9Renderer::SetupFrame()
{ normal.tx, -normal.ty, normal.tz, 0.f },
};
device->SetVertexShaderConstantF(DX9VC_NormalScale, &vtx[0][0], 2);
const float depthScale[4] = { pvr_depth_scale(pvrrc.fZ_max), 1.f / normal.sz, 0.f, 0.f };
device->SetVertexShaderConstantF(DX9VC_DepthScale, depthScale, 1);
float frag[5][4] = {};
// the clamping limits
+1
View File
@@ -28,6 +28,7 @@
#include "rend/tileclip.h"
#include "rend/transform_matrix.h"
#include "rend/shadows.h"
#include "rend/depth_scale.h"
#include "dx9context_lr.h"
#include "dx9_texture.h"
#include "dx9_texdecoder.h"
+12 -14
View File
@@ -26,8 +26,11 @@
* interpolation brings to the inverse of the straight line's value.
* - A pixel's centre is where its coordinates are whole numbers, and not
* half a pixel further on: the vertices are moved back by half a pixel.
* - No depth clipping can be turned off: the clip space's z is 0, inside
* the clip volume, and the depth is the pixel shader's own anyway.
* - The depth is the position's, as in the other renderers
* (rend/depth_scale.h): the vertex goes out at z = S, a depth of S*z,
* the guest's 1/w up to 1 at fZ_max; no pixel shader writes a depth, and
* one function places the vertices of every shader. (Shader model 3 has
* no precise: the same text in every shader is what there is.)
* - Vertex colours are read as D3DCOLOR, blue in the first byte: the
* vertices have red there, and the vertex shader puts it back.
* - Flat shading is the device's (D3DRS_SHADEMODE), as is culling. */
@@ -39,18 +42,22 @@ static const char VertexTransform[] = R"(
float4 normalScale : register(c0);
float4 normalOffset : register(c1);
float4 halfPixel : register(c2);
// 1/fZ_max, and the inverse of what the matrix scales z by (rend/depth_scale.h)
float4 depthScale : register(c3);
// A vertex's z is the guest's 1/w. It is made the clip space w's inverse,
// and x and y are multiplied by w, so that the division by it leaves them
// where they are and everything in between is interpolated with the
// perspective.
// perspective. The clip space z is S, so that the depth is S*z: the
// guest's 1/w, linear across the screen, as the chip has it.
float4 transformVertex(float3 pos, out float invW)
{
float4 vpos = float4(pos * normalScale.xyz + normalOffset.xyz, 1.0);
vpos.w = 1.0 / vpos.z;
invW = vpos.w;
vpos.xy = (vpos.xy + halfPixel.xy) * vpos.w;
vpos.z = 0.0;
// (a z beyond fZ_max is at depth 1, not clipped)
vpos.z = min(depthScale.x * depthScale.y, vpos.w);
return vpos;
}
)";
@@ -163,17 +170,10 @@ float fog_mode2(float w)
return floor((next * blend + cur * (255.0 - blend)) / 256.0) / 256.0;
}
// The depth written: the same function of 1/w as the other renderers write
float fragDepth(float w)
{
w *= 100000.0;
return log2(1.0 + max(w, -0.999999)) / 34.0;
}
// (the depth is the position's, which the depth test took: none written here)
struct PSO
{
float4 col : COLOR0;
float depth : DEPTH;
};
)";
@@ -344,7 +344,6 @@ PSO main(in Pixel inpix)
discard;
PSO pso;
pso.depth = fragDepth(w);
pso.col = color;
return pso;
}
@@ -356,7 +355,6 @@ static const char ModVolPixelShaderSource[] = R"(
PSO main(in float invW : TEXCOORD1)
{
PSO pso;
pso.depth = fragDepth(1.0 / invW);
pso.col = float4(0.0, 0.0, 0.0, 1.0 - frameParams.z);
return pso;
}
+1
View File
@@ -84,6 +84,7 @@ enum
DX9VC_NormalScale = 0,
DX9VC_NormalOffset = 1,
DX9VC_HalfPixel = 2, // half a pixel of the viewport, in clip space
DX9VC_DepthScale = 3, // 1/fZ_max, 1 / the normal matrix's z scale (rend/depth_scale.h)
// pixel shaders: the frame's, c0 to c4, and the polygon's, c5 and c6
DX9PC_ColorClampMin = 0,
DX9PC_ColorClampMax = 1,