aboutsummaryrefslogtreecommitdiff
path: root/src/GPU3D_Soft.cpp
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-04-22 18:04:54 +0200
committerStapleButter <thetotalworm@gmail.com>2017-04-22 18:04:54 +0200
commita086e220233ba2754913868372d6c0a421141467 (patch)
tree5bf1236917d3113275478c286a83bbeaddb933fa /src/GPU3D_Soft.cpp
parent70c72004acb079ff669d2916ba9fc0144f32472a (diff)
attempt at shadows. they're still a bit weird tho.
Diffstat (limited to 'src/GPU3D_Soft.cpp')
-rw-r--r--src/GPU3D_Soft.cpp60
1 files changed, 51 insertions, 9 deletions
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index 888b823..2ca3100 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -36,6 +36,12 @@ u32 AttrBuffer[256*192];
// bit24-29: polygon ID
// bit30: translucent flag
+u8 StencilBuffer[256*192];
+
+// note: the stencil buffer isn't emulated properly.
+// emulating it properly would require rendering polygons per-scanline
+// the stencil buffer is normally limited to 2 scanlines
+
bool Init()
{
@@ -662,9 +668,6 @@ void RenderPolygon(Polygon* polygon)
if (rnext >= nverts) rnext = 0;
}
-
- /*s32 dxl, dxr;
- s32 lslope, rslope;*/
Slope slopeL, slopeR;
s32 xL, xR;
bool l_xmajor, r_xmajor;
@@ -736,6 +739,13 @@ void RenderPolygon(Polygon* polygon)
}
if (ybot > 192) ybot = 192;
+
+ if (polygon->ClearStencil)
+ {
+ s32 height = ybot - ytop;
+ memset(&StencilBuffer[ytop*256], 0, height*256);
+ }
+
for (s32 y = ytop; y < ybot; y++)
{
if (!isline)
@@ -903,11 +913,43 @@ void RenderPolygon(Polygon* polygon)
if (wireframe && edge==0)
continue;
- interpX.SetX(x);
-
u32 pixeladdr = (y*256) + x;
+ u32 attr = polygon->Attr & 0x3F008000;
+
+ // check stencil buffer for shadows
+ if (polygon->IsShadow)
+ {
+ if (StencilBuffer[pixeladdr] == 0)
+ continue;
+ }
+
+ interpX.SetX(x);
s32 z = interpX.InterpolateZ(zl, zr);
+
+ if (polygon->IsShadowMask)
+ {
+ // for shadow masks: set stencil bits where the depth test fails.
+ // draw nothing.
+
+ // checkme
+ if (polyalpha == 31)
+ {
+ if (!wireframe)
+ {
+ if ((edge & 0x1) && !l_filledge)
+ continue;
+ if ((edge & 0x2) && !r_filledge)
+ continue;
+ }
+ }
+
+ if (!fnDepthTest(DepthBuffer[pixeladdr], z))
+ StencilBuffer[pixeladdr] = 1;
+
+ continue;
+ }
+
if (!fnDepthTest(DepthBuffer[pixeladdr], z))
continue;
@@ -919,8 +961,6 @@ void RenderPolygon(Polygon* polygon)
s16 t = interpX.Interpolate(tl, tr);
u32 color = RenderPixel(polygon, vr>>3, vg>>3, vb>>3, s, t);
- u32 attr = polygon->Attr & 0x3F008000;
-
u8 alpha = color >> 24;
// alpha test
@@ -952,11 +992,13 @@ void RenderPolygon(Polygon* polygon)
{
u32 dstattr = AttrBuffer[pixeladdr];
attr |= (1<<30);
+ if (polygon->IsShadow) dstattr |= (1<<30);
// skip if polygon IDs are equal
// note: this only happens if the destination pixel was translucent
- // the GPU keeps track of which pixels are translucent, regardless of
- // the destination alpha
+ // or always when drawing a shadow
+ // (the GPU keeps track of which pixels are translucent, regardless of
+ // the destination alpha)
if ((dstattr & 0x7F000000) == (attr & 0x7F000000))
continue;