Merge commit 'refs/pull/495/head' of https://github.com/coelckers/gzdoom

This commit is contained in:
Rachael Alexanderson 2018-05-31 20:01:36 -04:00
commit c745e9f3e6
15 changed files with 885 additions and 307 deletions

View file

@ -266,5 +266,7 @@ DEFINE_SPECIAL(Sector_SetFloorGlow, 277, 5, 5, 5)
DEFINE_SPECIAL(Sector_SetCeilingGlow, 278, 5, 5, 5)
DEFINE_SPECIAL(Floor_MoveToValueAndCrush, 279, 4, 5, 5)
DEFINE_SPECIAL(Ceiling_MoveToValueAndCrush, 280, 4, 5, 5)
DEFINE_SPECIAL(Line_SetAutomapFlags, 281, 3, 3, 3)
DEFINE_SPECIAL(Line_SetAutomapStyle, 282, 2, 2, 2)
#undef DEFINE_SPECIAL

View file

@ -2730,6 +2730,7 @@ void D_DoomMain (void)
ST_Clear();
D_ErrorCleanup ();
DThinker::DestroyThinkersInList(STAT_STATIC);
E_Shutdown(false);
P_FreeLevelData();
P_FreeExtraLevelData();
@ -2775,6 +2776,8 @@ void D_DoomMain (void)
restart++;
PClass::bShutdown = false;
PClass::bVMOperational = false;
gamestate = GS_STARTUP;
}
while (1);
}

View file

@ -63,7 +63,7 @@ bool FDynLightData::GetLight(int group, Plane & p, ADynamicLight * light, bool c
return false;
}
AddLightToList(group, light);
AddLightToList(group, light, false);
return true;
}
@ -72,7 +72,7 @@ bool FDynLightData::GetLight(int group, Plane & p, ADynamicLight * light, bool c
// Add one dynamic light to the light data list
//
//==========================================================================
void FDynLightData::AddLightToList(int group, ADynamicLight * light)
void FDynLightData::AddLightToList(int group, ADynamicLight * light, bool forceAttenuate)
{
int i = 0;
@ -109,7 +109,7 @@ void FDynLightData::AddLightToList(int group, ADynamicLight * light)
bool attenuate;
// Store attenuate flag in the sign bit of the float.
if (gl_attenuate == -1) attenuate = !!(light->lightflags & LF_ATTENUATE);
if (gl_attenuate == -1) attenuate = !!(light->lightflags & LF_ATTENUATE) || forceAttenuate;
else attenuate = !!gl_attenuate;
if (attenuate) shadowIndex = -shadowIndex;

View file

@ -54,7 +54,7 @@ struct FDynLightData
}
bool GetLight(int group, Plane & p, ADynamicLight * light, bool checkside);
void AddLightToList(int group, ADynamicLight * light);
void AddLightToList(int group, ADynamicLight * light, bool forceAttenuate);
};

View file

@ -220,7 +220,7 @@ void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata)
{
if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector
{
modellightdata.AddLightToList(group, light);
modellightdata.AddLightToList(group, light, true);
addedLights.Push(light);
}
}

View file

@ -2765,6 +2765,55 @@ FUNC(LS_Line_SetBlocking)
return true;
}
FUNC(LS_Line_SetAutomapFlags)
// Line_SetAutomapFlags (id, setflags, clearflags)
{
static const int flagtrans[] =
{
ML_SECRET,
ML_DONTDRAW,
ML_MAPPED,
ML_REVEALED,
-1
};
if (arg0 == 0) return false;
int setflags = 0;
int clearflags = 0;
for (int i = 0; flagtrans[i] != -1; i++, arg1 >>= 1, arg2 >>= 1)
{
if (arg1 & 1) setflags |= flagtrans[i];
if (arg2 & 1) clearflags |= flagtrans[i];
}
FLineIdIterator itr(arg0);
int line;
while ((line = itr.Next()) >= 0)
{
level.lines[line].flags = (level.lines[line].flags & ~clearflags) | setflags;
}
return true;
}
FUNC(LS_Line_SetAutomapStyle)
// Line_SetAutomapStyle (id, style)
{
if (arg1 < AMLS_COUNT && arg1 >= 0)
{
FLineIdIterator itr(arg0);
int line;
while ((line = itr.Next()) >= 0)
{
level.lines[line].automapstyle = (AutomapLineStyle) arg1;
}
return true;
}
return false;
}
FUNC(LS_ChangeCamera)
@ -3713,6 +3762,8 @@ static lnSpecFunc LineSpecials[] =
/* 278 */ LS_Sector_SetCeilingGlow,
/* 279 */ LS_Floor_MoveToValueAndCrush,
/* 280 */ LS_Ceiling_MoveToValueAndCrush,
/* 281 */ LS_Line_SetAutomapFlags,
/* 282 */ LS_Line_SetAutomapStyle,
};

View file

