- implement depth bias

This commit is contained in:
Magnus Norddahl 2019-05-28 06:45:21 +02:00
parent bc5b953633
commit bd591c75fb
5 changed files with 69 additions and 57 deletions

View file

@ -108,7 +108,7 @@ void PolyRenderState::Clear(int targets)
//if (targets & CT_Color)
// PolyTriangleDrawer::ClearColor(GetPolyFrameBuffer()->GetDrawCommands());
if (targets & CT_Depth)
PolyTriangleDrawer::ClearDepth(GetPolyFrameBuffer()->GetDrawCommands(), 0.0f);
PolyTriangleDrawer::ClearDepth(GetPolyFrameBuffer()->GetDrawCommands(), 65535.0f);
if (targets & CT_Stencil)
PolyTriangleDrawer::ClearStencil(GetPolyFrameBuffer()->GetDrawCommands(), 0);
}

View file

@ -338,10 +338,18 @@ void PolyTriangleThreadData::SetDepthFunc(int func)
void PolyTriangleThreadData::SetDepthRange(float min, float max)
{
// The only two variants used by hwrenderer layer
if (min == 0.0f && max == 1.0f)
{
}
else if (min == 1.0f && max == 1.0f)
{
}
}
void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor)
{
depthbias = (float)(depthBiasConstantFactor / 65536.0);
}
void PolyTriangleThreadData::SetColorMask(bool r, bool g, bool b, bool a)

View file

@ -121,7 +121,7 @@ public:
void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld);
void SetCullCCW(bool value) { ccw = value; }
void SetTwoSided(bool value) { twosided = value; }
void SetWeaponScene(bool value) { weaponScene = value; }
void SetWeaponScene(bool value) { depthbias = value ? -1.0f : 0.0f; }
void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; swVertexShader.modelInterpolationFactor = interpolationFactor; }
void SetInputAssembly(PolyInputAssembly *input) { inputAssembly = input; }
@ -187,6 +187,7 @@ public:
int32_t texelV[MAXWIDTH];
uint16_t lightarray[MAXWIDTH];
uint32_t dynlights[MAXWIDTH];
float depthvalues[MAXWIDTH];
static PolyTriangleThreadData *Get(DrawerThread *thread);
@ -195,7 +196,7 @@ public:
int dest_height = 0;
bool dest_bgra = false;
uint8_t *dest = nullptr;
bool weaponScene = false;
float depthbias = 0.0f;
int viewport_y = 0;

View file

