mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-01 00:21:43 +00:00
Fix portals not working in softpoly (#1323)
This commit is contained in:
parent
c7edb9d22f
commit
d6f8e80177
5 changed files with 105 additions and 103 deletions
|
@ -186,13 +186,8 @@ 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)
|
||||
{
|
||||
}
|
||||
DepthRangeStart = min;
|
||||
DepthRangeScale = max - min;
|
||||
}
|
||||
|
||||
void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor)
|
||||
|
@ -210,19 +205,18 @@ void PolyTriangleThreadData::SetStencil(int stencilRef, int op)
|
|||
StencilTestValue = stencilRef;
|
||||
if (op == SOP_Increment)
|
||||
{
|
||||
WriteStencil = StencilTest;
|
||||
StencilWriteValue = MIN(stencilRef + 1, (int)255);
|
||||
}
|
||||
else if (op == SOP_Decrement)
|
||||
{
|
||||
WriteStencil = StencilTest;
|
||||
StencilWriteValue = MAX(stencilRef - 1, (int)0);
|
||||
}
|
||||
else // SOP_Keep
|
||||
{
|
||||
WriteStencil = false;
|
||||
StencilWriteValue = stencilRef;
|
||||
}
|
||||
|
||||
WriteStencil = StencilTest && (StencilTestValue != StencilWriteValue);
|
||||
}
|
||||
|
||||
void PolyTriangleThreadData::SetCulling(int mode)
|
||||
|
|
|
@ -174,6 +174,8 @@ public:
|
|||
bool WriteDepth = true;
|
||||
uint8_t StencilTestValue = 0;
|
||||
uint8_t StencilWriteValue = 0;
|
||||
float DepthRangeStart = 0.0f;
|
||||
float DepthRangeScale = 1.0f;
|
||||
|
||||
void (*FragmentShader)(int x0, int x1, PolyTriangleThreadData* thread) = nullptr;
|
||||
void (*WriteColorFunc)(int y, int x0, int x1, PolyTriangleThreadData* thread) = nullptr;
|
||||
|
|
|
@ -70,11 +70,13 @@ void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangle
|
|||
mposW = _mm_add_ps(mposW, mstepW);
|
||||
}
|
||||
|
||||
posW += ssecount * stepW;
|
||||
mstepW = _mm_set_ss(stepW);
|
||||
for (int x = sseend; x < x1; x++)
|
||||
{
|
||||
w[x] = 1.0f / posW;
|
||||
posW += stepW;
|
||||
__m128 res = _mm_rcp_ss(mposW);
|
||||
__m128 muls = _mm_mul_ss(mposW, _mm_mul_ss(res, res));
|
||||
_mm_store_ss(w + x, _mm_sub_ss(_mm_add_ss(res, res), muls));
|
||||
mposW = _mm_add_ss(mposW, mstepW);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -34,19 +34,28 @@
|
|||
|
||||
static void WriteDepth(int y, int x0, int x1, PolyTriangleThreadData* thread)
|
||||
{
|
||||
size_t pitch = thread->depthstencil->Width();
|
||||
float* line = thread->depthstencil->DepthValues() + pitch * y;
|
||||
float* w = thread->scanline.W;
|
||||
for (int x = x0; x < x1; x++)
|
||||
float* line = thread->depthstencil->DepthValues() + (size_t)thread->depthstencil->Width() * y;
|
||||
|
||||
if (thread->DepthRangeScale != 0.0f)
|
||||
{
|
||||
line[x] = w[x];
|
||||
float* w = thread->scanline.W;
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
line[x] = w[x];
|
||||
}
|
||||
}
|
||||
else // portal fills always uses DepthRangeStart = 1 and DepthRangeScale = 0
|
||||
{
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
line[x] = 65536.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread)
|
||||
{
|
||||
size_t pitch = thread->depthstencil->Width();
|
||||
uint8_t* line = thread->depthstencil->StencilValues() + pitch * y;
|
||||
uint8_t* line = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y;
|
||||
uint8_t value = thread->StencilWriteValue;
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
|
@ -54,11 +63,16 @@ static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread)
|
|||
}
|
||||
}
|
||||
|
||||
static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
static void RunFragmentShader(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
{
|
||||
WriteVaryings(y, x0, x1, args, thread);
|
||||
|
||||
thread->FragmentShader(x0, x1, thread);
|
||||
}
|
||||
|
||||
static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
{
|
||||
if (thread->WriteColor || thread->AlphaTest)
|
||||
RunFragmentShader(y, x0, x1, args, thread);
|
||||
|
||||
if (!thread->AlphaTest)
|
||||
{
|
||||
|
@ -92,88 +106,83 @@ static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, Pol
|
|||
}
|
||||
}
|
||||
|
||||
template<typename OptT>
|
||||
static void TestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
static void NoTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
{
|
||||
WriteW(y, x0, x1, args, thread);
|
||||
DrawSpan(y, x0, x1, args, thread);
|
||||
}
|
||||
|
||||
static void DepthTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
{
|
||||
WriteW(y, x0, x1, args, thread);
|
||||
|
||||
if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_StencilTest))
|
||||
float* zbufferLine = thread->depthstencil->DepthValues() + (size_t)thread->depthstencil->Width() * y;
|
||||
float* w = thread->scanline.W;
|
||||
float depthbias = thread->depthbias;
|
||||
|
||||
int x = x0;
|
||||
int xend = x1;
|
||||
while (x < xend)
|
||||
{
|
||||
size_t pitch = thread->depthstencil->Width();
|
||||
int xstart = x;
|
||||
|
||||
uint8_t* stencilbuffer;
|
||||
uint8_t* stencilLine;
|
||||
uint8_t stencilTestValue;
|
||||
if (OptT::Flags & SWTRI_StencilTest)
|
||||
while (zbufferLine[x] >= w[x] + depthbias && x < xend)
|
||||
x++;
|
||||
|
||||
if (x > xstart)
|
||||
{
|
||||
stencilbuffer = thread->depthstencil->StencilValues();
|
||||
stencilLine = stencilbuffer + pitch * y;
|
||||
stencilTestValue = thread->StencilTestValue;
|
||||
DrawSpan(y, xstart, x, args, thread);
|
||||
}
|
||||
|
||||
float* zbuffer;
|
||||
float* zbufferLine;
|
||||
float* w;
|
||||
float depthbias;
|
||||
if (OptT::Flags & SWTRI_DepthTest)
|
||||
{
|
||||
zbuffer = thread->depthstencil->DepthValues();
|
||||
zbufferLine = zbuffer + pitch * y;
|
||||
w = thread->scanline.W;
|
||||
depthbias = thread->depthbias;
|
||||
}
|
||||
|
||||
int x = x0;
|
||||
int xend = x1;
|
||||
while (x < xend)
|
||||
{
|
||||
int xstart = x;
|
||||
|
||||
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
|
||||
{
|
||||
while (zbufferLine[x] >= w[x] + depthbias && stencilLine[x] == stencilTestValue && x < xend)
|
||||
x++;
|
||||
}
|
||||
else if (OptT::Flags & SWTRI_DepthTest)
|
||||
{
|
||||
while (zbufferLine[x] >= w[x] + depthbias && x < xend)
|
||||
x++;
|
||||
}
|
||||
else if (OptT::Flags & SWTRI_StencilTest)
|
||||
{
|
||||
while (stencilLine[x] == stencilTestValue && x < xend)
|
||||
x++;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = xend;
|
||||
}
|
||||
|
||||
if (x > xstart)
|
||||
{
|
||||
DrawSpan(y, xstart, x, args, thread);
|
||||
}
|
||||
|
||||
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
|
||||
{
|
||||
while ((zbufferLine[x] < w[x] + depthbias || stencilLine[x] != stencilTestValue) && x < xend)
|
||||
x++;
|
||||
}
|
||||
else if (OptT::Flags & SWTRI_DepthTest)
|
||||
{
|
||||
while (zbufferLine[x] < w[x] + depthbias && x < xend)
|
||||
x++;
|
||||
}
|
||||
else if (OptT::Flags & SWTRI_StencilTest)
|
||||
{
|
||||
while (stencilLine[x] != stencilTestValue && x < xend)
|
||||
x++;
|
||||
}
|
||||
}
|
||||
while (zbufferLine[x] < w[x] + depthbias && x < xend)
|
||||
x++;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
static void DepthStencilTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
{
|
||||
uint8_t* stencilLine = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y;
|
||||
uint8_t stencilTestValue = thread->StencilTestValue;
|
||||
|
||||
int x = x0;
|
||||
int xend = x1;
|
||||
while (x < xend)
|
||||
{
|
||||
DrawSpan(y, x0, x1, args, thread);
|
||||
int xstart = x;
|
||||
while (stencilLine[x] == stencilTestValue && x < xend)
|
||||
x++;
|
||||
|
||||
if (x > xstart)
|
||||
{
|
||||
DepthTestSpan(y, xstart, x, args, thread);
|
||||
}
|
||||
|
||||
while (stencilLine[x] != stencilTestValue && x < xend)
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
static void StencilTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
|
||||
{
|
||||
uint8_t* stencilLine = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y;
|
||||
uint8_t stencilTestValue = thread->StencilTestValue;
|
||||
|
||||
int x = x0;
|
||||
int xend = x1;
|
||||
while (x < xend)
|
||||
{
|
||||
int xstart = x;
|
||||
while (stencilLine[x] == stencilTestValue && x < xend)
|
||||
x++;
|
||||
|
||||
if (x > xstart)
|
||||
{
|
||||
WriteW(y, x0, x1, args, thread);
|
||||
DrawSpan(y, xstart, x, args, thread);
|
||||
}
|
||||
|
||||
while (stencilLine[x] != stencilTestValue && x < xend)
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,8 +296,8 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadDat
|
|||
|
||||
void(*ScreenTriangle::TestSpanOpts[])(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) =
|
||||
{
|
||||
&TestSpan<TestSpanOpt0>,
|
||||
&TestSpan<TestSpanOpt1>,
|
||||
&TestSpan<TestSpanOpt2>,
|
||||
&TestSpan<TestSpanOpt3>
|
||||
&NoTestSpan,
|
||||
&DepthTestSpan,
|
||||
&StencilTestSpan,
|
||||
&DepthStencilTestSpan
|
||||
};
|
||||
|
|
|
@ -122,8 +122,3 @@ enum SWTestSpan
|
|||
SWTRI_DepthTest = 1,
|
||||
SWTRI_StencilTest = 2
|
||||
};
|
||||
|
||||
struct TestSpanOpt0 { static const int Flags = 0; };
|
||||
struct TestSpanOpt1 { static const int Flags = 1; };
|
||||
struct TestSpanOpt2 { static const int Flags = 2; };
|
||||
struct TestSpanOpt3 { static const int Flags = 3; };
|
||||
|
|
Loading…
Reference in a new issue