@ -1163,7 +1163,8 @@ void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleT
// Draw the triangle:
auto drawfunc = (args->destBgra) ? DrawSpan32 : DrawSpan8;
int bmode = (int)args->uniforms->BlendMode();
auto drawfunc = args->destBgra ? ScreenTriangle::SpanDrawers32[bmode] : ScreenTriangle::SpanDrawers8[bmode];
float stepXW = args->gradientX.W;
float v1X = args->v1->x;
@ -1248,10 +1249,11 @@ void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleT
}
}
#ifndef NO_SSE
void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
template<typename ModeT>
void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
{
using namespace TriScreenDrawerModes;
float v1X = args->v1->x;
float v1Y = args->v1->y;
float v1W = args->v1->w;
@ -1267,9 +1269,13 @@ void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs
float posXV = v1V + stepXV * startX + args->gradientY.V * startY;
const uint32_t *texPixels = (const uint32_t*)args->uniforms->TexturePixels();
const uint32_t *translation = (const uint32_t*)args->uniforms->Translation();
int texWidth = args->uniforms->TextureWidth();
int texHeight = args->uniforms->TextureHeight();
int fillcolor = args->uniforms->Color();
int alpha = args->uniforms->SrcAlpha();
bool is_fixed_light = args->uniforms->FixedLight();
uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff;
uint32_t light = args->uniforms->Light();
@ -1281,163 +1287,376 @@ void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs
uint32_t *destLine = dest + args->pitch * y;
int x = x0;
#ifndef NO_SSE
__m128i mfillcolor = _mm_set1_epi32(fillcolor);
__m128i mcapcolor = _mm_unpacklo_epi8(mfillcolor, _mm_setzero_si128());
__m128i malpha = _mm_set1_epi32(alpha);
int sseEnd = x0 + ((x1 - x0) & ~3);
while (x < sseEnd)
{
uint32_t fgcolor[2];
int32_t lightshade[2];
__m128i fg;
float rcpW = 0x01000000 / posXW;
int32_t u = (int32_t)(posXU * rcpW);
int32_t v = (int32_t)(posXV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
fgcolor[0] = texPixels[texelX * texHeight + texelY];
if (ModeT::SWFlags & SWSTYLEF_Fill)
{
fg = mfillcolor;
}
else if (ModeT::SWFlags & SWSTYLEF_FogBoundary)
{
fg = _mm_loadl_epi64((const __m128i*)(destLine + x));
}
else
{
float rcpW0 = 0x01000000 / posXW;
float rcpW1 = 0x01000000 / (posXW + stepXW);
fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
lightshade[0] = lightpos >> 8;
int32_t u0 = (int32_t)(posXU * rcpW0);
int32_t u1 = (int32_t)((posXU + stepXU) * rcpW1);
int32_t v0 = (int32_t)(posXV * rcpW0);
int32_t v1 = (int32_t)((posXV + stepXV) * rcpW1);
uint32_t texelX0 = ((((uint32_t)u0 << 8) >> 16) * texWidth) >> 16;
uint32_t texelX1 = ((((uint32_t)u1 << 8) >> 16) * texWidth) >> 16;
uint32_t texelY0 = ((((uint32_t)v0 << 8) >> 16) * texHeight) >> 16;
uint32_t texelY1 = ((((uint32_t)v1 << 8) >> 16) * texHeight) >> 16;
posXW += stepXW;
posXU += stepXU;
posXV += stepXV;
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
uint32_t fg0 = translation[((const uint8_t*)texPixels)[texelX0 * texHeight + texelY0]];
uint32_t fg1 = translation[((const uint8_t*)texPixels)[texelX1 * texHeight + texelY1]];
fg = _mm_setr_epi32(fg0, fg1, 0, 0);
}
else
{
uint32_t fg0 = texPixels[texelX0 * texHeight + texelY0];
uint32_t fg1 = texPixels[texelX1 * texHeight + texelY1];
fg = _mm_setr_epi32(fg0, fg1, 0, 0);
}
}
rcpW = 0x01000000 / posXW;
u = (int32_t)(posXU * rcpW);
v = (int32_t)(posXV * rcpW);
texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
fgcolor[1] = texPixels[texelX * texHeight + texelY];
if (ModeT::SWFlags & SWSTYLEF_Skycap)
{
float rcpW0 = 0x01000000 / posXW;
float rcpW1 = 0x01000000 / (posXW + stepXW);
int32_t v0 = (int32_t)(posXV * rcpW0);
int32_t v1 = (int32_t)((posXV + stepXV) * rcpW1);
lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
lightshade[1] = lightpos >> 8;
int start_fade = 2; // How fast it should fade out
__m128i v = _mm_setr_epi32(v0, v0, v1, v1);
__m128i alpha_top = _mm_min_epi16(_mm_max_epi16(_mm_srai_epi32(v, 16 - start_fade), _mm_setzero_si128()), _mm_set1_epi16(256));
__m128i alpha_bottom = _mm_min_epi16(_mm_max_epi16(_mm_srai_epi32(_mm_sub_epi32(_mm_set1_epi32(2 << 24), v), 16 - start_fade), _mm_setzero_si128()), _mm_set1_epi16(256));
__m128i a = _mm_min_epi16(alpha_top, alpha_bottom);
a = _mm_shufflelo_epi16(_mm_shufflehi_epi16(a, _MM_SHUFFLE(0, 0, 0, 0)), _MM_SHUFFLE(0, 0, 0, 0));
__m128i inv_a = _mm_sub_epi32(_mm_set1_epi32(256), a);
posXW += stepXW;
posXU += stepXU;
posXV += stepXV;
fg = _mm_unpacklo_epi8(fg, _mm_setzero_si128());
__m128i c = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(_mm_mullo_epi16(fg, a), _mm_mullo_epi16(mcapcolor, inv_a)), _mm_set1_epi16(127)), 8);
_mm_storel_epi64((__m128i*)(destLine + x), _mm_packus_epi16(c, c));
}
else
{
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
{
__m128i rgbmask = _mm_set1_epi32(0x00ffffff);
if (ModeT::Flags & STYLEF_RedIsAlpha)
fg = _mm_or_si128(_mm_andnot_si128(rgbmask, _mm_slli_epi32(fg, 8)), _mm_and_si128(rgbmask, mfillcolor));
else
fg = _mm_or_si128(_mm_andnot_si128(rgbmask, fg), _mm_and_si128(rgbmask, mfillcolor));
}
__m128i mfgcolor = _mm_loadl_epi64((const __m128i*)fgcolor);
mfgcolor = _mm_unpacklo_epi8(mfgcolor, _mm_setzero_si128());
if (!(ModeT::Flags & STYLEF_Alpha1))
{
__m128i a = _mm_srli_epi32(fg, 24);
a = _mm_srli_epi32(_mm_mullo_epi16(a, malpha), 8);
fg = _mm_or_si128(_mm_and_si128(fg, _mm_set1_epi32(0x00ffffff)), _mm_slli_epi32(a, 24));
}
__m128i mlightshade = _mm_loadl_epi64((const __m128i*)lightshade);
mlightshade = _mm_shuffle_epi32(mlightshade, _MM_SHUFFLE(1, 0, 1, 0));
mlightshade = _mm_packs_epi32(mlightshade, mlightshade);
fg = _mm_unpacklo_epi8(fg, _mm_setzero_si128());
__m128i mdestcolor = _mm_srli_epi16(_mm_mullo_epi16(mfgcolor, mlightshade), 8);
mdestcolor = _mm_packus_epi16(mdestcolor, _mm_setzero_si128());
mdestcolor = _mm_or_si128(mdestcolor, _mm_set1_epi32(0xff000000));
fixed_t lightpos0 = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
fixed_t lightpos1 = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * (posXW + stepXW)), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos0 = (lightpos0 & lightmask) | ((light << 8) & ~lightmask);
lightpos1 = (lightpos1 & lightmask) | ((light << 8) & ~lightmask);
int lightshade0 = lightpos0 >> 8;
int lightshade1 = lightpos1 >> 8;
__m128i shadedfg = _mm_srli_epi16(_mm_mullo_epi16(fg, _mm_setr_epi16(lightshade0, lightshade0, lightshade0, 256, lightshade1, lightshade1, lightshade1, 256)), 8);
_mm_storel_epi64((__m128i*)(destLine + x), mdestcolor);
__m128i out;
if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero)
{
out = shadedfg;
}
else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One)
{
__m128i dest = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(destLine + x)), _mm_setzero_si128());
if (ModeT::BlendOp == STYLEOP_Add)
{
out = _mm_add_epi16(dest, shadedfg);
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
out = _mm_sub_epi16(dest, shadedfg);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
out = _mm_sub_epi16(shadedfg, dest);
}
}
else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor)
{
__m128i dest = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(destLine + x)), _mm_setzero_si128());
__m128i sfactor = _mm_add_epi16(shadedfg, _mm_srli_epi16(shadedfg, 7));
__m128i dfactor = _mm_sub_epi16(_mm_set1_epi16(256), sfactor);
out = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(_mm_mullo_epi16(dest, dfactor), _mm_mullo_epi16(shadedfg, sfactor)), _mm_set1_epi16(127)), 8);
}
else
{
__m128i dest = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(destLine + x)), _mm_setzero_si128());
__m128i sfactor = _mm_shufflehi_epi16(_mm_shufflelo_epi16(shadedfg, _MM_SHUFFLE(3, 3, 3, 3)), _MM_SHUFFLE(3, 3, 3, 3));
sfactor = _mm_add_epi16(sfactor, _mm_srli_epi16(sfactor, 7)); // 255 -> 256
__m128i dfactor = _mm_sub_epi16(_mm_set1_epi16(256), sfactor);
__m128i src = _mm_mullo_epi16(shadedfg, sfactor);
if (ModeT::BlendDest == STYLEALPHA_One)
{
dest = _mm_slli_epi16(dest, 8);
}
else
{
__m128i dfactor = _mm_sub_epi16(_mm_set1_epi16(256), sfactor);
dest = _mm_mullo_epi16(dest, dfactor);
}
if (ModeT::BlendOp == STYLEOP_Add)
{
out = _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(dest, src), _mm_set1_epi16(127)), 8);
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
out = _mm_srli_epi16(_mm_add_epi16(_mm_sub_epi16(dest, src), _mm_set1_epi16(127)), 8);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
out = _mm_srli_epi16(_mm_add_epi16(_mm_sub_epi16(src, dest), _mm_set1_epi16(127)), 8);
}
}
_mm_storel_epi64((__m128i*)(destLine + x), _mm_or_si128(_mm_packus_epi16(out, out), _mm_set1_epi32(0xff000000)));
}
posXW += stepXW + stepXW;
posXU += stepXU + stepXU;
posXV += stepXV + stepXV;
x += 2;
}
while (x < x1)
{
float rcpW = 0x01000000 / posXW;
int32_t u = (int32_t)(posXU * rcpW);
int32_t v = (int32_t)(posXV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
uint32_t fgcolor = texPixels[texelX * texHeight + texelY];
uint32_t fgcolor_r = RPART(fgcolor);
uint32_t fgcolor_g = GPART(fgcolor);
uint32_t fgcolor_b = BPART(fgcolor);
uint32_t fgcolor_a = APART(fgcolor);
if (fgcolor_a > 127)
{
fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
int lightshade = lightpos >> 8;
fgcolor_r = (fgcolor_r * lightshade) >> 8;
fgcolor_g = (fgcolor_g * lightshade) >> 8;
fgcolor_b = (fgcolor_b * lightshade) >> 8;
destLine[x] = 0xff000000 | (fgcolor_r << 16) | (fgcolor_g << 8) | fgcolor_b;
}
posXW += stepXW;
posXU += stepXU;
posXV += stepXV;
x++;
}
}
#else
void ScreenTriangle::DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
{
float v1X = args->v1->x;
float v1Y = args->v1->y;
float v1W = args->v1->w;
float v1U = args->v1->u * v1W;
float v1V = args->v1->v * v1W;
float stepXW = args->gradientX.W;
float stepXU = args->gradientX.U;
float stepXV = args->gradientX.V;
float startX = x0 + (0.5f - v1X);
float startY = y + (0.5f - v1Y);
float posXW = v1W + stepXW * startX + args->gradientY.W * startY;
float posXU = v1U + stepXU * startX + args->gradientY.U * startY;
float posXV = v1V + stepXV * startX + args->gradientY.V * startY;
const uint32_t *texPixels = (const uint32_t*)args->uniforms->TexturePixels();
int texWidth = args->uniforms->TextureWidth();
int texHeight = args->uniforms->TextureHeight();
bool is_fixed_light = args->uniforms->FixedLight();
uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff;
uint32_t light = args->uniforms->Light();
float shade = 2.0f - (light + 12.0f) / 128.0f;
float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f);
light += light >> 7; // 255 -> 256
uint32_t *dest = (uint32_t*)args->dest;
uint32_t *destLine = dest + args->pitch * y;
int x = x0;
while (x < x1)
{
float rcpW = 0x01000000 / posXW;
int32_t u = (int32_t)(posXU * rcpW);
int32_t v = (int32_t)(posXV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
uint32_t fgcolor = texPixels[texelX * texHeight + texelY];
uint32_t fgcolor_r = RPART(fgcolor);
uint32_t fgcolor_g = GPART(fgcolor);
uint32_t fgcolor_b = BPART(fgcolor);
uint32_t fgcolor_a = APART(fgcolor);
if (fgcolor_a > 127)
{
fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
int lightshade = lightpos >> 8;
fgcolor_r = (fgcolor_r * lightshade) >> 8;
fgcolor_g = (fgcolor_g * lightshade) >> 8;
fgcolor_b = (fgcolor_b * lightshade) >> 8;
destLine[x] = 0xff000000 | (fgcolor_r << 16) | (fgcolor_g << 8) | fgcolor_b;
}
posXW += stepXW;
posXU += stepXU;
posXV += stepXV;
x++;
}
}
#endif
void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
while (x < x1)
{
uint32_t fg;
if (ModeT::SWFlags & SWSTYLEF_Fill)
{
fg = fillcolor;
}
else if (ModeT::SWFlags & SWSTYLEF_FogBoundary)
{
fg = destLine[x];
}
else
{
float rcpW = 0x01000000 / posXW;
int32_t u = (int32_t)(posXU * rcpW);
int32_t v = (int32_t)(posXV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]];
}
else
{
fg = texPixels[texelX * texHeight + texelY];
}
}
if (ModeT::SWFlags & SWSTYLEF_Skycap)
{
float rcpW = 0x01000000 / posXW;
int32_t v = (int32_t)(posXV * rcpW);
int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(v >> (16 - start_fade), 0, 256);
int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256);
int a = MIN(alpha_top, alpha_bottom);
int inv_a = 256 - a;
if (a == 256)
{
destLine[x] = fg;
}
else
{
uint32_t r = RPART(fg);
uint32_t g = GPART(fg);
uint32_t b = BPART(fg);
uint32_t fg_a = APART(fg);
uint32_t bg_red = RPART(fillcolor);
uint32_t bg_green = GPART(fillcolor);
uint32_t bg_blue = BPART(fillcolor);
r = (r * a + bg_red * inv_a + 127) >> 8;
g = (g * a + bg_green * inv_a + 127) >> 8;
b = (b * a + bg_blue * inv_a + 127) >> 8;
destLine[x] = MAKEARGB(255, r, g, b);
}
}
else
{
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
{
if (ModeT::Flags & STYLEF_RedIsAlpha)
fg = ((fg << 8) & 0xff000000) | (fillcolor & 0x00ffffff);
else
fg = (fg & 0xff000000) | (fillcolor & 0x00ffffff);
}
uint32_t fgalpha = fg >> 24;
if (!(ModeT::Flags & STYLEF_Alpha1))
{
fgalpha = (fgalpha * alpha) >> 8;
}
fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
int lightshade = lightpos >> 8;
uint32_t shadedfg_r = (RPART(fg) * lightshade) >> 8;
uint32_t shadedfg_g = (GPART(fg) * lightshade) >> 8;
uint32_t shadedfg_b = (BPART(fg) * lightshade) >> 8;
if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero)
{
destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b);
}
else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One)
{
uint32_t dest = destLine[x];
if (ModeT::BlendOp == STYLEOP_Add)
{
uint32_t out_r = MIN<uint32_t>(RPART(dest) + shadedfg_r, 255);
uint32_t out_g = MIN<uint32_t>(GPART(dest) + shadedfg_g, 255);
uint32_t out_b = MIN<uint32_t>(BPART(dest) + shadedfg_b, 255);
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
uint32_t out_r = MAX<uint32_t>(RPART(dest) - shadedfg_r, 0);
uint32_t out_g = MAX<uint32_t>(GPART(dest) - shadedfg_g, 0);
uint32_t out_b = MAX<uint32_t>(BPART(dest) - shadedfg_b, 0);
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
uint32_t out_r = MAX<uint32_t>(shadedfg_r - RPART(dest), 0);
uint32_t out_g = MAX<uint32_t>(shadedfg_g - GPART(dest), 0);
uint32_t out_b = MAX<uint32_t>(shadedfg_b - BPART(dest), 0);
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
}
else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor)
{
uint32_t dest = destLine[x];
uint32_t sfactor_r = shadedfg_r; sfactor_r += sfactor_r >> 7; // 255 -> 256
uint32_t sfactor_g = shadedfg_g; sfactor_g += sfactor_g >> 7; // 255 -> 256
uint32_t sfactor_b = shadedfg_b; sfactor_b += sfactor_b >> 7; // 255 -> 256
uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256
uint32_t dfactor_r = 256 - sfactor_r;
uint32_t dfactor_g = 256 - sfactor_g;
uint32_t dfactor_b = 256 - sfactor_b;
uint32_t out_r = (RPART(dest) * dfactor_r + shadedfg_r * sfactor_r + 128) >> 8;
uint32_t out_g = (GPART(dest) * dfactor_g + shadedfg_g * sfactor_g + 128) >> 8;
uint32_t out_b = (BPART(dest) * dfactor_b + shadedfg_b * sfactor_b + 128) >> 8;
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
else if (fgalpha == 255)
{
destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b);
}
else if (fgalpha != 0)
{
uint32_t dest = destLine[x];
uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256
uint32_t dfactor = 256 - sfactor;
uint32_t src_r = shadedfg_r * sfactor;
uint32_t src_g = shadedfg_g * sfactor;
uint32_t src_b = shadedfg_b * sfactor;
uint32_t dest_r = RPART(dest);
uint32_t dest_g = GPART(dest);
uint32_t dest_b = BPART(dest);
if (ModeT::BlendDest == STYLEALPHA_One)
{
dest_r <<= 8;
dest_g <<= 8;
dest_b <<= 8;
}
else
{
uint32_t dfactor = 256 - sfactor;
dest_r *= dfactor;
dest_g *= dfactor;
dest_b *= dfactor;
}
uint32_t out_r, out_g, out_b;
if (ModeT::BlendOp == STYLEOP_Add)
{
if (ModeT::BlendDest == STYLEALPHA_One)
{
out_r = MIN<int32_t>((dest_r + src_r + 128) >> 8, 255);
out_g = MIN<int32_t>((dest_g + src_g + 128) >> 8, 255);
out_b = MIN<int32_t>((dest_b + src_b + 128) >> 8, 255);
}
else
{
out_r = (dest_r + src_r + 128) >> 8;
out_g = (dest_g + src_g + 128) >> 8;
out_b = (dest_b + src_b + 128) >> 8;
}
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(dest_r - src_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(dest_g - src_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(dest_b - src_b + 128) >> 8, 0);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(src_r - dest_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(src_g - dest_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(src_b - dest_b + 128) >> 8, 0);
}
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
}
}
posXW += stepXW;
posXU += stepXU;
posXV += stepXV;
x++;
}
}
template<typename ModeT>
void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
{
using namespace TriScreenDrawerModes;
float v1X = args->v1->x;
float v1Y = args->v1->y;
float v1W = args->v1->w;
@ -1455,9 +1674,17 @@ void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs
auto colormaps = args->uniforms->BaseColormap();
const uint8_t *texPixels = args->uniforms->TexturePixels();
const uint8_t *translation = args->uniforms->Translation();
int texWidth = args->uniforms->TextureWidth();
int texHeight = args->uniforms->TextureHeight();
int fillcolor = args->uniforms->Color();
int alpha = args->uniforms->SrcAlpha();
uint32_t capcolor = fillcolor;
if (ModeT::SWFlags & SWSTYLEF_Skycap)
capcolor = GPalette.BaseColors[capcolor].d;
bool is_fixed_light = args->uniforms->FixedLight();
uint32_t lightmask = is_fixed_light ? 0 : 0xffffffff;
uint32_t light = args->uniforms->Light();
@ -1471,23 +1698,197 @@ void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs
int x = x0;
while (x < x1)
{
float rcpW = 0x01000000 / posXW;
int32_t u = (int32_t)(posXU * rcpW);
int32_t v = (int32_t)(posXV * rcpW);
int fg;
int fgalpha = 255;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
uint8_t fgcolor = texPixels[texelX * texHeight + texelY];
if (ModeT::SWFlags & SWSTYLEF_Fill)
{
fg = fillcolor;
}
else if (ModeT::SWFlags & SWSTYLEF_FogBoundary)
{
fg = destLine[x];
}
else
{
float rcpW = 0x01000000 / posXW;
int32_t u = (int32_t)(posXU * rcpW);
int32_t v = (int32_t)(posXV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
fg = texPixels[texelX * texHeight + texelY];
fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
int lightshade = lightpos >> 8;
if (ModeT::SWFlags & SWSTYLEF_Translated)
fg = translation[fg];
lightshade = ((256 - lightshade) * NUMCOLORMAPS) & 0xffffff00;
uint8_t shadedfg = colormaps[lightshade + fgcolor];
fgalpha = (fg != 0) ? 255 : 0;
}
if (fgcolor != 0)
destLine[x] = shadedfg;
if (ModeT::SWFlags & SWSTYLEF_Skycap)
{
float rcpW = 0x01000000 / posXW;
int32_t v = (int32_t)(posXV * rcpW);
int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(v >> (16 - start_fade), 0, 256);
int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256);
int a = MIN(alpha_top, alpha_bottom);
int inv_a = 256 - a;
if (a == 256)
{
destLine[x] = fg;
}
else
{
uint32_t texelrgb = GPalette.BaseColors[fg].d;
uint32_t r = RPART(texelrgb);
uint32_t g = GPART(texelrgb);
uint32_t b = BPART(texelrgb);
uint32_t fg_a = APART(texelrgb);
uint32_t bg_red = RPART(capcolor);
uint32_t bg_green = GPART(capcolor);
uint32_t bg_blue = BPART(capcolor);
r = (r * a + bg_red * inv_a + 127) >> 8;
g = (g * a + bg_green * inv_a + 127) >> 8;
b = (b * a + bg_blue * inv_a + 127) >> 8;
destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)];
}
}
else
{
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
{
if (ModeT::Flags & STYLEF_RedIsAlpha)
fgalpha = fg;
fg = fillcolor;
}
if (!(ModeT::Flags & STYLEF_Alpha1))
{
fgalpha = (fgalpha * alpha) >> 8;
}
fixed_t lightpos = FRACUNIT - (int)(clamp(shade - MIN(24.0f / 32.0f, globVis * posXW), 0.0f, 31.0f / 32.0f) * (float)FRACUNIT);
lightpos = (lightpos & lightmask) | ((light << 8) & ~lightmask);
int lightshade = lightpos >> 8;
lightshade = ((256 - lightshade) * NUMCOLORMAPS) & 0xffffff00;
uint8_t shadedfg = colormaps[lightshade + fg];
if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero)
{
destLine[x] = shadedfg;
}
else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One)
{
uint32_t src = GPalette.BaseColors[shadedfg];
uint32_t dest = GPalette.BaseColors[destLine[x]];
if (ModeT::BlendOp == STYLEOP_Add)
{
uint32_t out_r = MIN<uint32_t>(RPART(dest) + RPART(src), 255);
uint32_t out_g = MIN<uint32_t>(GPART(dest) + GPART(src), 255);
uint32_t out_b = MIN<uint32_t>(BPART(dest) + BPART(src), 255);
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
uint32_t out_r = MAX<uint32_t>(RPART(dest) - RPART(src), 0);
uint32_t out_g = MAX<uint32_t>(GPART(dest) - GPART(src), 0);
uint32_t out_b = MAX<uint32_t>(BPART(dest) - BPART(src), 0);
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
uint32_t out_r = MAX<uint32_t>(RPART(src) - RPART(dest), 0);
uint32_t out_g = MAX<uint32_t>(GPART(src) - GPART(dest), 0);
uint32_t out_b = MAX<uint32_t>(BPART(src) - BPART(dest), 0);
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
}
else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor)
{
uint32_t src = GPalette.BaseColors[shadedfg];
uint32_t dest = GPalette.BaseColors[destLine[x]];
uint32_t sfactor_r = RPART(src); sfactor_r += sfactor_r >> 7; // 255 -> 256
uint32_t sfactor_g = GPART(src); sfactor_g += sfactor_g >> 7; // 255 -> 256
uint32_t sfactor_b = BPART(src); sfactor_b += sfactor_b >> 7; // 255 -> 256
uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256
uint32_t dfactor_r = 256 - sfactor_r;
uint32_t dfactor_g = 256 - sfactor_g;
uint32_t dfactor_b = 256 - sfactor_b;
uint32_t out_r = (RPART(dest) * dfactor_r + RPART(src) * sfactor_r + 128) >> 8;
uint32_t out_g = (GPART(dest) * dfactor_g + GPART(src) * sfactor_g + 128) >> 8;
uint32_t out_b = (BPART(dest) * dfactor_b + BPART(src) * sfactor_b + 128) >> 8;
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
else if (fgalpha == 255)
{
destLine[x] = shadedfg;
}
else if (fgalpha != 0)
{
uint32_t src = GPalette.BaseColors[shadedfg];
uint32_t dest = GPalette.BaseColors[destLine[x]];
uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256
uint32_t dfactor = 256 - sfactor;
uint32_t src_r = RPART(src) * sfactor;
uint32_t src_g = GPART(src) * sfactor;
uint32_t src_b = BPART(src) * sfactor;
uint32_t dest_r = RPART(dest);
uint32_t dest_g = GPART(dest);
uint32_t dest_b = BPART(dest);
if (ModeT::BlendDest == STYLEALPHA_One)
{
dest_r <<= 8;
dest_g <<= 8;
dest_b <<= 8;
}
else
{
uint32_t dfactor = 256 - sfactor;
dest_r *= dfactor;
dest_g *= dfactor;
dest_b *= dfactor;
}
uint32_t out_r, out_g, out_b;
if (ModeT::BlendOp == STYLEOP_Add)
{
if (ModeT::BlendDest == STYLEALPHA_One)
{
out_r = MIN<int32_t>((dest_r + src_r + 128) >> 8, 255);
out_g = MIN<int32_t>((dest_g + src_g + 128) >> 8, 255);
out_b = MIN<int32_t>((dest_b + src_b + 128) >> 8, 255);
}
else
{
out_r = (dest_r + src_r + 128) >> 8;
out_g = (dest_g + src_g + 128) >> 8;
out_b = (dest_b + src_b + 128) >> 8;
}
}
else if (ModeT::BlendOp == STYLEOP_RevSub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(dest_r - src_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(dest_g - src_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(dest_b - src_b + 128) >> 8, 0);
}
else //if (ModeT::BlendOp == STYLEOP_Sub)
{
out_r = MAX<int32_t>(static_cast<int32_t>(src_r - dest_r + 128) >> 8, 0);
out_g = MAX<int32_t>(static_cast<int32_t>(src_g - dest_g + 128) >> 8, 0);
out_b = MAX<int32_t>(static_cast<int32_t>(src_b - dest_b + 128) >> 8, 0);
}
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
}
}
posXW += stepXW;
posXU += stepXU;
@ -1496,6 +1897,70 @@ void ScreenTriangle::DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs
}
}
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *) =
{
&DrawSpan8<TriScreenDrawerModes::StyleOpaque>,
&DrawSpan8<TriScreenDrawerModes::StyleSkycap>,
&DrawSpan8<TriScreenDrawerModes::StyleFogBoundary>,
&DrawSpan8<TriScreenDrawerModes::StyleSrcColor>,
&DrawSpan8<TriScreenDrawerModes::StyleFill>,
&DrawSpan8<TriScreenDrawerModes::StyleNormal>,
&DrawSpan8<TriScreenDrawerModes::StyleFuzzy>,
&DrawSpan8<TriScreenDrawerModes::StyleStencil>,
&DrawSpan8<TriScreenDrawerModes::StyleTranslucent>,
&DrawSpan8<TriScreenDrawerModes::StyleAdd>,
&DrawSpan8<TriScreenDrawerModes::StyleShaded>,
&DrawSpan8<TriScreenDrawerModes::StyleTranslucentStencil>,
&DrawSpan8<TriScreenDrawerModes::StyleShadow>,
&DrawSpan8<TriScreenDrawerModes::StyleSubtract>,
&DrawSpan8<TriScreenDrawerModes::StyleAddStencil>,
&DrawSpan8<TriScreenDrawerModes::StyleAddShaded>,
&DrawSpan8<TriScreenDrawerModes::StyleOpaqueTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleSrcColorTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleNormalTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleStencilTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleTranslucentTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleAddTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleShadedTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleTranslucentStencilTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleShadowTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleSubtractTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleAddStencilTranslated>,
&DrawSpan8<TriScreenDrawerModes::StyleAddShadedTranslated>
};
void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs *) =
{
&DrawSpan32<TriScreenDrawerModes::StyleOpaque>,
&DrawSpan32<TriScreenDrawerModes::StyleSkycap>,
&DrawSpan32<TriScreenDrawerModes::StyleFogBoundary>,
&DrawSpan32<TriScreenDrawerModes::StyleSrcColor>,
&DrawSpan32<TriScreenDrawerModes::StyleFill>,
&DrawSpan32<TriScreenDrawerModes::StyleNormal>,
&DrawSpan32<TriScreenDrawerModes::StyleFuzzy>,
&DrawSpan32<TriScreenDrawerModes::StyleStencil>,
&DrawSpan32<TriScreenDrawerModes::StyleTranslucent>,
&DrawSpan32<TriScreenDrawerModes::StyleAdd>,
&DrawSpan32<TriScreenDrawerModes::StyleShaded>,
&DrawSpan32<TriScreenDrawerModes::StyleTranslucentStencil>,
&DrawSpan32<TriScreenDrawerModes::StyleShadow>,
&DrawSpan32<TriScreenDrawerModes::StyleSubtract>,
&DrawSpan32<TriScreenDrawerModes::StyleAddStencil>,
&DrawSpan32<TriScreenDrawerModes::StyleAddShaded>,
&DrawSpan32<TriScreenDrawerModes::StyleOpaqueTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleSrcColorTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleNormalTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleStencilTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleTranslucentTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleAddTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleShadedTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleTranslucentStencilTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleShadowTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleSubtractTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleAddStencilTranslated>,
&DrawSpan32<TriScreenDrawerModes::StyleAddShadedTranslated>
};
void(*ScreenTriangle::TriDrawers8[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *) =
{
&TriScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureOpaque

View file

@ -139,9 +139,9 @@ class ScreenTriangle
public:
static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void(*TriDrawers8[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *);
static void(*TriDrawers32[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *);
static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);
@ -152,6 +152,46 @@ public:
namespace TriScreenDrawerModes
{
enum SWStyleFlags
{
SWSTYLEF_Translated = 1,
SWSTYLEF_Skycap = 2,
SWSTYLEF_FogBoundary = 4,
SWSTYLEF_Fill = 8,
SWSTYLEF_SrcColorOneMinusSrcColor = 16
};
struct StyleOpaque { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = 0; };
struct StyleSkycap { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Skycap; };
struct StyleFogBoundary { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_FogBoundary; };
struct StyleSrcColor { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_SrcColorOneMinusSrcColor; };
struct StyleFill { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Fill; };
struct StyleNormal { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = 0; };
struct StyleFuzzy { static const int BlendOp = STYLEOP_Fuzz, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; };
struct StyleStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = 0; };
struct StyleTranslucent { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; };
struct StyleAdd { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = 0; };
struct StyleShaded { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = 0; };
struct StyleTranslucentStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_ColorIsFixed, SWFlags = 0; };
struct StyleShadow { static const int BlendOp = STYLEOP_Shadow, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = 0; };
struct StyleSubtract { static const int BlendOp = STYLEOP_RevSub, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = 0; };
struct StyleAddStencil { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_ColorIsFixed, SWFlags = 0; };
struct StyleAddShaded { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = 0; };
struct StyleOpaqueTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_One, BlendDest = STYLEALPHA_Zero, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated; };
struct StyleSrcColorTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated|SWSTYLEF_SrcColorOneMinusSrcColor; };
struct StyleNormalTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1, SWFlags = SWSTYLEF_Translated; };
struct StyleStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_Alpha1 | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; };
struct StyleTranslucentTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = SWSTYLEF_Translated; };
struct StyleAddTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = SWSTYLEF_Translated; };
struct StyleShadedTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; };
struct StyleTranslucentStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; };
struct StyleShadowTranslated { static const int BlendOp = STYLEOP_Shadow, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_InvSrc, Flags = 0, SWFlags = SWSTYLEF_Translated; };
struct StyleSubtractTranslated { static const int BlendOp = STYLEOP_RevSub, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = 0, SWFlags = SWSTYLEF_Translated; };
struct StyleAddStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; };
struct StyleAddShadedTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; };
enum class BlendModes { Opaque, Masked, AddClamp, SubClamp, RevSubClamp, AddSrcColorOneMinusSrcColor, Shaded, AddClampShaded };
struct OpaqueBlend { static const int Mode = (int)BlendModes::Opaque; };
struct MaskedBlend { static const int Mode = (int)BlendModes::Masked; };