@ -151,13 +151,37 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
TriangleDrawers[opt](args, thread, edges, topY, bottomY);
}
static void FillDepthValues(float *depthvalues, float posXW, float stepXW, int count, float depthbias)
{
#ifndef NO_SSE
__m128 mstepXW = _mm_set1_ps(stepXW * 4.0f);
__m128 mfirstStepXW = _mm_setr_ps(0.0f, stepXW, stepXW + stepXW, stepXW + stepXW + stepXW);
__m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW);
__m128 mdepthbias = _mm_set1_ps(depthbias);
while (count > 0)
{
_mm_storeu_ps(depthvalues, _mm_add_ps(_mm_rcp_ps(mposXW), mdepthbias));
mposXW = _mm_add_ps(mposXW, mstepXW);
depthvalues += 4;
count -= 4;
}
#else
while (count > 0)
{
*(depthvalues++) = 1.0f / posXW + depthbias;
posXW += stepXW;
count--;
}
#endif
}
template<typename OptT>
void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY)
{
using namespace TriScreenDrawerModes;
void(*drawfunc)(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
float stepXW, v1X, v1Y, v1W, posXW;
float stepXW, v1X, v1Y, v1W;
uint8_t stencilTestValue, stencilWriteValue;
float *zbuffer;
float *zbufferLine;
@ -194,12 +218,14 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
if (OptT::Flags & SWTRI_WriteStencil)
stencilWriteValue = args->uniforms->StencilWriteValue();
float weaponWOffset;
float depthbias;
if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth))
{
weaponWOffset = thread->weaponScene ? 1.0f : 0.0f;
depthbias = thread->depthbias;
}
float *depthvalues = thread->depthvalues;
int num_cores = thread->num_cores;
for (int y = topY; y < bottomY; y += num_cores)
{
@ -215,16 +241,11 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
float startX = x + (0.5f - v1X);
float startY = y + (0.5f - v1Y);
posXW = v1W + stepXW * startX + args->gradientY.W * startY + weaponWOffset;
float posXW = v1W + stepXW * startX + args->gradientY.W * startY;
FillDepthValues(depthvalues + x, posXW, stepXW, xend - x, depthbias);
}
#ifndef NO_SSE
__m128 mstepXW, mfirstStepXW;
if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth))
{
mstepXW = _mm_set1_ps(stepXW * 4.0f);
mfirstStepXW = _mm_setr_ps(0.0f, stepXW, stepXW + stepXW, stepXW + stepXW + stepXW);
}
while (x < xend)
{
int xstart = x;
@ -232,9 +253,9 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
{
int xendsse = x + ((xend - x) / 4);
__m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW);
__m128 mposXW;
while (x < xendsse &&
_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15 &&
_mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15 &&
stencilLine[x] == stencilTestValue &&
stencilLine[x + 1] == stencilTestValue &&
stencilLine[x + 2] == stencilTestValue &&
@ -242,37 +263,31 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
{
if (OptT::Flags & SWTRI_WriteDepth)
_mm_storeu_ps(zbufferLine + x, mposXW);
mposXW = _mm_add_ps(mposXW, mstepXW);
x += 4;
}
posXW = _mm_cvtss_f32(mposXW);
while (zbufferLine[x] <= posXW && stencilLine[x] == stencilTestValue && x < xend)
while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
zbufferLine[x] = posXW;
posXW += stepXW;
zbufferLine[x] = depthvalues[x];
x++;
}
}
else if (OptT::Flags & SWTRI_DepthTest)
{
int xendsse = x + ((xend - x) / 4);
__m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW);
while (x < xendsse && _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15)
__m128 mposXW;
while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 15)
{
if (OptT::Flags & SWTRI_WriteDepth)
_mm_storeu_ps(zbufferLine + x, mposXW);
mposXW = _mm_add_ps(mposXW, mstepXW);
x += 4;
}
posXW = _mm_cvtss_f32(mposXW);
while (zbufferLine[x] <= posXW && x < xend)
while (zbufferLine[x] >= depthvalues[x] && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
zbufferLine[x] = posXW;
posXW += stepXW;
zbufferLine[x] = depthvalues[x];
x++;
}
}
@ -315,8 +330,7 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
{
for (int i = xstart; i < x; i++)
{
zbufferLine[i] = posXW;
posXW += stepXW;
zbufferLine[i] = depthvalues[i];
}
}
}
@ -324,39 +338,33 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
{
int xendsse = x + ((xend - x) / 4);
__m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW);
__m128 mposXW;
while (x < xendsse &&
(_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0 ||
(_mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 0 ||
stencilLine[x] != stencilTestValue ||
stencilLine[x + 1] != stencilTestValue ||
stencilLine[x + 2] != stencilTestValue ||
stencilLine[x + 3] != stencilTestValue))
{
mposXW = _mm_add_ps(mposXW, mstepXW);
x += 4;
}
posXW = _mm_cvtss_f32(mposXW);
while ((zbufferLine[x] > posXW || stencilLine[x] != stencilTestValue) && x < xend)
while ((zbufferLine[x] < depthvalues[x] || stencilLine[x] != stencilTestValue) && x < xend)
{
posXW += stepXW;
x++;
}
}
else if (OptT::Flags & SWTRI_DepthTest)
{
int xendsse = x + ((xend - x) / 4);
__m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW);
while (x < xendsse && _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0)
__m128 mposXW;
while (x < xendsse && _mm_movemask_ps(_mm_cmpge_ps(_mm_loadu_ps(zbufferLine + x), mposXW = _mm_loadu_ps(depthvalues + x))) == 0)
{
mposXW = _mm_add_ps(mposXW, mstepXW);
x += 4;
}
posXW = _mm_cvtss_f32(mposXW);
while (zbufferLine[x] > posXW && x < xend)
while (zbufferLine[x] < depthvalues[x] && x < xend)
{
posXW += stepXW;
x++;
}
}
@ -381,21 +389,19 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
{
while (zbufferLine[x] <= posXW && stencilLine[x] == stencilTestValue && x < xend)
while (zbufferLine[x] >= depthvalues[x] && stencilLine[x] == stencilTestValue && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
zbufferLine[x] = posXW;
posXW += stepXW;
zbufferLine[x] = depthvalues[x];
x++;
}
}
else if (OptT::Flags & SWTRI_DepthTest)
{
while (zbufferLine[x] <= posXW && x < xend)
while (zbufferLine[x] >= depthvalues[x] && x < xend)
{
if (OptT::Flags & SWTRI_WriteDepth)
zbufferLine[x] = posXW;
posXW += stepXW;
zbufferLine[x] = depthvalues[x];
x++;
}
}
@ -424,25 +430,22 @@ void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *threa
{
for (int i = xstart; i < x; i++)
{
zbufferLine[i] = posXW;
posXW += stepXW;
zbufferLine[i] = depthvalues[i];
}
}
}
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
{
while ((zbufferLine[x] > posXW || stencilLine[x] != stencilTestValue) && x < xend)
while ((zbufferLine[x] < depthvalues[x] || stencilLine[x] != stencilTestValue) && x < xend)
{
posXW += stepXW;
x++;
}
}
else if (OptT::Flags & SWTRI_DepthTest)
{
while (zbufferLine[x] > posXW && x < xend)
while (zbufferLine[x] < depthvalues[x] && x < xend)
{
posXW += stepXW;
x++;
}
}

View file

@ -220,7 +220,7 @@ namespace swrenderer
class DepthColumnCommand : public DrawerCommand
{
public:
DepthColumnCommand(const WallDrawerArgs &args, float idepth) : idepth(idepth)
DepthColumnCommand(const WallDrawerArgs &args, float idepth) : idepth(1.0f / idepth)
{
auto rendertarget = args.Viewport()->RenderTarget;
if (rendertarget->IsBgra())
@ -244,7 +244,7 @@ namespace swrenderer
count = args.Count();
}
DepthColumnCommand(const SkyDrawerArgs &args, float idepth) : idepth(idepth)
DepthColumnCommand(const SkyDrawerArgs &args, float idepth) : idepth(1.0f / idepth)
{
auto rendertarget = args.Viewport()->RenderTarget;
if (rendertarget->IsBgra())
@ -319,7 +319,7 @@ namespace swrenderer
if (idepth1 == idepth2)
{
float depth = idepth1;
float depth = 1.0f / idepth1;
#ifdef DEPTH_DEBUG
uint32_t gray = clamp<int32_t>((int32_t)(1.0f / depth / 4.0f), 0, 255);
uint32_t color = MAKEARGB(255, gray, gray, gray);
@ -344,7 +344,7 @@ namespace swrenderer
dest[x] = color;
#endif
values[x] = depth;
values[x] = 1.0f / depth;
depth += step;
}
}