From 6877930ed9f1b52c76117c64a9215ea0a51d49c9 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Fri, 8 Sep 2017 00:56:58 +0100 Subject: [PATCH 01/27] Go through and draw MD2s and sprites at the same time so they are sorted from each other (mostly) correctly --- src/hardware/hw_main.c | 67 ++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 05391f4d0..f38e67ce6 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4914,7 +4914,8 @@ static void HWR_CreateDrawNodes(void) // Draw all vissprites // -------------------------------------------------------------------------- #ifdef SORTING -static void HWR_DrawSprites(void) +// added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other +static void HWR_DrawSprites(FTransform *stransform) { if (gr_visspritecount > 0) { @@ -4933,45 +4934,33 @@ static void HWR_DrawSprites(void) if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) + { + HWD.pfnSetTransform(stransform); HWR_DrawSprite(spr); - } - else if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) - HWR_DrawSprite(spr); - } - } -} -#endif -// -------------------------------------------------------------------------- -// Draw all MD2 -// -------------------------------------------------------------------------- -static void HWR_DrawMD2S(void) -{ - if (gr_visspritecount > 0) - { - gr_vissprite_t *spr; - - // draw all MD2 back to front - for (spr = gr_vsprsortedhead.next; - spr != &gr_vsprsortedhead; - spr = spr->next) - { -#ifdef HWPRECIP - if (!spr->precip) - { -#endif - if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - { - if (md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false && md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f) + } + else + { + HWD.pfnSetTransform(&atransform); HWR_DrawMD2(spr); + } + } + else + { + if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + { + HWD.pfnSetTransform(stransform); + HWR_DrawSprite(spr); + } + else + { + HWD.pfnSetTransform(&atransform); + HWR_DrawMD2(spr); + } } - else if (md2_models[spr->mobj->sprite].notfound == false && md2_models[spr->mobj->sprite].scale > 0.0f) - HWR_DrawMD2(spr); -#ifdef HWPRECIP - } -#endif } } } +#endif // -------------------------------------------------------------------------- // HWR_AddSprites @@ -5644,12 +5633,9 @@ if (0) #ifdef SORTING HWR_SortVisSprites(); #endif - HWR_DrawMD2S(); - // Draw the sprites with trivial transform - HWD.pfnSetTransform(&stransform); #ifdef SORTING - HWR_DrawSprites(); + HWR_DrawSprites(&stransform); #endif #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? @@ -5874,12 +5860,9 @@ if (0) #ifdef SORTING HWR_SortVisSprites(); #endif - HWR_DrawMD2S(); - // Draw the sprites with trivial transform - HWD.pfnSetTransform(&stransform); #ifdef SORTING - HWR_DrawSprites(); + HWR_DrawSprites(&stransform); #endif #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? From db99537a6b67f2942c08680787a7215844770f87 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sat, 9 Sep 2017 00:41:11 +0100 Subject: [PATCH 02/27] Various Transparent Texture Fixes Draw Textures and Flats that have holes in them like a solid polygon so they use the depth buffer and don't need to be sorted Disable all linear filtering on textures and flats that have holes in them, the linear filtering introduces translucency into the textures where the edges are. Leaving them with either a black border, or causing pixels behind the slightly translucent areas to not be drawn. Doesn't apply to sprites and the HUD as they are always already sorted properly. Make the Alpha Testing more strict on non-translucent blend modes. This makes it so any transparency below 0.5 is discarded instead. Would make anything that is blended and has holes in it look slightly better, only the HUD and MD2s where the texture has holes are effected currently. Set TF_TRANSPARENT on flat texture flags when there are holes in the texture. Minor fix to make sure MD2s always set the right blend mode --- src/hardware/hw_main.c | 30 +++++------------ src/hardware/r_opengl/r_opengl.c | 57 ++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index f38e67ce6..971789122 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1072,7 +1072,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts of the wall that can't be seen */ - GLTexture_t * glTex; float realtop, realbot, top, bot; float pegt, pegb, pegmul; @@ -1238,11 +1237,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - glTex = HWR_GetTexture(texnum); + //glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); - else if (glTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); @@ -1298,11 +1295,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - glTex = HWR_GetTexture(texnum); + //glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); - else if (glTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); } @@ -2033,15 +2028,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } #endif - if (grTex->mipmap.flags & TF_TRANSPARENT) - blendmode = PF_Translucent; - if (gr_frontsector->numlights) { if (!(blendmode & PF_Masked)) HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT); else + { HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + } } else if (!(blendmode & PF_Masked)) HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); @@ -2338,15 +2332,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT) + if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } - else if (grTex->mipmap.flags & TF_TRANSPARENT) - { - blendmode = PF_Environment; - } if (gr_frontsector->numlights) HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags); @@ -2461,15 +2451,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT) + if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } - else if (grTex->mipmap.flags & TF_TRANSPARENT) - { - blendmode = PF_Environment; - } if (gr_backsector->numlights) HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags); @@ -3575,7 +3561,7 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT) // SoM: Flags are more efficient + else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING @@ -3638,7 +3624,7 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT) + else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index e6ff83e89..80df8afba 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1056,30 +1056,48 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) switch (PolyFlags & PF_Blending) { case PF_Translucent & PF_Blending: pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; case PF_Masked & PF_Blending: // Hurdler: does that mean lighting is only made by alpha src? // it sounds ok, but not for polygonsmooth pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_GREATER, 0.5f); +#endif break; case PF_Additive & PF_Blending: #ifdef ATI_RAGE_PRO_COMPATIBILITY pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency #else pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest +#endif +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); #endif break; case PF_Environment & PF_Blending: pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; case PF_Substractive & PF_Blending: // good for shadow // not realy but what else ? pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; default : // must be 0, otherwise it's an error // No blending pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_GREATER, 0.5f); +#endif break; } } @@ -1339,6 +1357,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) tex[w*j+i].s.green = 0; tex[w*j+i].s.blue = 0; tex[w*j+i].s.alpha = 0; + pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it } else { @@ -1409,8 +1428,22 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) tex_downloaded = pTexInfo->downloaded; pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { +#ifdef KOS_GL_COMPATIBILITY + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NONE); +#else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +#endif + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } #ifdef KOS_GL_COMPATIBILITY pglTexImage2D(GL_TEXTURE_2D, 0, GL_ARGB4444, w, h, 0, GL_ARGB4444, GL_UNSIGNED_BYTE, ptex); @@ -1865,12 +1898,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration ambient[1] = 0.75f; if (ambient[2] > 0.75f) ambient[2] = 0.75f; - - if (color[3] < 255) - { - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - pglDepthMask(GL_FALSE); - } } pglEnable(GL_CULL_FACE); @@ -1897,10 +1924,12 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); #endif + if (color[3] < 255) + SetBlend(PF_Translucent|PF_Modulated|PF_Clip); + else + SetBlend(PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); } - DrawPolygon(NULL, NULL, 0, PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); - pglPushMatrix(); // should be the same as glLoadIdentity //Hurdler: now it seems to work pglTranslatef(pos->x, pos->z, pos->y); @@ -1908,14 +1937,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration scaley = -scaley; pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f); - //pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - - // Remove depth mask when the model is transparent so it doesn't cut thorugh sprites // SRB2CBTODO: For all stuff too?! - if (color && color[3] < 255) - { - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - pglDepthMask(GL_FALSE); - } val = *gl_cmd_buffer++; From f3a605de6b12a947a9819561f711ee637107e46d Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Fri, 15 Sep 2017 18:03:06 +0100 Subject: [PATCH 03/27] I need to stop leaving things commented out that are going --- src/hardware/hw_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 971789122..3a2b0f0ed 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1237,7 +1237,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - //glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); else @@ -1295,7 +1294,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - //glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); else From 67ee1637c98688f5d9cae6ad781373b27e372c48 Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 6 Mar 2018 03:48:15 +0000 Subject: [PATCH 04/27] Decrease far clipping plane The Far clipping plane did not need to be nearly as high as it was, the new value is 32768, which I suspect is about how far software can render before it completely falls apart. It is desirable to increase the near clipping plane to between 6-10, but it can introduce more issues with close geometry not being drawn when the player or camera is scaled or viewheight is set to MIN in first person view. It would also stop sprites from being drawn ever so slightly too early, but this isn't too much of an issue and isn't too noticeable with those values. Might look into scaling near clipping plane in accordance to camera scale in the future. The reason for wanting to increase the near clipping plane is because the small value can cause very noticeable Z-fighting where there shouldn't be on older GPU's, usually Intel ones, that don't support 24-bits for the depth buffer. --- src/hardware/hw_defs.h | 4 ++-- src/hardware/hw_main.c | 13 +++++++------ src/hardware/r_opengl/r_opengl.c | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 70d776d9e..04802122e 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -20,8 +20,8 @@ #define _HWR_DEFS_ #include "../doomtype.h" -#define ZCLIP_PLANE 4.0f -#define NZCLIP_PLANE 0.9f +#define ZCLIP_PLANE 4.0f // Used for the actual game drawing +#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures // ========================================================================== // SIMPLE TYPES diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3a2b0f0ed..3a1cf3d9b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5330,12 +5330,13 @@ static void HWR_DrawSkyBackground(player_t *player) //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 // because it's called just after clearing the screen // and thus, the near clipping plane is set to 3.99 - v[0].x = v[3].x = -4.0f; - v[1].x = v[2].x = 4.0f; - v[0].y = v[1].y = -4.0f; - v[2].y = v[3].y = 4.0f; + // Sryder: Just use the near clipping plane value then + v[0].x = v[3].x = -ZCLIP_PLANE-1; + v[1].x = v[2].x = ZCLIP_PLANE+1; + v[0].y = v[1].y = -ZCLIP_PLANE-1; + v[2].y = v[3].y = ZCLIP_PLANE+1; - v[0].z = v[1].z = v[2].z = v[3].z = 4.0f; + v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; // X @@ -5403,7 +5404,7 @@ static inline void HWR_ClearView(void) (INT32)gr_viewwindowy, (INT32)(gr_viewwindowx + gr_viewwidth), (INT32)(gr_viewwindowy + gr_viewheight), - 3.99f); + ZCLIP_PLANE); HWD.pfnClearBuffer(false, true, 0); //disable clip window - set to full size diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 2ee5c8a80..0ab2bdae8 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -59,7 +59,7 @@ typedef struct GLRGBAFloat GLRGBAFloat; #define N_PI_DEMI (M_PIl/2.0f) //(1.5707963268f) #define ASPECT_RATIO (1.0f) //(320.0f/200.0f) -#define FAR_CLIPPING_PLANE 150000.0f // Draw further! Tails 01-21-2001 +#define FAR_CLIPPING_PLANE 32768.0f // Draw further! Tails 01-21-2001 static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; // ************************************************************************** From 77af3a8f95c453cfd013cf37c97cfe03f5554e7f Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 7 Mar 2018 05:19:06 +0000 Subject: [PATCH 05/27] Optimise the screen texture setup for SDL2, Post-processor, and wipes. Only use glCopyTexImage2D when first creating the screen texture, use glCopyTexSubImage2D anytime after that as it does not define a new texture each time. Flushing of the screen textures has been implemented for when the screen size changes (so that the screen textures don't stay at a wrong size) and the game is closed, I believe they would leave a memory leak before. --- src/hardware/hw_drv.h | 2 + src/hardware/hw_main.c | 3 + src/hardware/r_opengl/r_opengl.c | 145 +++++++++++++++++++++++-------- src/sdl/hwsym_sdl.c | 1 + src/sdl/i_video.c | 1 + src/sdl12/hwsym_sdl.c | 1 + src/sdl12/i_video.c | 1 + src/win32/win_dll.c | 2 + 8 files changed, 122 insertions(+), 34 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 7672f47c2..a5ac82001 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -79,6 +79,7 @@ EXPORT char *HWRAPI(GetRenderer) (void); #define SCREENVERTS 10 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); #endif +EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(StartScreenWipe) (void); EXPORT void HWRAPI(EndScreenWipe) (void); EXPORT void HWRAPI(DoScreenWipe) (float alpha); @@ -124,6 +125,7 @@ struct hwdriver_s #ifdef SHUFFLE PostImgRedraw pfnPostImgRedraw; #endif + FlushScreenTextures pfnFlushScreenTextures; StartScreenWipe pfnStartScreenWipe; EndScreenWipe pfnEndScreenWipe; DoScreenWipe pfnDoScreenWipe; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3a1cf3d9b..d401bc374 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5443,6 +5443,8 @@ void HWR_SetViewSize(void) gr_pspritexscale = gr_viewwidth / BASEVIDWIDTH; gr_pspriteyscale = ((vid.height*gr_pspritexscale*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width; + + HWD.pfnFlushScreenTextures(); } // ========================================================================== @@ -6036,6 +6038,7 @@ void HWR_Shutdown(void) HWR_FreeExtraSubsectors(); HWR_FreePolyPool(); HWR_FreeTextureCache(); + HWD.pfnFlushScreenTextures(); } void transform(float *cx, float *cy, float *cz) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 0ab2bdae8..9eb013a13 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -107,10 +107,19 @@ static GLint viewport[4]; #endif // Yay for arbitrary numbers! NextTexAvail is buggy for some reason. -static GLuint screentexture = 60000; -static GLuint startScreenWipe = 60001; -static GLuint endScreenWipe = 60002; -static GLuint finalScreenTexture = 60003; +// Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing +// flush all of the stored textures, leaving them unavailable at times such as between levels +// These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs +// can know when the textures aren't there, as textures are always considered resident in their virtual memory +// TODO: Store them in a more normal way +#define SCRTEX_SCREENTEXTURE 65535 +#define SCRTEX_STARTSCREENWIPE 65534 +#define SCRTEX_ENDSCREENWIPE 65533 +#define SCRTEX_FINALSCREENTEXTURE 65532 +static GLuint screentexture = 0; +static GLuint startScreenWipe = 0; +static GLuint endScreenWipe = 0; +static GLuint finalScreenTexture = 0; #if 0 GLuint screentexture = FIRST_TEX_AVAIL; #endif @@ -263,6 +272,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) /* texture mapping */ //GL_EXT_copy_texture #ifndef KOS_GL_COMPATIBILITY #define pglCopyTexImage2D glCopyTexImage2D +#define pglCopyTexSubImage2D glCopyTexSubImage2D #endif #else //!STATIC_OPENGL @@ -387,6 +397,8 @@ static PFNglBindTexture pglBindTexture; /* texture mapping */ //GL_EXT_copy_texture typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); static PFNglCopyTexImage2D pglCopyTexImage2D; +typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +static PFNglCopyTexSubImage2D pglCopyTexSubImage2D; #endif /* GLU functions */ typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data); @@ -503,6 +515,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglBindTexture , glBindTexture) GETOPENGLFUNC(pglCopyTexImage2D , glCopyTexImage2D) + GETOPENGLFUNC(pglCopyTexSubImage2D , glCopyTexSubImage2D) #undef GETOPENGLFUNC @@ -654,6 +667,10 @@ void SetModelView(GLint w, GLint h) { // DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); + // The screen textures need to be flushed if the width or height change so that they be remade for the correct size + if (screen_width != w || screen_height != h) + FlushScreenTextures(); + screen_width = w; screen_height = h; @@ -801,6 +818,7 @@ void Flush(void) screentexture = FIRST_TEX_AVAIL; } #endif + tex_downloaded = 0; } @@ -2156,10 +2174,25 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) } #endif //SHUFFLE +// Sryder: This needs to be called whenever the screen changes resolution in order to reset the screen textures to use +// a new size +EXPORT void HWRAPI(FlushScreenTextures) (void) +{ + pglDeleteTextures(1, &screentexture); + pglDeleteTextures(1, &startScreenWipe); + pglDeleteTextures(1, &endScreenWipe); + pglDeleteTextures(1, &finalScreenTexture); + screentexture = 0; + startScreenWipe = 0; + endScreenWipe = 0; + finalScreenTexture = 0; +} + // Create Screen to fade from EXPORT void HWRAPI(StartScreenWipe) (void) { INT32 texsize = 2048; + boolean firstTime = (startScreenWipe == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2168,27 +2201,38 @@ EXPORT void HWRAPI(StartScreenWipe) (void) texsize = 1024; // Create screen texture + if (firstTime) + startScreenWipe = SCRTEX_STARTSCREENWIPE; pglBindTexture(GL_TEXTURE_2D, startScreenWipe); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = startScreenWipe; } // Create Screen to fade to EXPORT void HWRAPI(EndScreenWipe)(void) { INT32 texsize = 2048; + boolean firstTime = (endScreenWipe == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2197,21 +2241,32 @@ EXPORT void HWRAPI(EndScreenWipe)(void) texsize = 1024; // Create screen texture + if (firstTime) + endScreenWipe = SCRTEX_ENDSCREENWIPE; pglBindTexture(GL_TEXTURE_2D, endScreenWipe); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + + tex_downloaded = endScreenWipe; } @@ -2253,7 +2308,7 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) pglEnd(); - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = screentexture; } // Do screen fades! @@ -2344,6 +2399,7 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit pglActiveTexture(GL_TEXTURE0); + tex_downloaded = endScreenWipe; } else { @@ -2369,11 +2425,10 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) pglTexCoord2f(xfix, 0.0f); pglVertex3f(1.0f, -1.0f, 1.0f); pglEnd(); + tex_downloaded = endScreenWipe; #ifndef MINI_GL_COMPATIBILITY } #endif - - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now } @@ -2381,6 +2436,7 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) EXPORT void HWRAPI(MakeScreenTexture) (void) { INT32 texsize = 2048; + boolean firstTime = (screentexture == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2389,7 +2445,12 @@ EXPORT void HWRAPI(MakeScreenTexture) (void) texsize = 1024; // Create screen texture + if (firstTime) + screentexture = SCRTEX_SCREENTEXTURE; pglBindTexture(GL_TEXTURE_2D, screentexture); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); @@ -2400,15 +2461,21 @@ EXPORT void HWRAPI(MakeScreenTexture) (void) Clamp2D(GL_TEXTURE_WRAP_S); Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = screentexture; } EXPORT void HWRAPI(MakeScreenFinalTexture) (void) { INT32 texsize = 2048; + boolean firstTime = (finalScreenTexture == 0); // Use a power of two texture, dammit if(screen_width <= 512) @@ -2417,21 +2484,31 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void) texsize = 1024; // Create screen texture + if (firstTime) + finalScreenTexture = SCRTEX_FINALSCREENTEXTURE; pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + + if (firstTime) + { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); +#endif + } + else +#ifndef KOS_GL_COMPATIBILITY + pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); #endif - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = finalScreenTexture; } @@ -2476,7 +2553,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) SetModelView(screen_width, screen_height); SetStates(); - tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now + tex_downloaded = finalScreenTexture; } #endif //HWRENDER diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index f4686d2bf..05ac6450e 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -94,6 +94,7 @@ void *hwSym(const char *funcName,void *handle) #ifdef SHUFFLE GETFUNC(PostImgRedraw); #endif //SHUFFLE + GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); GETFUNC(EndScreenWipe); GETFUNC(DoScreenWipe); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 1bda0e180..87ce84158 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1442,6 +1442,7 @@ void I_StartupGraphics(void) #ifdef SHUFFLE HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); #endif + HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); diff --git a/src/sdl12/hwsym_sdl.c b/src/sdl12/hwsym_sdl.c index 54f5da3a0..49340138f 100644 --- a/src/sdl12/hwsym_sdl.c +++ b/src/sdl12/hwsym_sdl.c @@ -100,6 +100,7 @@ void *hwSym(const char *funcName,void *handle) #ifdef SHUFFLE GETFUNC(PostImgRedraw); #endif //SHUFFLE + GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); GETFUNC(EndScreenWipe); GETFUNC(DoScreenWipe); diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index 197924eda..349e06cba 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1972,6 +1972,7 @@ void I_StartupGraphics(void) #ifdef SHUFFLE HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); #endif + HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 8fa4d17f7..c9b3fba4e 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -117,6 +117,7 @@ static loadfunc_t hwdFuncTable[] = { #ifdef SHUFFLE {"PostImgRedraw@4", &hwdriver.pfnPostImgRedraw}, #endif + {"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures}, {"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe}, {"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe}, {"DoScreenWipe@4", &hwdriver.pfnDoScreenWipe}, @@ -147,6 +148,7 @@ static loadfunc_t hwdFuncTable[] = { #ifdef SHUFFLE {"PostImgRedraw", &hwdriver.pfnPostImgRedraw}, #endif + {"FlushScreenTextures"},&hwdriver.pfnFlushScreenTextures}, {"StartScreenWipe", &hwdriver.pfnStartScreenWipe}, {"EndScreenWipe", &hwdriver.pfnEndScreenWipe}, {"DoScreenWipe", &hwdriver.pfnDoScreenWipe}, From 121fcd83692d2e3946678bc270a80fe679247110 Mon Sep 17 00:00:00 2001 From: Sryder Date: Thu, 8 Mar 2018 22:28:38 +0000 Subject: [PATCH 06/27] Fix screenshot functionality in fullscreen in SDL2 --- src/hardware/hw_draw.c | 14 ++++++ src/hardware/hw_drv.h | 6 +++ src/hardware/r_opengl/r_opengl.c | 79 ++++++++++++++++++++++++++++++++ src/sdl/hwsym_sdl.c | 1 + src/sdl/i_video.c | 1 + src/sdl12/hwsym_sdl.c | 1 + src/sdl12/i_video.c | 1 + 7 files changed, 103 insertions(+) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index f23753ee5..867a86a15 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -769,6 +769,9 @@ UINT8 *HWR_GetScreenshot(void) if (!buf) return NULL; // returns 24bit 888 RGB +#ifdef HAVE_SDL + if (!HWD.pfnReadScreenTexture(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf)) +#endif HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); return buf; } @@ -782,8 +785,19 @@ boolean HWR_Screenshot(const char *lbmname) return false; // returns 24bit 888 RGB +#ifdef HAVE_SDL + // Sryder: SDL2 uses borderless fullscreen mode, and creates a screen texture to upscale to the screen size. + // This breaks screenshots because the code here takes a screenshot of just the resolution from the bottom + // left corner, while the "true" resolution is the monitor resolution. We can either take a screenshot of + // the true resolution or just use the already made screen texture + // NOTE: The SDL1.2 version should get a return of false from ReadScreenTexture as no screen texture will have + // been made, this will also mean that if the screen texture doesn't exist for some reason it will fall + // back to the old version + if (!HWD.pfnReadScreenTexture(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf)) +#endif HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); + #ifdef USE_PNG ret = M_SavePNG(lbmname, buf, vid.width, vid.height, NULL); #else diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index a5ac82001..ab4025697 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -58,6 +58,9 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); +#ifdef HAVE_SDL +EXPORT boolean HWRAPI(ReadScreenTexture) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 * dst_data); +#endif EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -104,6 +107,9 @@ struct hwdriver_s ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; ReadRect pfnReadRect; +#ifdef HAVE_SDL + ReadScreenTexture pfnReadScreenTexture; +#endif GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 9eb013a13..fb8555aa9 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -260,6 +260,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D +#define pglGetTexImage glGetTexImage /* Fog */ #define pglFogf glFogf @@ -381,6 +382,8 @@ typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint static PFNglTexParameteri pglTexParameteri; typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexImage2D pglTexImage2D; +typedef void (APIENTRY * PFNglGetTexImage) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +static PFNglGetTexImage pglGetTexImage; /* Fog */ typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); @@ -507,6 +510,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglTexEnvi , glTexEnvi) GETOPENGLFUNC(pglTexParameteri , glTexParameteri) GETOPENGLFUNC(pglTexImage2D , glTexImage2D) + GETOPENGLFUNC(pglGetTexImage , glGetTexImage) GETOPENGLFUNC(pglFogf , glFogf) GETOPENGLFUNC(pglFogfv , glFogfv) @@ -933,6 +937,81 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, #endif } +#ifdef HAVE_SDL +EXPORT boolean HWRAPI(ReadScreenTexture) (INT32 x, INT32 y, INT32 width, + INT32 height, INT32 dst_stride, + UINT16 * dst_data) +{ +#ifdef KOS_GL_COMPATIBILITY + (void)x; + (void)y; + (void)width; + (void)height; + (void)dst_stride; + (void)dst_data; +#else + INT32 i, j; + INT32 texsize = 2048; + GLubyte *image; + // DBG_Printf ("ReadScreenTexture()\n"); + if (screentexture == 0) + return false; // No screen texture + + if(screen_width <= 1024) + texsize = 1024; + if(screen_width <= 512) + texsize = 512; + + if (x < 0) + x = 0; + if (x + width > screen_width) + width = screen_width - x; + if (y < 0) + y = 0; + if (y + height > screen_height) + height = screen_height - y; + + image = malloc(texsize*texsize*3*sizeof (*image)); + if (!image) + return false; + pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + tex_downloaded = finalScreenTexture; + pglGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image); + + if (dst_stride == width*3) + { + UINT8 *dest = (void *)dst_data; + for (i = y + height-1; i >= y; i--) + { + for (j = x; j < width + x; j++) + { + dest[((height-1-i-y)*width+j-x)*3] = image[(i*texsize+j)*3]; + dest[((height-1-i-y)*width+j-x)*3+1] = image[(i*texsize+j)*3+1]; + dest[((height-1-i-y)*width+j-x)*3+2] = image[(i*texsize+j)*3+2]; + } + } + } + else + { + // Sryder: NOTE: I'm not entirely sure this works, as far as I know nothing in the game uses it. + for (i = y + height-1; i >= y; i--) + { + for (j = x; j < width + x; j++) + { + dst_data[(height-1-i-y)*width+j-x] = + (UINT16)( + ((image[(i*texsize+j)*3]>>3)<<11) | + ((image[(i*texsize+j)*3+1]>>2)<<5) | + ((image[(i*texsize+j)*3+2]>>3))); + } + } + } + free(image); + return true; +#endif +} +#endif + // -----------------+ // GClipRect : Defines the 2D hardware clipping window diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 05ac6450e..33bcfd6f3 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -83,6 +83,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearBuffer); GETFUNC(SetTexture); GETFUNC(ReadRect); + GETFUNC(ReadScreenTexture); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 87ce84158..2df8a6ff5 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1430,6 +1430,7 @@ void I_StartupGraphics(void) HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); + HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); diff --git a/src/sdl12/hwsym_sdl.c b/src/sdl12/hwsym_sdl.c index 49340138f..3a10d8253 100644 --- a/src/sdl12/hwsym_sdl.c +++ b/src/sdl12/hwsym_sdl.c @@ -89,6 +89,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearBuffer); GETFUNC(SetTexture); GETFUNC(ReadRect); + GETFUNC(ReadScreenTexture); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index 349e06cba..076ce4fd2 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1960,6 +1960,7 @@ void I_StartupGraphics(void) HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); + HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); From e4ed3a793b7ad37db1ecb8cc600f300af6b20c91 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 9 Mar 2018 09:58:10 +0000 Subject: [PATCH 07/27] Small hacky fix for MD2s and sprites until sorting for walls, floors, and sprites is done Sorts all translucent sprites and MD2s so they're drawn after all the opaque ones. Fixes most of the observable issues between translucent MD2s and opaque sprites/MD2s. --- src/hardware/hw_main.c | 30 ++++++++++++++++++++++++++++++ src/hardware/r_opengl/r_opengl.c | 1 - 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d401bc374..33cf54a38 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4565,6 +4565,33 @@ static void HWR_SortVisSprites(void) gr_vsprsortedhead.prev->next = best; gr_vsprsortedhead.prev = best; } + + // Sryder: Oh boy, while it's nice having ALL the sprites sorted properly, it fails when we bring MD2's into the + // mix and they want to be translucent. So let's place all the translucent sprites and MD2's AFTER + // everything else, but still ordered of course, the depth buffer can handle the opaque ones plenty fine. + // We just need to move all translucent ones to the end in order + // TODO: Fully sort all sprites and MD2s with walls and floors, this part will be unnecessary after that + best = gr_vsprsortedhead.next; + for (i = 0; i < gr_visspritecount; i++) + { + if ((best->mobj->flags2 & MF2_SHADOW) || (best->mobj->frame & FF_TRANSMASK)) + { + if (best == gr_vsprsortedhead.next) + { + gr_vsprsortedhead.next = best->next; + } + best->prev->next = best->next; + best->next->prev = best->prev; + best->prev = gr_vsprsortedhead.prev; + gr_vsprsortedhead.prev->next = best; + gr_vsprsortedhead.prev = best; + ds = best; + best = best->next; + ds->next = &gr_vsprsortedhead; + } + else + best = best->next; + } } // A drawnode is something that points to a 3D floor, 3D side, or masked @@ -4912,7 +4939,10 @@ static void HWR_DrawSprites(FTransform *stransform) { #ifdef HWPRECIP if (spr->precip) + { + HWD.pfnSetTransform(stransform); HWR_DrawPrecipitationSprite(spr); + } else #endif if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index fb8555aa9..14cff5995 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2100,7 +2100,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, if (color) pglDisable(GL_LIGHTING); pglShadeModel(GL_FLAT); - pglDepthMask(GL_TRUE); pglDisable(GL_CULL_FACE); } From 5a4ea9fab3d447abc5374ab24a361c43e6784ddf Mon Sep 17 00:00:00 2001 From: Sryder Date: Thu, 15 Mar 2018 23:58:37 +0000 Subject: [PATCH 08/27] Better fog block colouring They still aren't perfect, but now they are at least not quite so obviously just translucent polygons over the level. A mixture between partially modulating the background colours and adding the fog colour. Notably white fog blocks look like they're brightening what's behind them. Additive was also setting noalphatest before, can probably decide that depending on what it needs anyway. I don't think it's currently used anyway. --- src/hardware/hw_defs.h | 5 ++-- src/hardware/hw_main.c | 40 +++++++++++++++----------------- src/hardware/r_opengl/r_opengl.c | 8 +++++++ 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 04802122e..c05ff3e79 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -133,12 +133,13 @@ enum EPolyFlags PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture) PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency - PF_Additive = 0x00000024, // Poly is added to the frame buffer + PF_Additive = 0x00000004, // Poly is added to the frame buffer PF_Environment = 0x00000008, // Poly should be drawn environment mapped. // Hurdler: used for text drawing PF_Substractive = 0x00000010, // for splat PF_NoAlphaTest = 0x00000020, // hiden param - PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive)&~PF_NoAlphaTest, + PF_Fog = 0x00000040, // Fog blocks + PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest, // other flag bits diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 33cf54a38..284c2c555 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -489,10 +489,10 @@ UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogbloc } -static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color, UINT32 fadecolor) // Let's see if this can work +static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this can work { - RGBA_t realcolor, fogcolor, surfcolor; - INT32 alpha, fogalpha; + RGBA_t realcolor, surfcolor; + INT32 alpha; // Don't go out of bounds if (light < 0) @@ -501,13 +501,11 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color, UINT32 fadecolor) // L light = 255; realcolor.rgba = color; - fogcolor.rgba = fadecolor; alpha = (realcolor.s.alpha*255)/25; - fogalpha = (fogcolor.s.alpha*255)/25; - // Fog blocks seem to get slightly more opaque with more opaque colourmap opacity, and much more opaque with darker brightness - surfcolor.s.alpha = (UINT8)(CALCLIGHT(light, ((0xFF-light)+alpha)/2)+CALCLIGHT(0xFF-light, ((light)+fogalpha)/2)); + // at 255 brightness, alpha is between 0 and 127, at 0 brightness alpha will always be 255 + surfcolor.s.alpha = (alpha*light)/(2*256)+255-light; return surfcolor.s.alpha; } @@ -773,7 +771,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); } - if (PolyFlags & PF_Translucent) + if (PolyFlags & (PF_Translucent|PF_Fog)) { Surf.FlatColor.s.alpha = (UINT8)alpha; PolyFlags |= PF_Modulated|PF_Occlude|PF_Clip; @@ -1380,7 +1378,7 @@ static void HWR_SplitFog(sector_t *sector, wallVert3D *wallVerts, FSurfaceInfo* wallVerts[0].y = wallVerts[1].y = bot; if (!solid) // Don't draw it if there's more fog behind it - HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Translucent|PF_NoTexture, true, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Fog|PF_NoTexture, true, lightnum, colormap); top = height; } @@ -2306,7 +2304,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode; - blendmode = PF_Translucent|PF_NoTexture; + blendmode = PF_Fog|PF_NoTexture; lightnum = rover->master->frontsector->lightlevel; colormap = rover->master->frontsector->extra_colormap; @@ -2314,11 +2312,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->master->frontsector->extra_colormap) { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba,rover->master->frontsector->extra_colormap->fadergba); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); } else { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG,FADEFOG); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); } if (gr_frontsector->numlights) @@ -2426,18 +2424,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode; - blendmode = PF_Translucent|PF_NoTexture; + blendmode = PF_Fog|PF_NoTexture; lightnum = rover->master->frontsector->lightlevel; colormap = rover->master->frontsector->extra_colormap; if (rover->master->frontsector->extra_colormap) { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba,rover->master->frontsector->extra_colormap->fadergba); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,rover->master->frontsector->extra_colormap->rgba); } else { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG,FADEFOG); + Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); } if (gr_backsector->numlights) @@ -3547,16 +3545,16 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG, FADEFOG); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, *gr_frontsector->lightlist[light].lightlevel, - alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, + alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient @@ -3610,16 +3608,16 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG, FADEFOG); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, *gr_frontsector->lightlist[light].lightlevel, - alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, + alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 14cff5995..cf87c101e 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1187,6 +1187,14 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); #ifndef KOS_GL_COMPATIBILITY pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif + break; + case PF_Fog & PF_Fog: + // Sryder: Fog + // multiplies input colour by input alpha, and destination colour by input colour, then adds them + pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); #endif break; default : // must be 0, otherwise it's an error From 1b3e1f78af6d58519a011eb84b55f3edf22e3cd0 Mon Sep 17 00:00:00 2001 From: Sryder Date: Thu, 15 Mar 2018 23:59:01 +0000 Subject: [PATCH 09/27] Translucent floors shouldn't write into the depth buffer --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 284c2c555..83783072f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -774,7 +774,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (PolyFlags & (PF_Translucent|PF_Fog)) { Surf.FlatColor.s.alpha = (UINT8)alpha; - PolyFlags |= PF_Modulated|PF_Occlude|PF_Clip; + PolyFlags |= PF_Modulated|PF_Clip; } else PolyFlags |= PF_Masked|PF_Modulated|PF_Clip; From 7764a1bb5dcc8c91929c5c9a475e1f61633dce0c Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 16 Mar 2018 18:08:24 +0000 Subject: [PATCH 10/27] Match HWR_DrawFixedPatch to V_DrawFixedPatch --- src/hardware/hw_draw.c | 103 ++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 21 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 867a86a15..30b0518cb 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -147,10 +147,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // | /| // |/ | // 0--1 - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + float dupx, dupy, fscale, fwidth, fheight; if (alphalevel >= 10 && alphalevel < 13) return; @@ -161,40 +158,104 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, else HWR_GetMappedPatch(gpatch, colormap); + dupx = (float)vid.dupx; + dupy = (float)vid.dupy; + switch (option & V_SCALEPATCHMASK) { case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; + dupx = dupy = 1.0f; break; case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); + dupx = (float)vid.smalldupx; + dupy = (float)vid.smalldupy; break; case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); + dupx = (float)vid.meddupx; + dupy = (float)vid.meddupy; break; } - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; + dupx = dupy = (dupx < dupy ? dupx : dupy); + fscale = FIXED_TO_FLOAT(pscale); - if (option & V_SPLITSCREEN) - sdupy /= 2.0f; - - if (option & V_FLIP) // Need to flip both this and sow + if (option & V_OFFSET) { - v[0].x = v[3].x = (cx*sdupx-(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[2].x = v[1].x = (cx*sdupx+gpatch->leftoffset*pdupx)/vid.width - 1; + cx -= (float)gpatch->leftoffset * dupx * fscale; + cy -= (float)gpatch->topoffset * dupy * fscale; } else { - v[0].x = v[3].x = (cx*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (cx*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; + cy -= (float)gpatch->topoffset * fscale; + if (option & V_FLIP) + cx -= ((float)gpatch->width - (float)gpatch->leftoffset) * fscale; + else + cx -= (float)gpatch->leftoffset * fscale; } - v[0].y = v[1].y = 1-(cy*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(cy*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; + if (option & V_SPLITSCREEN) + cy /= 2; + + if (!(option & V_NOSCALESTART)) + { + cx = cx * dupx; + cy = cy * dupy; + + if (!(option & V_SCALEPATCHMASK)) + { + // centre screen + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (option & V_SNAPTORIGHT) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(option & V_SNAPTOLEFT)) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2; + } + if (vid.height != BASEVIDHEIGHT * vid.dupy) + { + if ((option & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM)) + cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy)); + else if (option & V_SNAPTOBOTTOM) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(option & V_SNAPTOTOP)) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; + } + // if it's meant to cover the whole screen, black out the rest + // TODO + /*if (x == 0 && SHORT(gpatch->width) == BASEVIDWIDTH && y == 0 && SHORT(gpatch->height) == BASEVIDHEIGHT) + { + const column_t *column = (const column_t *)((const UINT8 *)((patch_t *)gpatch) + LONG(((patch_t *)gpatch)->columnofs[0])); + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + }*/ + } + } + + if (pscale != FRACUNIT) + { + fwidth = (float)gpatch->width * fscale * dupx; + fheight = (float)gpatch->height * fscale * dupy; + } + else + { + fwidth = (float)gpatch->width * dupx; + fheight = (float)gpatch->height * dupy; + } + + // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 + cx = -1 + (cx / (vid.width/2)); + cy = 1 - (cy / (vid.height/2)); + + // fwidth and fheight are similar + fwidth /= vid.width / 2; + fheight /= vid.height / 2; + + // set the polygon vertices to the right positions + v[0].x = v[3].x = cx; + v[2].x = v[1].x = cx + fwidth; + + v[0].y = v[1].y = cy; + v[2].y = v[3].y = cy - fheight; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; From 7830c031f786e8820c7b29b9da7d2b5f094f75be Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 16 Mar 2018 19:46:45 +0000 Subject: [PATCH 11/27] Make HWR_DrawFill match V_DrawFill --- src/hardware/hw_draw.c | 81 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 30b0518cb..c9ba87786 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -717,7 +717,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) { FOutVector v[4]; FSurfaceInfo Surf; - float sdupx, sdupy; + float fx, fy, fw, fh; if (w < 0 || h < 0) return; // consistency w/ software @@ -726,16 +726,79 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) // | /| // |/ | // 0--1 - sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - if (color & V_NOSCALESTART) - sdupx = sdupy = 2.0f; + fx = (float)x; + fy = (float)y; + fw = (float)w; + fh = (float)h; - v[0].x = v[3].x = (x*sdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx + w*sdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy + h*sdupy)/vid.height; + if (!(color & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { + RGBA_t rgbaColour = V_GetColor(color); + FRGBAFloat clearColour; + clearColour.red = (float)rgbaColour.s.red / 255; + clearColour.green = (float)rgbaColour.s.green / 255; + clearColour.blue = (float)rgbaColour.s.blue / 255; + clearColour.alpha = 1; + HWD.pfnClearBuffer(true, false, &clearColour); + return; + } + + fx *= dupx; + fy *= dupy; + fw *= dupx; + fh *= dupy; + + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (color & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(color & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (color & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(color & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + } + } + + if (fx >= vid.width || fy >= vid.height) + return; + if (fx < 0) + { + fw += fx; + fx = 0; + } + if (fy < 0) + { + fh += fy; + fy = 0; + } + + if (fw <= 0 || fh <= 0) + return; + if (fx + fw > vid.width) + fw = (float)vid.width - fx; + if (fy + fh > vid.height) + fh = (float)vid.height - fy; + + fx = -1 + fx / (vid.width / 2); + fy = 1 - fy / (vid.height / 2); + fw = fw / (vid.width / 2); + fh = fh / (vid.height / 2); + + v[0].x = v[3].x = fx; + v[2].x = v[1].x = fx + fw; + v[0].y = v[1].y = fy; + v[2].y = v[3].y = fy - fh; //Hurdler: do we still use this argb color? if not, we should remove it v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; From 801f7547d3893a338fa40fe86afeeab46a60f87d Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 17 Mar 2018 13:26:43 +0000 Subject: [PATCH 12/27] Add the full-screen drawfill functionality to HWR_DrawFixedPatch --- src/hardware/hw_draw.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index c9ba87786..8b5c2f76c 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -203,6 +203,18 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (!(option & V_SCALEPATCHMASK)) { + // if it's meant to cover the whole screen, black out the rest + // cx and cy are possibly *slightly* off from float maths + // This is done before here compared to software because we directly alter cx and cy to centre + if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) + { + // Need to temporarily cache the real patch to get the colour of the top left pixel + patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + Z_Free(realpatch); + } // centre screen if (vid.width != BASEVIDWIDTH * vid.dupx) { @@ -220,14 +232,6 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, else if (!(option & V_SNAPTOTOP)) cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; } - // if it's meant to cover the whole screen, black out the rest - // TODO - /*if (x == 0 && SHORT(gpatch->width) == BASEVIDWIDTH && y == 0 && SHORT(gpatch->height) == BASEVIDHEIGHT) - { - const column_t *column = (const column_t *)((const UINT8 *)((patch_t *)gpatch) + LONG(((patch_t *)gpatch)->columnofs[0])); - const UINT8 *source = (const UINT8 *)(column) + 3; - HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - }*/ } } From a9214ebd378414401d67c3beb720bcd7b8b1ecf3 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 17 Mar 2018 13:58:44 +0000 Subject: [PATCH 13/27] Match HWR_DrawCroppedPatch to V_DrawCroppedPatch --- src/hardware/hw_draw.c | 108 +++++++++++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 15 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 8b5c2f76c..14e9b6f54 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -312,10 +312,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // | /| // |/ | // 0--1 - float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f*FIXED_TO_FLOAT(pscale); - float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f*FIXED_TO_FLOAT(pscale); + float dupx, dupy, fscale, fwidth, fheight; if (alphalevel >= 10 && alphalevel < 13) return; @@ -323,28 +320,109 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // make patch ready in hardware cache HWR_GetPatch(gpatch); + dupx = (float)vid.dupx; + dupy = (float)vid.dupy; + switch (option & V_SCALEPATCHMASK) { case V_NOSCALEPATCH: - pdupx = pdupy = 2.0f; + dupx = dupy = 1.0f; break; case V_SMALLSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy); + dupx = (float)vid.smalldupx; + dupy = (float)vid.smalldupy; break; case V_MEDSCALEPATCH: - pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx); - pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy); + dupx = (float)vid.meddupx; + dupy = (float)vid.meddupy; break; } - if (option & V_NOSCALESTART) - sdupx = sdupy = 2.0f; + dupx = dupy = (dupx < dupy ? dupx : dupy); + fscale = FIXED_TO_FLOAT(pscale); - v[0].x = v[3].x = (cx*sdupx - gpatch->leftoffset * pdupx) / vid.width - 1; - v[2].x = v[1].x = (cx*sdupx + ((w-sx) - gpatch->leftoffset) * pdupx) / vid.width - 1; - v[0].y = v[1].y = 1 - (cy*sdupy - gpatch->topoffset * pdupy) / vid.height; - v[2].y = v[3].y = 1 - (cy*sdupy + ((h-sy) - gpatch->topoffset) * pdupy) / vid.height; + cy -= (float)gpatch->topoffset * fscale; + cx -= (float)gpatch->leftoffset * fscale; + + if (!(option & V_NOSCALESTART)) + { + cx = cx * dupx; + cy = cy * dupy; + + if (!(option & V_SCALEPATCHMASK)) + { + // if it's meant to cover the whole screen, black out the rest + // cx and cy are possibly *slightly* off from float maths + // This is done before here compared to software because we directly alter cx and cy to centre + if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) + { + // Need to temporarily cache the real patch to get the colour of the top left pixel + patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + Z_Free(realpatch); + } + // centre screen + if (vid.width != BASEVIDWIDTH * vid.dupx) + { + if (option & V_SNAPTORIGHT) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(option & V_SNAPTOLEFT)) + cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2; + } + if (vid.height != BASEVIDHEIGHT * vid.dupy) + { + if ((option & (V_SPLITSCREEN|V_SNAPTOBOTTOM)) == (V_SPLITSCREEN|V_SNAPTOBOTTOM)) + cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy)); + else if (option & V_SNAPTOBOTTOM) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(option & V_SNAPTOTOP)) + cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; + } + } + } + + fwidth = w; + fheight = h; + + if (fwidth > w - sx) + fwidth = w - sx; + + if (fheight > h - sy) + fheight = h - sy; + + if (fwidth > gpatch->width) + fwidth = gpatch->width; + + if (fheight > gpatch->height) + fheight = gpatch->height; + + if (pscale != FRACUNIT) + { + fwidth *= fscale * dupx; + fheight *= fscale * dupy; + } + else + { + fwidth *= dupx; + fheight *= dupy; + } + + // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 + cx = -1 + (cx / (vid.width/2)); + cy = 1 - (cy / (vid.height/2)); + + // fwidth and fheight are similar + fwidth /= vid.width / 2; + fheight /= vid.height / 2; + + // set the polygon vertices to the right positions + v[0].x = v[3].x = cx; + v[2].x = v[1].x = cx + fwidth; + + v[0].y = v[1].y = cy; + v[2].y = v[3].y = cy - fheight; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; From 6de0cc6bccb02529107cc2c7a093969784214d6f Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 17 Mar 2018 14:47:06 +0000 Subject: [PATCH 14/27] Remove the OpenGL only code from V_DrawPatchFill That's all of the HUD drawing functions that are currently used updated in GL. --- src/v_video.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index cc81cedbc..161c03d0b 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -937,14 +937,6 @@ void V_DrawPatchFill(patch_t *pat) INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; -#ifdef HWRENDER - if (rendermode == render_opengl) - { - pw = FixedMul(SHORT(pat->width)*FRACUNIT, vid.fdupx)>>FRACBITS; - ph = FixedMul(SHORT(pat->height)*FRACUNIT, vid.fdupy)>>FRACBITS; - } -#endif - for (x = 0; x < vid.width; x += pw) { for (y = 0; y < vid.height; y += ph) From 527df5c248cbb9e453355cdd9a14aa8698dea00e Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 17 Mar 2018 15:11:32 +0000 Subject: [PATCH 15/27] Fix OpenGL Title Screen Sky My IDE doesn't seem to like Vada's name. --- src/f_finale.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 692abb35f..f2a9f4038 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -233,11 +233,19 @@ static void F_SkyScroll(INT32 scrollspeed) #ifdef HWRENDER else if (rendermode != render_none) { // if only software rendering could be this simple and retarded - scrolled = animtimer; - if (scrolled > 0) - V_DrawScaledPatch(scrolled - SHORT(pat->width), 0, 0, pat); - for (x = 0; x < fakedwidth; x += SHORT(pat->width)) - V_DrawScaledPatch(x + scrolled, 0, 0, pat); + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; + scrolled = animtimer * dupz; + for (x = 0; x < vid.width; x += pw) + { + for (y = 0; y < vid.height; y += ph) + { + if (scrolled > 0) + V_DrawScaledPatch(scrolled - pw, y, V_NOSCALESTART, pat); + + V_DrawScaledPatch(x + scrolled, y, V_NOSCALESTART, pat); + } + } } #endif @@ -999,7 +1007,7 @@ static const char *credits[] = { "", "\1Sprite Artists", "Odi \"Iceman404\" Atunzu", - "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: + "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: "Jim \"MotorRoach\" DeMello", "Desmond \"Blade\" DesJardins", "Sherman \"CoatRack\" DesJardins", From 31d1ef8db05c77a755d243c6b612fd32886cbc45 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 17 Mar 2018 19:22:14 +0000 Subject: [PATCH 16/27] Draw the final screen texture in the centre with black bars Only applies when the monitor aspect ratio is different to the game's aspect ratio. --- src/hardware/r_opengl/r_opengl.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index cf87c101e..026d0126b 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2601,6 +2601,9 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void) EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) { float xfix, yfix; + float origaspect, newaspect; + float xoff = 1, yoff = 1; // xoffset and yoffset for the polygon to have black bars around the screen + FRGBAFloat clearColour; INT32 texsize = 2048; if(screen_width <= 1024) @@ -2611,28 +2614,43 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); - //pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + origaspect = (float)screen_width / screen_height; + newaspect = (float)width / height; + if (origaspect < newaspect) + { + xoff = origaspect / newaspect; + yoff = 1; + } + else if (origaspect > newaspect) + { + xoff = 1; + yoff = newaspect / origaspect; + } + pglViewport(0, 0, width, height); + clearColour.red = clearColour.green = clearColour.blue = 0; + clearColour.alpha = 1; + ClearBuffer(true, false, &clearColour); pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); pglBegin(GL_QUADS); pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Bottom left pglTexCoord2f(0.0f, 0.0f); - pglVertex3f(-1, -1, 1.0f); + pglVertex3f(-xoff, -yoff, 1.0f); // Top left pglTexCoord2f(0.0f, yfix); - pglVertex3f(-1, 1, 1.0f); + pglVertex3f(-xoff, yoff, 1.0f); // Top right pglTexCoord2f(xfix, yfix); - pglVertex3f(1, 1, 1.0f); + pglVertex3f(xoff, yoff, 1.0f); // Bottom right pglTexCoord2f(xfix, 0.0f); - pglVertex3f(1, -1, 1.0f); + pglVertex3f(xoff, -yoff, 1.0f); pglEnd(); From a984d979d113e119ca64ca4e53693064470c22f9 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 18 Mar 2018 17:12:12 +0000 Subject: [PATCH 17/27] Fix wipes in low resolutions --- src/hardware/r_opengl/r_opengl.c | 15 ++++++--------- src/sdl/ogl_sdl.c | 7 +++++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 026d0126b..5d861e618 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2538,14 +2538,14 @@ EXPORT void HWRAPI(MakeScreenTexture) (void) if (firstTime) { #ifdef KOS_GL_COMPATIBILITY - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_FILTER_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_FILTER_NONE); #else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #endif - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); + Clamp2D(GL_TEXTURE_WRAP_S); + Clamp2D(GL_TEXTURE_WRAP_T); #ifndef KOS_GL_COMPATIBILITY pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); #endif @@ -2654,9 +2654,6 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) pglEnd(); - SetModelView(screen_width, screen_height); - SetStates(); - tex_downloaded = finalScreenTexture; } diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index cd7ced7ca..4347b35b2 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -214,8 +214,11 @@ void OglSdlFinishUpdate(boolean waitvbl) HWR_DrawScreenFinalTexture(sdlw, sdlh); SDL_GL_SwapWindow(window); - SetModelView(realwidth, realheight); - SetStates(); + GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE); + + // Sryder: We need to draw the final screen texture again into the other buffer in the original position so that + // effects that want to take the old screen can do so after this + HWR_DrawScreenFinalTexture(realwidth, realheight); } EXPORT void HWRAPI( OglSdlSetPalette) (RGBA_t *palette, RGBA_t *pgamma) From f3d63b82cedd57b668d334607d4d22f935c3381d Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 18 Mar 2018 18:31:51 +0000 Subject: [PATCH 18/27] Revert "Fix screenshot functionality in fullscreen in SDL2" This reverts commit 121fcd83692d2e3946678bc270a80fe679247110. The reason I am reverting this is because the last commit actually fixes the *old* screenshot functionality, as the screen is being drawn back onto the buffer after they're swapped in the "real" size. Meaning the old function actually works perfectly fine now. --- src/hardware/hw_draw.c | 14 ------ src/hardware/hw_drv.h | 6 --- src/hardware/r_opengl/r_opengl.c | 79 -------------------------------- src/sdl/hwsym_sdl.c | 1 - src/sdl/i_video.c | 1 - src/sdl12/hwsym_sdl.c | 1 - src/sdl12/i_video.c | 1 - 7 files changed, 103 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 14e9b6f54..84081dd25 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -975,9 +975,6 @@ UINT8 *HWR_GetScreenshot(void) if (!buf) return NULL; // returns 24bit 888 RGB -#ifdef HAVE_SDL - if (!HWD.pfnReadScreenTexture(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf)) -#endif HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); return buf; } @@ -991,19 +988,8 @@ boolean HWR_Screenshot(const char *lbmname) return false; // returns 24bit 888 RGB -#ifdef HAVE_SDL - // Sryder: SDL2 uses borderless fullscreen mode, and creates a screen texture to upscale to the screen size. - // This breaks screenshots because the code here takes a screenshot of just the resolution from the bottom - // left corner, while the "true" resolution is the monitor resolution. We can either take a screenshot of - // the true resolution or just use the already made screen texture - // NOTE: The SDL1.2 version should get a return of false from ReadScreenTexture as no screen texture will have - // been made, this will also mean that if the screen texture doesn't exist for some reason it will fall - // back to the old version - if (!HWD.pfnReadScreenTexture(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf)) -#endif HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); - #ifdef USE_PNG ret = M_SavePNG(lbmname, buf, vid.width, vid.height, NULL); #else diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index ab4025697..a5ac82001 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -58,9 +58,6 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); -#ifdef HAVE_SDL -EXPORT boolean HWRAPI(ReadScreenTexture) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 * dst_data); -#endif EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -107,9 +104,6 @@ struct hwdriver_s ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; ReadRect pfnReadRect; -#ifdef HAVE_SDL - ReadScreenTexture pfnReadScreenTexture; -#endif GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 5d861e618..8e3ae3e21 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -260,7 +260,6 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D -#define pglGetTexImage glGetTexImage /* Fog */ #define pglFogf glFogf @@ -382,8 +381,6 @@ typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint static PFNglTexParameteri pglTexParameteri; typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexImage2D pglTexImage2D; -typedef void (APIENTRY * PFNglGetTexImage) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -static PFNglGetTexImage pglGetTexImage; /* Fog */ typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); @@ -510,7 +507,6 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglTexEnvi , glTexEnvi) GETOPENGLFUNC(pglTexParameteri , glTexParameteri) GETOPENGLFUNC(pglTexImage2D , glTexImage2D) - GETOPENGLFUNC(pglGetTexImage , glGetTexImage) GETOPENGLFUNC(pglFogf , glFogf) GETOPENGLFUNC(pglFogfv , glFogfv) @@ -937,81 +933,6 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, #endif } -#ifdef HAVE_SDL -EXPORT boolean HWRAPI(ReadScreenTexture) (INT32 x, INT32 y, INT32 width, - INT32 height, INT32 dst_stride, - UINT16 * dst_data) -{ -#ifdef KOS_GL_COMPATIBILITY - (void)x; - (void)y; - (void)width; - (void)height; - (void)dst_stride; - (void)dst_data; -#else - INT32 i, j; - INT32 texsize = 2048; - GLubyte *image; - // DBG_Printf ("ReadScreenTexture()\n"); - if (screentexture == 0) - return false; // No screen texture - - if(screen_width <= 1024) - texsize = 1024; - if(screen_width <= 512) - texsize = 512; - - if (x < 0) - x = 0; - if (x + width > screen_width) - width = screen_width - x; - if (y < 0) - y = 0; - if (y + height > screen_height) - height = screen_height - y; - - image = malloc(texsize*texsize*3*sizeof (*image)); - if (!image) - return false; - pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); - tex_downloaded = finalScreenTexture; - pglGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image); - - if (dst_stride == width*3) - { - UINT8 *dest = (void *)dst_data; - for (i = y + height-1; i >= y; i--) - { - for (j = x; j < width + x; j++) - { - dest[((height-1-i-y)*width+j-x)*3] = image[(i*texsize+j)*3]; - dest[((height-1-i-y)*width+j-x)*3+1] = image[(i*texsize+j)*3+1]; - dest[((height-1-i-y)*width+j-x)*3+2] = image[(i*texsize+j)*3+2]; - } - } - } - else - { - // Sryder: NOTE: I'm not entirely sure this works, as far as I know nothing in the game uses it. - for (i = y + height-1; i >= y; i--) - { - for (j = x; j < width + x; j++) - { - dst_data[(height-1-i-y)*width+j-x] = - (UINT16)( - ((image[(i*texsize+j)*3]>>3)<<11) | - ((image[(i*texsize+j)*3+1]>>2)<<5) | - ((image[(i*texsize+j)*3+2]>>3))); - } - } - } - free(image); - return true; -#endif -} -#endif - // -----------------+ // GClipRect : Defines the 2D hardware clipping window diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 33bcfd6f3..05ac6450e 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -83,7 +83,6 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearBuffer); GETFUNC(SetTexture); GETFUNC(ReadRect); - GETFUNC(ReadScreenTexture); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 2df8a6ff5..87ce84158 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1430,7 +1430,6 @@ void I_StartupGraphics(void) HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); - HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); diff --git a/src/sdl12/hwsym_sdl.c b/src/sdl12/hwsym_sdl.c index 3a10d8253..49340138f 100644 --- a/src/sdl12/hwsym_sdl.c +++ b/src/sdl12/hwsym_sdl.c @@ -89,7 +89,6 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(ClearBuffer); GETFUNC(SetTexture); GETFUNC(ReadRect); - GETFUNC(ReadScreenTexture); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index 076ce4fd2..349e06cba 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1960,7 +1960,6 @@ void I_StartupGraphics(void) HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); - HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); From 4e95066f5ac700bd868c140c90394bd94a9c2fad Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 20 Mar 2018 14:20:02 +0000 Subject: [PATCH 19/27] Some fixes and updates for HWR_SplitWall Solid walls *can* be cut Fix issues with water and fog FOFs not cutting each other out correctly Fix Fog colourmap and lighting setting that is done here. Remove HWR_SplitFog There is currently a bug with FF_DOUBLESHADOW (that also exists in software) but has a larger impact here. When 2 FF_DOUBLESHADOW lights are directly stacked on each other the bottom one has its height set incorrectly. This causes all the Fog in the timed gravity flipping section of ERZ2 to be drawn and it looks really bad. --- src/hardware/hw_main.c | 246 +++++++++++++---------------------------- 1 file changed, 76 insertions(+), 170 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 83783072f..c4e3d879e 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1065,7 +1065,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) // // HWR_SplitWall // -static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, FSurfaceInfo* Surf, UINT32 cutflag) +static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, FSurfaceInfo* Surf, UINT32 cutflag, ffloor_t *pfloor) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts @@ -1093,7 +1093,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, lightlist_t * list = sector->lightlist; const UINT8 alpha = Surf->FlatColor.s.alpha; FUINT lightnum; - extracolormap_t *colormap; + extracolormap_t *colormap = NULL; realtop = top = wallVerts[3].y; realbot = bot = wallVerts[0].y; @@ -1109,7 +1109,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, endpegmul = (endpegb - endpegt) / (endtop - endbot); #endif - for (i = 1; i < sector->numlights; i++) + for (i = 0; i < sector->numlights; i++) { #ifdef ESLOPE if (endtop < endrealbot) @@ -1117,35 +1117,38 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (top < realbot) return; - //Hurdler: fix a crashing bug, but is it correct? -// if (!list[i].caster) -// continue; + // There's a compiler warning here if this comment isn't here because of indentation + if (!(list[i].flags & FF_NOSHADE)) + { + if (pfloor && (pfloor->flags & FF_FOG)) + { + lightnum = pfloor->master->frontsector->lightlevel; + colormap = pfloor->master->frontsector->extra_colormap; + } + else + { + lightnum = *list[i].lightlevel; + colormap = list[i].extra_colormap; + } + } solid = false; - if (list[i].caster) + if ((sector->lightlist[i].flags & FF_CUTSOLIDS) && !(cutflag & FF_EXTRA)) + solid = true; + else if ((sector->lightlist[i].flags & FF_CUTEXTRA) && (cutflag & FF_EXTRA)) { - if (sector->lightlist[i].caster->flags & FF_CUTSOLIDS && !(cutflag & FF_EXTRA)) - solid = true; - else if (sector->lightlist[i].caster->flags & FF_CUTEXTRA && cutflag & FF_EXTRA) + if (sector->lightlist[i].flags & FF_EXTRA) { - if (sector->lightlist[i].caster->flags & FF_EXTRA) - { - if (sector->lightlist[i].caster->flags == cutflag) // Only merge with your own types - solid = true; - } - else + if ((sector->lightlist[i].flags & (FF_FOG|FF_SWIMMABLE)) == (cutflag & (FF_FOG|FF_SWIMMABLE))) // Only merge with your own types solid = true; } else - solid = false; + solid = true; } else solid = false; - if (cutflag == FF_CUTSOLIDS) // These are regular walls sent in from StoreWallRange, they shouldn't be cut from this - solid = false; - #ifdef ESLOPE if (list[i].slope) { @@ -1185,34 +1188,53 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (solid && endtop > endbheight) endtop = endbheight; #endif - continue; } +#ifdef ESLOPE + if (i + 1 < sector->numlights) + { + if (list[i+1].slope) + { + temp = P_GetZAt(list[i+1].slope, v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetZAt(list[i+1].slope, v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); + } + else + bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + endbheight = endrealbot; + } +#else + if (i + 1 < sector->numlights) + { + bheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + } +#endif + + if (endbheight >= endtop) + if (bheight >= top) + continue; + //Found a break; - bot = height; + bot = bheight; if (bot < realbot) bot = realbot; #ifdef ESLOPE - endbot = endheight; + endbot = endbheight; if (endbot < endrealbot) endbot = endrealbot; #endif - - // colormap test - if (list[i-1].caster) - { - lightnum = *list[i-1].lightlevel; - colormap = list[i-1].extra_colormap; - } - else - { - lightnum = sector->lightlevel; - colormap = sector->extra_colormap; - } - Surf->FlatColor.s.alpha = alpha; #ifdef ESLOPE @@ -1235,20 +1257,16 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - if (cutflag & FF_TRANSLUCENT) + if (cutflag & FF_FOG) + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); + else if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); - if (solid) - top = bheight; - else - top = height; + top = bot; #ifdef ESLOPE - if (solid) - endtop = endbheight; - else - endtop = endheight; + endtop = endbot; #endif } @@ -1260,17 +1278,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (top <= realbot) return; - if (list[i-1].caster) - { - lightnum = *list[i-1].lightlevel; - colormap = list[i-1].extra_colormap; - } - else - { - lightnum = sector->lightlevel; - colormap = sector->extra_colormap; - } - Surf->FlatColor.s.alpha = alpha; + Surf->FlatColor.s.alpha = alpha; #ifdef ESLOPE wallVerts[3].t = pegt + ((realtop - top) * pegmul); @@ -1292,116 +1300,14 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - if (cutflag & FF_TRANSLUCENT) + if (cutflag & FF_FOG) + HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); + else if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); } -// -// HWR_SplitFog -// Exclusively for fog -// -static void HWR_SplitFog(sector_t *sector, wallVert3D *wallVerts, FSurfaceInfo* Surf, UINT32 cutflag, FUINT lightnum, extracolormap_t *colormap) -{ - /* SoM: split up and light walls according to the - lightlist. This may also include leaving out parts - of the wall that can't be seen */ - float realtop, realbot, top, bot; - float pegt, pegb, pegmul; - float height = 0.0f, bheight = 0.0f; - INT32 solid, i; - lightlist_t * list = sector->lightlist; - const UINT8 alpha = Surf->FlatColor.s.alpha; - - realtop = top = wallVerts[2].y; - realbot = bot = wallVerts[0].y; - pegt = wallVerts[2].t; - pegb = wallVerts[0].t; - pegmul = (pegb - pegt) / (top - bot); - - for (i = 1; i < sector->numlights; i++) - { - if (top < realbot) - return; - - //Hurdler: fix a crashing bug, but is it correct? -// if (!list[i].caster) -// continue; - - solid = false; - - if (list[i].caster) - { - if (sector->lightlist[i].caster->flags & FF_FOG && cutflag & FF_FOG) // Only fog cuts fog - { - if (sector->lightlist[i].caster->flags & FF_EXTRA) - { - if (sector->lightlist[i].caster->flags == cutflag) // only cut by the same - solid = true; - } - else - solid = true; - } - } - - height = FIXED_TO_FLOAT(list[i].height); - - if (solid) - bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight); - - if (height >= top) - { - if (solid && top > bheight) - top = bheight; - continue; - } - - //Found a break; - bot = height; - - if (bot < realbot) - bot = realbot; - - { - - - - Surf->FlatColor.s.alpha = alpha; - } - - wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); - wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); - - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; - - if (!solid) // Don't draw it if there's more fog behind it - HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Fog|PF_NoTexture, true, lightnum, colormap); - - top = height; - } - - bot = realbot; - if (top <= realbot) - return; - - { - - Surf->FlatColor.s.alpha = alpha; - } - - wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); - wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); - - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; - - HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Translucent|PF_NoTexture, true, lightnum, colormap); -} - // HWR_DrawSkyWalls // Draw walls into the depth buffer so that anything behind is culled properly static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t bottom, fixed_t top) @@ -1678,7 +1584,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTLEVEL, NULL); else if (grTex->mipmap.flags & TF_TRANSPARENT) HWR_AddTransparentWall(wallVerts, &Surf, gr_toptexture, PF_Environment, false, lightnum, colormap); else @@ -1761,7 +1667,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTLEVEL, NULL); else if (grTex->mipmap.flags & TF_TRANSPARENT) HWR_AddTransparentWall(wallVerts, &Surf, gr_bottomtexture, PF_Environment, false, lightnum, colormap); else @@ -2027,10 +1933,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (gr_frontsector->numlights) { if (!(blendmode & PF_Masked)) - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT); + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT, NULL); else { - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTLEVEL, NULL); } } else if (!(blendmode & PF_Masked)) @@ -2182,7 +2088,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif // I don't think that solid walls can use translucent linedef types... if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTLEVEL, NULL); else { if (grTex->mipmap.flags & TF_TRANSPARENT) @@ -2320,7 +2226,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } if (gr_frontsector->numlights) - HWR_SplitFog(gr_frontsector, wallVerts, &Surf, rover->flags, lightnum, colormap); + HWR_SplitWall(gr_frontsector, wallVerts, 0, &Surf, rover->flags, rover); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -2335,7 +2241,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags); + HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags, rover); else { if (blendmode != PF_Masked) @@ -2439,7 +2345,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } if (gr_backsector->numlights) - HWR_SplitFog(gr_backsector, wallVerts, &Surf, rover->flags, lightnum, colormap); + HWR_SplitWall(gr_backsector, wallVerts, 0, &Surf, rover->flags, rover); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -2454,7 +2360,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } if (gr_backsector->numlights) - HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags); + HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags, rover); else { if (blendmode != PF_Masked) From 0885d271711155e02d389c04f12bf2c234d1a7f1 Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 21 Mar 2018 19:45:37 +0000 Subject: [PATCH 20/27] Transform sprites in world space rather than screen space Transformation based on screen space would make sense if we didn't want anything in the world to effect the sprites. This should allow sprite splitting and sorting of sprites with level geometry easier. stransform is no longer needed. --- src/hardware/hw_glob.h | 1 + src/hardware/hw_main.c | 249 +++++++++++++---------------------------- 2 files changed, 79 insertions(+), 171 deletions(-) diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 94eef1d3e..fea06caff 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -68,6 +68,7 @@ typedef struct gr_vissprite_s struct gr_vissprite_s *prev; struct gr_vissprite_s *next; float x1, x2; + float z1, z2; float tz, ty; lumpnum_t patchlumpnum; boolean flip; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c4e3d879e..7b9628b3d 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3928,12 +3928,10 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale) { - UINT8 i; - float tr_x, tr_y; - FOutVector *wv; FOutVector swallVerts[4]; FSurfaceInfo sSurf; fixed_t floorheight, mobjfloor; + float offset = 0; mobjfloor = HWR_OpaqueFloorAtPos( spr->mobj->x, spr->mobj->y, @@ -3972,6 +3970,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t } floorheight = FixedInt(spr->mobj->z - floorheight); + + offset = floorheight; } else floorheight = FixedInt(spr->mobj->z - mobjfloor); @@ -3984,47 +3984,42 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t // 0--1 // x1/x2 were already scaled in HWR_ProjectSprite + // First match the normal sprite swallVerts[0].x = swallVerts[3].x = spr->x1; swallVerts[2].x = swallVerts[1].x = spr->x2; + swallVerts[0].z = swallVerts[3].z = spr->z1; + swallVerts[2].z = swallVerts[1].z = spr->z2; if (spr->mobj && this_scale != 1.0f) { // Always a pixel above the floor, perfectly flat. swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3); - swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset) * this_scale; - swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset * this_scale; + // Now transform the TOP vertices along the floor in the direction of the camera + swallVerts[3].x = spr->x1 + ((gpatch->height * this_scale) + offset) * gr_viewcos; + swallVerts[2].x = spr->x2 + ((gpatch->height * this_scale) + offset) * gr_viewcos; + swallVerts[3].z = spr->z1 + ((gpatch->height * this_scale) + offset) * gr_viewsin; + swallVerts[2].z = spr->z2 + ((gpatch->height * this_scale) + offset) * gr_viewsin; } else { // Always a pixel above the floor, perfectly flat. swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3); - // Spread out top away from the camera. (Fixme: Make it always move out in the same direction!... somehow.) - swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset); - swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset; + // Now transform the TOP vertices along the floor in the direction of the camera + swallVerts[3].x = spr->x1 + (gpatch->height + offset) * gr_viewcos; + swallVerts[2].x = spr->x2 + (gpatch->height + offset) * gr_viewcos; + swallVerts[3].z = spr->z1 + (gpatch->height + offset) * gr_viewsin; + swallVerts[2].z = spr->z2 + (gpatch->height + offset) * gr_viewsin; } - // transform - wv = swallVerts; - - for (i = 0; i < 4; i++,wv++) + // We also need to move the bottom ones away when shadowoffs is on + if (cv_shadowoffs.value) { - // Offset away from the camera based on height from floor. - if (cv_shadowoffs.value) - wv->z += floorheight; - wv->z += 3; - - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_x = wv->z; - tr_y = wv->y; - wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - // ---------------------- mega lame test ---------------------------------- - - //scale y before frustum so that frustum can be scaled to screen height - wv->y *= ORIGINAL_ASPECT * gr_fovlud; - wv->x *= gr_fovlud; + swallVerts[0].x = spr->x1 + offset * gr_viewcos; + swallVerts[1].x = spr->x2 + offset * gr_viewcos; + swallVerts[0].z = spr->z1 + offset * gr_viewsin; + swallVerts[1].z = spr->z2 + offset * gr_viewsin; } if (spr->flip) @@ -4111,10 +4106,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t // -----------------+ static void HWR_DrawSprite(gr_vissprite_t *spr) { - UINT8 i; - float tr_x, tr_y, this_scale = 1.0f; + float this_scale = 1.0f; FOutVector wallVerts[4]; - FOutVector *wv; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); @@ -4161,24 +4154,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // make a wall polygon (with 2 triangles), using the floor/ceiling heights, // and the 2d map coords of start/end vertices - wallVerts[0].z = wallVerts[1].z = wallVerts[2].z = wallVerts[3].z = spr->tz; - - // transform - wv = wallVerts; - - for (i = 0; i < 4; i++,wv++) - { - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_x = wv->z; - tr_y = wv->y; - wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - // ---------------------- mega lame test ---------------------------------- - - //scale y before frustum so that frustum can be scaled to screen height - wv->y *= ORIGINAL_ASPECT * gr_fovlud; - wv->x *= gr_fovlud; - } + wallVerts[0].z = wallVerts[3].z = spr->z1; + wallVerts[1].z = wallVerts[2].z = spr->z2; if (spr->flip) { @@ -4289,11 +4266,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // Sprite drawer for precipitation static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) { - UINT8 i; FBITFIELD blend = 0; - float tr_x, tr_y; FOutVector wallVerts[4]; - FOutVector *wv; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; @@ -4319,24 +4293,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // make a wall polygon (with 2 triangles), using the floor/ceiling heights, // and the 2d map coords of start/end vertices - wallVerts[0].z = wallVerts[1].z = wallVerts[2].z = wallVerts[3].z = spr->tz; - - // transform - wv = wallVerts; - - for (i = 0; i < 4; i++, wv++) - { - //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - tr_x = wv->z; - tr_y = wv->y; - wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin); - wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos); - // ---------------------- mega lame test ---------------------------------- - - //scale y before frustum so that frustum can be scaled to screen height - wv->y *= ORIGINAL_ASPECT * gr_fovlud; - wv->x *= gr_fovlud; - } + wallVerts[0].z = wallVerts[3].z = spr->z1; + wallVerts[1].z = wallVerts[2].z = spr->z2; wallVerts[0].sow = wallVerts[3].sow = 0; wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; @@ -4830,7 +4788,7 @@ static void HWR_CreateDrawNodes(void) // -------------------------------------------------------------------------- #ifdef SORTING // added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other -static void HWR_DrawSprites(FTransform *stransform) +static void HWR_DrawSprites() { if (gr_visspritecount > 0) { @@ -4843,37 +4801,22 @@ static void HWR_DrawSprites(FTransform *stransform) { #ifdef HWPRECIP if (spr->precip) - { - HWD.pfnSetTransform(stransform); HWR_DrawPrecipitationSprite(spr); - } else #endif if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) - { - HWD.pfnSetTransform(stransform); HWR_DrawSprite(spr); - } else - { - HWD.pfnSetTransform(&atransform); HWR_DrawMD2(spr); - } } else { if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) - { - HWD.pfnSetTransform(stransform); HWR_DrawSprite(spr); - } else - { - HWD.pfnSetTransform(&atransform); HWR_DrawMD2(spr); - } } } } @@ -4963,8 +4906,10 @@ static void HWR_ProjectSprite(mobj_t *thing) { gr_vissprite_t *vis; float tr_x, tr_y; - float tx, tz; + float tz; float x1, x2; + float z1, z2; + float rightsin, rightcos; float this_scale; float gz, gzt; spritedef_t *sprdef; @@ -4991,7 +4936,9 @@ static void HWR_ProjectSprite(mobj_t *thing) if (tz < ZCLIP_PLANE && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear return; - tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos); + // The above can stay as it works for cutting sprites that are too close + tr_x = FIXED_TO_FLOAT(thing->x); + tr_y = FIXED_TO_FLOAT(thing->y); // decide which patch to use for sprite relative to player #ifdef RANGECHECK @@ -5046,23 +4993,23 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); - // calculate edges of the shape + rightsin = FIXED_TO_FLOAT(FINESINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); if (flip) - tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale; + { + x1 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale); + x2 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale); + } else - tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale; + { + x1 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale); + x2 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale); + } - // project x - x1 = gr_windowcenterx + (tx * gr_centerx / tz); - - //faB : tr_x doesnt matter - // hurdler: it's used in cliptosolidsegs - tr_x = x1; - - x1 = tx; - - tx += FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale; - x2 = gr_windowcenterx + (tx * gr_centerx / tz); + z1 = tr_y + x1 * rightsin; + z2 = tr_y - x2 * rightsin; + x1 = tr_x + x1 * rightcos; + x2 = tr_x - x2 * rightcos; if (thing->eflags & MFE_VERTICALFLIP) { @@ -5099,13 +5046,10 @@ static void HWR_ProjectSprite(mobj_t *thing) // store information in a vissprite vis = HWR_NewVisSprite(); vis->x1 = x1; -#if 0 vis->x2 = x2; -#else - (void)x2; -#endif - vis->x2 = tx; - vis->tz = tz; + vis->z1 = z1; + vis->z2 = z2; + vis->tz = tz; // Keep tz for the simple sprite sorting that happens vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST vis->patchlumpnum = sprframe->lumppat[rot]; vis->flip = flip; @@ -5136,7 +5080,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->colormap = colormaps; // set top/bottom coords - vis->ty = gzt - gr_viewz; + vis->ty = gzt; //CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n", // thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]); @@ -5155,8 +5099,10 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) { gr_vissprite_t *vis; float tr_x, tr_y; - float tx, tz; + float tz; float x1, x2; + float z1, z2; + float rightsin, rightcos; spritedef_t *sprdef; spriteframe_t *sprframe; size_t lumpoff; @@ -5174,7 +5120,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) if (tz < ZCLIP_PLANE) return; - tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos); + tr_x = FIXED_TO_FLOAT(thing->x); + tr_y = FIXED_TO_FLOAT(thing->y); // decide which patch to use for sprite relative to player if ((unsigned)thing->sprite >= numsprites) @@ -5201,32 +5148,32 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) lumpoff = sprframe->lumpid[0]; flip = sprframe->flip; // Will only be 0x00 or 0xFF - // calculate edges of the shape - tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset); + rightsin = FIXED_TO_FLOAT(FINESINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); + if (flip) + { + x1 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset); + x2 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset); + } + else + { + x1 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset); + x2 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset); + } - // project x - x1 = gr_windowcenterx + (tx * gr_centerx / tz); - - //faB : tr_x doesnt matter - // hurdler: it's used in cliptosolidsegs - tr_x = x1; - - x1 = tx; - - tx += FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width); - x2 = gr_windowcenterx + (tx * gr_centerx / tz); + z1 = tr_y + x1 * rightsin; + z2 = tr_y - x2 * rightsin; + x1 = tr_x + x1 * rightcos; + x2 = tr_x - x2 * rightcos; // // store information in a vissprite // vis = HWR_NewVisSprite(); vis->x1 = x1; -#if 0 vis->x2 = x2; -#else - (void)x2; -#endif - vis->x2 = tx; + vis->z1 = z1; + vis->z2 = z2; vis->tz = tz; vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST vis->patchlumpnum = sprframe->lumppat[rot]; @@ -5236,7 +5183,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->colormap = colormaps; // set top/bottom coords - vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset) - gr_viewz; + vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); vis->precip = true; } @@ -5387,7 +5334,6 @@ void HWR_SetViewSize(void) void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); - FTransform stransform; postimg_t *type; if (splitscreen && player == &players[secondarydisplayplayer]) @@ -5457,25 +5403,6 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) atransform.fovyangle = fpov; // Tails atransform.splitscreen = splitscreen; - // Transform for sprites - stransform.anglex = 0.0f; - stransform.angley = -270.0f; - - if (*type == postimg_flip) - stransform.flip = true; - else - stransform.flip = false; - - stransform.x = 0.0f; - stransform.y = 0.0f; - stransform.z = 0.0f; - stransform.scalex = 1; - stransform.scaley = 1; - stransform.scalez = 1; - stransform.fovxangle = 90.0f; - stransform.fovyangle = 90.0f; - stransform.splitscreen = splitscreen; - gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); //------------------------------------------------------------------------ @@ -5556,7 +5483,7 @@ if (0) #endif #ifdef SORTING - HWR_DrawSprites(&stransform); + HWR_DrawSprites(); #endif #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? @@ -5599,7 +5526,6 @@ if (0) void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) { const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); - FTransform stransform; postimg_t *type; const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on @@ -5684,25 +5610,6 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) atransform.fovyangle = fpov; // Tails atransform.splitscreen = splitscreen; - // Transform for sprites - stransform.anglex = 0.0f; - stransform.angley = -270.0f; - - if (*type == postimg_flip) - stransform.flip = true; - else - stransform.flip = false; - - stransform.x = 0.0f; - stransform.y = 0.0f; - stransform.z = 0.0f; - stransform.scalex = 1; - stransform.scaley = 1; - stransform.scalez = 1; - stransform.fovxangle = 90.0f; - stransform.fovyangle = 90.0f; - stransform.splitscreen = splitscreen; - gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); //------------------------------------------------------------------------ @@ -5783,7 +5690,7 @@ if (0) #endif #ifdef SORTING - HWR_DrawSprites(&stransform); + HWR_DrawSprites(); #endif #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? From 839ee0ab852c0ccfe8b974b93dccbb0a38fdba6d Mon Sep 17 00:00:00 2001 From: Sryder Date: Thu, 22 Mar 2018 00:52:14 +0000 Subject: [PATCH 21/27] OpenGL Sprite Splitting --- src/hardware/hw_main.c | 309 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 289 insertions(+), 20 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7b9628b3d..b17ead955 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1219,7 +1219,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, } #endif +#ifdef ESLOPE if (endbheight >= endtop) +#endif if (bheight >= top) continue; @@ -4099,6 +4101,285 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t } } +static void HWR_SplitSprite(gr_vissprite_t *spr) +{ + float this_scale = 1.0f; + FOutVector wallVerts[4]; + GLPatch_t *gpatch; + FSurfaceInfo Surf; + const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); + extracolormap_t *colormap; + FUINT lightlevel; + FBITFIELD blend = 0; + UINT8 alpha; + + INT32 i; + float realtop, realbot, top, bot; + float towtop, towbot, towmult; + float bheight; + const sector_t *sector = spr->mobj->subsector->sector; + const lightlist_t *list = sector->lightlist; +#ifdef ESLOPE + float endrealtop, endrealbot, endtop, endbot; + float endbheight; + fixed_t temp; + fixed_t v1x, v1y, v2x, v2y; +#endif + + this_scale = FIXED_TO_FLOAT(spr->mobj->scale); + + if (hires) + this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale); + + gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + + // cache the patch in the graphics card memory + //12/12/99: Hurdler: same comment as above (for md2) + //Hurdler: 25/04/2000: now support colormap in hardware mode + HWR_GetMappedPatch(gpatch, spr->colormap); + + // Draw shadow BEFORE sprite + if (cv_shadow.value // Shadows enabled + && (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow. + && !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow. +#ifdef ALAM_LIGHTING + && !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow. + && (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players. +#endif + && (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground. + { + //////////////////// + // SHADOW SPRITE! // + //////////////////// + HWR_DrawSpriteShadow(spr, gpatch, this_scale); + } + + wallVerts[0].x = wallVerts[3].x = spr->x1; + wallVerts[2].x = wallVerts[1].x = spr->x2; + wallVerts[0].z = wallVerts[3].z = spr->z1; + wallVerts[1].z = wallVerts[2].z = spr->z2; + + wallVerts[2].y = wallVerts[3].y = spr->ty; + if (spr->mobj && this_scale != 1.0f) + wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale; + else + wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height; + + v1x = FLOAT_TO_FIXED(spr->x1); + v1y = FLOAT_TO_FIXED(spr->z1); + v2x = FLOAT_TO_FIXED(spr->x2); + v2y = FLOAT_TO_FIXED(spr->z2); + + if (spr->flip) + { + wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s; + wallVerts[2].sow = wallVerts[1].sow = 0; + }else{ + wallVerts[0].sow = wallVerts[3].sow = 0; + wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + } + + // flip the texture coords (look familiar?) + if (spr->vflip) + { + wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t; + wallVerts[0].tow = wallVerts[1].tow = 0; + }else{ + wallVerts[3].tow = wallVerts[2].tow = 0; + wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + } + + realtop = top = wallVerts[3].y; + realbot = bot = wallVerts[0].y; + towtop = wallVerts[3].tow; + towbot = wallVerts[0].tow; + towmult = (towbot - towtop) / (top - bot); + +#ifdef ESLOPE + endrealtop = endtop = wallVerts[2].y; + endrealbot = endbot = wallVerts[1].y; +#endif + + if (!cv_translucency.value) // translucency disabled + { + Surf.FlatColor.s.alpha = 0xFF; + blend = PF_Translucent|PF_Occlude; + } + else if (spr->mobj->flags2 & MF2_SHADOW) + { + Surf.FlatColor.s.alpha = 0x40; + blend = PF_Translucent; + } + else if (spr->mobj->frame & FF_TRANSMASK) + blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); + else + { + // BP: i agree that is little better in environement but it don't + // work properly under glide nor with fogcolor to ffffff :( + // Hurdler: PF_Environement would be cool, but we need to fix + // the issue with the fog before + Surf.FlatColor.s.alpha = 0xFF; + blend = PF_Translucent|PF_Occlude; + } + + alpha = Surf.FlatColor.s.alpha; + + // Start with the lightlevel and colormap from the top of the sprite + lightlevel = *list[sector->numlights - 1].lightlevel; + colormap = list[sector->numlights - 1].extra_colormap; + i = 0; + temp = FLOAT_TO_FIXED(realtop); + +#ifdef ESLOPE + for (i = 1; i < sector->numlights; i++) + { + fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y) + : sector->lightlist[i].height; + if (h <= temp) + { + lightlevel = *list[i-1].lightlevel; + colormap = list[i-1].extra_colormap; + break; + } + } +#else + i = R_GetPlaneLight(sector, temp, false); + lightlevel = *list[i].lightlevel; + colormap = list[i].extra_colormap; +#endif + + for (i = 0; i < sector->numlights; i++) + { +#ifdef ESLOPE + if (endtop < endrealbot) +#endif + if (top < realbot) + return; + + // even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite + if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES)) + { + lightlevel = *list[i].lightlevel; + colormap = list[i].extra_colormap; + } + +#ifdef ESLOPE + if (i + 1 < sector->numlights) + { + if (list[i+1].slope) + { + temp = P_GetZAt(list[i+1].slope, v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetZAt(list[i+1].slope, v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); + } + else + bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + endbheight = endrealbot; + } +#else + if (i + 1 < sector->numlights) + { + bheight = FIXED_TO_FLOAT(list[i+1].height); + } + else + { + bheight = realbot; + } +#endif + +#ifdef ESLOPE + if (endbheight >= endtop) +#endif + if (bheight >= top) + continue; + + bot = bheight; + + if (bot < realbot) + bot = realbot; + +#ifdef ESLOPE + endbot = endbheight; + + if (endbot < endrealbot) + endbot = endrealbot; +#endif + +#ifdef ESLOPE + wallVerts[3].tow = towtop + ((realtop - top) * towmult); + wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); + wallVerts[0].tow = towtop + ((realtop - bot) * towmult); + wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + + wallVerts[3].y = top; + wallVerts[2].y = endtop; + wallVerts[0].y = bot; + wallVerts[1].y = endbot; +#else + wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); + wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); + + wallVerts[2].y = wallVerts[3].y = top; + wallVerts[0].y = wallVerts[1].y = bot; +#endif + + if (colormap) + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); + else + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + + Surf.FlatColor.s.alpha = alpha; + + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + + top = bot; +#ifdef ESLOPE + endtop = endbot; +#endif + } + + bot = realbot; +#ifdef ESLOPE + endbot = endrealbot; + if (endtop <= endrealbot) +#endif + if (top <= realbot) + return; + + // If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite +#ifdef ESLOPE + wallVerts[3].tow = towtop + ((realtop - top) * towmult); + wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult); + wallVerts[0].tow = towtop + ((realtop - bot) * towmult); + wallVerts[1].tow = towtop + ((endrealtop - endbot) * towmult); + + wallVerts[3].y = top; + wallVerts[2].y = endtop; + wallVerts[0].y = bot; + wallVerts[1].y = endbot; +#else + wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult); + wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult); + + wallVerts[2].y = wallVerts[3].y = top; + wallVerts[0].y = wallVerts[1].y = bot; +#endif + + if (colormap) + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); + else + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + + Surf.FlatColor.s.alpha = alpha; + + HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); +} + // -----------------+ // HWR_DrawSprite : Draw flat sprites // : (monsters, bonuses, weapons, lights, ...) @@ -4122,6 +4403,12 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (!spr->mobj->subsector) return; + if (spr->mobj->subsector->sector->numlights) + { + HWR_SplitSprite(spr); + return; + } + // cache sprite graphics //12/12/99: Hurdler: // OK, I don't change anything for MD2 support because I want to be @@ -4207,26 +4494,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) UINT8 lightlevel = 255; extracolormap_t *colormap = sector->extra_colormap; - if (sector->numlights) - { - INT32 light; - - light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before - - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = *sector->lightlist[light].lightlevel; - - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; - } - else - { - if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = sector->lightlevel; - - if (sector->extra_colormap) - colormap = sector->extra_colormap; - } + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = sector->lightlevel; if (colormap) Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); From fab4b7f5eab7509a6c2a3a6bc1b05ce7d3452ebd Mon Sep 17 00:00:00 2001 From: Sryder Date: Thu, 22 Mar 2018 01:10:53 +0000 Subject: [PATCH 22/27] Stop squashing the screen vertically in non-green resolutions --- src/hardware/hw_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b17ead955..86b80904f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5666,7 +5666,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) atransform.y = gr_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gr_viewz; // FIXED_TO_FLOAT(viewz) atransform.scalex = 1; - atransform.scaley = ORIGINAL_ASPECT; + atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails @@ -5873,7 +5873,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) atransform.y = gr_viewy; // FIXED_TO_FLOAT(viewy) atransform.z = gr_viewz; // FIXED_TO_FLOAT(viewz) atransform.scalex = 1; - atransform.scaley = ORIGINAL_ASPECT; + atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails From f62cb3a30a7bd36d52a5c6a7853baf9aaf887aa9 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 23 Mar 2018 22:27:29 +0000 Subject: [PATCH 23/27] I've commented out the call to HWR_CorrectSWTricks. I don't think it does anything for us anymore, and might even break things with slopes. Someone let me know if I'm wrong and am breaking things horribly here. --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 8e746457b..e93cbed51 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2718,7 +2718,7 @@ boolean P_SetupLevel(boolean skipprecip) HWR_ResetLights(); #endif // Correct missing sidedefs & deep water trick - HWR_CorrectSWTricks(); + //HWR_CorrectSWTricks(); HWR_CreatePlanePolygons((INT32)numnodes - 1); } #endif From 65c893da86e23bc3c75aeb16a4d4ec1cdebdc79d Mon Sep 17 00:00:00 2001 From: Sryder Date: Thu, 29 Mar 2018 23:28:54 +0100 Subject: [PATCH 24/27] static tempsec for R_FakeFlat I don't fully understand this, but it's what software does and it fixes the issue of the lighting in DSZ3. Also don't need the extra call to R_Prep3DFloors. --- src/hardware/hw_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 86b80904f..a0ea9b47a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2676,7 +2676,7 @@ static void HWR_AddLine(seg_t * line) angle_t span, tspan; // SoM: Backsector needs to be run through R_FakeFlat - sector_t tempsec; + static sector_t tempsec; if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) return; @@ -3235,7 +3235,7 @@ static void HWR_Subsector(size_t num) INT16 count; seg_t *line; subsector_t *sub; - sector_t tempsec; //SoM: 4/7/2000 + static sector_t tempsec; //SoM: 4/7/2000 INT32 floorlightlevel; INT32 ceilinglightlevel; INT32 locFloorHeight, locCeilingHeight; @@ -3418,8 +3418,6 @@ static void HWR_Subsector(size_t num) { /// \todo fix light, xoffs, yoffs, extracolormap ? ffloor_t * rover; - - R_Prep3DFloors(gr_frontsector); for (rover = gr_frontsector->ffloors; rover; rover = rover->next) { From f3aa02e26dad0ce1178925284f65cc8eb7b6e4f3 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 30 Mar 2018 18:13:52 +0100 Subject: [PATCH 25/27] Start with lightnum on sector lightlevel --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index a0ea9b47a..16587e5db 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1092,7 +1092,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, INT32 solid, i; lightlist_t * list = sector->lightlist; const UINT8 alpha = Surf->FlatColor.s.alpha; - FUINT lightnum; + FUINT lightnum = sector->lightlevel; extracolormap_t *colormap = NULL; realtop = top = wallVerts[3].y; From 0aaae501d379ee8526d190634e8af02ce4e8d1e8 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 30 Mar 2018 18:53:23 +0100 Subject: [PATCH 26/27] Warnings must die --- src/f_finale.c | 2 +- src/hardware/hw_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index cd699b6cb..958bef0f6 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -234,7 +234,7 @@ static void F_SkyScroll(INT32 scrollspeed) else if (rendermode != render_none) { // if only software rendering could be this simple and retarded INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; + INT32 y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; scrolled = animtimer * dupz; for (x = 0; x < vid.width; x += pw) { diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 16587e5db..becd1b1c2 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5055,7 +5055,7 @@ static void HWR_CreateDrawNodes(void) // -------------------------------------------------------------------------- #ifdef SORTING // added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other -static void HWR_DrawSprites() +static void HWR_DrawSprites(void) { if (gr_visspritecount > 0) { From 6f2de824fb015d71940e9c4d12b321b30bcb63b2 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 30 Mar 2018 23:12:44 +0100 Subject: [PATCH 27/27] Uncomment HWR_CorrectSWTricks but set gr_correcttricks to be off by default I wasn't aware of the cvar, this should do for now since I don't believe any maps use these software tricks, probably an old leftover from DOOM. --- src/hardware/hw_main.c | 2 +- src/p_setup.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index becd1b1c2..81021ef7f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -117,7 +117,7 @@ consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_CALL, grfiltermode_c consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL, granisotropicmode_cons_t, CV_anisotropic_ONChange, 0, NULL, NULL, 0, 0, NULL}; //static consvar_t cv_grzbuffer = {"gr_zbuffer", "On", 0, CV_OnOff}; -consvar_t cv_grcorrecttricks = {"gr_correcttricks", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grcorrecttricks = {"gr_correcttricks", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static void CV_FogDensity_ONChange(void) diff --git a/src/p_setup.c b/src/p_setup.c index e93cbed51..8e746457b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2718,7 +2718,7 @@ boolean P_SetupLevel(boolean skipprecip) HWR_ResetLights(); #endif // Correct missing sidedefs & deep water trick - //HWR_CorrectSWTricks(); + HWR_CorrectSWTricks(); HWR_CreatePlanePolygons((INT32)numnodes - 1); } #endif