View file

@ -139,7 +139,7 @@ void PolyDrawLinePortal::Render(int portalDepth)
DVector2 pt2 = clipLine->v2->fPos() - PolyRenderer::Instance()->Viewpoint.Pos;
bool backfacing = (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0);
PortalViewpoint = PolyRenderer::Instance()->SetupPerspectiveMatrix(Mirror);
PortalViewpoint = PolyRenderer::Instance()->SetupPerspectiveMatrix(Mirror != nullptr);
PortalViewpoint.StencilValue = StencilValue;
PortalViewpoint.PortalDepth = portalDepth;
PortalViewpoint.PortalEnterLine = clipLine;

View file

@ -29,11 +29,11 @@ float unpackuvert( uint32_t n, int c )
switch( c )
{
case 2:
return ((int16_t)((n&0x7ff)<<5))/127.f;
return ((int16_t)((n&0x7ff)<<5))/128.f;
case 1:
return ((int16_t)(((n>>11)&0x7ff)<<5))/127.f;
return ((int16_t)(((n>>11)&0x7ff)<<5))/128.f;
case 0:
return ((int16_t)(((n>>22)&0x3ff)<<6))/127.f;
return ((int16_t)(((n>>22)&0x3ff)<<6))/128.f;
default:
return 0.f;
}
@ -98,9 +98,9 @@ void FUE1Model::LoadGeometry()
{
UE1Vertex Vert;
// unpack position
Vert.Pos = FVector3(unpackuvert(averts[j+i*numVerts],0),
unpackuvert(averts[j+i*numVerts],1),
unpackuvert(averts[j+i*numVerts],2));
Vert.Pos = FVector3(unpackuvert(averts[j+i*numVerts],2),
unpackuvert(averts[j+i*numVerts],0),
-unpackuvert(averts[j+i*numVerts],1));
// push vertex (without normals, will be calculated later)
verts.Push(Vert);
}
@ -136,8 +136,6 @@ void FUE1Model::LoadGeometry()
vert[l] = verts[polys[k].V[l]+numVerts*i].Pos;
dir[0] = vert[1]-vert[0];
dir[1] = vert[2]-vert[0];
dir[0].MakeUnit();
dir[1].MakeUnit();
norm = dir[0]^dir[1];
nsum += norm.Unit();
}
@ -223,7 +221,7 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
{
for ( int k=0; k<groups[j].numPolys; k++ )
{
for ( int l=2; l>=0; l-- )
for ( int l=0; l<3; l++ )
{
UE1Vertex V = verts[polys[groups[j].P[k]].V[l]+i*numVerts];
FVector2 C = polys[groups[j].P[k]].C[l];

View file

@ -102,7 +102,7 @@ bool ViewportIsScaled43()
void R_ShowCurrentScaling()
{
int x1 = screen->GetClientWidth(), y1 = screen->GetClientHeight(), x2 = x1 * vid_scalefactor, y2 = y1 * vid_scalefactor;
int x1 = screen->GetClientWidth(), y1 = screen->GetClientHeight(), x2 = int(x1 * vid_scalefactor), y2 = int(y1 * vid_scalefactor);
Printf("Current Scale: %f\n", (float)(vid_scalefactor));
Printf("Real resolution: %i x %i\nEmulated resolution: %i x %i\n", x1, y1, x2, y2);
}

View file

@ -607,12 +607,6 @@ void FTextureManager::AddHiresTextures (int wadnum)
void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname)
{
int remapLump, lastLump;
FString src;
bool is32bit;
int width, height;
ETextureType type;
int mode;
TArray<FTextureID> tlist;
lastLump = 0;
@ -620,142 +614,166 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname)
{
if (Wads.GetLumpFile(remapLump) == wadnum)
{
FScanner sc(remapLump);
while (sc.GetString())
ParseTextureDef(remapLump);
}
}
}
void FTextureManager::ParseTextureDef(int lump)
{
TArray<FTextureID> tlist;
FScanner sc(lump);
while (sc.GetString())
{
if (sc.Compare("remap")) // remap an existing texture
{
sc.MustGetString();
// allow selection by type
int mode;
ETextureType type;
if (sc.Compare("wall")) type=ETextureType::Wall, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("flat")) type=ETextureType::Flat, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("sprite")) type=ETextureType::Sprite, mode=0;
else type = ETextureType::Any, mode = 0;
if (type != ETextureType::Any) sc.MustGetString();
sc.String[8]=0;
tlist.Clear();
int amount = ListTextures(sc.String, tlist);
FName texname = sc.String;
sc.MustGetString();
int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches);
if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics);
if (tlist.Size() == 0)
{
if (sc.Compare("remap")) // remap an existing texture
Printf("Attempting to remap non-existent texture %s to %s\n",
texname.GetChars(), sc.String);
}
else if (lumpnum == -1)
{
Printf("Attempting to remap texture %s to non-existent lump %s\n",
texname.GetChars(), sc.String);
}
else
{
for(unsigned int i = 0; i < tlist.Size(); i++)
{
sc.MustGetString();
FTexture * oldtex = Textures[tlist[i].GetIndex()].Texture;
int sl;
// allow selection by type
if (sc.Compare("wall")) type=ETextureType::Wall, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("flat")) type=ETextureType::Flat, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("sprite")) type=ETextureType::Sprite, mode=0;
else type = ETextureType::Any, mode = 0;
if (type != ETextureType::Any) sc.MustGetString();
sc.String[8]=0;
tlist.Clear();
int amount = ListTextures(sc.String, tlist);
FName texname = sc.String;
sc.MustGetString();
int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches);
if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics);
if (tlist.Size() == 0)
// only replace matching types. For sprites also replace any MiscPatches
// based on the same lump. These can be created for icons.
if (oldtex->UseType == type || type == ETextureType::Any ||
(mode == TEXMAN_Overridable && oldtex->UseType == ETextureType::Override) ||
(type == ETextureType::Sprite && oldtex->UseType == ETextureType::MiscPatch &&
(sl=oldtex->GetSourceLump()) >= 0 && Wads.GetLumpNamespace(sl) == ns_sprites)
)
{
Printf("Attempting to remap non-existent texture %s to %s\n",
texname.GetChars(), sc.String);
}
else if (lumpnum == -1)
{
Printf("Attempting to remap texture %s to non-existent lump %s\n",
texname.GetChars(), sc.String);
}
else
{
for(unsigned int i = 0; i < tlist.Size(); i++)
FTexture * newtex = FTexture::CreateTexture (lumpnum, ETextureType::Any);
if (newtex != NULL)
{
FTexture * oldtex = Textures[tlist[i].GetIndex()].Texture;
int sl;
// only replace matching types. For sprites also replace any MiscPatches
// based on the same lump. These can be created for icons.
if (oldtex->UseType == type || type == ETextureType::Any ||
(mode == TEXMAN_Overridable && oldtex->UseType == ETextureType::Override) ||
(type == ETextureType::Sprite && oldtex->UseType == ETextureType::MiscPatch &&
(sl=oldtex->GetSourceLump()) >= 0 && Wads.GetLumpNamespace(sl) == ns_sprites)
)
{
FTexture * newtex = FTexture::CreateTexture (lumpnum, ETextureType::Any);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(oldtex->GetScaledWidth(), oldtex->GetScaledHeight());
newtex->_LeftOffset[0] = int(oldtex->GetScaledLeftOffset(0) * newtex->Scale.X);
newtex->_LeftOffset[1] = int(oldtex->GetScaledLeftOffset(1) * newtex->Scale.X);
newtex->_TopOffset[0] = int(oldtex->GetScaledTopOffset(0) * newtex->Scale.Y);
newtex->_TopOffset[1] = int(oldtex->GetScaledTopOffset(1) * newtex->Scale.Y);
ReplaceTexture(tlist[i], newtex, true);
}
}
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(oldtex->GetScaledWidth(), oldtex->GetScaledHeight());
newtex->_LeftOffset[0] = int(oldtex->GetScaledLeftOffset(0) * newtex->Scale.X);
newtex->_LeftOffset[1] = int(oldtex->GetScaledLeftOffset(1) * newtex->Scale.X);
newtex->_TopOffset[0] = int(oldtex->GetScaledTopOffset(0) * newtex->Scale.Y);
newtex->_TopOffset[1] = int(oldtex->GetScaledTopOffset(1) * newtex->Scale.Y);
ReplaceTexture(tlist[i], newtex, true);
}
}
}
else if (sc.Compare("define")) // define a new "fake" texture
{
sc.GetString();
FString base = ExtractFileBase(sc.String, false);
if (!base.IsEmpty())
{
src = base.Left(8);
int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches);
if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics);
sc.GetString();
is32bit = !!sc.Compare("force32bit");
if (!is32bit) sc.UnGet();
sc.MustGetNumber();
width = sc.Number;
sc.MustGetNumber();
height = sc.Number;
if (lumpnum>=0)
{
FTexture *newtex = FTexture::CreateTexture(lumpnum, ETextureType::Override);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(width, height);
newtex->Name = src;
FTextureID oldtex = TexMan.CheckForTexture(src, ETextureType::MiscPatch);
if (oldtex.isValid())
{
ReplaceTexture(oldtex, newtex, true);
newtex->UseType = ETextureType::Override;
}
else AddTexture(newtex);
}
}
}
//else Printf("Unable to define hires texture '%s'\n", tex->Name);
}
else if (sc.Compare("texture"))
{
ParseXTexture(sc, ETextureType::Override);
}
else if (sc.Compare("sprite"))
{
ParseXTexture(sc, ETextureType::Sprite);
}
else if (sc.Compare("walltexture"))
{
ParseXTexture(sc, ETextureType::Wall);
}
else if (sc.Compare("flat"))
{
ParseXTexture(sc, ETextureType::Flat);
}
else if (sc.Compare("graphic"))
{
ParseXTexture(sc, ETextureType::MiscPatch);
}
else
{
sc.ScriptError("Texture definition expected, found '%s'", sc.String);
}
}
}
else if (sc.Compare("define")) // define a new "fake" texture
{
sc.GetString();
FString base = ExtractFileBase(sc.String, false);
if (!base.IsEmpty())
{
FString src = base.Left(8);
int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches);
if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics);
sc.GetString();
bool is32bit = !!sc.Compare("force32bit");
if (!is32bit) sc.UnGet();
sc.MustGetNumber();
int width = sc.Number;
sc.MustGetNumber();
int height = sc.Number;
if (lumpnum>=0)
{
FTexture *newtex = FTexture::CreateTexture(lumpnum, ETextureType::Override);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(width, height);
newtex->Name = src;
FTextureID oldtex = TexMan.CheckForTexture(src, ETextureType::MiscPatch);
if (oldtex.isValid())
{
ReplaceTexture(oldtex, newtex, true);
newtex->UseType = ETextureType::Override;
}
else AddTexture(newtex);
}
}
}
//else Printf("Unable to define hires texture '%s'\n", tex->Name);
}
else if (sc.Compare("texture"))
{
ParseXTexture(sc, ETextureType::Override);
}
else if (sc.Compare("sprite"))
{
ParseXTexture(sc, ETextureType::Sprite);
}
else if (sc.Compare("walltexture"))
{
ParseXTexture(sc, ETextureType::Wall);
}
else if (sc.Compare("flat"))
{
ParseXTexture(sc, ETextureType::Flat);
}
else if (sc.Compare("graphic"))
{
ParseXTexture(sc, ETextureType::MiscPatch);
}
else if (sc.Compare("#include"))
{
sc.MustGetString();
// This is not using sc.Open because it can print a more useful error message when done here
int includelump = Wads.CheckNumForFullName(sc.String, true);
if (includelump == -1)
{
sc.ScriptError("Lump '%s' not found", sc.String);
}
else
{
ParseTextureDef(includelump);
}
}
else
{
sc.ScriptError("Texture definition expected, found '%s'", sc.String);
}
}
}

View file

@ -584,6 +584,7 @@ public:
void AddPatches (int lumpnum);
void AddHiresTextures (int wadnum);
void LoadTextureDefs(int wadnum, const char *lumpname);
void ParseTextureDef(int remapLump);
void ParseXTexture(FScanner &sc, ETextureType usetype);
void SortTexturesByType(int start, int end);
bool AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2);

View file

@ -754,7 +754,7 @@ void WI_Start(wbstartstruct_t *wbstartstruct)
cls = PClass::FindClass(screenclass);
if (cls == nullptr)
{
I_FatalError("Cannot create statis screen");
I_FatalError("Cannot create status screen");
}
}
// Set up some global stuff that is always needed.

View file

@ -12,7 +12,7 @@ vec3 lightContribution(int i, vec3 normal)
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
float dotprod = dot(normal, lightdir);
if (dotprod < 0.0) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases.
if (dotprod < -0.0001) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases. Note that this can cause precision issues.
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);