From 780ddd21bd0929c1c21f51d7d3de9da58d5e6bb7 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 4 Jun 2018 13:10:58 -0400 Subject: [PATCH 01/14] - fixed - sector sounds were not translated through portal groups properly --- src/s_sound.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 9e2830cd9..2f272019e 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -757,8 +757,8 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, { // listener must be reversely offset to calculate the proper sound origin. CalcSectorSoundOrg(listenpos + disp, sector, channum, *pos); - pos->X += (float)disp.X; - pos->Z += (float)disp.Y; + pos->X -= (float)disp.X; + pos->Z -= (float)disp.Y; } else { From af3d17af8b55bc02f88b0076fb3531c9cc81aba3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 4 Jun 2018 21:22:47 +0200 Subject: [PATCH 02/14] Revert "- fix memory arena allocation alignment for 32 bit systems." This reverts commit 23fce56b5e14615991de9937dcebc2c740eac6b9. This did not do what it was supposed to because of how the block header was created. --- src/memarena.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/memarena.cpp b/src/memarena.cpp index 2c0336a5e..d19521edf 100644 --- a/src/memarena.cpp +++ b/src/memarena.cpp @@ -55,14 +55,13 @@ struct FMemArena::Block // // RoundPointer // -// Rounds a pointer up to the size of the largest integral type. +// Rounds a pointer up to a pointer-sized boundary. // //========================================================================== static inline void *RoundPointer(void *ptr) { - const auto roundsize = std::max(sizeof(void*), sizeof(double)); - return (void *)(((size_t)ptr + roundsize - 1) & ~(roundsize - 1)); + return (void *)(((size_t)ptr + sizeof(void*) - 1) & ~(sizeof(void*) - 1)); } //========================================================================== From 2f6dc46f14642ef2c15d7c238b82224f976b8eaa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 4 Jun 2018 21:50:36 +0200 Subject: [PATCH 03/14] - fixed FMemArena to always return 16 byte aligned pointers. Unfortunately this turned out harder than expected because of FSharedStringArena making some strong assumptions about the underlying implementation. --- src/memarena.cpp | 12 +++++++++--- src/memarena.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/memarena.cpp b/src/memarena.cpp index d19521edf..f5544708d 100644 --- a/src/memarena.cpp +++ b/src/memarena.cpp @@ -46,6 +46,7 @@ struct FMemArena::Block Block *NextBlock; void *Limit; // End of this block void *Avail; // Start of free space in this block + void *alignme; // align to 16 bytes. void Reset(); void *Alloc(size_t size); @@ -94,7 +95,7 @@ FMemArena::~FMemArena() // //========================================================================== -void *FMemArena::Alloc(size_t size) +void *FMemArena::iAlloc(size_t size) { Block *block; @@ -110,6 +111,11 @@ void *FMemArena::Alloc(size_t size) return block->Alloc(size); } +void *FMemArena::Alloc(size_t size) +{ + return iAlloc((size + 15) & ~15); +} + //========================================================================== // // FMemArena :: FreeAll @@ -316,7 +322,7 @@ FString *FSharedStringArena::Alloc(const FString &source) strnode = FindString(source, source.Len(), hash); if (strnode == NULL) { - strnode = (Node *)FMemArena::Alloc(sizeof(Node)); + strnode = (Node *)iAlloc(sizeof(Node)); ::new(&strnode->String) FString(source); strnode->Hash = hash; hash %= countof(Buckets); @@ -351,7 +357,7 @@ FString *FSharedStringArena::Alloc(const char *source, size_t strlen) strnode = FindString(source, strlen, hash); if (strnode == NULL) { - strnode = (Node *)FMemArena::Alloc(sizeof(Node)); + strnode = (Node *)iAlloc(sizeof(Node)); ::new(&strnode->String) FString(source, strlen); strnode->Hash = hash; hash %= countof(Buckets); diff --git a/src/memarena.h b/src/memarena.h index 7b3b34be4..f8a15aefa 100644 --- a/src/memarena.h +++ b/src/memarena.h @@ -54,6 +54,7 @@ protected: Block *AddBlock(size_t size); void FreeBlockChain(Block *&top); + void *iAlloc(size_t size); Block *TopBlock; Block *FreeBlocks; From fae514f30d17071620ebb8a1a3c6b9160bf6cfca Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Sun, 3 Jun 2018 21:11:47 +0200 Subject: [PATCH 04/14] BLOCKASPLAYER flag: treat non-player actors as blockable by "block players" lines --- src/actor.h | 1 + src/p_map.cpp | 9 ++++++--- src/po_man.cpp | 2 +- src/scripting/thingdef_data.cpp | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/actor.h b/src/actor.h index 863e4fb46..2199c205e 100644 --- a/src/actor.h +++ b/src/actor.h @@ -401,6 +401,7 @@ enum ActorFlag8 { MF8_FRIGHTENING = 0x00000001, // for those moments when halloween just won't do MF8_INSCROLLSEC = 0x00000002, // actor is partially inside a scrolling sector + MF8_BLOCKASPLAYER = 0x00000004, // actor is blocked by player-blocking lines even if not a player }; // --- mobj.renderflags --- diff --git a/src/p_map.cpp b/src/p_map.cpp index 8a7134967..8181df71b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -930,7 +930,10 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST) || ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY))); - if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE))) + uint32_t ProjectileBlocking = ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE; + if ( tm.thing->flags8 & MF8_BLOCKASPLAYER ) ProjectileBlocking |= ML_BLOCK_PLAYERS | ML_BLOCKING; + + if (!(Projectile) || (ld->flags & ProjectileBlocking) ) { if (ld->flags & ML_RAILING) { @@ -938,7 +941,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec } else if ((ld->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) || // explicitly blocking everything (!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only - (tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players + (((tm.thing->player != NULL) || (tm.thing->flags8 & MF8_BLOCKASPLAYER)) && (ld->flags & ML_BLOCK_PLAYERS)) || // block players ((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles ((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters { @@ -3100,7 +3103,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end) { goto isblocking; } - if (li->flags & ML_BLOCK_PLAYERS && slidemo->player != NULL) + if (li->flags & ML_BLOCK_PLAYERS && ((slidemo->player != NULL) || (slidemo->flags8 & MF8_BLOCKASPLAYER))) { goto isblocking; } diff --git a/src/po_man.cpp b/src/po_man.cpp index 76355d4db..ca12120de 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1157,7 +1157,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd) // [TN] Check wether this actor gets blocked by the line. if (ld->backsector != NULL && !(ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) - && !(ld->flags & ML_BLOCK_PLAYERS && mobj->player) + && !(ld->flags & ML_BLOCK_PLAYERS && (mobj->player || (mobj->flags8 & MF8_BLOCKASPLAYER))) && !(ld->flags & ML_BLOCKMONSTERS && mobj->flags3 & MF3_ISMONSTER) && !((mobj->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS)) && (!(ld->flags & ML_3DMIDTEX) || diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 002c0a81a..1416cbc7a 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -316,6 +316,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF7, FORCEINFIGHTING, AActor, flags7), DEFINE_FLAG(MF8, FRIGHTENING, AActor, flags8), + DEFINE_FLAG(MF8, BLOCKASPLAYER, AActor, flags8), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From 7009755c52e14a8d317611218eb42a3b05180db9 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 5 Jun 2018 11:06:31 +0300 Subject: [PATCH 05/14] - fix crash on dying when player class has no death states https://forum.zdoom.org/viewtopic.php?t=60815 --- src/p_interaction.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index db1578d49..5240d91ed 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -714,7 +714,9 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) tics = 1; } } - else + // The following condition is needed to avoid crash when player class has no death states + // Instance of player pawn will be garbage collected on reloading of level + else if (player == nullptr) { Destroy(); } From 9cd751ae7ac1316209b0ed20eebae45d2b57a696 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 5 Jun 2018 15:16:04 +0200 Subject: [PATCH 06/14] - fix softpoly colored fog bug in the new drawers --- src/polyrenderer/drawers/poly_draw_args.cpp | 19 +- src/polyrenderer/drawers/screen_triangle.cpp | 414 +++++++++++-------- 2 files changed, 257 insertions(+), 176 deletions(-) diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 3e02940cd..3a921ae0a 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -106,15 +106,24 @@ void PolyDrawArgs::SetLight(FSWColormap *base_colormap, uint32_t lightlevel, dou mLight = clamp(lightlevel, 0, 255); mFixedLight = fixed; - mLightRed = base_colormap->Color.r * 256 / 255; - mLightGreen = base_colormap->Color.g * 256 / 255; - mLightBlue = base_colormap->Color.b * 256 / 255; - mLightAlpha = base_colormap->Color.a * 256 / 255; + mLightRed = base_colormap->Color.r; + mLightRed += mLightRed >> 7; + mLightGreen = base_colormap->Color.g; + mLightGreen += mLightGreen >> 7; + mLightBlue = base_colormap->Color.b; + mLightBlue += mLightBlue >> 7; + mLightAlpha = base_colormap->Color.a; + mLightAlpha += mLightAlpha >> 7; mFadeRed = base_colormap->Fade.r; + mFadeRed += mFadeRed >> 7; mFadeGreen = base_colormap->Fade.g; + mFadeGreen += mFadeGreen >> 7; mFadeBlue = base_colormap->Fade.b; + mFadeBlue += mFadeBlue >> 7; mFadeAlpha = base_colormap->Fade.a; - mDesaturate = MIN(abs(base_colormap->Desaturate), 255) * 255 / 256; + mFadeAlpha += mFadeAlpha >> 7; + mDesaturate = MIN(abs(base_colormap->Desaturate), 255); + mDesaturate += mDesaturate >> 7; mSimpleShade = (base_colormap->Color.d == 0x00ffffff && base_colormap->Fade.d == 0x00000000 && base_colormap->Desaturate == 0); mColormaps = base_colormap->Maps; } diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index 858ed0633..98d8ecbf0 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -385,8 +385,8 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) float v1X, v1Y, v1W, v1U, v1V, v1WorldX, v1WorldY, v1WorldZ; float startX, startY; - float stepXW, stepXU, stepXV, stepWorldX, stepWorldY, stepWorldZ; - float posXW, posXU, posXV, posWorldX, posWorldY, posWorldZ; + float stepW, stepU, stepV, stepWorldX, stepWorldY, stepWorldZ; + float posW, posU, posV, posWorldX, posWorldY, posWorldZ; PolyLight *lights; int num_lights; @@ -410,12 +410,12 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) v1V = args->v1->v * v1W; startX = x0 + (0.5f - v1X); startY = y + (0.5f - v1Y); - stepXW = args->gradientX.W; - stepXU = args->gradientX.U; - stepXV = args->gradientX.V; - posXW = v1W + stepXW * startX + args->gradientY.W * startY; - posXU = v1U + stepXU * startX + args->gradientY.U * startY; - posXV = v1V + stepXV * startX + args->gradientY.V * startY; + stepW = args->gradientX.W; + stepU = args->gradientX.U; + stepV = args->gradientX.V; + posW = v1W + stepW * startX + args->gradientY.W * startY; + posU = v1U + stepU * startX + args->gradientY.U * startY; + posV = v1V + stepV * startX + args->gradientY.V * startY; texPixels = (const uint32_t*)args->uniforms->TexturePixels(); translation = (const uint32_t*)args->uniforms->Translation(); @@ -434,8 +434,8 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f); shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT); - lightpos = (fixed_t)(globVis * posXW * (float)FRACUNIT); - lightstep = (fixed_t)(globVis * stepXW * (float)FRACUNIT); + lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT); + lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT); int affineOffset = x0 / 16 * 16 - x0; lightpos = lightpos + lightstep * affineOffset; @@ -481,11 +481,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) dynlightcolor = args->uniforms->DynLightColor(); int affineOffset = x0 / 16 * 16 - x0; - float posLightW = posXW + stepXW * affineOffset; + float posLightW = posW + stepW * affineOffset; posWorldX = posWorldX + stepWorldX * affineOffset; posWorldY = posWorldY + stepWorldY * affineOffset; posWorldZ = posWorldZ + stepWorldZ * affineOffset; - float stepLightW = stepXW * 16.0f; + float stepLightW = stepW * 16.0f; stepWorldX *= 16.0f; stepWorldY *= 16.0f; stepWorldZ *= 16.0f; @@ -496,10 +496,10 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) uint32_t lit_g = GPART(dynlightcolor); uint32_t lit_b = BPART(dynlightcolor); - float rcp_posXW = 1.0f / posLightW; - float worldposX = posWorldX * rcp_posXW; - float worldposY = posWorldY * rcp_posXW; - float worldposZ = posWorldZ * rcp_posXW; + float rcp_posW = 1.0f / posLightW; + float worldposX = posWorldX * rcp_posW; + float worldposY = posWorldY * rcp_posW; + float worldposZ = posWorldZ * rcp_posW; for (int i = 0; i < num_lights; i++) { float lightposX = lights[i].x; @@ -592,45 +592,13 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) int x = x0; while (x < x1) { - uint32_t fg = 0; - - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) - { - fg = destLine[x]; - } - else if (ModeT::BlendOp != STYLEOP_Fuzz) - { - 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 if (ModeT::Flags & STYLEF_RedIsAlpha) - { - fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY]; - } - else - { - fg = texPixels[texelX * texHeight + texelY]; - } - } - if (ModeT::BlendOp == STYLEOP_Fuzz) { using namespace swrenderer; - float rcpW = 0x01000000 / posXW; - int32_t u = (int32_t)(posXU * rcpW); - int32_t v = (int32_t)(posXV * rcpW); + float rcpW = 0x01000000 / posW; + int32_t u = (int32_t)(posU * rcpW); + int32_t v = (int32_t)(posV * rcpW); uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); @@ -657,8 +625,13 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) } else if (ModeT::SWFlags & SWSTYLEF_Skycap) { - float rcpW = 0x01000000 / posXW; - int32_t v = (int32_t)(posXV * rcpW); + float rcpW = 0x01000000 / posW; + int32_t u = (int32_t)(posU * rcpW); + int32_t v = (int32_t)(posV * rcpW); + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + + uint32_t fg = texPixels[texelX * texHeight + texelY]; int start_fade = 2; // How fast it should fade out int alpha_top = clamp(v >> (16 - start_fade), 0, 256); @@ -686,8 +659,71 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) destLine[x] = MAKEARGB(255, r, g, b); } } + else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) + { + uint32_t fg = destLine[x]; + + int lightshade; + if (OptT::Flags & SWOPT_FixedLight) + { + lightshade = light; + } + else + { + lightshade = lightpos >> 4; + } + + uint32_t shadedfg_r, shadedfg_g, shadedfg_b; + if (OptT::Flags & SWOPT_ColoredFog) + { + uint32_t fg_r = RPART(fg); + uint32_t fg_g = GPART(fg); + uint32_t fg_b = BPART(fg); + uint32_t intensity = ((fg_r * 77 + fg_g * 143 + fg_b * 37) >> 8) * desaturate; + int inv_light = 256 - lightshade; + shadedfg_r = (((shade_fade_r * inv_light + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8; + shadedfg_g = (((shade_fade_g * inv_light + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8; + shadedfg_b = (((shade_fade_b * inv_light + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8; + } + else + { + shadedfg_r = (RPART(fg) * lightshade) >> 8; + shadedfg_g = (GPART(fg) * lightshade) >> 8; + shadedfg_b = (BPART(fg) * lightshade) >> 8; + } + + destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b); + } else { + uint32_t fg = 0; + + if (ModeT::SWFlags & SWSTYLEF_Fill) + { + fg = fillcolor; + } + else + { + float rcpW = 0x01000000 / posW; + int32_t u = (int32_t)(posU * rcpW); + int32_t v = (int32_t)(posV * 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 if (ModeT::Flags & STYLEF_RedIsAlpha) + { + fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY]; + } + else + { + fg = texPixels[texelX * texHeight + texelY]; + } + } + if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) { if (ModeT::Flags & STYLEF_RedIsAlpha) @@ -713,14 +749,6 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) lightshade = lightpos >> 4; } - uint32_t lit_r = 0, lit_g = 0, lit_b = 0; - if (OptT::Flags & SWOPT_DynLights) - { - lit_r = posdynlight_r >> 4; - lit_g = posdynlight_g >> 4; - lit_b = posdynlight_b >> 4; - } - uint32_t shadedfg_r, shadedfg_g, shadedfg_b; if (OptT::Flags & SWOPT_ColoredFog) { @@ -728,19 +756,38 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) uint32_t fg_g = GPART(fg); uint32_t fg_b = BPART(fg); uint32_t intensity = ((fg_r * 77 + fg_g * 143 + fg_b * 37) >> 8) * desaturate; - shadedfg_r = (((shade_fade_r + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8; - shadedfg_g = (((shade_fade_g + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8; - shadedfg_b = (((shade_fade_b + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8; + int inv_light = 256 - lightshade; + shadedfg_r = (((shade_fade_r * inv_light + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8; + shadedfg_g = (((shade_fade_g * inv_light + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8; + shadedfg_b = (((shade_fade_b * inv_light + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8; - shadedfg_r = MIN(shadedfg_r + ((fg_r * lit_r) >> 8), (uint32_t)255); - shadedfg_g = MIN(shadedfg_g + ((fg_g * lit_g) >> 8), (uint32_t)255); - shadedfg_b = MIN(shadedfg_b + ((fg_b * lit_b) >> 8), (uint32_t)255); + if (OptT::Flags & SWOPT_DynLights) + { + uint32_t lit_r = posdynlight_r >> 4; + uint32_t lit_g = posdynlight_g >> 4; + uint32_t lit_b = posdynlight_b >> 4; + shadedfg_r = MIN(shadedfg_r + ((fg_r * lit_r) >> 8), (uint32_t)255); + shadedfg_g = MIN(shadedfg_g + ((fg_g * lit_g) >> 8), (uint32_t)255); + shadedfg_b = MIN(shadedfg_b + ((fg_b * lit_b) >> 8), (uint32_t)255); + } } else { - shadedfg_r = (RPART(fg) * MIN(lightshade + lit_r, (uint32_t)256)) >> 8; - shadedfg_g = (GPART(fg) * MIN(lightshade + lit_g, (uint32_t)256)) >> 8; - shadedfg_b = (BPART(fg) * MIN(lightshade + lit_b, (uint32_t)256)) >> 8; + if (OptT::Flags & SWOPT_DynLights) + { + uint32_t lit_r = posdynlight_r >> 4; + uint32_t lit_g = posdynlight_g >> 4; + uint32_t lit_b = posdynlight_b >> 4; + shadedfg_r = (RPART(fg) * MIN(lightshade + lit_r, (uint32_t)256)) >> 8; + shadedfg_g = (GPART(fg) * MIN(lightshade + lit_g, (uint32_t)256)) >> 8; + shadedfg_b = (BPART(fg) * MIN(lightshade + lit_b, (uint32_t)256)) >> 8; + } + else + { + shadedfg_r = (RPART(fg) * lightshade) >> 8; + shadedfg_g = (GPART(fg) * lightshade) >> 8; + shadedfg_b = (BPART(fg) * lightshade) >> 8; + } } if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) @@ -852,9 +899,9 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) } } - posXW += stepXW; - posXU += stepXU; - posXV += stepXV; + posW += stepW; + posU += stepU; + posV += stepV; if (OptT::Flags & SWOPT_DynLights) { posdynlight_r += dynlights_r[x >> 4]; @@ -915,8 +962,8 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) float v1X, v1Y, v1W, v1U, v1V, v1WorldX, v1WorldY, v1WorldZ; float startX, startY; - float stepXW, stepXU, stepXV, stepWorldX, stepWorldY, stepWorldZ; - float posXW, posXU, posXV, posWorldX, posWorldY, posWorldZ; + float stepW, stepU, stepV, stepWorldX, stepWorldY, stepWorldZ; + float posW, posU, posV, posWorldX, posWorldY, posWorldZ; PolyLight *lights; int num_lights; @@ -939,12 +986,12 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) v1V = args->v1->v * v1W; startX = x0 + (0.5f - v1X); startY = y + (0.5f - v1Y); - stepXW = args->gradientX.W; - stepXU = args->gradientX.U; - stepXV = args->gradientX.V; - posXW = v1W + stepXW * startX + args->gradientY.W * startY; - posXU = v1U + stepXU * startX + args->gradientY.U * startY; - posXV = v1V + stepXV * startX + args->gradientY.V * startY; + stepW = args->gradientX.W; + stepU = args->gradientX.U; + stepV = args->gradientX.V; + posW = v1W + stepW * startX + args->gradientY.W * startY; + posU = v1U + stepU * startX + args->gradientY.U * startY; + posV = v1V + stepV * startX + args->gradientY.V * startY; texPixels = args->uniforms->TexturePixels(); translation = args->uniforms->Translation(); @@ -968,8 +1015,8 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f); shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT); - lightpos = (fixed_t)(globVis * posXW * (float)FRACUNIT); - lightstep = (fixed_t)(globVis * stepXW * (float)FRACUNIT); + lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT); + lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT); int affineOffset = x0 / 16 * 16 - x0; lightpos = lightpos + lightstep * affineOffset; @@ -1015,11 +1062,11 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) dynlightcolor = args->uniforms->DynLightColor(); int affineOffset = x0 / 16 * 16 - x0; - float posLightW = posXW + stepXW * affineOffset; + float posLightW = posW + stepW * affineOffset; posWorldX = posWorldX + stepWorldX * affineOffset; posWorldY = posWorldY + stepWorldY * affineOffset; posWorldZ = posWorldZ + stepWorldZ * affineOffset; - float stepLightW = stepXW * 16.0f; + float stepLightW = stepW * 16.0f; stepWorldX *= 16.0f; stepWorldY *= 16.0f; stepWorldZ *= 16.0f; @@ -1030,10 +1077,10 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) uint32_t lit_g = GPART(dynlightcolor); uint32_t lit_b = BPART(dynlightcolor); - float rcp_posXW = 1.0f / posLightW; - float worldposX = posWorldX * rcp_posXW; - float worldposY = posWorldY * rcp_posXW; - float worldposZ = posWorldZ * rcp_posXW; + float rcp_posW = 1.0f / posLightW; + float worldposX = posWorldX * rcp_posW; + float worldposY = posWorldY * rcp_posW; + float worldposZ = posWorldZ * rcp_posW; for (int i = 0; i < num_lights; i++) { float lightposX = lights[i].x; @@ -1114,39 +1161,13 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) int x = x0; while (x < x1) { - int fg = 0; - int fgalpha = 255; - - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) - { - fg = destLine[x]; - } - else if (ModeT::BlendOp != STYLEOP_Fuzz) - { - 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]; - - if (ModeT::SWFlags & SWSTYLEF_Translated) - fg = translation[fg]; - - fgalpha = (fg != 0) ? 255 : 0; - } - if (ModeT::BlendOp == STYLEOP_Fuzz) { using namespace swrenderer; - float rcpW = 0x01000000 / posXW; - int32_t u = (int32_t)(posXU * rcpW); - int32_t v = (int32_t)(posXV * rcpW); + float rcpW = 0x01000000 / posW; + int32_t u = (int32_t)(posU * rcpW); + int32_t v = (int32_t)(posV * rcpW); uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0; @@ -1172,8 +1193,12 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) } else if (ModeT::SWFlags & SWSTYLEF_Skycap) { - float rcpW = 0x01000000 / posXW; - int32_t v = (int32_t)(posXV * rcpW); + float rcpW = 0x01000000 / posW; + int32_t u = (int32_t)(posU * rcpW); + int32_t v = (int32_t)(posV * rcpW); + uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; + int fg = texPixels[texelX * texHeight + texelY]; int start_fade = 2; // How fast it should fade out int alpha_top = clamp(v >> (16 - start_fade), 0, 256); @@ -1203,8 +1228,48 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)]; } } + else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) + { + int fg = destLine[x]; + + uint8_t shadedfg; + if (OptT::Flags & SWOPT_FixedLight) + { + shadedfg = colormaps[light + fg]; + } + else + { + int lightshade = (lightpos >> 4) & 0xffffff00; + shadedfg = colormaps[lightshade + fg]; + } + + destLine[x] = shadedfg; + } else { + int fg; + if (ModeT::SWFlags & SWSTYLEF_Fill) + { + fg = fillcolor; + } + else + { + float rcpW = 0x01000000 / posW; + int32_t u = (int32_t)(posU * rcpW); + int32_t v = (int32_t)(posV * 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]; + } + + int fgalpha = 255; + + if (ModeT::BlendDest == STYLEALPHA_InvSrc) + { + if (fg == 0) + fgalpha = 0; + } + if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) { if (ModeT::Flags & STYLEF_RedIsAlpha) @@ -1217,6 +1282,9 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) fgalpha = (fgalpha * alpha) >> 8; } + if (ModeT::SWFlags & SWSTYLEF_Translated) + fg = translation[fg]; + uint8_t shadedfg; if (OptT::Flags & SWOPT_FixedLight) { @@ -1359,9 +1427,9 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) } } - posXW += stepXW; - posXU += stepXU; - posXV += stepXV; + posW += stepW; + posU += stepU; + posV += stepV; if (OptT::Flags & SWOPT_DynLights) { posdynlight_r += dynlights_r[x >> 4]; @@ -1444,25 +1512,6 @@ void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch uint32_t posU = startU; for (int x = x0; x < x1; x++) { - int fg = 0; - int fgalpha = 255; - - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else if (ModeT::BlendOp != STYLEOP_Fuzz) - { - uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; - fg = texPixels[texelX * texHeight + texelY]; - - if (ModeT::SWFlags & SWSTYLEF_Translated) - fg = translation[fg]; - - fgalpha = (fg != 0) ? 255 : 0; - } - if (ModeT::BlendOp == STYLEOP_Fuzz) { using namespace swrenderer; @@ -1492,6 +1541,26 @@ void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch } else { + int fg = 0; + if (ModeT::SWFlags & SWSTYLEF_Fill) + { + fg = fillcolor; + } + else + { + uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; + fg = texPixels[texelX * texHeight + texelY]; + } + + int fgalpha = 255; + + if (ModeT::BlendDest == STYLEALPHA_InvSrc) + { + if (fg == 0) + fgalpha = 0; + } + if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) { if (ModeT::Flags & STYLEF_RedIsAlpha) @@ -1504,6 +1573,9 @@ void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch fgalpha = (fgalpha * alpha) >> 8; } + if (ModeT::SWFlags & SWSTYLEF_Translated) + fg = translation[fg]; + uint8_t shadedfg = colormaps[light + fg]; if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero) @@ -1684,35 +1756,6 @@ void DrawRectOpt32(const void *destOrg, int destWidth, int destHeight, int destP uint32_t posU = startU; for (int x = x0; x < x1; x++) { - uint32_t fg = 0; - - if (ModeT::SWFlags & SWSTYLEF_Fill) - { - fg = fillcolor; - } - else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) - { - fg = destLine[x]; - } - else if (ModeT::BlendOp != STYLEOP_Fuzz) - { - uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; - uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; - - if (ModeT::SWFlags & SWSTYLEF_Translated) - { - fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]]; - } - else if (ModeT::Flags & STYLEF_RedIsAlpha) - { - fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY]; - } - else - { - fg = texPixels[texelX * texHeight + texelY]; - } - } - if (ModeT::BlendOp == STYLEOP_Fuzz) { using namespace swrenderer; @@ -1743,6 +1786,35 @@ void DrawRectOpt32(const void *destOrg, int destWidth, int destHeight, int destP } else { + uint32_t fg = 0; + + if (ModeT::SWFlags & SWSTYLEF_Fill) + { + fg = fillcolor; + } + else if (ModeT::SWFlags & SWSTYLEF_FogBoundary) + { + fg = destLine[x]; + } + else + { + uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16; + uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; + + if (ModeT::SWFlags & SWSTYLEF_Translated) + { + fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]]; + } + else if (ModeT::Flags & STYLEF_RedIsAlpha) + { + fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY]; + } + else + { + fg = texPixels[texelX * texHeight + texelY]; + } + } + if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) { if (ModeT::Flags & STYLEF_RedIsAlpha) From 51fd715404dc0ce0f1fef8aa5460d2d944348464 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 5 Jun 2018 15:32:27 +0200 Subject: [PATCH 07/14] - fix dynlight color not being applied on sprites --- src/polyrenderer/drawers/screen_triangle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index 98d8ecbf0..566f8df7a 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -919,7 +919,7 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args) { using namespace TriScreenDrawerModes; - if (args->uniforms->NumLights() == 0) + if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0) { if (!args->uniforms->FixedLight()) { @@ -1447,7 +1447,7 @@ void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args) { using namespace TriScreenDrawerModes; - if (args->uniforms->NumLights() == 0) + if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0) { if (!args->uniforms->FixedLight()) DrawSpanOpt8(y, x0, x1, args); From 674b6ee85c1bc68f17841417356330f63ca6ce37 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 5 Jun 2018 15:43:03 +0200 Subject: [PATCH 08/14] - avoid using global variables in the inner fuzz drawer loop --- src/polyrenderer/drawers/screen_triangle.cpp | 48 +++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index 566f8df7a..5043bf362 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -586,6 +586,14 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) inv_desaturate = 256 - desaturate; } + fixed_t fuzzscale; + int _fuzzpos; + if (ModeT::BlendOp == STYLEOP_Fuzz) + { + fuzzscale = (200 << FRACBITS) / viewheight; + _fuzzpos = swrenderer::fuzzpos; + } + uint32_t *dest = (uint32_t*)args->dest; uint32_t *destLine = dest + args->pitch * y; @@ -604,10 +612,8 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); sampleshadeout += sampleshadeout >> 7; // 255 -> 256 - fixed_t fuzzscale = (200 << FRACBITS) / viewheight; - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos; + int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; fixed_t fuzzcount = FUZZTABLE << FRACBITS; fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; @@ -1155,6 +1161,14 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) } } + fixed_t fuzzscale; + int _fuzzpos; + if (ModeT::BlendOp == STYLEOP_Fuzz) + { + fuzzscale = (200 << FRACBITS) / viewheight; + _fuzzpos = swrenderer::fuzzpos; + } + uint8_t *dest = (uint8_t*)args->dest; uint8_t *destLine = dest + args->pitch * y; @@ -1172,10 +1186,8 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16; unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0; - fixed_t fuzzscale = (200 << FRACBITS) / viewheight; - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos; + int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; fixed_t fuzzcount = FUZZTABLE << FRACBITS; fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; @@ -1493,6 +1505,14 @@ void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch light += light >> 7; // 255 -> 256 light = ((256 - light) * NUMCOLORMAPS) & 0xffffff00; + fixed_t fuzzscale; + int _fuzzpos; + if (ModeT::BlendOp == STYLEOP_Fuzz) + { + fuzzscale = (200 << FRACBITS) / viewheight; + _fuzzpos = swrenderer::fuzzpos; + } + float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0()); float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0()); uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000); @@ -1520,10 +1540,8 @@ void DrawRect8(const void *destOrg, int destWidth, int destHeight, int destPitch uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16; unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0; - fixed_t fuzzscale = (200 << FRACBITS) / viewheight; - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos; + int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; fixed_t fuzzcount = FUZZTABLE << FRACBITS; fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; @@ -1737,6 +1755,14 @@ void DrawRectOpt32(const void *destOrg, int destWidth, int destHeight, int destP inv_desaturate = 256 - desaturate; } + fixed_t fuzzscale; + int _fuzzpos; + if (ModeT::BlendOp == STYLEOP_Fuzz) + { + fuzzscale = (200 << FRACBITS) / viewheight; + _fuzzpos = swrenderer::fuzzpos; + } + float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0()); float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0()); uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000); @@ -1765,10 +1791,8 @@ void DrawRectOpt32(const void *destOrg, int destWidth, int destHeight, int destP unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]); sampleshadeout += sampleshadeout >> 7; // 255 -> 256 - fixed_t fuzzscale = (200 << FRACBITS) / viewheight; - int scaled_x = (x * fuzzscale) >> FRACBITS; - int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos; + int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + _fuzzpos; fixed_t fuzzcount = FUZZTABLE << FRACBITS; fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount; From 477cf23fd2c0b8e50c8d0d0def89794ae834aa55 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Wed, 11 Apr 2018 16:49:42 +0200 Subject: [PATCH 09/14] Adds "OnGiveSecret" virtual function on Actor for customizing behavior of secret finding. --- src/p_spec.cpp | 11 ++++++++++- wadsrc/static/zscript/actor.txt | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 5b32b410a..e8dbe8d2f 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -589,7 +589,15 @@ void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornu { actor->player->secretcount++; } - if (cl_showsecretmessage && actor->CheckLocalView(consoleplayer)) + int retval = 1; + IFVIRTUALPTR(actor, AActor, OnGiveSecret) + { + VMValue params[] = { actor, printmessage, playsound }; + VMReturn ret; + ret.IntAt(&retval); + VMCall(func, params, countof(params), &ret, 1); + } + if (retval && cl_showsecretmessage && actor->CheckLocalView(consoleplayer)) { if (printmessage) { @@ -616,6 +624,7 @@ DEFINE_ACTION_FUNCTION(AActor, GiveSecret) return 0; } + DEFINE_ACTION_FUNCTION(FLevelLocals, GiveSecret) { PARAM_PROLOGUE; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 61afdef0d..5eb3a16ad 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -539,6 +539,9 @@ class Actor : Thinker native { return damage; } + + // called on getting a secret, return false to disable default "secret found" message/sound + virtual bool OnGiveSecret(bool printmsg, bool playsound); native virtual bool OkayToSwitchTarget(Actor other); native static class GetReplacement(class cls); From 512082b222db7bc0536034efb146cad7f34e24e6 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 5 Jun 2018 10:20:02 -0400 Subject: [PATCH 10/14] - fixed: 'empty function OnGiveSecret' - this was my fault, giving bad advice to Marisa in her PR. I fixed it. --- wadsrc/static/zscript/actor.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5eb3a16ad..48148f23c 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -541,7 +541,7 @@ class Actor : Thinker native } // called on getting a secret, return false to disable default "secret found" message/sound - virtual bool OnGiveSecret(bool printmsg, bool playsound); + virtual bool OnGiveSecret(bool printmsg, bool playsound) { return true; } native virtual bool OkayToSwitchTarget(Actor other); native static class GetReplacement(class cls); From b74a9965b8f1e678f04c52fc8747cc98e6df6cf8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 5 Jun 2018 19:36:57 +0200 Subject: [PATCH 11/14] - draw models in mirrors and portals at the right location in the software renderer --- src/swrenderer/scene/r_portal.cpp | 7 +++++++ src/swrenderer/scene/r_scene.cpp | 8 ++++++++ src/swrenderer/things/r_model.cpp | 25 ++++++++++++++++++------- src/swrenderer/things/r_model.h | 6 +++++- src/swrenderer/viewport/r_viewport.cpp | 4 ++++ 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/swrenderer/scene/r_portal.cpp b/src/swrenderer/scene/r_portal.cpp index 46e6e8357..323480c32 100644 --- a/src/swrenderer/scene/r_portal.cpp +++ b/src/swrenderer/scene/r_portal.cpp @@ -173,6 +173,7 @@ namespace swrenderer Thread->Viewport->viewpoint.sector = port->mDestination; assert(Thread->Viewport->viewpoint.sector != nullptr); R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow); + Thread->Viewport->SetupPolyViewport(Thread); Thread->OpaquePass->ClearSeenSprites(); Thread->Clip3D->ClearFakeFloors(); @@ -239,6 +240,7 @@ namespace swrenderer // Masked textures and planes need the view coordinates restored for proper positioning. viewposStack.Pop(Thread->Viewport->viewpoint.Pos); + Thread->Viewport->SetupPolyViewport(Thread); Thread->TranslucentPass->Render(); VisiblePlane *pl = nullptr; // quiet, GCC! @@ -259,6 +261,7 @@ namespace swrenderer Thread->Viewport->viewpoint.extralight = savedextralight; Thread->Viewport->viewpoint.Angles = savedangles; R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow); + Thread->Viewport->SetupPolyViewport(Thread); CurrentPortalInSkybox = false; Thread->Clip3D->LeaveSkybox(); @@ -426,6 +429,8 @@ namespace swrenderer else MirrorFlags |= RF_XFLIP; } + Thread->Viewport->SetupPolyViewport(Thread); + // some portals have height differences, account for this here Thread->Clip3D->EnterSkybox(); // push 3D floor height map CurrentPortalInSkybox = false; // first portal in a skybox should set this variable to false for proper clipping in skyboxes. @@ -478,6 +483,8 @@ namespace swrenderer viewpoint.Pos = startpos; viewpoint.Path[0] = savedpath[0]; viewpoint.Path[1] = savedpath[1]; + + viewport->SetupPolyViewport(Thread); } #if 0 diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index d51eef63a..bf6653568 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -159,6 +159,8 @@ namespace swrenderer if (r_models) MainThread()->Viewport->SetupPolyViewport(MainThread()); + FRenderViewpoint origviewpoint = MainThread()->Viewport->viewpoint; + ActorRenderFlags savedflags = MainThread()->Viewport->viewpoint.camera->renderflags; // Never draw the player unless in chasecam mode if (!MainThread()->Viewport->viewpoint.showviewer) @@ -167,6 +169,12 @@ namespace swrenderer } RenderThreadSlices(); + + // Mirrors fail to restore the original viewpoint -- we need it for the HUD weapon to draw correctly. + MainThread()->Viewport->viewpoint = origviewpoint; + if (r_models) + MainThread()->Viewport->SetupPolyViewport(MainThread()); + RenderPSprites(); MainThread()->Viewport->viewpoint.camera->renderflags = savedflags; diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index d3eac67e0..831fc09f8 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -47,12 +47,22 @@ namespace swrenderer if (tz < MINZ) return; - // too far off the side? double tx = tr_x * thread->Viewport->viewpoint.Sin - tr_y * thread->Viewport->viewpoint.Cos; + + // Flip for mirrors + if (thread->Portal->MirrorFlags & RF_XFLIP) + { + tx = viewwidth - tx - 1; + } + + // too far off the side? if (fabs(tx / 64) > fabs(tz)) return; RenderModel *vis = thread->FrameMemory->NewObject(x, y, z, smf, actor, float(1 / tz)); + vis->CurrentPortalUniq = thread->Portal->CurrentPortalUniq; + vis->WorldToClip = thread->Viewport->WorldToClip; + vis->MirrorWorldToClip = !!(thread->Portal->MirrorFlags & RF_XFLIP); thread->SpriteList->Push(vis); } @@ -64,7 +74,7 @@ namespace swrenderer void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) { - SWModelRenderer renderer(thread, clip3DFloor); + SWModelRenderer renderer(thread, clip3DFloor, &WorldToClip, MirrorWorldToClip); renderer.RenderModel(x, y, z, smf, actor); } @@ -72,13 +82,14 @@ namespace swrenderer void RenderHUDModel(RenderThread *thread, DPSprite *psp, float ofsx, float ofsy) { - SWModelRenderer renderer(thread, Fake3DTranslucent()); + SWModelRenderer renderer(thread, Fake3DTranslucent(), &thread->Viewport->WorldToClip, false); renderer.RenderHUDModel(psp, ofsx, ofsy); } ///////////////////////////////////////////////////////////////////////////// - SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor) : Thread(thread), Clip3DFloor(clip3DFloor) + SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip) + : Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip) { } @@ -123,7 +134,7 @@ namespace swrenderer if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES)) PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !mirrored); + PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip)); } void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) @@ -194,7 +205,7 @@ namespace swrenderer if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]) PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true); - PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, mirrored); + PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip)); } void SWModelRenderer::EndDrawHUDModel(AActor *actor) @@ -225,7 +236,7 @@ namespace swrenderer swapYZ.Matrix[2 + 1 * 4] = 1.0f; swapYZ.Matrix[3 + 3 * 4] = 1.0f; - PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject(Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld)); + PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject((*WorldToClip) * swapYZ * ObjectToWorld)); } void SWModelRenderer::DrawArrays(int start, int count) diff --git a/src/swrenderer/things/r_model.h b/src/swrenderer/things/r_model.h index ee6608358..2c08c95c1 100644 --- a/src/swrenderer/things/r_model.h +++ b/src/swrenderer/things/r_model.h @@ -47,12 +47,14 @@ namespace swrenderer float x, y, z; FSpriteModelFrame *smf; AActor *actor; + Mat4f WorldToClip; + bool MirrorWorldToClip; }; class SWModelRenderer : public FModelRenderer { public: - SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor); + SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip); ModelRendererType GetType() const override { return SWModelRendererType; } @@ -81,6 +83,8 @@ namespace swrenderer unsigned int *IndexBuffer = nullptr; TriVertex *VertexBuffer = nullptr; float InterpolationFactor = 0.0; + Mat4f *WorldToClip = nullptr; + bool MirrorWorldToClip = false; }; class SWModelVertexBuffer : public IModelVertexBuffer diff --git a/src/swrenderer/viewport/r_viewport.cpp b/src/swrenderer/viewport/r_viewport.cpp index 57994d899..e3cfc1548 100644 --- a/src/swrenderer/viewport/r_viewport.cpp +++ b/src/swrenderer/viewport/r_viewport.cpp @@ -62,6 +62,10 @@ namespace swrenderer void RenderViewport::SetupPolyViewport(RenderThread *thread) { WorldToView = SoftwareWorldToView(viewpoint); + + if (thread->Portal->MirrorFlags & RF_XFLIP) + WorldToView = Mat4f::Scale(-1.0f, 1.0f, 1.0f) * WorldToView; + ViewToClip = SoftwareViewToClip(); WorldToClip = ViewToClip * WorldToView; } From f5386a706f8383f07b14212af9a504865a62d4c7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 5 Jun 2018 20:09:02 +0200 Subject: [PATCH 12/14] - fix software renderer dynamic lights not working properly in mirrors --- src/swrenderer/line/r_walldraw.cpp | 7 ++++++- src/swrenderer/plane/r_flatplane.cpp | 10 +++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 64f14135f..92235ae34 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -189,7 +189,12 @@ namespace swrenderer { auto viewport = Thread->Viewport.get(); - drawerargs.dc_viewpos.X = (float)((x + 0.5 - viewport->CenterX) / viewport->CenterX * zcol); + int tx = x; + bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP); + if (mirror) + tx = viewwidth - tx - 1; + + drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zcol); drawerargs.dc_viewpos.Y = zcol; drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y1 - 0.5) / viewport->InvZtoScale * zcol); drawerargs.dc_viewpos_step.Z = (float)(-zcol / viewport->InvZtoScale); diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index 8d0120559..88b3871a6 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -205,13 +205,21 @@ namespace swrenderer if (r_dynlights) { + int tx = x1; + bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP); + if (mirror) + tx = viewwidth - tx - 1; + // Find row position in view space float zspan = (float)(planeheight / (fabs(y + 0.5 - viewport->CenterY) / viewport->InvZtoScale)); - drawerargs.dc_viewpos.X = (float)((x1 + 0.5 - viewport->CenterX) / viewport->CenterX * zspan); + drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zspan); drawerargs.dc_viewpos.Y = zspan; drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y - 0.5) / viewport->InvZtoScale * zspan); drawerargs.dc_viewpos_step.X = (float)(zspan / viewport->CenterX); + if (mirror) + drawerargs.dc_viewpos_step.X = -drawerargs.dc_viewpos_step.X; + // Plane normal drawerargs.dc_normal.X = 0.0f; drawerargs.dc_normal.Y = 0.0f; From 60b6dbadb2c06b23e463ab0d759fb38abd0ba3c7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 5 Jun 2018 20:35:01 +0200 Subject: [PATCH 13/14] - fixed autoaiming for unranged attacks. The abort condition for the extended checks must completely stop any further processing but the check for this was missing. --- src/p_map.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_map.cpp b/src/p_map.cpp index 8181df71b..6853bfedf 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4271,6 +4271,7 @@ struct aim_t thingtoppitch = -VecToAngle(exitdist, th->Top() - shootz); if (thingtoppitch > bottompitch) continue; } + else continue; // shot over the thing } else continue; // shot over the thing } @@ -4289,6 +4290,7 @@ struct aim_t thingbottompitch = -VecToAngle(exitdist, th->Z() - shootz); if (thingbottompitch < toppitch) continue; } + else continue; // shot over the thing } continue; // shot under the thing } From 2baed338f7b91571ee1149162738ce5b35a264ce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 5 Jun 2018 21:44:38 +0200 Subject: [PATCH 14/14] - flat rendering must check for missing vertex buffer data. --- src/gl/scene/gl_flats.cpp | 53 +++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 63c4f9a01..2fe139c62 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -210,44 +210,47 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool auto vcount = flat->sector->ibocount; gl_RenderState.Apply(); + auto iboindex = flat->iboindex; if (gl.legacyMode) { processlights = false; - goto legacy; + iboindex = -1; } - if (vcount > 0 && !gl_RenderState.GetClipLineShouldBeActive()) + if (iboindex >= 0) { - if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli); - drawcalls.Clock(); - glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + flat->iboindex); - drawcalls.Unclock(); - flatvertices += vcount; - flatprimitives++; - } - else if (flat->iboindex >= 0) - { - int index = flat->iboindex; - for (int i=0; isector->subsectorcount; i++) + if (vcount > 0 && !gl_RenderState.GetClipLineShouldBeActive()) { - subsector_t * sub = flat->sector->subsectors[i]; - if (sub->numlines <= 2) continue; - - if (ss_renderflags[sub->Index()]& flat->renderflags || istrans) + if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli); + drawcalls.Clock(); + glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + iboindex); + drawcalls.Unclock(); + flatvertices += vcount; + flatprimitives++; + } + else + { + int index = iboindex; + for (int i = 0; i < flat->sector->subsectorcount; i++) { - if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli); - drawcalls.Clock(); - glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index); - drawcalls.Unclock(); - flatvertices += sub->numlines; - flatprimitives++; + subsector_t * sub = flat->sector->subsectors[i]; + if (sub->numlines <= 2) continue; + + if (ss_renderflags[sub->Index()] & flat->renderflags || istrans) + { + if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli); + drawcalls.Clock(); + glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index); + drawcalls.Unclock(); + flatvertices += sub->numlines; + flatprimitives++; + } + index += (sub->numlines - 2) * 3; } - index += (sub->numlines - 2) * 3; } } else { - legacy: // Draw the subsectors belonging to this sector for (int i=0; isector->subsectorcount; i++) {