- backend update from GZDoom.

This commit is contained in:
Christoph Oelckers 2021-03-07 13:21:15 +01:00
parent ad8654ed06
commit ee5950e7ad
11 changed files with 164 additions and 136 deletions

View file

@ -15,15 +15,16 @@ void FlushModels();
extern TDeletingArray<FModel*> Models;
extern TArray<FSpriteModelFrame> SpriteModelFrames;
#define MAX_MODELS_PER_FRAME 4
#define MD3_MAX_SURFACES 32
#define MIN_MODELS 4
struct FSpriteModelFrame
{
int modelIDs[MAX_MODELS_PER_FRAME];
FTextureID skinIDs[MAX_MODELS_PER_FRAME];
FTextureID surfaceskinIDs[MAX_MODELS_PER_FRAME][MD3_MAX_SURFACES];
int modelframes[MAX_MODELS_PER_FRAME];
uint8_t modelsAmount = 0;
TArray<int> modelIDs;
TArray<FTextureID> skinIDs;
TArray<FTextureID> surfaceskinIDs;
TArray<int> modelframes;
float xscale, yscale, zscale;
// [BB] Added zoffset, rotation parameters and flags.
// Added xoffset, yoffset

View file

@ -306,9 +306,10 @@ void FMD3Model::AddSkins(uint8_t *hitlist)
{
for (unsigned i = 0; i < Surfaces.Size(); i++)
{
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid())
int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
{
hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat;
hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat;
}
MD3Surface * surf = &Surfaces[i];
@ -359,9 +360,10 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f
{
if (curSpriteMDLFrame)
{
if (curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid())
int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
{
surfaceSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i], true);
surfaceSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true);
}
else if (surf->numSkins > 0 && surf->Skins[0].isValid())
{

View file

@ -638,9 +638,10 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f
FGameTexture *userSkin = skin;
if (!userSkin && curSpriteMDLFrame)
{
if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid())
int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES;
if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
{
userSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i], true);
userSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true);
}
else if (surf->skin.isValid())
{
@ -669,13 +670,14 @@ void FOBJModel::AddSkins(uint8_t* hitlist)
{
for (size_t i = 0; i < surfaces.Size(); i++)
{
if (curSpriteMDLFrame && i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid())
size_t ssIndex = i + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame && i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
{
// Precache skins manually reassigned by the user.
// On OBJs with lots of skins, such as Doom map OBJs exported from GZDB,
// there may be too many skins for the user to manually change, unless
// the limit is bumped or surfaceskinIDs is changed to a TArray<FTextureID>.
hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat;
hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat;
return; // No need to precache skin that was replaced
}

View file

@ -242,8 +242,9 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int f
FGameTexture *sskin = skin;
if ( !sskin )
{
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() )
sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum], true);
int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true);
if ( !sskin )
{
vofs += vsize;
@ -302,9 +303,12 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
void FUE1Model::AddSkins( uint8_t *hitlist )
{
for ( int i=0; i<numGroups; i++ )
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() )
hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].GetIndex()] |= FTextureManager::HIT_Flat;
for (int i = 0; i < numGroups; i++)
{
int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat;
}
}
FUE1Model::~FUE1Model()

View file

@ -28,7 +28,6 @@
#include "v_text.h"
#include "i_video.h"
#include "v_draw.h"
#include "colormaps.h"
#include "hw_clock.h"
#include "hw_vrmodes.h"

View file

