diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca94f1b95..b4bb035af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -216,6 +216,8 @@ set(SRB2_CONFIG_HWRENDER ON CACHE BOOL "Enable hardware rendering through OpenGL.") set(SRB2_CONFIG_STATIC_OPENGL OFF CACHE BOOL "Use statically linked OpenGL. NOT RECOMMENDED.") +set(SRB2_CONFIG_USE_FBO_OGL ON CACHE BOOL + "Enable OpenGL FBO Downsampling support.") ### use internal libraries? if(${CMAKE_SYSTEM} MATCHES "Windows") ###set on Windows only @@ -510,6 +512,12 @@ if(${SRB2_CONFIG_HWRENDER} AND ${SRB2_CONFIG_STATIC_OPENGL}) endif() endif() +if(${SRB2_CONFIG_HWRENDER}) + if(${SRB2_CONFIG_USE_FBO_OGL}) + set(SRB2_USE_FBO_OGL ON) + add_definitions(-DUSE_FBO_OGL) + endif() +endif() # Targets diff --git a/src/Makefile b/src/Makefile index bc4eb6f3d..af8dd67b0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -199,6 +199,10 @@ ifndef NOOPENMPT HAVE_OPENMPT=1 endif +ifndef NOSCREENFBO +USE_FBO_OGL=1 +endif + ifdef MINGW include win32/Makefile.cfg endif #ifdef MINGW @@ -372,6 +376,12 @@ ifdef STATIC LIBS:=-static $(LIBS) endif +ifndef NOHW +ifdef USE_FBO_OGL +OPTS+=-DUSE_FBO_OGL +endif +endif + ifdef HAVE_MINIUPNPC ifdef NONET HAVE_MINIUPNPC='' diff --git a/src/Makefile.cfg b/src/Makefile.cfg index c97b4d5a9..77779f7d5 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -12,6 +12,7 @@ # to avoid a false positive with the version detection... SUPPORTED_GCC_VERSIONS:=\ + 141 14\ 132 131 130 13\ 123 122 121 120 12\ 114 113 112 111 110 11\ @@ -23,7 +24,7 @@ SUPPORTED_GCC_VERSIONS:=\ 55 54 53 52 51 50\ 49 48 47 46 45 44 43 42 41 40 -LATEST_GCC_VERSION=13.2 +LATEST_GCC_VERSION=14.1 # gcc or g++ ifdef PREFIX @@ -77,6 +78,14 @@ ifeq (,$(filter GCC%,$(.VARIABLES))) endif endif +ifdef GCC141 +GCC141=1 +endif + +ifdef GCC14 +GCC14=1 +endif + ifdef GCC132 GCC131=1 endif diff --git a/src/apng.c b/src/apng.c index 694b3d1e8..711024ee3 100644 --- a/src/apng.c +++ b/src/apng.c @@ -71,7 +71,7 @@ apng_create_info_struct (png_structp pngp) { apng_infop ainfop; (void)pngp; - if (( ainfop = calloc(sizeof (apng_info),1) )) + if (( ainfop = calloc(1, sizeof (apng_info)) )) { apng_set_write_fn(pngp, ainfop, 0, 0, 0, 0, 0); apng_set_set_acTL_fn(pngp, ainfop, 0); diff --git a/src/command.c b/src/command.c index 37e120d52..b7e1e01de 100644 --- a/src/command.c +++ b/src/command.c @@ -2132,7 +2132,12 @@ void CV_SaveVariables(FILE *f) // Silly hack for Min/Max vars if (!strcmp(cvar->string, "MAX") || !strcmp(cvar->string, "MIN")) - sprintf(stringtowrite, "%d", cvar->value); + { + if (cvar->flags & CV_FLOAT) + sprintf(stringtowrite, "%f", FixedToFloat(cvar->value)); + else + sprintf(stringtowrite, "%d", cvar->value); + } else strcpy(stringtowrite, cvar->string); diff --git a/src/d_net.c b/src/d_net.c index 1b4550d35..6b45e009d 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1445,6 +1445,12 @@ void Command_Ping_f(void) pingv[pingc].ms = ms; pingc++; } + else + { + pingv[pingc].num = 0; + pingv[pingc].f = 0; + pingv[pingc].ms = 0; + } } if (f_width < 10) f_width = 1; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b85e3a0ea..1e46da57f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2659,13 +2659,9 @@ void D_ModifyClientVote(SINT8 voted, UINT8 splitplayer) { char buf[2]; char *p = buf; - UINT8 player = consoleplayer; - - if (splitplayer > 0) - player = displayplayers[splitplayer]; WRITESINT8(p, voted); - WRITEUINT8(p, player); + WRITEUINT8(p, splitplayer); SendNetXCmd(XD_MODIFYVOTE, &buf, 2); } diff --git a/src/dehacked.c b/src/dehacked.c index 8c1ba8e4d..8b181a563 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -334,7 +334,7 @@ static void readPlayer(MYFILE *f, INT32 num) // It works down here, though. { INT32 numline = 0; - for (i = 0; i < MAXLINELEN-1; i++) + for (i = 0; (size_t)i < sizeof(description[num].notes)-1; i++) { if (numline < 20 && description[num].notes[i] == '\n') numline++; @@ -8940,7 +8940,11 @@ static char *lua_enumlib_sprintf_upper(char **buf, int* size, const char *format if (length > *size) { void *ptr = realloc(*buf, length+1); - if (!ptr) return NULL; + if (!ptr) + { + va_end(va); + return NULL; + } *buf = ptr; *size = length+1; diff --git a/src/doomdef.h b/src/doomdef.h index d1bbe04e0..2b5f93b19 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -127,8 +127,13 @@ extern char logfilename[1024]; #else #define VERSION 1 // Game version #define SUBVERSION 6 // more precise version number -#define VERSIONSTRING "Saturn v6.1 " -#define VERSIONSTRINGW L"Saturn v6.1" +#ifndef USE_FBO_OGL +#define VERSIONSTRING "Saturn v6.2 " +#define VERSIONSTRINGW L"Saturn v6.2" +#else +#define VERSIONSTRING "Saturn v6.2 - FBO " +#define VERSIONSTRINGW L"Saturn v6.2 - FBO" +#endif // Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates! // And change CMakeLists.txt (not src/, but in root), for CMake users! // AND appveyor.yml, for the build bots! diff --git a/src/g_game.c b/src/g_game.c index d7ac0e8ff..8352d0b98 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2117,6 +2117,8 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) { camerap = &camera[viewnum-1]; P_ResetCamera(&players[(*displayplayerp)], camerap); + + R_ResetViewInterpolation(viewnum); } if (viewnum > splits) @@ -6221,7 +6223,10 @@ void G_ReadMetalTic(mobj_t *metal) // Read changes from the tic if (ziptic & GZT_XYZ) { - P_MoveOrigin(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p)); + oldmetal.x = READFIXED(metal_p); + oldmetal.y = READFIXED(metal_p); + oldmetal.z = READFIXED(metal_p); + P_MoveOrigin(metal, oldmetal.x, oldmetal.y, oldmetal.z); oldmetal.x = metal->x; oldmetal.y = metal->y; oldmetal.z = metal->z; @@ -8374,7 +8379,7 @@ void G_SaveDemo(void) size_t i, strindex = 0; boolean dash = true; - for (i = 0; demo.titlename[i] && i < 127; i++) + for (i = 0; i < 127 && demo.titlename[i]; i++) { if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') || (demo.titlename[i] >= '0' && demo.titlename[i] <= '9')) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index b49c0f316..b55c10bb9 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -287,6 +287,9 @@ typedef struct FSurfaceInfo FSurfaceInfo; enum hwdsetspecialstate { +#ifdef USE_FBO_OGL + HWD_SET_FRAMEBUFFER, +#endif HWD_SET_SHADERS, HWD_SET_TEXTUREFILTERMODE, diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ff7f2a207..53f0e8786 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -69,6 +69,9 @@ static boolean gr_palette_rendering_state = false; // Commands and console variables // ========================================================================== +#ifdef USE_FBO_OGL +static void CV_grframebuffer_OnChange(void); +#endif static void CV_filtermode_ONChange(void); static void CV_anisotropic_ONChange(void); static void CV_screentextures_ONChange(void); @@ -96,6 +99,10 @@ consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, consvar_t cv_grbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +#ifdef USE_FBO_OGL +consvar_t cv_grframebuffer = {"gr_framebuffer", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, CV_grframebuffer_OnChange, 0, NULL, NULL, 0, 0, NULL}; +#endif + consvar_t cv_grfofcut = {"gr_fofcut", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fofzfightfix = {"fofzfightfix", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -177,6 +184,8 @@ static void CV_anisotropic_ONChange(void) static void CV_screentextures_ONChange(void) { ONLY_IF_GL_LOADED + if (cv_grscreentextures.value != 3) + CV_Set(&cv_grpaletterendering, "Off"); HWD.pfnSetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_grscreentextures.value); } @@ -208,6 +217,16 @@ static void CV_grpalettedepth_OnChange(void) HWR_SetPalette(pLocalPalette); } +#ifdef USE_FBO_OGL +static void CV_grframebuffer_OnChange(void) +{ + ONLY_IF_GL_LOADED + HWD.pfnSetSpecialState(HWD_SET_FRAMEBUFFER, cv_grframebuffer.value); + I_DownSample(); + RefreshOGLSDLSurface(); +} +#endif + // // Sets the shader state. // @@ -263,6 +282,8 @@ ps_metric_t ps_hw_numcolors = {0}; ps_metric_t ps_hw_batchsorttime = {0}; ps_metric_t ps_hw_batchdrawtime = {0}; +static void HWR_AddPrecipitationSprites(void); + // ========================================================================== // View position // ========================================================================== @@ -494,6 +515,8 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col poly_color.s.blue = (UINT8)blue; } + light_level = SOFTLIGHT(light_level); + // Clamp the light level, since it can sometimes go out of the 0-255 range from animations light_level = min(max(light_level, cv_secbright.value), 255); @@ -1109,7 +1132,7 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, { if (HWR_ShouldUsePaletteRendering()) { - lightnum = SOFTLIGHT(pfloor->master->frontsector->lightlevel); + lightnum = pfloor->master->frontsector->lightlevel; colormap = pfloor->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); }else{ @@ -1121,7 +1144,7 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, { if (HWR_ShouldUsePaletteRendering()) { - lightnum = SOFTLIGHT(*list[i].lightlevel); + lightnum = *list[i].lightlevel; colormap = list[i].extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); }else{ @@ -1496,7 +1519,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (HWR_ShouldUsePaletteRendering()) { - lightnum = SOFTLIGHT(gr_frontsector->lightlevel); + lightnum = gr_frontsector->lightlevel; colormap = gr_frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); } @@ -2227,7 +2250,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (HWR_ShouldUsePaletteRendering()) { - lightnum = SOFTLIGHT(rover->master->frontsector->lightlevel); + lightnum = rover->master->frontsector->lightlevel; colormap = rover->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); }else{ @@ -2235,7 +2258,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom colormap = rover->master->frontsector->extra_colormap; } - Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(SOFTLIGHT(rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap); + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gr_frontsector->numlights) HWR_SplitWall(gr_frontsector, wallVerts, 0, false, &Surf, rover->flags, rover, 0); @@ -2366,7 +2389,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (HWR_ShouldUsePaletteRendering()) { - lightnum = SOFTLIGHT(rover->master->frontsector->lightlevel); + lightnum = rover->master->frontsector->lightlevel; colormap = rover->master->frontsector->extra_colormap; lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); }else{ @@ -2374,7 +2397,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom colormap = rover->master->frontsector->extra_colormap; } - Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(SOFTLIGHT(rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap); + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gr_backsector->numlights) HWR_SplitWall(gr_backsector, wallVerts, 0, false, &Surf, rover->flags, rover, 0); @@ -3051,13 +3074,13 @@ void HWR_AddPolyObjectPlanes(void) FSurfaceInfo Surf; FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight, - SOFTLIGHT(polyobjsector->lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); + polyobjsector->lightlevel, Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); } else { HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum, R_NoEncore(polyobjsector, false)); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, - SOFTLIGHT(polyobjsector->lightlevel), levelflats[polyobjsector->floorpic].lumpnum, + polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, polyobjsector, 255, NULL); } } @@ -3073,13 +3096,13 @@ void HWR_AddPolyObjectPlanes(void) memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight, - SOFTLIGHT(polyobjsector->lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); + polyobjsector->lightlevel, Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); } else { HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum, R_NoEncore(polyobjsector, true)); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, - SOFTLIGHT(polyobjsector->lightlevel), levelflats[polyobjsector->ceilingpic].lumpnum, + polyobjsector->lightlevel, levelflats[polyobjsector->ceilingpic].lumpnum, polyobjsector, 255, NULL); } } @@ -3221,12 +3244,12 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, locFloorHeight, false); if (gr_frontsector->floorlightsec == -1) - floorlightlevel = SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel); + floorlightlevel = *gr_frontsector->lightlist[light].lightlevel; floorcolormap = gr_frontsector->lightlist[light].extra_colormap; light = R_GetPlaneLight(gr_frontsector, locCeilingHeight, false); if (gr_frontsector->ceilinglightsec == -1) - ceilinglightlevel = SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel); + ceilinglightlevel = *gr_frontsector->lightlist[light].lightlevel; ceilingcolormap = gr_frontsector->lightlist[light].extra_colormap; } @@ -3294,7 +3317,7 @@ static void HWR_Subsector(size_t num) centerHeight = P_GetFFloorBottomZAt(rover, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); if (centerHeight <= locCeilingHeight && centerHeight >= locFloorHeight && - ((viewz < bottomCullHeight && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + ((viewz < bottomCullHeight && !(rover->flags & FF_INVERTPLANES)) || (viewz > bottomCullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) @@ -3303,13 +3326,13 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, - SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), + *gr_frontsector->lightlist[light].lightlevel, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } @@ -3320,7 +3343,7 @@ static void HWR_Subsector(size_t num) &extrasubsectors[num], false, *rover->bottomheight, - SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), + *gr_frontsector->lightlist[light].lightlevel, max(0, min(rover->alpha, 255)), rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, false, gr_frontsector->lightlist[light].extra_colormap); } @@ -3328,7 +3351,7 @@ static void HWR_Subsector(size_t num) { HWR_GetFlat(levelflats[*rover->bottompic].lumpnum, R_NoEncore(gr_frontsector, false)); light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), levelflats[*rover->bottompic].lumpnum, + HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap); } } @@ -3338,7 +3361,7 @@ static void HWR_Subsector(size_t num) if (centerHeight >= locFloorHeight && centerHeight <= locCeilingHeight && - ((viewz > topCullHeight && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + ((viewz > topCullHeight && !(rover->flags & FF_INVERTPLANES)) || (viewz < topCullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) @@ -3347,13 +3370,13 @@ static void HWR_Subsector(size_t num) light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < topCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, - SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), + *gr_frontsector->lightlist[light].lightlevel, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } @@ -3364,7 +3387,7 @@ static void HWR_Subsector(size_t num) &extrasubsectors[num], true, *rover->topheight, - SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), + *gr_frontsector->lightlist[light].lightlevel, max(0, min(rover->alpha, 255)), rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, false, gr_frontsector->lightlist[light].extra_colormap); } @@ -3372,7 +3395,7 @@ static void HWR_Subsector(size_t num) { HWR_GetFlat(levelflats[*rover->toppic].lumpnum, R_NoEncore(gr_frontsector, true)); light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < topCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, SOFTLIGHT(*gr_frontsector->lightlist[light].lightlevel), levelflats[*rover->toppic].lumpnum, + HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap); } } @@ -3996,7 +4019,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) alpha = Surf.PolyColor.s.alpha; // Start with the lightlevel and colormap from the top of the sprite - lightlevel = SOFTLIGHT(*list[sector->numlights - 1].lightlevel); + lightlevel = *list[sector->numlights - 1].lightlevel; colormap = list[sector->numlights - 1].extra_colormap; i = 0; @@ -4011,7 +4034,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (h <= temp) { if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = *list[i-1].lightlevel > 255 ? 255 : SOFTLIGHT(*list[i-1].lightlevel); + lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel; colormap = list[i-1].extra_colormap; break; } @@ -4026,7 +4049,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES)) { if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = *list[i].lightlevel > 255 ? 255 : SOFTLIGHT(*list[i].lightlevel); + lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel; colormap = list[i].extra_colormap; } @@ -4245,7 +4268,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) extracolormap_t *colormap = sector->extra_colormap; if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = sector->lightlevel > 255 ? 255 : SOFTLIGHT(sector->lightlevel); + lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; HWR_Lighting(&Surf, lightlevel, colormap); } @@ -4346,7 +4369,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) 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 > 255 ? 255 : SOFTLIGHT(*sector->lightlist[light].lightlevel); + lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel; if (sector->lightlist[light].extra_colormap) colormap = sector->lightlist[light].extra_colormap; @@ -4354,7 +4377,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) else { if (!(spr->mobj->frame & FF_FULLBRIGHT)) - lightlevel = sector->lightlevel > 255 ? 255 : SOFTLIGHT(sector->lightlevel); + lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; if (sector->extra_colormap) colormap = sector->extra_colormap; @@ -4402,8 +4425,9 @@ static int CompareVisSprites(const void *p1, const void *p2) // make transparent sprites last // "boolean to int" - int transparency1 = (spr1->mobj->flags2 & MF2_SHADOW) || (spr1->mobj->frame & FF_TRANSMASK); - int transparency2 = (spr2->mobj->flags2 & MF2_SHADOW) || (spr2->mobj->frame & FF_TRANSMASK); + int transparency1 = (!spr1->precip && (spr1->mobj->flags2 & MF2_SHADOW)) || (spr1->mobj->frame & FF_TRANSMASK); + int transparency2 = (!spr2->precip && (spr2->mobj->flags2 & MF2_SHADOW)) || (spr2->mobj->frame & FF_TRANSMASK); + idiff = transparency1 - transparency2; if (idiff != 0) return idiff; @@ -4416,8 +4440,6 @@ static int CompareVisSprites(const void *p1, const void *p2) return -1; } -#undef SOFTLIGHT - static void HWR_SortVisSprites(void) { UINT32 i; @@ -4746,8 +4768,7 @@ void HWR_DrawSprites(void) void HWR_AddSprites(sector_t *sec) { mobj_t *thing; - precipmobj_t *precipthing; - fixed_t approx_dist, limit_dist, precip_limit_dist; + fixed_t approx_dist, limit_dist; INT32 splitflags; boolean split_drawsprite; // drawing with splitscreen flags @@ -4769,13 +4790,9 @@ void HWR_AddSprites(sector_t *sec) limit_dist = min(current_bsp_culling_distance, cv_drawdist.value << FRACBITS); else limit_dist = current_bsp_culling_distance; - precip_limit_dist = min(current_bsp_culling_distance, cv_drawdist_precip.value << FRACBITS); } else - { limit_dist = cv_drawdist.value << FRACBITS; - precip_limit_dist = cv_drawdist_precip.value << FRACBITS; - } // Handle all things in sector. // If a limit exists, handle things a tiny bit different. @@ -4783,7 +4800,6 @@ void HWR_AddSprites(sector_t *sec) { for (thing = sec->thinglist; thing; thing = thing->snext) { - split_drawsprite = false; if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) @@ -4828,7 +4844,6 @@ void HWR_AddSprites(sector_t *sec) // Draw everything in sector, no checks for (thing = sec->thinglist; thing; thing = thing->snext) { - split_drawsprite = false; if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) @@ -4863,21 +4878,46 @@ void HWR_AddSprites(sector_t *sec) HWR_ProjectSprite(thing); } } +} + +// -------------------------------------------------------------------------- +// HWR_AddPrecipitationSprites +// This renders through the blockmap instead of BSP to avoid +// iterating a huge amount of precipitation sprites in sectors +// that are beyond drawdist. +// -------------------------------------------------------------------------- +static void HWR_AddPrecipitationSprites(void) +{ + //const fixed_t drawdist = cv_drawdist_precip.value * mapobjectscale; + fixed_t drawdist; + + INT32 xl, xh, yl, yh, bx, by; + precipmobj_t *th; + + if (current_bsp_culling_distance) + drawdist = min(current_bsp_culling_distance, cv_drawdist_precip.value * mapobjectscale); + else + drawdist = cv_drawdist_precip.value * mapobjectscale; // No to infinite precipitation draw distance. - if (precip_limit_dist) + if (drawdist == 0) { - for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) + return; + } + + R_GetRenderBlockMapDimensions(drawdist, &xl, &xh, &yl, &yh); + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) { - if (precipthing->precipflags & PCF_INVISIBLE) - continue; + for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = th->bnext) + { + if (th->precipflags & PCF_INVISIBLE) + continue; - approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); - - if (approx_dist > precip_limit_dist) - continue; - - HWR_ProjectPrecipitationSprite(precipthing); + HWR_ProjectPrecipitationSprite(th); + } } } } @@ -4906,11 +4946,11 @@ void HWR_ProjectSprite(mobj_t *thing) size_t lumpoff; unsigned rot; UINT8 flip; - boolean mirrored = thing->mirrored; - boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); + boolean mirrored; + boolean hflip; angle_t ang, camang; - const boolean papersprite = (thing->frame & FF_PAPERSPRITE); + boolean papersprite; INT32 heightsec, phs; INT32 dist = -1; @@ -4929,6 +4969,10 @@ void HWR_ProjectSprite(mobj_t *thing) if (!thing) return; + mirrored = thing->mirrored; + hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); + papersprite = (thing->frame & FF_PAPERSPRITE); + if (cv_grmaxinterpdist.value) dist = R_QuickCamDist(thing->x, thing->y); @@ -5701,6 +5745,8 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, playe if (cv_grbatching.value) HWR_StartBatching(); + HWR_AddPrecipitationSprites(); + ps_numbspcalls.value.i = 0; ps_numpolyobjects.value.i = 0; PS_START_TIMING(ps_bsptime); @@ -5720,7 +5766,7 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, playe gr_portal = oldgl_portal_state; PS_STOP_TIMING(ps_bsptime); - + if (cv_grbatching.value) HWR_RenderBatches(); @@ -5936,6 +5982,9 @@ void HWR_TogglePaletteRendering(void) //added by Hurdler: console varibale that are saved void HWR_AddCommands(void) { +#ifdef USE_FBO_OGL + CV_RegisterVar(&cv_grframebuffer); +#endif CV_RegisterVar(&cv_grfiltermode); CV_RegisterVar(&cv_granisotropicmode); CV_RegisterVar(&cv_grsolvetjoin); @@ -5999,6 +6048,10 @@ void HWR_Startup(void) HWR_TogglePaletteRendering(); +#ifdef USE_FBO_OGL + HWD.pfnSetSpecialState(HWD_SET_FRAMEBUFFER, cv_grframebuffer.value); +#endif + if (msaa) { if (a2c) diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ec5420f2c..1c51e2981 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -152,6 +152,9 @@ void HWR_SetShaderState(void); // Console variables extern consvar_t cv_grshaders; +#ifdef USE_FBO_OGL +extern consvar_t cv_grframebuffer; +#endif extern consvar_t cv_grfofcut; extern consvar_t cv_fofzfightfix; extern consvar_t cv_splitwallfix; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 8d98f190b..0ea12a793 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -119,6 +119,14 @@ static GLfloat modelMatrix[16]; GLfloat projMatrix[16]; static GLint viewport[4]; +#ifdef USE_FBO_OGL +static boolean GLFramebuffer_IsFuncAvailible(void); + +GLuint FramebufferObject, FramebufferTexture, RenderbufferObject; +GLboolean FrameBufferEnabled = GL_FALSE, RenderToFramebuffer = GL_FALSE; + +boolean supportFBO = false; +#endif // 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 @@ -428,7 +436,32 @@ typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenu 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 + +#ifdef USE_FBO_OGL +/* 3.0 functions for framebuffers and renderbuffers */ +typedef void (APIENTRY * PFNglGenFramebuffers) (GLsizei n, GLuint *ids); +static PFNglGenFramebuffers pglGenFramebuffers; +typedef void (APIENTRY * PFNglBindFramebuffer) (GLenum target, GLuint framebuffer); +static PFNglBindFramebuffer pglBindFramebuffer; +typedef void (APIENTRY * PFNglDeleteFramebuffers) (GLsizei n, GLuint *ids); +static PFNglDeleteFramebuffers pglDeleteFramebuffers; +typedef void (APIENTRY * PFNglFramebufferTexture2D) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +static PFNglFramebufferTexture2D pglFramebufferTexture2D; +typedef GLenum (APIENTRY * PFNglCheckFramebufferStatus) (GLenum target); +static PFNglCheckFramebufferStatus pglCheckFramebufferStatus; +typedef void (APIENTRY * PFNglGenRenderbuffers) (GLsizei n, GLuint *renderbuffers); +static PFNglGenRenderbuffers pglGenRenderbuffers; +typedef void (APIENTRY * PFNglBindRenderbuffer) (GLenum target, GLuint renderbuffer); +static PFNglBindRenderbuffer pglBindRenderbuffer; +typedef void (APIENTRY * PFNglDeleteRenderbuffers) (GLsizei n, GLuint *renderbuffers); +static PFNglDeleteRenderbuffers pglDeleteRenderbuffers; +typedef void (APIENTRY * PFNglRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +static PFNglRenderbufferStorage pglRenderbufferStorage; +typedef void (APIENTRY * PFNglFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLenum renderbuffer); +static PFNglFramebufferRenderbuffer pglFramebufferRenderbuffer; +#endif // USE_FBO_OGL + +#endif //!STATIC_OPENGL /* 1.2 functions for 3D textures */ typedef void (APIENTRY * PFNglTexImage3D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); @@ -712,8 +745,39 @@ void SetupGLFunc4(void) pglUniform2fv = GetGLFunc("glUniform2fv"); pglUniform3fv = GetGLFunc("glUniform3fv"); pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); + +#ifdef USE_FBO_OGL + if (GLFramebuffer_IsFuncAvailible()) + { + pglGenFramebuffers = GetGLFunc("glGenFramebuffers"); + pglBindFramebuffer = GetGLFunc("glBindFramebuffer"); + pglDeleteFramebuffers = GetGLFunc("glDeleteFramebuffers"); + pglFramebufferTexture2D = GetGLFunc("glFramebufferTexture2D"); + pglCheckFramebufferStatus = GetGLFunc("glCheckFramebufferStatus"); + pglGenRenderbuffers = GetGLFunc("glGenRenderbuffers"); + pglBindRenderbuffer = GetGLFunc("glBindRenderbuffer"); + pglDeleteRenderbuffers = GetGLFunc("glDeleteRenderbuffers"); + pglRenderbufferStorage = GetGLFunc("glRenderbufferStorage"); + pglFramebufferRenderbuffer = GetGLFunc("glFramebufferRenderbuffer"); + } +#endif } +#ifdef USE_FBO_OGL +static boolean GLFramebuffer_IsFuncAvailible(void) +{ + //this stuff needs atleast OGL 3.0 + if (majorGL < 3) + return false; + + return((isExtAvailable("GL_ARB_framebuffer_no_attachments",gl_extensions)) && + (isExtAvailable("GL_ARB_framebuffer_object",gl_extensions)) && + (isExtAvailable("GL_ARB_framebuffer_sRGB",gl_extensions))); + + return false; +} +#endif + EXPORT boolean HWRAPI(InitShaders) (void) { if (!pglUseProgram) @@ -889,13 +953,6 @@ void SetModelView(GLint w, GLint h) { //GL_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; - pglViewport(0, 0, w, h); pglMatrixMode(GL_PROJECTION); @@ -980,6 +1037,117 @@ EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *pTexInfo) pTexInfo->downloaded = 0; } +#ifdef USE_FBO_OGL +void GLFramebuffer_Generate(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Generate the framebuffer + if (FramebufferObject == 0) + pglGenFramebuffers(1, &FramebufferObject); + + if (pglCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) + GLFramebuffer_GenerateAttachments(); +} + +void GLFramebuffer_Delete(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Unbind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (FramebufferObject) + pglDeleteFramebuffers(1, &FramebufferObject); + + GLFramebuffer_DeleteAttachments(); + FramebufferObject = 0; +} + +void GLFramebuffer_GenerateAttachments(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Bind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject); + + // Generate the framebuffer texture + if (FramebufferTexture == 0) + { + pglGenTextures(1, &FramebufferTexture); + pglBindTexture(GL_TEXTURE_2D, FramebufferTexture); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screen_width, screen_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + pglBindTexture(GL_TEXTURE_2D, 0); + + // Attach the framebuffer texture to the framebuffer + pglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FramebufferTexture, 0); + } + + // Generate the renderbuffer + if (RenderbufferObject == 0) + { + pglGenRenderbuffers(1, &RenderbufferObject); + + pglBindRenderbuffer(GL_RENDERBUFFER, RenderbufferObject); + pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screen_width, screen_height); + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RenderbufferObject); + + // Clear the renderbuffer + ClearBuffer(true, true, true, NULL); + + pglBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + // Unbind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void GLFramebuffer_DeleteAttachments(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Unbind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (FramebufferTexture) + pglDeleteTextures(1, &FramebufferTexture); + + if (RenderbufferObject) + pglDeleteRenderbuffers(1, &RenderbufferObject); + + FramebufferTexture = 0; + RenderbufferObject = 0; +} + +void GLFramebuffer_Enable(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + if (FramebufferObject == 0) + GLFramebuffer_Generate(); + else if (FramebufferTexture == 0 || RenderbufferObject == 0) + GLFramebuffer_GenerateAttachments(); + + pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject); + pglBindRenderbuffer(GL_RENDERBUFFER, RenderbufferObject); +} + +void GLFramebuffer_Disable(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + pglBindFramebuffer(GL_FRAMEBUFFER, 0); + pglBindRenderbuffer(GL_RENDERBUFFER, 0); +} +#endif // -----------------+ // Flush : flush OpenGL textures @@ -2156,7 +2324,18 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) case HWD_SET_SHADERS: gl_allowshaders = Value; break; +#ifdef USE_FBO_OGL + case HWD_SET_FRAMEBUFFER: + FrameBufferEnabled = Value ? GL_TRUE : GL_FALSE; + supportFBO = GLFramebuffer_IsFuncAvailible(); + if (!supportFBO) + { + FrameBufferEnabled = GL_FALSE; + CV_Set(&cv_grframebuffer, "Off"); + } + break; +#endif case HWD_SET_TEXTUREFILTERMODE: switch (Value) { diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index c67c69303..255969d5a 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -104,6 +104,21 @@ static PFNglEnableClientState pglEnableClientState; #endif #endif +#ifdef USE_FBO_OGL +void GLFramebuffer_Generate(void); +void GLFramebuffer_Delete(void); + +void GLFramebuffer_GenerateAttachments(void); +void GLFramebuffer_DeleteAttachments(void); + +void GLFramebuffer_Enable(void); +void GLFramebuffer_Disable(void); + +extern GLuint FramebufferObject, FramebufferTexture, RenderbufferObject; +extern GLboolean FrameBufferEnabled, RenderToFramebuffer; +extern boolean supportFBO; +#endif + // ========================================================================== // GLOBAL // ========================================================================== diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 4224b992c..cd0f42a9c 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -531,7 +531,8 @@ static void HU_removeChatText_Log(void) free(chat_log[0]); size_t i; - for(i=0;i= y) - x -= y; - if (n) - return -x; - else - return x; + return x % y; } /** \brief The FixedSqrt function diff --git a/src/m_menu.c b/src/m_menu.c index b672357a1..cc7d45d33 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -58,6 +58,7 @@ #ifdef HWRENDER #include "hardware/hw_main.h" +#include "hardware/r_opengl/r_opengl.h" #endif #include "d_net.h" @@ -1339,9 +1340,9 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_SUBMENU|IT_STRING, NULL, "Advanced Color Settings...", &OP_ColorOptionsDef, 50}, - {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 65}, - {IT_STRING | IT_CVAR, NULL, "Weather Draw Distance",&cv_drawdist_precip, 75}, - {IT_STRING | IT_CVAR, NULL, "Field of View", &cv_fov, 95}, + {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 65}, + {IT_STRING | IT_CVAR, NULL, "Weather Draw Distance",&cv_drawdist_precip, 75}, + {IT_STRING | IT_CVAR | IT_CV_BIGFLOAT, NULL, "Field of View", &cv_fov, 95}, {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 105}, {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 115}, @@ -1451,26 +1452,29 @@ static menuitem_t OP_ColorOptionsMenu[] = static menuitem_t OP_ExpOptionsMenu[] = { {IT_HEADER, NULL, "Experimental Options", NULL, 10}, - {IT_STRING|IT_CVAR, NULL, "Interpolation Distance", &cv_grmaxinterpdist, 25}, - {IT_STRING|IT_CVAR, NULL, "Mobj Subsector Interpolation", &cv_mobjssector, 35}, - {IT_STRING | IT_CVAR, NULL, "Weather Interpolation", &cv_precipinterp, 45}, - {IT_STRING | IT_CVAR, NULL, "Less Weather Effects", &cv_lessprecip, 55}, + {IT_STRING|IT_CVAR, NULL, "Interpolation Distance", &cv_grmaxinterpdist, 20}, + {IT_STRING|IT_CVAR, NULL, "Mobj Subsector Interpolation", &cv_mobjssector, 25}, + {IT_STRING | IT_CVAR, NULL, "Weather Interpolation", &cv_precipinterp, 30}, + {IT_STRING | IT_CVAR, NULL, "Less Weather Effects", &cv_lessprecip, 35}, - {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 70}, + {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 42}, - {IT_STRING | IT_CVAR, NULL, "Clipping R_PointToAngle Version", &cv_pointoangleexor64, 85}, + {IT_STRING | IT_CVAR, NULL, "Clipping R_PointToAngle Version", &cv_pointoangleexor64, 49}, - {IT_STRING | IT_CVAR, NULL, "FFloorclip", &cv_ffloorclip, 95}, - {IT_STRING | IT_CVAR, NULL, "Spriteclip", &cv_spriteclip, 105}, + {IT_STRING | IT_CVAR, NULL, "FFloorclip", &cv_ffloorclip, 56}, + {IT_STRING | IT_CVAR, NULL, "Spriteclip", &cv_spriteclip, 61}, #ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 95}, + {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 68}, +#ifdef USE_FBO_OGL + {IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_grframebuffer, 73}, +#endif - {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 105}, + {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 80}, - {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 125}, - {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 135}, - {IT_STRING | IT_CVAR, NULL, "ZFighting fix for fofs", &cv_fofzfightfix, 145}, - {IT_STRING | IT_CVAR, NULL, "FOF wall cutoff for slopes", &cv_grfofcut, 155}, + {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 87}, + {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 92}, + {IT_STRING | IT_CVAR, NULL, "ZFighting fix for fofs", &cv_fofzfightfix, 97}, + {IT_STRING | IT_CVAR, NULL, "FOF wall cutoff for slopes", &cv_grfofcut, 102}, #endif }; @@ -1487,6 +1491,9 @@ static const char* OP_ExpTooltips[] = "Hides Sprites which are not visible\npotentially resulting in a performance boost.", #ifdef HWRENDER "Should the game do Screen Textures? Provides a good boost to frames\nat the cost of some visual effects not working when disabled.", +#ifdef USE_FBO_OGL + "Allows the game to downsample from a higher resolution than your display in OpenGL renderer mode\nrequires a GPU with atleast OpenGL 3.0 support.", +#endif "Change the depth of the Palette in Palette rendering mod\n 16 bits is like software looks ingame\nwhile 24 bits is how software looks in screenshots.", "Fixes issues that resulted in Textures sticking from the ground sometimes.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures not being properly skewed\n example: Fences on slopes that didnt show proper.\n This may be CPU heavy and result in worse performance in some cases.", @@ -1508,6 +1515,10 @@ enum op_exp_sprclip, #ifdef HWRENDER op_exp_grscrtx, +#ifdef USE_FBO_OGL + op_exp_fbo, +#endif + op_exp_paldepth, op_exp_spltwal, op_exp_pegging, op_exp_fofzfight, @@ -2351,7 +2362,7 @@ static menuitem_t OP_DriftGaugeMenu[] = {IT_HEADER, NULL, "Driftgauge", NULL, 0}, {IT_STRING | IT_CVAR, NULL, "Driftgauge", &cv_driftgauge, 20}, {IT_STRING | IT_CVAR, NULL, "Driftgauge Transparency", &cv_driftgaugetrans, 30}, - {IT_STRING | IT_CVAR, NULL, "Driftgauge Offset", &cv_driftgaugeofs, 40}, + {IT_STRING | IT_CVAR | IT_CV_BIGFLOAT, NULL, "Driftgauge Offset", &cv_driftgaugeofs, 40}, {IT_STRING | IT_CVAR, NULL, "Driftgauge Style", &cv_driftgaugestyle, 50}, }; @@ -2909,7 +2920,7 @@ menu_t OP_MonitorToggleDef = menu_t OP_OpenGLOptionsDef = DEFAULTSCROLLSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); #endif -menu_t OP_ExpOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_ExpOptionsMenu, &OP_VideoOptionsDef, 30, 20); +menu_t OP_ExpOptionsDef = DEFAULTSCROLLSTYLE("M_VIDEO", OP_ExpOptionsMenu, &OP_VideoOptionsDef, 30, 35); menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); @@ -3305,7 +3316,11 @@ static void M_ChangeCvar(INT32 choice) else if (cv->flags & CV_FLOAT) { char s[20]; - sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); + float increment; + + increment = (currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5 : (1.f/16); + + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*increment); CV_Set(cv,s); } else @@ -4464,16 +4479,23 @@ void M_Init(void) { OP_VideoOptionsMenu[op_video_ogl].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_grscrtx].status = IT_DISABLED; +#ifdef USE_FBO_OGL + OP_ExpOptionsMenu[op_exp_fbo].status = IT_DISABLED; +#endif OP_ExpOptionsMenu[op_exp_spltwal].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_pegging].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_fofzfight].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_fofcut].status = IT_DISABLED; } - + if (rendermode == render_opengl) { OP_ExpOptionsMenu[op_exp_ffclip].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_sprclip].status = IT_DISABLED; +#ifdef USE_FBO_OGL + if (!supportFBO) + OP_ExpOptionsMenu[op_exp_fbo].status = IT_GRAYEDOUT; +#endif } #endif diff --git a/src/m_menu.h b/src/m_menu.h index bb504642d..bba8d3db3 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -129,6 +129,10 @@ extern boolean menu_text_input; #define IT_CV_NOMOD 2048 #define IT_CV_INVISSLIDER 2560 +// For cv_float's, will use 1/2 as increment instead of 1/16 +// Not sure if i should add it to cvartype, since its more a flag than type +#define IT_CV_BIGFLOAT 4096 + //call/submenu specific // There used to be a lot more here but ... // A lot of them became redundant with the advent of the Pause menu, so they were removed diff --git a/src/m_misc.c b/src/m_misc.c index 97dcbed84..7d0ce6bfc 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1589,7 +1589,7 @@ char *va(const char *format, ...) static char string[1024]; va_start(argptr, format); - vsprintf(string, format, argptr); + vsnprintf(string, 1024, format, argptr); va_end(argptr); return string; diff --git a/src/p_local.h b/src/p_local.h index dc473b648..e1a07526a 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -387,6 +387,7 @@ extern INT32 bmapheight; // in mapblocks extern fixed_t bmaporgx; extern fixed_t bmaporgy; // origin of block map extern mobj_t **blocklinks; // for thing chains +extern precipmobj_t **precipblocklinks; // special blockmap for precip rendering // // P_INTER diff --git a/src/p_maputl.c b/src/p_maputl.c index c680931d0..3c91dc922 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -754,15 +754,45 @@ void P_UnsetThingPosition(mobj_t *thing) void P_UnsetPrecipThingPosition(precipmobj_t *thing) { - precipmobj_t **sprev = thing->sprev; - precipmobj_t *snext = thing->snext; - if ((*sprev = snext) != NULL) // unlink from sector list - snext->sprev = sprev; + precipmobj_t **bprev = thing->bprev; + precipmobj_t *bnext = thing->bnext; + + if (bprev && (*bprev = bnext) != NULL) // unlink from block map + bnext->bprev = bprev; precipsector_list = thing->touching_sectorlist; thing->touching_sectorlist = NULL; //to be restored by P_SetPrecipThingPosition } +static void P_LinkToBlockMap(mobj_t *thing, mobj_t **bmap) +{ + const INT32 blockx = (unsigned)(thing->x - bmaporgx) >> MAPBLOCKSHIFT; + const INT32 blocky = (unsigned)(thing->y - bmaporgy) >> MAPBLOCKSHIFT; + + if (blockx >= 0 && blockx < bmapwidth + && blocky >= 0 && blocky < bmapheight) + { + // killough 8/11/98: simpler scheme using + // pointer-to-pointer prev pointers -- + // allows head nodes to be treated like everything else + + mobj_t **link = &bmap[(blocky * bmapwidth) + blockx]; + mobj_t *bnext = *link; + + thing->bnext = bnext; + + if (bnext != NULL) + bnext->bprev = &thing->bnext; + + thing->bprev = link; + *link = thing; + } + else // thing is off the map + { + thing->bnext = NULL, thing->bprev = NULL; + } +} + // // P_SetThingPosition // Links a thing into both a block and a subsector @@ -819,24 +849,7 @@ void P_SetThingPosition(mobj_t *thing) if (!(thing->flags & MF_NOBLOCKMAP)) { // inert things don't need to be in blockmap - const INT32 blockx = (unsigned)(thing->x - bmaporgx)>>MAPBLOCKSHIFT; - const INT32 blocky = (unsigned)(thing->y - bmaporgy)>>MAPBLOCKSHIFT; - if (blockx >= 0 && blockx < bmapwidth - && blocky >= 0 && blocky < bmapheight) - { - // killough 8/11/98: simpler scheme using - // pointer-to-pointer prev pointers -- - // allows head nodes to be treated like everything else - - mobj_t **link = &blocklinks[blocky*bmapwidth + blockx]; - mobj_t *bnext = *link; - if ((thing->bnext = bnext) != NULL) - bnext->bprev = &thing->bnext; - thing->bprev = link; - *link = thing; - } - else // thing is off the map - thing->bnext = NULL, thing->bprev = NULL; + P_LinkToBlockMap(thing, blocklinks); } // Allows you to 'step' on a new linedef exec when the previous @@ -891,18 +904,15 @@ void P_SetUnderlayPosition(mobj_t *thing) void P_SetPrecipitationThingPosition(precipmobj_t *thing) { - subsector_t *ss = thing->subsector = R_PointInSubsector(thing->x, thing->y); - - precipmobj_t **link = &ss->sector->preciplist; - precipmobj_t *snext = *link; - if ((thing->snext = snext) != NULL) - snext->sprev = &thing->snext; - thing->sprev = link; - *link = thing; + thing->subsector = R_PointInSubsector(thing->x, thing->y); P_CreatePrecipSecNodeList(thing, thing->x, thing->y); thing->touching_sectorlist = precipsector_list; // Attach to Thing's precipmobj_t precipsector_list = NULL; // clear for next time + + // NOTE: this works because bnext/bprev are at the same + // offsets in precipmobj_t and mobj_t + P_LinkToBlockMap((mobj_t*)thing, (mobj_t**)precipblocklinks); } // diff --git a/src/p_mobj.c b/src/p_mobj.c index cbc08c02c..608d9e821 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1329,7 +1329,7 @@ void P_XYMovement(mobj_t *mo) fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls boolean moved; pslope_t *oldslope = NULL; - vector3_t slopemom; + vector3_t slopemom = {0,0,0}; fixed_t predictedz = 0; I_Assert(mo != NULL); @@ -4978,18 +4978,17 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle -= InvAngle(angle)/8; // Spawn energy particles - for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) { + for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) + { dist = P_AproxDistance(spawner->x - mobj->x, spawner->y - mobj->y); if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1) break; } - if (spawner) { + if (spawner && dist) + { mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/4); - if (dist == 0) - missile->fuse = 0; - else - missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); + missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); if (missile->fuse > mobj->fuse) P_RemoveMobj(missile); } @@ -10147,6 +10146,9 @@ void P_SpawnPrecipitation(void) //for (j = 0; j < cv_precipdensity.value; ++j) -- density is 1 for kart always { + INT32 floorz; + INT32 ceilingz; + x = ((cv_lessprecip.value ? basex*1.5 : basex) + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3)); y = ((cv_lessprecip.value ? basey*1.5 : basey) + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3)); @@ -10180,8 +10182,19 @@ void P_SpawnPrecipitation(void) else // everything else. rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); - // Randomly assign a height, now that floorz is set. - rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<floorz >> FRACBITS; + ceilingz = rainmo->ceilingz >> FRACBITS; + + if (floorz < ceilingz) + { + // Randomly assign a height, now that floorz is set. + rainmo->z = M_RandomRange(floorz, ceilingz) << FRACBITS; + } + else + { + // ...except if the floor is above the ceiling. + rainmo->z = ceilingz << FRACBITS; + } } } @@ -10270,7 +10283,8 @@ void P_PrecipitationEffects(void) volume = 255; // Sky above? We get it full blast. else { - fixed_t x, y, yl, yh, xl, xh; + /* GCC is optimizing away y >= yl, FUCK YOU */ + volatile fixed_t x, y, yl, yh, xl, xh; fixed_t closedist, newdist; // Essentially check in a 1024 unit radius of the player for an outdoor area. @@ -10279,8 +10293,8 @@ void P_PrecipitationEffects(void) xl = players[displayplayers[0]].mo->x - 1024*FRACUNIT; xh = players[displayplayers[0]].mo->x + 1024*FRACUNIT; closedist = 2048*FRACUNIT; - for (y = yl; y <= yh; y += FRACUNIT*64) - for (x = xl; x <= xh; x += FRACUNIT*64) + for (y = yl; y >= yl && y <= yh; y += FRACUNIT*64) + for (x = xl; x >= xl && x <= xh; x += FRACUNIT*64) { if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) // Found the outdoors! { diff --git a/src/p_mobj.h b/src/p_mobj.h index 5d26f9b44..a824edc6a 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -279,8 +279,8 @@ typedef struct mobj_s fixed_t old_x2, old_y2, old_z2; // More list: links in sector (if needed) - struct mobj_s *snext; - struct mobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr + struct mobj_s *bnext; + struct mobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr // More drawing info: to determine current sprite. angle_t angle, pitch, roll; // orientation @@ -338,8 +338,8 @@ typedef struct mobj_s // Interaction info, by BLOCKMAP. // Links in blocks (if needed). - struct mobj_s *bnext; - struct mobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr + struct mobj_s *snext; + struct mobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr // Additional pointers for NiGHTS hoops struct mobj_s *hnext; @@ -432,8 +432,8 @@ typedef struct precipmobj_s fixed_t old_x2, old_y2, old_z2; // More list: links in sector (if needed) - struct precipmobj_s *snext; - struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr + struct precipmobj_s *bnext; + struct precipmobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr // More drawing info: to determine current sprite. angle_t angle, pitch, roll; // orientation diff --git a/src/p_polyobj.c b/src/p_polyobj.c index fa98ad9a5..9a3376595 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1206,7 +1206,7 @@ static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y) // http://www.inversereality.org/tutorials/graphics%20programming/2dtransformations.html // It is, of course, just a vector-matrix multiplication. // -static inline void Polyobj_rotatePoint(vertex_t *v, const vertex_t *c, angle_t ang) +static inline void Polyobj_rotatePoint(vertex_t *v, const vector2_t *c, angle_t ang) { vertex_t tmp = *v; @@ -1267,7 +1267,7 @@ static void Polyobj_rotateLine(line_t *ld) // // Causes objects resting on top of the rotating polyobject to 'ride' with its movement. // -static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta, UINT8 turnthings) +static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, UINT8 turnthings) { static INT32 pomovecount = 10000; INT32 x, y; @@ -1367,7 +1367,7 @@ static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings) { size_t i; angle_t angle; - vertex_t origin; + vector2_t origin; INT32 hitflags = 0; // don't move bad polyobjects diff --git a/src/p_setup.c b/src/p_setup.c index 9ae36afc9..c99326116 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -127,6 +127,7 @@ INT32 *blockmaplump; // Big blockmap fixed_t bmaporgx, bmaporgy; // for thing chains mobj_t **blocklinks; +precipmobj_t **precipblocklinks; // REJECT // For fast sight rejection. @@ -714,7 +715,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i) ss->thinglist = NULL; ss->touching_thinglist = NULL; - ss->preciplist = NULL; + ss->touching_preciplist = NULL; ss->floordata = NULL; @@ -1948,6 +1949,9 @@ static void P_CreateBlockMap(void) // haleyjd 2/22/06: setup polyobject blockmap count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); + + count = sizeof (*precipblocklinks)* bmapwidth*bmapheight; + precipblocklinks = Z_Calloc(count, PU_LEVEL, NULL); } } @@ -1982,10 +1986,6 @@ static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) // this should return false. static boolean P_LoadBlockMap(lumpnum_t lumpnum) { -#if 0 - (void)lumpnum; - return false; -#else size_t count; const char *lumpname = W_CheckNameForNum(lumpnum); @@ -2023,27 +2023,11 @@ static boolean P_LoadBlockMap(lumpnum_t lumpnum) // haleyjd 2/22/06: setup polyobject blockmap count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); + + count = sizeof (*precipblocklinks)* bmapwidth*bmapheight; + precipblocklinks = Z_Calloc(count, PU_LEVEL, NULL); + return true; -/* Original - blockmaplump = W_CacheLumpNum(lump, PU_LEVEL); - blockmap = blockmaplump+4; - count = W_LumpLength (lump)/2; - - for (i = 0; i < count; i++) - blockmaplump[i] = SHORT(blockmaplump[i]); - - bmaporgx = blockmaplump[0]<player == &players[displayplayers[i]] && camera[i].chase) + if (thing->player != &players[displayplayers[i]]) + continue; + if (camera[i].chase) P_ResetCamera(thing->player, &camera[i]); + R_ResetViewInterpolation(i + 1); + break; } // don't run in place after a teleport diff --git a/src/p_tick.c b/src/p_tick.c index 183c42a4b..6416142ce 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -581,6 +581,13 @@ void P_Ticker(boolean run) if (playeringame[i]) ++players[i].jointime; + if (run) + { + // Update old view state BEFORE ticking so resetting + // the old interpolation state from game logic works. + R_UpdateViewInterpolation(); + } + if (objectplacing) { if (OP_FreezeObjectplace()) @@ -827,7 +834,6 @@ void P_Ticker(boolean run) if (run) { R_UpdateLevelInterpolators(); - R_UpdateViewInterpolation(); // Hack: ensure newview is assigned every tic. // Ensures view interpolation is T-1 to T in poor network conditions diff --git a/src/p_user.c b/src/p_user.c index 5d97e9ac6..6b076a132 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2510,18 +2510,15 @@ static void P_MovePlayer(player_t *player) if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) && !(player->mo->flags & MF_NOCLIP)) { - if (player->mo->ceilingz - player->mo->floorz < player->mo->height) + if ((netgame || multiplayer) && player->spectator) + P_DamageMobj(player->mo, NULL, NULL, 42000); // Respawn crushed spectators + else { - if ((netgame || multiplayer) && player->spectator) - P_DamageMobj(player->mo, NULL, NULL, 42000); // Respawn crushed spectators - else - { - K_SquishPlayer(player, NULL, NULL); // SRB2kart - we don't kill when squished, we squish when squished. - } - - if (player->playerstate == PST_DEAD) - return; + K_SquishPlayer(player, NULL, NULL); // SRB2kart - we don't kill when squished, we squish when squished. } + + if (player->playerstate == PST_DEAD) + return; } #ifdef HWRENDER @@ -3962,7 +3959,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { P_MoveChaseCamera(player, thiscam, false); R_ResetViewInterpolation(num + 1); - R_ResetViewInterpolation(num + 1); } return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); diff --git a/src/qs22j.c b/src/qs22j.c index 53277521e..16dc217bd 100644 --- a/src/qs22j.c +++ b/src/qs22j.c @@ -41,33 +41,33 @@ typedef void *pref_typ; #define COMP(a, b) ((*compar)((void *)(a), (void *)(b))) -static void swapbytes(void *a0, void *b0, size_t n) +static inline void swapbytes(void *a0, void *b0, size_t n) { char *a = a0, *b = b0, t; do {ASWAP(*a, *b, t); a++; b++;} while (--n); } -static void swapdword(void *a0, void *b0, size_t n) +static inline void swapdword(void *a0, void *b0, size_t n) { DWORD *a = a0, *b = b0, t; ASWAP(*a, *b, t); (void)n; } -static void swapdwords(void *a0, void *b0, size_t n) +static inline void swapdwords(void *a0, void *b0, size_t n) { DWORD *a = a0, *b = b0, t; do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(DWORD)); } -static void swapword(void *a0, void *b0, size_t n) +static inline void swapword(void *a0, void *b0, size_t n) { WORD *a = a0, *b = b0, t; ASWAP(*a, *b, t); (void)n; } -static void swapwords(void *a0, void *b0, size_t n) +static inline void swapwords(void *a0, void *b0, size_t n) { WORD *a = a0, *b = b0, t; do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(WORD)); @@ -75,7 +75,7 @@ static void swapwords(void *a0, void *b0, size_t n) typedef void (*swapf_typ)(void *, void *, size_t); -static char *med3(char *a, char *b, char *c, int (*compar)(const void *, const void *)) +static inline char *med3(char *a, char *b, char *c, int (*compar)(const void *, const void *)) { return COMP(a, b) < 0 ? (COMP(b, c) < 0 ? b : COMP(a, c) < 0 ? c : a) : diff --git a/src/r_data.c b/src/r_data.c index 772d76925..69b0ce1ac 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1088,6 +1088,7 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) { char colormap[9] = "COLORMAP"; lumpnum_t lump; + const lumpnum_t basecolormaplump = W_GetNumForName(colormap); if (num > 0 && num <= 10000) snprintf(colormap, 8, "CLM%04u", num-1); @@ -1095,8 +1096,16 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) // Load in the light tables, now 64k aligned for smokie... lump = W_GetNumForName(colormap); if (lump == LUMPERROR) - lump = W_GetNumForName("COLORMAP"); - W_ReadLump(lump, colormaps); + lump = basecolormaplump; + else + { + if (W_LumpLength(lump) != W_LumpLength(basecolormaplump)) + { + CONS_Alert(CONS_WARNING, "%s lump size does not match COLORMAP, results may be unexpected.\n", colormap); + } + } + + W_ReadLumpHeader(lump, colormaps, W_LumpLength(basecolormaplump), 0U); // Encore mode. if (newencoremap != LUMPERROR) diff --git a/src/r_defs.h b/src/r_defs.h index 5a78a362b..81e3f0c3a 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -350,7 +350,6 @@ typedef struct sector_s fixed_t floorspeed, ceilspeed; // list of precipitation mobjs in sector - precipmobj_t *preciplist; struct mprecipsecnode_s *touching_preciplist; // Eternity engine slope diff --git a/src/r_fps.c b/src/r_fps.c index 44518ea4d..91044b42e 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -23,6 +23,8 @@ #include "r_state.h" #include "z_zone.h" #include "console.h" // con_startup_loadprogress +#include "i_time.h" + #ifdef HWRENDER #include "hardware/hw_main.h" // for cv_grshearing #endif @@ -80,6 +82,7 @@ static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS]; static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS]; static viewvars_t *oldview = &pview_old[0]; +static tic_t last_view_update; static int oldview_invalid[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; viewvars_t *newview = &pview_new[0]; @@ -200,21 +203,27 @@ void R_UpdateViewInterpolation(void) if (oldview_invalid[i]) oldview_invalid[i]--; } + + last_view_update = I_GetTime(); } void R_ResetViewInterpolation(UINT8 p) { + // Wait an extra tic if the interpolation state hasn't + // updated yet. + int t = last_view_update == I_GetTime() ? 1 : 2; + if (p == 0) { UINT8 i; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - oldview_invalid[i]++; + oldview_invalid[i] = t; } } else { - oldview_invalid[p - 1]++; + oldview_invalid[p - 1] = t; } } diff --git a/src/r_main.c b/src/r_main.c index 3b7a8b063..a15258c48 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -32,6 +32,7 @@ #include "m_random.h" // quake camera shake #include "doomstat.h" // MAXSPLITSCREENPLAYERS #include "r_fps.h" // Frame interpolation/uncapped +#include "tables.h" #ifdef HWRENDER #include "hardware/hw_main.h" @@ -594,6 +595,33 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe return false; } +// Returns search dimensions within a blockmap, in the direction of viewangle and out to a certain distance. +void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh) +{ + const angle_t left = viewangle - clipangle; + const angle_t right = viewangle + clipangle; + + const fixed_t vxleft = viewx + FixedMul(drawdist, FCOS(left)); + const fixed_t vyleft = viewy + FixedMul(drawdist, FSIN(left)); + + const fixed_t vxright = viewx + FixedMul(drawdist, FCOS(right)); + const fixed_t vyright = viewy + FixedMul(drawdist, FSIN(right)); + + // Try to narrow the search to within only the field of view + *xl = (unsigned)(min(viewx, min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT; + *xh = (unsigned)(max(viewx, max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT; + *yl = (unsigned)(min(viewy, min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT; + *yh = (unsigned)(max(viewy, max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT; + + if (*xh >= bmapwidth) + *xh = bmapwidth - 1; + + if (*yh >= bmapheight) + *yh = bmapheight - 1; + + BMBOUNDFIX(*xl, *xh, *yl, *yh); +} + // // R_InitTextureMapping // @@ -1728,6 +1756,7 @@ void R_RenderPlayerView(player_t *player) PS_START_TIMING(ps_bsptime); R_RenderBSPNode((INT32)numnodes - 1); PS_STOP_TIMING(ps_bsptime); + R_AddPrecipitationSprites(); PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(); PS_STOP_TIMING(ps_sw_spritecliptime); diff --git a/src/r_main.h b/src/r_main.h index b3f38e156..56e351138 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -80,6 +80,7 @@ subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); +void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh); // Performance stats extern precise_t ps_prevframetime;// time when previous frame was rendered diff --git a/src/r_things.c b/src/r_things.c index c66ca9f58..dfe05dbdf 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1897,7 +1897,6 @@ weatherthink: void R_AddSprites(sector_t *sec, INT32 lightlevel) { mobj_t *thing; - precipmobj_t *precipthing; // Tails 08-25-2002 INT32 lightnum; fixed_t approx_dist, limit_dist; @@ -2016,21 +2015,42 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) R_ProjectSprite(thing); } } +} + +// R_AddPrecipitationSprites +// This renders through the blockmap instead of BSP to avoid +// iterating a huge amount of precipitation sprites in sectors +// that are beyond drawdist. +// +void R_AddPrecipitationSprites(void) +{ + const fixed_t drawdist = cv_drawdist_precip.value * mapobjectscale; + + INT32 xl, xh, yl, yh, bx, by; + precipmobj_t *th, *next; + + if (drawdist == 0) + { + return; + } + + R_GetRenderBlockMapDimensions(drawdist, &xl, &xh, &yl, &yh); // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off - if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) + for (bx = xl; bx <= xh; bx++) { - for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) + for (by = yl; by <= yh; by++) { - if (precipthing->precipflags & PCF_INVISIBLE) - continue; + for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = next) + { + // Store this beforehand because R_ProjectPrecipitionSprite may free th (see P_PrecipThinker) + next = th->bnext; - approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); + if (th->precipflags & PCF_INVISIBLE) + continue; - if (approx_dist > limit_dist) - continue; - - R_ProjectPrecipitationSprite(precipthing); + R_ProjectPrecipitationSprite(th); + } } } } diff --git a/src/r_things.h b/src/r_things.h index b9e05022e..88e1abdab 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -67,6 +67,7 @@ void R_AddSpriteDefs(UINT16 wadnum); //SoM: 6/5/2000: Light sprites correctly! void R_AddSprites(sector_t *sec, INT32 lightlevel); +void R_AddPrecipitationSprites(void); void R_InitSprites(void); void R_ClearSprites(void); void R_DrawMasked(void); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index bc932d87f..f90f5bb18 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -80,6 +80,7 @@ #ifdef HWRENDER #include "../hardware/hw_main.h" #include "../hardware/hw_drv.h" +#include "../hardware/r_opengl/r_opengl.h" //for supportFBO // For dynamic referencing of HW rendering functions #include "hwsym_sdl.h" #include "ogl_sdl.h" @@ -215,6 +216,15 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); //static void Impl_SetWindowName(const char *title); static void Impl_SetWindowIcon(void); +#ifdef USE_FBO_OGL +boolean downsample = false; +void RefreshOGLSDLSurface(void) +{ + if (rendermode == render_opengl) + OglSdlSurface(vid.width, vid.height); +} +#endif + static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) { static SDL_bool wasfullscreen = SDL_FALSE; @@ -736,11 +746,41 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) return raxis; } +#ifdef USE_FBO_OGL +void I_DownSample(void) +{ + if (!cv_grframebuffer.value || !(rendermode == render_opengl) || (!supportFBO)) //no sense to do this crap if we cant benefit from it + { + downsample = false; + return; + } + + int currentDisplayIndex = SDL_GetWindowDisplayIndex(window); + SDL_DisplayMode curmode; + + if (SDL_GetCurrentDisplayMode(currentDisplayIndex, &curmode) == 0) + { + if ((vid.width > curmode.w) || (vid.height > curmode.h)) //check if current resolution is higher than current display resolution + { + downsample = true; + RefreshOGLSDLSurface(); + } + else + downsample = false; // its not so no need to do crap + } + else + downsample = false; // couldnt get display info so turn the thing off +} +#endif + static void Impl_HandleWindowEvent(SDL_WindowEvent evt) { static SDL_bool firsttimeonmouse = SDL_TRUE; static SDL_bool mousefocus = SDL_TRUE; static SDL_bool kbfocus = SDL_TRUE; +#ifdef USE_FBO_OGL + static SDL_bool windowmoved = SDL_FALSE; +#endif switch (evt.event) { @@ -760,6 +800,11 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) break; case SDL_WINDOWEVENT_MAXIMIZED: break; +#ifdef USE_FBO_OGL + case SDL_WINDOWEVENT_MOVED: + windowmoved = SDL_TRUE; + break; +#endif } if (mousefocus && kbfocus) @@ -799,6 +844,12 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) } } +#ifdef USE_FBO_OGL + if (windowmoved && rendermode == render_opengl) + { + I_DownSample(); + } +#endif } static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type) @@ -1877,6 +1928,11 @@ INT32 VID_SetMode(INT32 modeNum) } //Impl_SetWindowName("SRB2Kart "VERSIONSTRING); +#ifdef USE_FBO_OGL + if (rendermode == render_opengl) + I_DownSample(); +#endif + SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); Impl_VideoSetupBuffer(); diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 7c69b2a61..5bb6b7347 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -42,6 +42,7 @@ #include "../i_system.h" #include "hwsym_sdl.h" #include "../m_argv.h" +#include "../i_video.h" #ifdef DEBUG_TO_FILE #include @@ -149,31 +150,54 @@ boolean OglSdlSurface(INT32 w, INT32 h) "- GPU vendor has dropped OpenGL support on your GPU and OS. (Old GPU?)\n" "- GPU drivers are missing or broken. You may need to update your drivers."); } + + SetupGLInfo(); + + SetupGLFunc4(); + + if (majorGL == 1 && minorGL <= 3) // GL_GENERATE_MIPMAP is unavailible for OGL 1.3 and below + supportMipMap = false; + else + supportMipMap = true; + + if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) + pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); + else + maximumAnisotropy = 1; + + granisotropicmode_cons_t[1].value = maximumAnisotropy; +#ifdef USE_FBO_OGL + I_DownSample(); +#endif } first_init = true; - if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) - pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); - else - maximumAnisotropy = 1; - - SetupGLInfo(); - - SetupGLFunc4(); - - if (majorGL == 1 && minorGL <= 3) // GL_GENERATE_MIPMAP is unavailible for OGL 1.3 and below - supportMipMap = false; - else - supportMipMap = true; - - granisotropicmode_cons_t[1].value = maximumAnisotropy; - SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0); + // 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(); +#ifdef USE_FBO_OGL + GLFramebuffer_DeleteAttachments(); +#endif + } + + screen_width = (GLint)w; + screen_height = (GLint)h; + SetModelView(w, h); SetStates(); pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); +#ifdef USE_FBO_OGL + RenderToFramebuffer = FrameBufferEnabled; + GLFramebuffer_Disable(); + + if (RenderToFramebuffer && downsample) + GLFramebuffer_Enable(); +#endif + HWR_Startup(); textureformatGL = cbpp > 16 ? GL_RGBA : GL_RGB5_A1; @@ -198,9 +222,20 @@ void OglSdlFinishUpdate(boolean waitvbl) oldwaitvbl = waitvbl; SDL_GetWindowSize(window, &sdlw, &sdlh); - HWR_MakeScreenFinalTexture(); + +#ifdef USE_FBO_OGL + GLFramebuffer_Disable(); + RenderToFramebuffer = FrameBufferEnabled; +#endif + HWR_DrawScreenFinalTexture(sdlw, sdlh); + +#ifdef USE_FBO_OGL + if (RenderToFramebuffer && downsample) + GLFramebuffer_Enable(); +#endif + SDL_GL_SwapWindow(window); GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE, FAR_ZCLIP_DEFAULT); diff --git a/src/tables.h b/src/tables.h index 353bf591f..761a6499e 100644 --- a/src/tables.h +++ b/src/tables.h @@ -24,6 +24,7 @@ #define FINEMASK (FINEANGLES - 1) #define ANGLETOFINESHIFT 19 // 0x100000000 to 0x2000 #define FINEANGLE_C(x) ((FixedAngle((x)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK) // ((x*(ANGLE_45/45))>>ANGLETOFINESHIFT) & FINEMASK +#define ANGLETOFINE(x) (((x)>>ANGLETOFINESHIFT) & FINEMASK) // Effective size is 10240. extern fixed_t finesine[5*FINEANGLES/4]; @@ -121,4 +122,8 @@ void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z); #define FINECOSINE(n) (finecosine[n]>>(FINE_FRACBITS-FRACBITS)) #define FINETANGENT(n) (finetangent[n]>>(FINE_FRACBITS-FRACBITS)) +// FSIN(ANGLE_90) = FRACUNIT +#define FSIN(n) FINESINE(ANGLETOFINE(n)) +#define FCOS(n) FINECOSINE(ANGLETOFINE(n)) + #endif diff --git a/src/v_video.c b/src/v_video.c index c56711f20..4ea028cc3 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2944,6 +2944,9 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 continue; + if (c < HU_FONTSTART) + continue; + if (!lowercase || !tny_font[c-HU_FONTSTART]) c = toupper(c); c -= HU_FONTSTART; @@ -3367,7 +3370,7 @@ void V_Init(void) #ifdef DEBUG CONS_Debug(DBG_RENDER, "V_Init done:\n"); - for (i = 0; i < NUMSCREENS+1; i++) + for (i = 0; i < NUMSCREENS; i++) CONS_Debug(DBG_RENDER, " screens[%d] = %x\n", i, screens[i]); #endif } diff --git a/src/w_wad.c b/src/w_wad.c index 86536c03f..cd2968494 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -186,9 +186,9 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) if (filenamebuf != *filename) { // avoid overlap strncpy(filenamebuf, *filename, MAX_WADPATH); + filenamebuf[MAX_WADPATH - 1] = '\0'; + *filename = filenamebuf; } - filenamebuf[MAX_WADPATH - 1] = '\0'; - *filename = filenamebuf; // open wad file if ((handle = fopen_utf8(*filename, "rb")) == NULL) diff --git a/src/y_inter.c b/src/y_inter.c index 0520b4730..807332c9d 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1486,7 +1486,7 @@ void Y_VoteTicker(void) if ((InputDown(gc_accelerate, i+1) || JoyAxis(AXISMOVE, i+1) > 0) && !pressed) { - D_ModifyClientVote(voteclient.playerinfo[i].selection, i); + D_ModifyClientVote(voteclient.playerinfo[i].selection, p); pressed = true; } }