diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp index 1204e12fe4..b7cef6ccac 100644 --- a/GPU/Software/Clipper.cpp +++ b/GPU/Software/Clipper.cpp @@ -162,13 +162,16 @@ void ProcessQuad(VertexData* data) verts[1].drawpos.x = data[1].drawpos.x; verts[4].drawpos.x = data[0].drawpos.x; - // Color values of second vertex are used for the whole rectangle + // Color and depth values of second vertex are used for the whole rectangle verts[0].color0 = verts[1].color0; verts[1].color0 = verts[1].color0; verts[5].color0 = verts[1].color0; verts[0].color1 = verts[1].color1; verts[1].color1 = verts[1].color1; verts[5].color1 = verts[1].color1; + verts[0].drawpos.z = verts[1].drawpos.z; + verts[1].drawpos.z = verts[1].drawpos.z; + verts[5].drawpos.z = verts[1].drawpos.z; Rasterizer::DrawTriangle(verts); Rasterizer::DrawTriangle(verts+3); diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index cba4186f18..9c3c0ee6f4 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -21,6 +21,7 @@ #include "Rasterizer.h" extern u8* fb; +extern u8* depthbuf; namespace Rasterizer { @@ -100,7 +101,7 @@ void DrawTriangle(VertexData vertexdata[3]) minY = std::max(minY, gstate.getScissorY1()); maxY = std::min(maxY, gstate.getScissorY2()); - DrawingCoords p(minX, minY); + DrawingCoords p(minX, minY, 0); for (p.y = minY; p.y <= maxY; ++p.y) { for (p.x = minX; p.x <= maxX; ++p.x) @@ -114,6 +115,57 @@ void DrawTriangle(VertexData vertexdata[3]) if (w0 >=0 && w1 >= 0 && w2 >= 0) { float den = 1.0f/vertexdata[0].clippos.w * w0 + 1.0f/vertexdata[1].clippos.w * w1 + 1.0f/vertexdata[2].clippos.w * w2; + + // TODO: Depth range test + + // TODO: Is it safe to ignore gstate.isDepthTestEnabled() when clear mode is enabled? + if ((gstate.isDepthTestEnabled() && !gstate.isModeThrough()) || gstate.isModeClear()) { + u16 z = (u16)((vertexdata[0].drawpos.z * w0 / vertexdata[0].clippos.w + vertexdata[1].drawpos.z * w1 / vertexdata[1].clippos.w + vertexdata[2].drawpos.z * w2 / vertexdata[2].clippos.w) / den); + u16 reference_z = *(u16*)&depthbuf[p.x*2+p.y*(gstate.zbwidth&0x7C0)*2]; + bool pass = true; + + switch (gstate.getDepthTestFunc()) { + case GE_COMP_NEVER: + pass = false; + break; + + case GE_COMP_ALWAYS: + pass = true; + break; + + case GE_COMP_EQUAL: + pass = (z == reference_z); + break; + + case GE_COMP_NOTEQUAL: + pass = (z != reference_z); + break; + + case GE_COMP_LESS: + pass = (z < reference_z); + break; + + case GE_COMP_LEQUAL: + pass = (z <= reference_z); + break; + + case GE_COMP_GREATER: + pass = (z > reference_z); + break; + + case GE_COMP_GEQUAL: + pass = (z >= reference_z); + break; + } + + // Clear mode forces depth test func to be ALWAYS + if (!pass && !gstate.isModeClear()) + continue; + + if (gstate.isDepthWriteEnabled() || (gstate.clearmode&0x40)) // TODO: Correct to enable depth writing in the clearmode case? + *(u16*)&depthbuf[p.x*2+p.y*(gstate.zbwidth&0x7C0)*2] = z; + } + float s = (vertexdata[0].texturecoords.s() * w0 / vertexdata[0].clippos.w + vertexdata[1].texturecoords.s() * w1 / vertexdata[1].clippos.w + vertexdata[2].texturecoords.s() * w2 / vertexdata[2].clippos.w) / den; float t = (vertexdata[0].texturecoords.t() * w0 / vertexdata[0].clippos.w + vertexdata[1].texturecoords.t() * w1 / vertexdata[1].clippos.w + vertexdata[2].texturecoords.t() * w2 / vertexdata[2].clippos.w) / den; u32 color = 0; @@ -129,7 +181,7 @@ void DrawTriangle(VertexData vertexdata[3]) if (gstate.isTextureMapEnabled()) color |= /*TextureDecoder::*/SampleNearest(0, s, t); - *(u32*)&fb[p.x*4+p.y*(gstate.fbwidth&0x3C0)*4] = color; + *(u32*)&fb[p.x*4+p.y*(gstate.fbwidth&0x7C0)*4] = color; } } } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 9751eb27f8..f1d7c5457c 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -34,7 +34,8 @@ static GLint uni_tex = -1; static GLuint program; const int FB_HEIGHT = 272; -u8* fb = NULL; // TODO: Default address? +u8* fb = NULL; +u8* depthbuf = NULL; GLuint OpenGL_CompileProgram(const char* vertexShader, const char* fragmentShader) { @@ -135,7 +136,8 @@ SoftGPU::SoftGPU() attr_pos = glGetAttribLocation(program, "pos"); attr_tex = glGetAttribLocation(program, "TexCoordIn"); - fb = Memory::GetPointer(0x44000000); + fb = Memory::GetPointer(0x44000000); // TODO: correct default address? + depthbuf = Memory::GetPointer(0x44000000); // TODO: correct default address? } SoftGPU::~SoftGPU() @@ -531,6 +533,7 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_ZBUFPTR: { u32 ptr = op & 0xFFE000; + depthbuf = Memory::GetPointer(0x44000000 | (gstate.fbptr & 0xFFE000) | ((gstate.fbwidth & 0xFF0000) << 8)); DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); } break; @@ -538,6 +541,7 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_ZBUFWIDTH: { u32 w = data & 0xFFFFFF; + depthbuf = Memory::GetPointer(0x44000000 | (gstate.fbptr & 0xFFE000) | ((gstate.fbwidth & 0xFF0000) << 8)); DEBUG_LOG(G3D,"Zbuf Width: %i", w); } break; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index a2906bb91c..f51fa48619 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -63,6 +63,7 @@ DrawingCoords TransformUnit::ScreenToDrawing(const ScreenCoords& coords) // TODO: What to do when offset > coord? ret.x = (((u32)coords.x - (gstate.offsetx&0xffff))/16) & 0x3ff; ret.y = (((u32)coords.y - (gstate.offsety&0xffff))/16) & 0x3ff; + ret.z = coords.z; return ret; } @@ -152,6 +153,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type } else { data[i].drawpos.x = pos[0]; data[i].drawpos.y = pos[1]; + data[i].drawpos.z = 0; // TODO: Not sure if that's what we should do here } } diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index 1a4844702c..b6f48dd5f4 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -35,7 +35,15 @@ struct ScreenCoords u16 z; }; -typedef Vec2 DrawingCoords; // TODO: Keep z component? +struct DrawingCoords +{ + DrawingCoords() {} + DrawingCoords(u10 x, u10 y, u16 z) : x(x), y(y), z(z) {} + + u10 x; + u10 y; + u16 z; +}; struct VertexData { @@ -51,8 +59,10 @@ struct VertexData clippos.z = LINTERP(t, a.clippos.z, b.clippos.z); clippos.w = LINTERP(t, a.clippos.w, b.clippos.w); + // TODO: Should use a LINTERP_INT, too drawpos.x = LINTERP(t, a.drawpos.x, b.drawpos.x); drawpos.y = LINTERP(t, a.drawpos.y, b.drawpos.y); + drawpos.z = LINTERP(t, a.drawpos.z, b.drawpos.z); texturecoords.x = LINTERP(t, a.texturecoords.x, b.texturecoords.x); texturecoords.y = LINTERP(t, a.texturecoords.y, b.texturecoords.y);