@ -165,6 +165,7 @@ void PolyTriangleThreadData::SetViewpointUniforms(const HWViewpointUniforms *uni
void PolyTriangleThreadData::SetDepthClamp(bool on)
{
DepthClamp = on;
}
void PolyTriangleThreadData::SetDepthMask(bool on)
@ -186,13 +187,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 +206,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)
@ -436,8 +431,16 @@ void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert)
clipd[1] = v.gl_Position.W - v.gl_Position.X;
clipd[2] = v.gl_Position.Y + v.gl_Position.W;
clipd[3] = v.gl_Position.W - v.gl_Position.Y;
clipd[4] = v.gl_Position.Z + v.gl_Position.W;
clipd[5] = v.gl_Position.W - v.gl_Position.Z;
if (DepthClamp)
{
clipd[4] = 1.0f;
clipd[5] = 1.0f;
}
else
{
clipd[4] = v.gl_Position.Z + v.gl_Position.W;
clipd[5] = v.gl_Position.W - v.gl_Position.Z;
}
clipd[6] = v.gl_ClipDistance[0];
clipd[7] = v.gl_ClipDistance[1];
clipd[8] = v.gl_ClipDistance[2];
@ -690,8 +693,16 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *const* verts)
clipd[1] = v.gl_Position.W - v.gl_Position.X;
clipd[2] = v.gl_Position.Y + v.gl_Position.W;
clipd[3] = v.gl_Position.W - v.gl_Position.Y;
clipd[4] = v.gl_Position.Z + v.gl_Position.W;
clipd[5] = v.gl_Position.W - v.gl_Position.Z;
if (DepthClamp)
{
clipd[4] = 1.0f;
clipd[5] = 1.0f;
}
else
{
clipd[4] = v.gl_Position.Z + v.gl_Position.W;
clipd[5] = v.gl_Position.W - v.gl_Position.Z;
}
clipd[6] = v.gl_ClipDistance[0];
clipd[7] = v.gl_ClipDistance[1];
clipd[8] = v.gl_ClipDistance[2];
@ -715,8 +726,8 @@ int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *const* verts)
__m128 clipd1 = _mm_sub_ps(mw, mx);
__m128 clipd2 = _mm_add_ps(my, mw);
__m128 clipd3 = _mm_sub_ps(mw, my);
__m128 clipd4 = _mm_add_ps(mz, mw);
__m128 clipd5 = _mm_sub_ps(mw, mz);
__m128 clipd4 = DepthClamp ? _mm_set1_ps(1.0f) : _mm_add_ps(mz, mw);
__m128 clipd5 = DepthClamp ? _mm_set1_ps(1.0f) : _mm_sub_ps(mw, mz);
__m128 clipd6 = _mm_setr_ps(verts[0]->gl_ClipDistance[0], verts[1]->gl_ClipDistance[0], verts[2]->gl_ClipDistance[0], 0.0f);
__m128 clipd7 = _mm_setr_ps(verts[0]->gl_ClipDistance[1], verts[1]->gl_ClipDistance[1], verts[2]->gl_ClipDistance[1], 0.0f);
__m128 clipd8 = _mm_setr_ps(verts[0]->gl_ClipDistance[2], verts[1]->gl_ClipDistance[2], verts[2]->gl_ClipDistance[2], 0.0f);

View file

@ -174,6 +174,9 @@ public:
bool WriteDepth = true;
uint8_t StencilTestValue = 0;
uint8_t StencilWriteValue = 0;
float DepthRangeStart = 0.0f;
float DepthRangeScale = 1.0f;
bool DepthClamp = true;
void (*FragmentShader)(int x0, int x1, PolyTriangleThreadData* thread) = nullptr;
void (*WriteColorFunc)(int y, int x0, int x1, PolyTriangleThreadData* thread) = nullptr;

View file

@ -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

View file

@ -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
};

View file

@ -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; };

View file

@ -56,6 +56,14 @@ struct FSpecialColormap
PalEntry GrayscaleToColor[256];
};
extern TArray<FSpecialColormap> SpecialColormaps;
extern uint8_t DesaturateColormap[31][256];
int AddSpecialColormap(PalEntry *pe, float r1, float g1, float b1, float r2, float g2, float b2);
void InitSpecialColormaps(PalEntry* pe);
void UpdateSpecialColormap(PalEntry* BaseColors, unsigned int index, float r1, float g1, float b1, float r2, float g2, float b2);
int ReadPalette(int lumpnum, uint8_t* buffer);
enum EColorManipulation
{
CM_PLAIN2D = -2, // regular 2D drawing.
@ -65,11 +73,3 @@ enum EColorManipulation
};
#define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size())
extern TArray<FSpecialColormap> SpecialColormaps;
extern uint8_t DesaturateColormap[31][256];
int AddSpecialColormap(PalEntry *pe, float r1, float g1, float b1, float r2, float g2, float b2);
void InitSpecialColormaps(PalEntry* pe);
void UpdateSpecialColormap(PalEntry* BaseColors, unsigned int index, float r1, float g1, float b1, float r2, float g2, float b2);
int ReadPalette(int lumpnum, uint8_t* buffer);