diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0a593bb1..7a3f0564d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -418,6 +418,7 @@ endif() if(${SRB2_CONFIG_HWRENDER}) add_definitions(-DHWRENDER) set(SRB2_HWRENDER_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c @@ -433,6 +434,7 @@ if(${SRB2_CONFIG_HWRENDER}) ) set (SRB2_HWRENDER_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h diff --git a/src/Makefile b/src/Makefile index fdf9c78b7..e00c84bc9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -222,12 +222,10 @@ endif ifdef NOHW OPTS+=-DNOHW else - #Hurdler: not really supported and not tested recently - #OPTS+=-DUSE_PALETTED_TEXTURE OPTS+=-DHWRENDER OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \ - $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o + $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o endif ifdef NOHS diff --git a/src/console.c b/src/console.c index 0f1ccbd33..aac94d473 100644 --- a/src/console.c +++ b/src/console.c @@ -770,7 +770,7 @@ boolean CON_Responder(event_t *ev) // check for console toggle key if (ev->type != ev_console) { - if (modeattacking || metalrecording) + if (modeattacking || metalrecording || marathonmode) return false; if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1]) @@ -1649,10 +1649,7 @@ void CON_Drawer(void) return; if (needpatchrecache) - { - W_FlushCachedPatches(); HU_LoadGraphics(); - } if (con_recalc) { diff --git a/src/d_main.c b/src/d_main.c index 902074947..28570b909 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -129,6 +129,7 @@ UINT16 numskincolors; menucolor_t *menucolorhead, *menucolortail; char savegamename[256]; +char liveeventbackup[256]; char srb2home[256] = "."; char srb2path[256] = "."; @@ -416,6 +417,7 @@ static void D_Display(void) if (!automapactive && !dedicated && cv_renderview.value) { + rs_rendercalltime = I_GetTimeMicros(); if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) { topleft = screens[0] + viewwindowy*vid.width + viewwindowx; @@ -462,6 +464,7 @@ static void D_Display(void) if (postimgtype2) V_DoPostProcessor(1, postimgtype2, postimgparam2); } + rs_rendercalltime = I_GetTimeMicros() - rs_rendercalltime; } if (lastdraw) @@ -596,23 +599,97 @@ static void D_Display(void) snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent); V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s); } + + if (cv_renderstats.value) + { + char s[50]; + int frametime = I_GetTimeMicros() - rs_prevframetime; + int divisor = 1; + rs_prevframetime = I_GetTimeMicros(); + if (rs_rendercalltime > 10000) divisor = 1000; + + snprintf(s, sizeof s - 1, "ft %d", frametime / divisor); + V_DrawThinString(30, 10, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "rtot %d", rs_rendercalltime / divisor); + V_DrawThinString(30, 20, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "bsp %d", rs_bsptime / divisor); + V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "nbsp %d", rs_numbspcalls); + V_DrawThinString(80, 10, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "nspr %d", rs_numsprites); + V_DrawThinString(80, 20, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "nnod %d", rs_numdrawnodes); + V_DrawThinString(80, 30, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "npob %d", rs_numpolyobjects); + V_DrawThinString(80, 40, V_MONOSPACE | V_BLUEMAP, s); + if (rendermode == render_opengl) // OpenGL specific stats + { + snprintf(s, sizeof s - 1, "nsrt %d", rs_hw_nodesorttime / divisor); + V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "ndrw %d", rs_hw_nodedrawtime / divisor); + V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "ssrt %d", rs_hw_spritesorttime / divisor); + V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor); + V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor); + V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s); + if (cv_grbatching.value) + { + snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor); + V_DrawThinString(80, 55, V_MONOSPACE | V_REDMAP, s); + snprintf(s, sizeof s - 1, "bdrw %d", rs_hw_batchdrawtime / divisor); + V_DrawThinString(80, 65, V_MONOSPACE | V_REDMAP, s); + + snprintf(s, sizeof s - 1, "npol %d", rs_hw_numpolys); + V_DrawThinString(130, 10, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "ndc %d", rs_hw_numcalls); + V_DrawThinString(130, 20, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "nshd %d", rs_hw_numshaders); + V_DrawThinString(130, 30, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "nvrt %d", rs_hw_numverts); + V_DrawThinString(130, 40, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "ntex %d", rs_hw_numtextures); + V_DrawThinString(185, 10, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "npf %d", rs_hw_numpolyflags); + V_DrawThinString(185, 20, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "ncol %d", rs_hw_numcolors); + V_DrawThinString(185, 30, V_MONOSPACE | V_PURPLEMAP, s); + } + } + else // software specific stats + { + snprintf(s, sizeof s - 1, "prtl %d", rs_sw_portaltime / divisor); + V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "plns %d", rs_sw_planetime / divisor); + V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "mskd %d", rs_sw_maskedtime / divisor); + V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor); + V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s); + } + } + + rs_swaptime = I_GetTimeMicros(); I_FinishUpdate(); // page flip or blit buffer + rs_swaptime = I_GetTimeMicros() - rs_swaptime; } needpatchflush = false; needpatchrecache = false; } -// Lactozilla: Check the renderer's state +// Check the renderer's state // after a possible renderer switch. void D_CheckRendererState(void) { // flush all patches from memory - // (also frees memory tagged with PU_CACHE) - // (which are not necessarily patches but I don't care) if (needpatchflush) + { Z_FlushCachedPatches(); + needpatchflush = false; + } // some patches have been freed, // so cache them again @@ -668,7 +745,7 @@ void D_SRB2Loop(void) */ /* Smells like a hack... Don't fade Sonic's ass into the title screen. */ if (gamestate != GS_TITLESCREEN) - V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE)); + V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_PATCH)); for (;;) { @@ -820,6 +897,7 @@ void D_StartTitle(void) // In case someone exits out at the same time they start a time attack run, // reset modeattacking modeattacking = ATTACKING_NONE; + marathonmode = 0; // empty maptol so mario/etc sounds don't play in sound test when they shouldn't maptol = 0; @@ -1136,6 +1214,7 @@ void D_SRB2Main(void) // default savegame strcpy(savegamename, SAVEGAMENAME"%u.ssg"); + strcpy(liveeventbackup, "live"SAVEGAMENAME".bkp"); // intentionally not ending with .ssg { const char *userhome = D_Home(); //Alam: path to home @@ -1164,6 +1243,7 @@ void D_SRB2Main(void) // can't use sprintf since there is %u in savegamename strcatbf(savegamename, srb2home, PATHSEP); + strcatbf(liveeventbackup, srb2home, PATHSEP); snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home); #else // DEFAULTDIR @@ -1176,6 +1256,7 @@ void D_SRB2Main(void) // can't use sprintf since there is %u in savegamename strcatbf(savegamename, userhome, PATHSEP); + strcatbf(liveeventbackup, userhome, PATHSEP); snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome); #endif // DEFAULTDIR diff --git a/src/dehacked.c b/src/dehacked.c index dba759894..61775bd56 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1669,6 +1669,22 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->nextlevel = (INT16)i; } + else if (fastcmp(word, "MARATHONNEXT")) + { + if (fastcmp(word2, "TITLE")) i = 1100; + else if (fastcmp(word2, "EVALUATION")) i = 1101; + else if (fastcmp(word2, "CREDITS")) i = 1102; + else if (fastcmp(word2, "ENDING")) i = 1103; + else + // Support using the actual map name, + // i.e., MarathonNext = AB, MarathonNext = FZ, etc. + + // Convert to map number + if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0') + i = M_MapNumber(word2[0], word2[1]); + + mapheaderinfo[num-1]->marathonnext = (INT16)i; + } else if (fastcmp(word, "TYPEOFLEVEL")) { if (i) // it's just a number @@ -4011,7 +4027,20 @@ static void readmaincfg(MYFILE *f) else value = get_number(word2); - spstage_start = (INT16)value; + spstage_start = spmarathon_start = (INT16)value; + } + else if (fastcmp(word, "SPMARATHON_START")) + { + // Support using the actual map name, + // i.e., Level AB, Level FZ, etc. + + // Convert to map number + if (word2[0] >= 'A' && word2[0] <= 'Z') + value = M_MapNumber(word2[0], word2[1]); + else + value = get_number(word2); + + spmarathon_start = (INT16)value; } else if (fastcmp(word, "SSTAGE_START")) { @@ -4105,6 +4134,17 @@ static void readmaincfg(MYFILE *f) introtoplay = 128; introchanged = true; } + else if (fastcmp(word, "CREDITSCUTSCENE")) + { + creditscutscene = (UINT8)get_number(word2); + // range check, you morons. + if (creditscutscene > 128) + creditscutscene = 128; + } + else if (fastcmp(word, "USEBLACKROCK")) + { + useBlackRock = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); + } else if (fastcmp(word, "LOOPTITLE")) { looptitle = (value || word2[0] == 'T' || word2[0] == 'Y'); @@ -4206,13 +4246,6 @@ static void readmaincfg(MYFILE *f) titlescrollyspeed = get_number(word2); titlechanged = true; } - else if (fastcmp(word, "CREDITSCUTSCENE")) - { - creditscutscene = (UINT8)get_number(word2); - // range check, you morons. - if (creditscutscene > 128) - creditscutscene = 128; - } else if (fastcmp(word, "DISABLESPEEDADJUST")) { disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y'); @@ -4269,6 +4302,9 @@ static void readmaincfg(MYFILE *f) // can't use sprintf since there is %u in savegamename strcatbf(savegamename, srb2home, PATHSEP); + strcpy(liveeventbackup, va("live%s.bkp", timeattackfolder)); + strcatbf(liveeventbackup, srb2home, PATHSEP); + gamedataadded = true; titlechanged = true; } @@ -9364,8 +9400,6 @@ static const char *const MENUTYPES_LIST[] = { "OP_COLOR", "OP_OPENGL", "OP_OPENGL_LIGHTING", - "OP_OPENGL_FOG", - "OP_OPENGL_COLOR", "OP_SOUND", @@ -9998,6 +10032,12 @@ struct { {"TC_BLINK",TC_BLINK}, {"TC_DASHMODE",TC_DASHMODE}, + // marathonmode flags + {"MA_INIT",MA_INIT}, + {"MA_RUNNING",MA_RUNNING}, + {"MA_NOCUTSCENES",MA_NOCUTSCENES}, + {"MA_INGAME",MA_INGAME}, + {NULL,0} }; diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c index f525b96ca..d2483e318 100644 --- a/src/djgppdos/i_video.c +++ b/src/djgppdos/i_video.c @@ -90,6 +90,9 @@ static unsigned long nombre = NEWTICRATE*10; static void I_BlitScreenVesa1(void); //see later void I_FinishUpdate (void) { + if (marathonmode) + SCR_DisplayMarathonInfo(); + // draw captions if enabled if (cv_closedcaptioning.value) SCR_ClosedCaptions(); diff --git a/src/doomdef.h b/src/doomdef.h index 1cb491a10..0b76cebc7 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -479,6 +479,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) FUNCDEBUG; // Things that used to be in dstrings.h #define SAVEGAMENAME "srb2sav" extern char savegamename[256]; +extern char liveeventbackup[256]; // m_misc.h #ifdef GETTEXT @@ -638,17 +639,13 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +/// OpenGL shaders +#define GL_SHADERS + /// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them. #define SECTORSPECIALSAFTERTHINK -/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up -/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down) -/// on the bright side it fixes some weird issues with translucent walls -/// \note SRB2CB port. -/// SRB2CB itself ported this from PrBoom+ -#define NEWCLIP - /// Cache patches in Lua in a way that renderer switching will work flawlessly. //#define LUA_PATCH_SAFETY diff --git a/src/doomstat.h b/src/doomstat.h index fa346540c..3abaf2988 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -45,7 +45,19 @@ extern INT32 curWeather; extern INT32 cursaveslot; //extern INT16 lastmapsaved; extern INT16 lastmaploaded; -extern boolean gamecomplete; +extern UINT8 gamecomplete; + +// Extra abilities/settings for skins (combinable stuff) +typedef enum +{ + MA_RUNNING = 1, // In action + MA_INIT = 1<<1, // Initialisation + MA_NOCUTSCENES = 1<<2, // No cutscenes + MA_INGAME = 1<<3 // Timer ignores loads +} marathonmode_t; + +extern marathonmode_t marathonmode; +extern tic_t marathontime; #define maxgameovers 13 extern UINT8 numgameovers; @@ -127,7 +139,7 @@ extern INT32 displayplayer; extern INT32 secondarydisplayplayer; // for splitscreen // Maps of special importance -extern INT16 spstage_start; +extern INT16 spstage_start, spmarathon_start; extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end; extern INT16 titlemap; @@ -289,6 +301,7 @@ typedef struct UINT8 actnum; ///< Act number or 0 for none. UINT32 typeoflevel; ///< Combination of typeoflevel flags. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. + INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. char keywords[33]; ///< Keywords separated by space to search for. 32 characters. char musname[7]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. @@ -575,11 +588,12 @@ extern UINT16 nightslinktics; extern UINT8 introtoplay; extern UINT8 creditscutscene; +extern UINT8 useBlackRock; extern UINT8 use1upSound; extern UINT8 maxXtraLife; // Max extra lives from rings extern UINT8 useContinues; -#define continuesInSession (!multiplayer && (useContinues || ultimatemode || !(cursaveslot > 0))) +#define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0)))) extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index 5c0f7eb99..4a657ed19 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -16,6 +16,11 @@ tic_t I_GetTime(void) return 0; } +int I_GetTimeMicros(void) +{ + return 0; +} + void I_Sleep(void){} void I_GetEvent(void){} diff --git a/src/f_finale.c b/src/f_finale.c index 8b5a69ae4..a41005b43 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1330,10 +1330,6 @@ void F_StartCredits(void) // Just in case they're open ... somehow M_ClearMenus(true); - // Save the second we enter the credits - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0) - G_SaveGame((UINT32)cursaveslot); - if (creditscutscene) { F_StartCustomCutscene(creditscutscene - 1, false, false); @@ -1529,12 +1525,6 @@ void F_StartGameEvaluation(void) // Just in case they're open ... somehow M_ClearMenus(true); - // Save the second we enter the evaluation - // We need to do this again! Remember, it's possible a mod designed skipped - // the credits sequence! - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0) - G_SaveGame((UINT32)cursaveslot); - goodending = (ALL7EMERALDS(emeralds)); gameaction = ga_nothing; @@ -1551,13 +1541,20 @@ void F_GameEvaluationDrawer(void) angle_t fa; INT32 eemeralds_cur; char patchname[7] = "CEMGx0"; - const char* endingtext = (goodending ? "CONGRATULATIONS!" : "TRY AGAIN..."); + const char* endingtext; + + if (marathonmode) + endingtext = "THANKS FOR THE RUN!"; + else if (goodending) + endingtext = "CONGRATULATIONS!"; + else + endingtext = "TRY AGAIN..."; V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Draw all the good crap here. - if (finalecount > 0) + if (finalecount > 0 && useBlackRock) { INT32 scale = FRACUNIT; patch_t *rockpat; @@ -1684,7 +1681,9 @@ void F_GameEvaluationTicker(void) return; } - if (!goodending) + if (!useBlackRock) + ; + else if (!goodending) { if (sparklloop) sparklloop--; @@ -1841,10 +1840,6 @@ void F_StartEnding(void) // Just in case they're open ... somehow M_ClearMenus(true); - // Save before the credits sequence. - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0) - G_SaveGame((UINT32)cursaveslot); - gameaction = ga_nothing; paused = false; CON_ToggleOff(); @@ -3959,6 +3954,7 @@ static void F_AdvanceToNextScene(void) animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum]; } +// See also G_AfterIntermission, the only other place which handles intra-map/ending transitions void F_EndCutScene(void) { cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later diff --git a/src/g_game.c b/src/g_game.c index 2aa11e0db..73d21ad54 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -82,7 +82,10 @@ INT32 curWeather = PRECIP_NONE; INT32 cursaveslot = 0; // Auto-save 1p savegame slot //INT16 lastmapsaved = 0; // Last map we auto-saved at INT16 lastmaploaded = 0; // Last map the game loaded -boolean gamecomplete = false; +UINT8 gamecomplete = 0; + +marathonmode_t marathonmode = 0; +tic_t marathontime = 0; UINT8 numgameovers = 0; // for startinglives balance SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40, 50, 75, 99, 0x7F}; @@ -118,7 +121,7 @@ UINT32 ssspheres; // old special stage INT16 lastmap; // last level you were at (returning from special stages) tic_t timeinmap; // Ticker for time spent in level (used for levelcard display) -INT16 spstage_start; +INT16 spstage_start, spmarathon_start; INT16 sstage_start, sstage_end, smpstage_start, smpstage_end; INT16 titlemap = 0; @@ -223,6 +226,7 @@ UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scena UINT8 introtoplay; UINT8 creditscutscene; +UINT8 useBlackRock = 1; // Emerald locations mobj_t *hunt1; @@ -769,6 +773,8 @@ void G_SetGameModified(boolean silent) // If in record attack recording, cancel it. if (modeattacking) M_EndModeAttackRun(); + else if (marathonmode) + Command_ExitGame_f(); } /** Builds an original game map name from a map number. @@ -2179,6 +2185,10 @@ void G_Ticker(boolean run) UINT32 i; INT32 buf; + // see also SCR_DisplayMarathonInfo + if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL) + marathontime++; + P_MapStart(); // do player reborns if needed if (gamestate == GS_LEVEL) @@ -2195,8 +2205,13 @@ void G_Ticker(boolean run) } else { - // Costs a life to retry ... unless the player in question is dead already. - if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) + // Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run. + if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime) + { + marathonmode |= MA_INIT; + marathontime = 0; + } + else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) players[consoleplayer].lives -= 1; G_DoReborn(consoleplayer); @@ -2963,7 +2978,7 @@ void G_DoReborn(INT32 playernum) players[i].starpostnum = 0; } } - if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD)) + if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD) && !(marathonmode & MA_INIT)) { P_RespawnThings(); @@ -3696,8 +3711,14 @@ static void G_DoCompleted(void) // nextmap is 0-based, unlike gamemap if (nextmapoverride != 0) nextmap = (INT16)(nextmapoverride-1); + else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext) + nextmap = (INT16)(mapheaderinfo[gamemap-1]->marathonnext-1); else + { nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1); + if (marathonmode && nextmap == spmarathon_start-1) + nextmap = 1100-1; // No infinite loop for you + } // Remember last map for when you come out of the special stage. if (!spec) @@ -3721,10 +3742,12 @@ static void G_DoCompleted(void) visitedmap[cm/8] |= (1<<(cm&7)); if (!mapheaderinfo[cm]) cm = -1; // guarantee error execution + else if (marathonmode && mapheaderinfo[cm]->marathonnext) + cm = (INT16)(mapheaderinfo[cm]->marathonnext-1); else cm = (INT16)(mapheaderinfo[cm]->nextlevel-1); - if (cm >= NUMMAPS || cm < 0) // out of range (either 1100-1102 or error) + if (cm >= NUMMAPS || cm < 0) // out of range (either 1100ish or error) { cm = nextmap; //Start the loop again so that the error checking below is executed. @@ -3793,6 +3816,25 @@ static void G_DoCompleted(void) if (nextmap < NUMMAPS && !mapheaderinfo[nextmap]) P_AllocMapHeader(nextmap); + // do this before going to the intermission or starting a custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c + if (nextmap >= 1100-1) + { + if (!gamecomplete) + gamecomplete = 2; // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission + if (cursaveslot > 0) + { + if (marathonmode) + { + // don't keep a backup around when the run is done! + if (FIL_FileExists(liveeventbackup)) + remove(liveeventbackup); + cursaveslot = 0; + } + else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) + G_SaveGame((UINT32)cursaveslot); + } + } + if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed)) { G_UpdateVisited(); @@ -3806,6 +3848,7 @@ static void G_DoCompleted(void) } } +// See also F_EndCutscene, the only other place which handles intra-map/ending transitions void G_AfterIntermission(void) { Y_CleanupScreenBuffer(); @@ -3816,9 +3859,12 @@ void G_AfterIntermission(void) return; } + if (gamecomplete == 2) // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission + gamecomplete = 1; + HU_ClearCEcho(); - if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); else { @@ -3959,7 +4005,7 @@ void G_EndGame(void) void G_LoadGameSettings(void) { // defaults - spstage_start = 1; + spstage_start = spmarathon_start = 1; sstage_start = 50; sstage_end = 56; // 7 special stages in vanilla SRB2 sstage_end++; // plus one weirdo @@ -4279,7 +4325,10 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) startonmapnum = mapoverride; #endif - sprintf(savename, savegamename, slot); + if (marathonmode) + strcpy(savename, liveeventbackup); + else + sprintf(savename, savegamename, slot); length = FIL_ReadFile(savename, &savebuffer); if (!length) @@ -4291,7 +4340,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) save_p = savebuffer; memset(vcheck, 0, sizeof (vcheck)); - sprintf(vcheck, "version %d", VERSION); + sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); if (strcmp((const char *)save_p, (const char *)vcheck)) { #ifdef SAVEGAME_OTHERVERSIONS @@ -4331,6 +4380,11 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) memset(&savedata, 0, sizeof(savedata)); return; } + if (marathonmode) + { + marathontime = READUINT32(save_p); + marathonmode |= READUINT8(save_p); + } // done Z_Free(savebuffer); @@ -4359,13 +4413,12 @@ void G_SaveGame(UINT32 slot) char savename[256] = ""; const char *backup; - sprintf(savename, savegamename, slot); + if (marathonmode) + strcpy(savename, liveeventbackup); + else + sprintf(savename, savegamename, slot); backup = va("%s",savename); - // save during evaluation or credits? game's over, folks! - if (gamestate == GS_ENDING || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) - gamecomplete = true; - gameaction = ga_nothing; { char name[VERSIONSIZE]; @@ -4379,10 +4432,15 @@ void G_SaveGame(UINT32 slot) } memset(name, 0, sizeof (name)); - sprintf(name, "version %d", VERSION); + sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION); WRITEMEM(save_p, name, VERSIONSIZE); P_SaveGame(); + if (marathonmode) + { + WRITEUINT32(save_p, marathontime); + WRITEUINT8(save_p, (marathonmode & ~MA_INIT)); + } length = save_p - savebuffer; saved = FIL_WriteFile(backup, savebuffer, length); @@ -4395,7 +4453,7 @@ void G_SaveGame(UINT32 slot) if (cv_debug && saved) CONS_Printf(M_GetText("Game saved.\n")); else if (!saved) - CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, savegamename); + CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); } #define BADSAVE goto cleanup; @@ -4408,7 +4466,10 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) char savename[255]; const char *backup; - sprintf(savename, savegamename, slot); + if (marathonmode) + strcpy(savename, liveeventbackup); + else + sprintf(savename, savegamename, slot); backup = va("%s",savename); length = FIL_ReadFile(savename, &savebuffer); @@ -4427,7 +4488,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) save_p = savebuffer; // Version check memset(vcheck, 0, sizeof (vcheck)); - sprintf(vcheck, "version %d", VERSION); + sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE save_p += VERSIONSIZE; @@ -4494,7 +4555,7 @@ cleanup: if (cv_debug && saved) CONS_Printf(M_GetText("Game saved.\n")); else if (!saved) - CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, savegamename); + CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); Z_Free(savebuffer); save_p = savebuffer = NULL; @@ -4632,7 +4693,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean automapactive = false; imcontinuing = false; - if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); else G_DoLoadLevel(resetplayer); diff --git a/src/hardware/hw3dsdrv.h b/src/hardware/hw3dsdrv.h index 8811d4546..9b8670705 100644 --- a/src/hardware/hw3dsdrv.h +++ b/src/hardware/hw3dsdrv.h @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3dsdrv.h /// \brief 3D sound import/export prototypes for low-level hardware interface #ifndef __HW_3DS_DRV_H__ diff --git a/src/hardware/hw3sound.c b/src/hardware/hw3sound.c index 7858640c0..81f1d8e68 100644 --- a/src/hardware/hw3sound.c +++ b/src/hardware/hw3sound.c @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3sound.c /// \brief Hardware 3D sound general code #include "../doomdef.h" diff --git a/src/hardware/hw3sound.h b/src/hardware/hw3sound.h index a8a475b69..1796dd696 100644 --- a/src/hardware/hw3sound.h +++ b/src/hardware/hw3sound.h @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3sound.h /// \brief High-level functions of hardware 3D sound #ifndef __HW3_SOUND_H__ diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c new file mode 100644 index 000000000..5c5379f6d --- /dev/null +++ b/src/hardware/hw_batching.c @@ -0,0 +1,454 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.c +/// \brief Draw call batching and related things. + +#ifdef HWRENDER +#include "hw_glob.h" +#include "hw_batching.h" +#include "../i_system.h" + +// The texture for the next polygon given to HWR_ProcessPolygon. +// Set with HWR_SetCurrentTexture. +GLMipmap_t *current_texture = NULL; + +boolean currently_batching = false; + +FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu +UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion +// NOTE have this alloced as 3x finalVertexArray size +int finalVertexArrayAllocSize = 65536; +//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed +//int colorArrayAllocSize = 65536; +// not gonna use this for now, just sort by color and change state when it changes +// later maybe when using vertex attributes if it's needed + +PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed +int polygonArraySize = 0; +UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray +int polygonArrayAllocSize = 65536; + +FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon +int unsortedVertexArraySize = 0; +int unsortedVertexArrayAllocSize = 65536; + +// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend. +// Call HWR_RenderBatches to render all the collected geometry. +void HWR_StartBatching(void) +{ + if (currently_batching) + I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); + + // init arrays if that has not been done yet + if (!finalVertexArray) + { + finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + } + + currently_batching = true; +} + +// This replaces the direct calls to pfnSetTexture in cases where batching is available. +// The texture selection is saved for the next HWR_ProcessPolygon call. +// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon. +void HWR_SetCurrentTexture(GLMipmap_t *texture) +{ + if (currently_batching) + { + current_texture = texture; + } + else + { + HWD.pfnSetTexture(texture); + } +} + +// If batching is enabled, this function collects the polygon data and the chosen texture +// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to +// render the polygon immediately. +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +{ + if (currently_batching) + { + if (!pSurf) + I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to + if (polygonArraySize == polygonArrayAllocSize) + { + PolygonArrayEntry* new_array; + // ran out of space, make new array double the size + polygonArrayAllocSize *= 2; + new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); + free(polygonArray); + polygonArray = new_array; + // also need to redo the index array, dont need to copy it though + free(polygonIndexArray); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + } + + while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) + { + FOutVector* new_array; + // need more space for vertices in unsortedVertexArray + unsortedVertexArrayAllocSize *= 2; + new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); + free(unsortedVertexArray); + unsortedVertexArray = new_array; + } + + // add the polygon data to the arrays + + polygonArray[polygonArraySize].surf = *pSurf; + polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; + polygonArray[polygonArraySize].numVerts = iNumPts; + polygonArray[polygonArraySize].polyFlags = PolyFlags; + polygonArray[polygonArraySize].texture = current_texture; + polygonArray[polygonArraySize].shader = shader; + polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; + polygonArraySize++; + + memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); + unsortedVertexArraySize += iNumPts; + } + else + { + if (shader) + HWD.pfnSetShader(shader); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } +} + +static int comparePolygons(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + int shader1 = poly1->shader; + int shader2 = poly2->shader; + // make skywalls and horizon lines first in order + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + shader1 = -1; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + shader2 = -1; + diff = shader1 - shader2; + if (diff != 0) return diff; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (shader1 == -1 && shader2 == -1) + return index1 - index2; + + diff64 = poly1->texture - poly2->texture; + if (diff64 != 0) return diff64; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; + return diff; +} + +static int comparePolygonsNoShaders(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + GLMipmap_t *texture1 = poly1->texture; + GLMipmap_t *texture2 = poly2->texture; + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + texture1 = NULL; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + texture2 = NULL; + diff64 = texture1 - texture2; + if (diff64 != 0) return diff64; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (texture1 == NULL && texture2 == NULL) + return index1 - index2; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + return 0; +} + +// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses +// the rendering backend to draw them. +void HWR_RenderBatches(void) +{ + int finalVertexWritePos = 0;// position in finalVertexArray + int finalIndexWritePos = 0;// position in finalVertexIndexArray + + int polygonReadPos = 0;// position in polygonIndexArray + + int currentShader; + int nextShader = 0; + GLMipmap_t *currentTexture; + GLMipmap_t *nextTexture = NULL; + FBITFIELD currentPolyFlags = 0; + FBITFIELD nextPolyFlags = 0; + FSurfaceInfo currentSurfaceInfo; + FSurfaceInfo nextSurfaceInfo; + + int i; + + if (!currently_batching) + I_Error("HWR_RenderBatches called without starting batching"); + + nextSurfaceInfo.LightInfo.fade_end = 0; + nextSurfaceInfo.LightInfo.fade_start = 0; + nextSurfaceInfo.LightInfo.light_level = 0; + + currently_batching = false;// no longer collecting batches + if (!polygonArraySize) + { + rs_hw_numpolys = rs_hw_numcalls = rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 0; + return;// nothing to draw + } + // init stats vars + rs_hw_numpolys = polygonArraySize; + rs_hw_numcalls = rs_hw_numverts = 0; + rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 1; + // init polygonIndexArray + for (i = 0; i < polygonArraySize; i++) + { + polygonIndexArray[i] = i; + } + + // sort polygons + rs_hw_batchsorttime = I_GetTimeMicros(); + if (cv_grshaders.value && gr_shadersavailable) + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); + else + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); + rs_hw_batchsorttime = I_GetTimeMicros() - rs_hw_batchsorttime; + // sort order + // 1. shader + // 2. texture + // 3. polyflags + // 4. colors + light level + // not sure about what order of the last 2 should be, or if it even matters + + rs_hw_batchdrawtime = I_GetTimeMicros(); + + currentShader = polygonArray[polygonIndexArray[0]].shader; + currentTexture = polygonArray[polygonIndexArray[0]].texture; + currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; + currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; + // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms + // and a color array could replace the color calls. + + // set state for first batch + + if (cv_grshaders.value && gr_shadersavailable) + { + HWD.pfnSetShader(currentShader); + } + + if (currentPolyFlags & PF_NoTexture) + currentTexture = NULL; + else + HWD.pfnSetTexture(currentTexture); + + while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) + { + int firstIndex; + int lastIndex; + + boolean stopFlag = false; + boolean changeState = false; + boolean changeShader = false; + boolean changeTexture = false; + boolean changePolyFlags = false; + boolean changeSurfaceInfo = false; + + // steps: + // write vertices + // check for changes or end, otherwise go back to writing + // changes will affect the next vars and the change bools + // end could set flag for stopping + // execute draw call + // could check ending flag here + // change states according to next vars and change bools, updating the current vars and reseting the bools + // reset write pos + // repeat loop + + int index = polygonIndexArray[polygonReadPos++]; + int numVerts = polygonArray[index].numVerts; + // before writing, check if there is enough room + // using 'while' instead of 'if' here makes sure that there will *always* be enough room. + // probably never will this loop run more than once though + while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) + { + FOutVector* new_array; + unsigned int* new_index_array; + finalVertexArrayAllocSize *= 2; + new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); + free(finalVertexArray); + finalVertexArray = new_array; + // also increase size of index array, 3x of vertex array since + // going from fans to triangles increases vertex count to 3x + new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); + free(finalVertexIndexArray); + finalVertexIndexArray = new_index_array; + } + // write the vertices of the polygon + memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], + numVerts * sizeof(FOutVector)); + // write the indexes, pointing to the fan vertexes but in triangles format + firstIndex = finalVertexWritePos; + lastIndex = finalVertexWritePos + numVerts; + finalVertexWritePos += 2; + while (finalVertexWritePos < lastIndex) + { + finalVertexIndexArray[finalIndexWritePos++] = firstIndex; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; + } + + if (polygonReadPos >= polygonArraySize) + { + stopFlag = true; + } + else + { + // check if a state change is required, set the change bools and next vars + int nextIndex = polygonIndexArray[polygonReadPos]; + nextShader = polygonArray[nextIndex].shader; + nextTexture = polygonArray[nextIndex].texture; + nextPolyFlags = polygonArray[nextIndex].polyFlags; + nextSurfaceInfo = polygonArray[nextIndex].surf; + if (nextPolyFlags & PF_NoTexture) + nextTexture = 0; + if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable) + { + changeState = true; + changeShader = true; + } + if (currentTexture != nextTexture) + { + changeState = true; + changeTexture = true; + } + if (currentPolyFlags != nextPolyFlags) + { + changeState = true; + changePolyFlags = true; + } + if (cv_grshaders.value && gr_shadersavailable) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || + currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) + { + changeState = true; + changeSurfaceInfo = true; + } + } + } + + if (changeState || stopFlag) + { + // execute draw call + HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + // update stats + rs_hw_numcalls++; + rs_hw_numverts += finalIndexWritePos; + // reset write positions + finalVertexWritePos = 0; + finalIndexWritePos = 0; + } + else continue; + + // if we're here then either its time to stop or time to change state + if (stopFlag) break; + + // change state according to change bools and next vars, update current vars and reset bools + if (changeShader) + { + HWD.pfnSetShader(nextShader); + currentShader = nextShader; + changeShader = false; + + rs_hw_numshaders++; + } + if (changeTexture) + { + // texture should be already ready for use from calls to SetTexture during batch collection + HWD.pfnSetTexture(nextTexture); + currentTexture = nextTexture; + changeTexture = false; + + rs_hw_numtextures++; + } + if (changePolyFlags) + { + currentPolyFlags = nextPolyFlags; + changePolyFlags = false; + + rs_hw_numpolyflags++; + } + if (changeSurfaceInfo) + { + currentSurfaceInfo = nextSurfaceInfo; + changeSurfaceInfo = false; + + rs_hw_numcolors++; + } + // and that should be it? + } + // reset the arrays (set sizes to 0) + polygonArraySize = 0; + unsortedVertexArraySize = 0; + + rs_hw_batchdrawtime = I_GetTimeMicros() - rs_hw_batchdrawtime; +} + + +#endif // HWRENDER diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h new file mode 100644 index 000000000..7c108a4bd --- /dev/null +++ b/src/hardware/hw_batching.h @@ -0,0 +1,37 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.h +/// \brief Draw call batching and related things. + +#ifndef __HWR_BATCHING_H__ +#define __HWR_BATCHING_H__ + +#include "hw_defs.h" +#include "hw_data.h" +#include "hw_drv.h" + +typedef struct +{ + FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused + unsigned int vertsIndex;// location of verts in unsortedVertexArray + FUINT numVerts; + FBITFIELD polyFlags; + GLMipmap_t *texture; + int shader; + // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls + boolean horizonSpecial; +} PolygonArrayEntry; + +void HWR_StartBatching(void); +void HWR_SetCurrentTexture(GLMipmap_t *texture); +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial); +void HWR_RenderBatches(void); + +#endif diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index ebb74f653..6987e9d01 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_bsp.c /// \brief convert SRB2 map #include "../doomdef.h" diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 059556f15..ab9a50dd5 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_cache.c /// \brief load and convert graphics to the hardware format #include "../doomdef.h" @@ -22,6 +15,7 @@ #ifdef HWRENDER #include "hw_glob.h" #include "hw_drv.h" +#include "hw_batching.h" #include "../doomstat.h" //gamemode #include "../i_video.h" //rendermode @@ -33,9 +27,6 @@ #include "../r_patch.h" #include "../p_setup.h" -// Values set after a call to HWR_ResizeBlock() -static INT32 blocksize, blockwidth, blockheight; - INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole @@ -308,13 +299,13 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, if (pwidth <= 0 || pheight <= 0) return; - ncols = (pwidth * pblockwidth) / pwidth; + ncols = pwidth; // source advance xfrac = 0; - xfracstep = (pwidth << FRACBITS) / pblockwidth; - yfracstep = (pheight << FRACBITS) / pblockheight; - scale_y = (pblockheight << FRACBITS) / pheight; + xfracstep = FRACUNIT; + yfracstep = FRACUNIT; + scale_y = FRACUNIT; bpp = format2bpp[mipmap->grInfo.format]; @@ -322,7 +313,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); // NOTE: should this actually be pblockwidth*bpp? - blockmodulo = blockwidth*bpp; + blockmodulo = pblockwidth*bpp; // Draw each column to the block cache for (; ncols--; block += bpp, xfrac += xfracstep) @@ -415,7 +406,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); // NOTE: should this actually be pblockwidth*bpp? - blockmodulo = blockwidth*bpp; + blockmodulo = pblockwidth*bpp; // Draw each column to the block cache for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep) @@ -433,142 +424,12 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, } } - -// resize the patch to be 3dfx compliant -// set : blocksize = blockwidth * blockheight (no bpp used) -// blockwidth -// blockheight -//note : 8bit (1 byte per pixel) palettized format -static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, - GrTexInfo *grInfo) -{ -#ifdef GLIDE_API_COMPATIBILITY - // Build the full textures from patches. - static const GrLOD_t gr_lods[9] = - { - GR_LOD_LOG2_256, - GR_LOD_LOG2_128, - GR_LOD_LOG2_64, - GR_LOD_LOG2_32, - GR_LOD_LOG2_16, - GR_LOD_LOG2_8, - GR_LOD_LOG2_4, - GR_LOD_LOG2_2, - GR_LOD_LOG2_1 - }; - - typedef struct - { - GrAspectRatio_t aspect; - float max_s; - float max_t; - } booring_aspect_t; - - static const booring_aspect_t gr_aspects[8] = - { - {GR_ASPECT_LOG2_1x1, 255, 255}, - {GR_ASPECT_LOG2_2x1, 255, 127}, - {GR_ASPECT_LOG2_4x1, 255, 63}, - {GR_ASPECT_LOG2_8x1, 255, 31}, - - {GR_ASPECT_LOG2_1x1, 255, 255}, - {GR_ASPECT_LOG2_1x2, 127, 255}, - {GR_ASPECT_LOG2_1x4, 63, 255}, - {GR_ASPECT_LOG2_1x8, 31, 255} - }; - - INT32 j,k; - INT32 max,min; -#else - (void)grInfo; -#endif - - // find a power of 2 width/height - if (cv_grrounddown.value) - { - blockwidth = 256; - while (originalwidth < blockwidth) - blockwidth >>= 1; - if (blockwidth < 1) - I_Error("3D GenerateTexture : too small"); - - blockheight = 256; - while (originalheight < blockheight) - blockheight >>= 1; - if (blockheight < 1) - I_Error("3D GenerateTexture : too small"); - } - else - { -#ifdef GLIDE_API_COMPATIBILITY - //size up to nearest power of 2 - blockwidth = 1; - while (blockwidth < originalwidth) - blockwidth <<= 1; - // scale down the original graphics to fit in 256 - if (blockwidth > 2048) - blockwidth = 2048; - //I_Error("3D GenerateTexture : too big"); - - //size up to nearest power of 2 - blockheight = 1; - while (blockheight < originalheight) - blockheight <<= 1; - // scale down the original graphics to fit in 256 - if (blockheight > 2048) - blockheight = 2048; - //I_Error("3D GenerateTexture : too big"); -#else - blockwidth = originalwidth; - blockheight = originalheight; -#endif - } - - // do the boring LOD stuff.. blech! -#ifdef GLIDE_API_COMPATIBILITY - if (blockwidth >= blockheight) - { - max = blockwidth; - min = blockheight; - } - else - { - max = blockheight; - min = blockwidth; - } - - for (k = 2048, j = 0; k > max; j++) - k>>=1; - grInfo->smallLodLog2 = gr_lods[j]; - grInfo->largeLodLog2 = gr_lods[j]; - - for (k = max, j = 0; k > min && j < 4; j++) - k>>=1; - // aspect ratio too small for 3Dfx (eg: 8x128 is 1x16 : use 1x8) - if (j == 4) - { - j = 3; - //CONS_Debug(DBG_RENDER, "HWR_ResizeBlock : bad aspect ratio %dx%d\n", blockwidth,blockheight); - if (blockwidth < blockheight) - blockwidth = max>>3; - else - blockheight = max>>3; - } - if (blockwidth < blockheight) - j += 4; - grInfo->aspectRatioLog2 = gr_aspects[j].aspect; -#endif - - blocksize = blockwidth * blockheight; - - //CONS_Debug(DBG_RENDER, "Width is %d, Height is %d\n", blockwidth, blockheight); -} - static UINT8 *MakeBlock(GLMipmap_t *grMipmap) { UINT8 *block; INT32 bpp, i; UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX); + INT32 blocksize = (grMipmap->width * grMipmap->height); bpp = format2bpp[grMipmap->grInfo.format]; block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data)); @@ -599,6 +460,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) texpatch_t *patch; patch_t *realpatch; UINT8 *pdata; + INT32 blockwidth, blockheight, blocksize; INT32 i; boolean skyspecial = false; //poor hack for Legacy large skies.. @@ -619,11 +481,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) else grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY; - HWR_ResizeBlock (texture->width, texture->height, &grtex->mipmap.grInfo); - grtex->mipmap.width = (UINT16)blockwidth; - grtex->mipmap.height = (UINT16)blockheight; + grtex->mipmap.width = (UINT16)texture->width; + grtex->mipmap.height = (UINT16)texture->height; grtex->mipmap.grInfo.format = textureformat; + blockwidth = texture->width; + blockheight = texture->height; + blocksize = (blockwidth * blockheight); block = MakeBlock(&grtex->mipmap); if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading) @@ -692,8 +556,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // patch may be NULL if grMipmap has been initialised already and makebitmap is false void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) { - INT32 newwidth, newheight; - #ifndef NO_PNG_LUMPS // lump is a png so convert it size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum); @@ -712,51 +574,32 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm grPatch->leftoffset = SHORT(patch->leftoffset); grPatch->topoffset = SHORT(patch->topoffset); - // find the good 3dfx size (boring spec) - HWR_ResizeBlock (SHORT(patch->width), SHORT(patch->height), &grMipmap->grInfo); - grMipmap->width = (UINT16)blockwidth; - grMipmap->height = (UINT16)blockheight; + grMipmap->width = grMipmap->height = 1; + while (grMipmap->width < grPatch->width) grMipmap->width <<= 1; + while (grMipmap->height < grPatch->height) grMipmap->height <<= 1; // no wrap around, no chroma key grMipmap->flags = 0; // setup the texture info grMipmap->grInfo.format = patchformat; - } - else - { - blockwidth = grMipmap->width; - blockheight = grMipmap->height; - blocksize = blockwidth * blockheight; + + //grPatch->max_s = grPatch->max_t = 1.0f; + grPatch->max_s = (float)grPatch->width / (float)grMipmap->width; + grPatch->max_t = (float)grPatch->height / (float)grMipmap->height; } Z_Free(grMipmap->grInfo.data); grMipmap->grInfo.data = NULL; - // if rounddown, rounddown patches as well as textures - if (cv_grrounddown.value) - { - newwidth = blockwidth; - newheight = blockheight; - } - else - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(grPatch->width, blockwidth); - newheight = min(grPatch->height, blockheight); - } - if (makebitmap) { MakeBlock(grMipmap); HWR_DrawPatchInCache(grMipmap, - newwidth, newheight, + grMipmap->width, grMipmap->height, grPatch->width, grPatch->height, patch); } - - grPatch->max_s = (float)newwidth / (float)blockwidth; - grPatch->max_t = (float)newheight / (float)blockheight; } @@ -896,8 +739,11 @@ GLTexture_t *HWR_GetTexture(INT32 tex) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) HWR_GenerateTexture(tex, grtex); - // Tell the hardware driver to bind the current texture to the flat's mipmap - HWD.pfnSetTexture(&grtex->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + + HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -910,11 +756,6 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) size_t size, pflatsize; // setup the texture info -#ifdef GLIDE_API_COMPATIBILITY - grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -957,15 +798,7 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) { UINT8 *flat; - if (needpatchflush) - W_FlushCachedPatches(); - // setup the texture info -#ifdef GLIDE_API_COMPATIBILITY - grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif grMipmap->grInfo.format = GR_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; @@ -985,14 +818,15 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) if (flatlumpnum == LUMPERROR) return; - if (needpatchflush) - W_FlushCachedPatches(); - grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFlat(grmip, flatlumpnum); - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -1026,14 +860,17 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum); - // Tell the hardware driver to bind the current texture to the flat's mipmap - HWD.pfnSetTexture(&grtex->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + + HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); } else // set no texture - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); } // @@ -1055,7 +892,11 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) Z_Free(patch); } - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -1066,9 +907,6 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) // -----------------+ void HWR_GetPatch(GLPatch_t *gpatch) { - if (needpatchflush) - W_FlushCachedPatches(); - // is it in hardware cache if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data) { @@ -1085,7 +923,11 @@ void HWR_GetPatch(GLPatch_t *gpatch) Z_Free(ptr); } - HWD.pfnSetTexture(gpatch->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!gpatch->mipmap->downloaded) + HWD.pfnSetTexture(gpatch->mipmap); + + HWR_SetCurrentTexture(gpatch->mipmap); // The system-memory patch data can be purged now. Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -1099,9 +941,6 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) { GLMipmap_t *grmip, *newmip; - if (needpatchflush) - W_FlushCachedPatches(); - if (colormap == colormaps || colormap == NULL) { // Load the default (green) color in doom cache (temporary?) AND hardware cache @@ -1225,19 +1064,12 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig // -----------------+ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) { - GLPatch_t *grpatch; - - if (needpatchflush) - W_FlushCachedPatches(); - - grpatch = HWR_GetCachedGLPatch(lumpnum); - + GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum); if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data) { pic_t *pic; UINT8 *block; size_t len; - INT32 newwidth, newheight; pic = W_CacheLumpNum(lumpnum, PU_CACHE); grpatch->width = SHORT(pic->width); @@ -1247,10 +1079,8 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) grpatch->leftoffset = 0; grpatch->topoffset = 0; - // find the good 3dfx size (boring spec) - HWR_ResizeBlock (grpatch->width, grpatch->height, &grpatch->mipmap->grInfo); - grpatch->mipmap->width = (UINT16)blockwidth; - grpatch->mipmap->height = (UINT16)blockheight; + grpatch->mipmap->width = (UINT16)grpatch->width; + grpatch->mipmap->height = (UINT16)grpatch->height; if (pic->mode == PALETTE) grpatch->mipmap->grInfo.format = textureformat; // can be set by driver @@ -1262,30 +1092,16 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) // allocate block block = MakeBlock(grpatch->mipmap); - // if rounddown, rounddown patches as well as textures - if (cv_grrounddown.value) - { - newwidth = blockwidth; - newheight = blockheight; - } - else - { - // no rounddown, do not size up patches, so they don't look 'scaled' - newwidth = min(SHORT(pic->width),blockwidth); - newheight = min(SHORT(pic->height),blockheight); - } - - - if (grpatch->width == blockwidth && - grpatch->height == blockheight && + if (grpatch->width == SHORT(pic->width) && + grpatch->height == SHORT(pic->height) && format2bpp[grpatch->mipmap->grInfo.format] == format2bpp[picmode2GR[pic->mode]]) { // no conversion needed M_Memcpy(grpatch->mipmap->grInfo.data, pic->data,len); } else - HWR_DrawPicInCache(block, newwidth, newheight, - blockwidth*format2bpp[grpatch->mipmap->grInfo.format], + HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height), + SHORT(pic->width)*format2bpp[grpatch->mipmap->grInfo.format], pic, format2bpp[grpatch->mipmap->grInfo.format]); @@ -1293,8 +1109,7 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); grpatch->mipmap->flags = 0; - grpatch->max_s = (float)newwidth / (float)blockwidth; - grpatch->max_t = (float)newheight / (float)blockheight; + grpatch->max_s = grpatch->max_t = 1.0f; } HWD.pfnSetTexture(grpatch->mipmap); //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded); @@ -1330,7 +1145,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 { INT32 i,j; fixed_t posx, posy, stepx, stepy; - UINT8 *block = mipmap->grInfo.data; // places the data directly into here, it already has the space allocated from HWR_ResizeBlock + UINT8 *block = mipmap->grInfo.data; // places the data directly into here UINT8 *flat; UINT8 *dest, *src, texel; RGBA_t col; @@ -1345,7 +1160,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 for (j = 0; j < pblockheight; j++) { posx = 0; - dest = &block[j*blockwidth]; // 1bpp + dest = &block[j*(mipmap->width)]; // 1bpp src = &flat[(posy>>FRACBITS)*SHORT(fmwidth)]; for (i = 0; i < pblockwidth;i++) { @@ -1399,14 +1214,12 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) } // Thankfully, this will still work for this scenario - HWR_ResizeBlock(fmwidth, fmheight, &grMipmap->grInfo); - - grMipmap->width = blockwidth; - grMipmap->height = blockheight; + grMipmap->width = fmwidth; + grMipmap->height = fmheight; MakeBlock(grMipmap); - HWR_DrawFadeMaskInCache(grMipmap, blockwidth, blockheight, fademasklumpnum, fmwidth, fmheight); + HWR_DrawFadeMaskInCache(grMipmap, fmwidth, fmheight, fademasklumpnum, fmwidth, fmheight); // I DO need to convert this because it isn't power of 2 and we need the alpha } @@ -1414,13 +1227,7 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { - GLMipmap_t *grmip; - - if (needpatchflush) - W_FlushCachedPatches(); - - grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; - + GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFadeMask(grmip, fademasklumpnum); diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index a63527083..86e0c58d2 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -78,8 +78,8 @@ #include "r_opengl/r_opengl.h" #ifdef HAVE_SPHEREFRUSTRUM -static GLfloat viewMatrix[16]; -static GLfloat projMatrix[16]; +static GLdouble viewMatrix[16]; +static GLdouble projMatrix[16]; float frustum[6][4]; #endif @@ -320,12 +320,12 @@ void gld_clipper_Clear(void) #define RMUL (1.6f/1.333333f) -angle_t gld_FrustumAngle(void) +angle_t gld_FrustumAngle(angle_t tiltangle) { double floatangle; angle_t a1; - float tilt = (float)fabs(((double)(int)aimingangle) / ANG1); + float tilt = (float)fabs(((double)(int)tiltangle) / ANG1); // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function @@ -339,7 +339,7 @@ angle_t gld_FrustumAngle(void) } // If the pitch is larger than this you can look all around at a FOV of 90 - if (abs((signed)aimingangle) > 46 * ANG1) + if (abs((signed)tiltangle) > 46 * ANG1) return 0xffffffff; // ok, this is a gross hack that barely works... @@ -352,7 +352,7 @@ angle_t gld_FrustumAngle(void) } // SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either -// compiler complains about (p)glGetDoublev anyway, in case anyone wants this +// compiler complains about (p)glGetFloatv anyway, in case anyone wants this // only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks // btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h #ifdef HAVE_SPHEREFRUSTRUM @@ -381,7 +381,7 @@ void gld_FrustrumSetup(void) float t; float clip[16]; - pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix); clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12); diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h index 3ba26e5e5..27a2ed1ef 100644 --- a/src/hardware/hw_clip.h +++ b/src/hardware/hw_clip.h @@ -17,7 +17,7 @@ boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle); void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle); void gld_clipper_Clear(void); -angle_t gld_FrustumAngle(void); +angle_t gld_FrustumAngle(angle_t tiltangle); #ifdef HAVE_SPHEREFRUSTRUM void gld_FrustrumSetup(void); boolean gld_SphereInFrustum(float x, float y, float z, float radius); diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index ef57426a4..686d522a0 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -1,21 +1,14 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief defines structures and exports for the standard 3D driver DLL used by Doom Legacy +/// \file hw_data.h +/// \brief defines structures and exports for the hardware interface used by Sonic Robo Blast 2 #ifndef _HWR_DATA_ #define _HWR_DATA_ diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 95882b03e..715c45ef3 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -1,24 +1,19 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_defs.h /// \brief 3D hardware renderer definitions #ifndef _HWR_DEFS_ #define _HWR_DEFS_ #include "../doomtype.h" +#include "../r_defs.h" #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 @@ -82,16 +77,18 @@ typedef struct // Simple 3D vector typedef struct FVector { - FLOAT x,y,z; + FLOAT x,y,z; } FVector; -// 3D model vector (coords + texture coords) -typedef struct -{ - //FVector Point; - FLOAT x,y,z; - FLOAT s,t,w; // texture coordinates -} v3d_t, wallVert3D; +// ====================== +// wallVert3D +// ---------------------- +// :crab: IS GONE! :crab: +// ====================== + +// ----------- +// structures +// ----------- //Hurdler: Transform (coords + angles) //BP: transform order : scale(rotation_x(rotation_y(translation(v)))) @@ -123,15 +120,16 @@ typedef struct #ifdef USE_FTRANSFORM_MIRROR boolean mirror; // SRB2Kart: Encore Mode #endif + boolean shearing; // 14042019 + float viewaiming; // 17052019 } FTransform; // Transformed vector, as passed to HWR API typedef struct { FLOAT x,y,z; - FUINT argb; // flat-shaded color - FLOAT sow; // s texture ordinate (s over w) - FLOAT tow; // t texture ordinate (t over w) + FLOAT s; // s texture ordinate (s over w) + FLOAT t; // t texture ordinate (t over w) } FOutVector; @@ -162,10 +160,10 @@ enum EPolyFlags PF_Invisible = 0x00000400, // Disable write to color buffer PF_Decal = 0x00000800, // Enable polygon offset PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB) - // When set, pass the color constant into the FSurfaceInfo -> FlatColor + // When set, pass the color constant into the FSurfaceInfo -> PolyColor PF_NoTexture = 0x00002000, // Use the small white texture PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona - PF_Unused = 0x00008000, // Unused + PF_Ripple = 0x00008000, // Water shader effect PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapY = 0x00040000, // Force repeat texture on Y @@ -178,7 +176,6 @@ enum EPolyFlags enum ESurfFlags { SF_DYNLIGHT = 0x00000001, - }; enum ETextureFlags @@ -190,38 +187,36 @@ enum ETextureFlags TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 }; -#ifdef TODO -struct FTextureInfo -{ - FUINT Width; // Pixels - FUINT Height; // Pixels - FUBYTE *TextureData; // Image data - FUINT Format; // FORMAT_RGB, ALPHA ... - FBITFIELD Flags; // Flags to tell driver about texture (see ETextureFlags) - void DriverExtra; // (OpenGL texture object nr, ...) - // chromakey enabled,... - - struct FTextureInfo *Next; // Manage list of downloaded textures. -}; -#else typedef struct GLMipmap_s FTextureInfo; -#endif + +// jimita 14032019 +struct FLightInfo +{ + FUINT light_level; + FUINT fade_start; + FUINT fade_end; +}; +typedef struct FLightInfo FLightInfo; // Description of a renderable surface struct FSurfaceInfo { - FUINT PolyFlags; // Surface flags -- UNUSED YET -- - RGBA_t FlatColor; // Flat-shaded color used with PF_Modulated mode + FUINT PolyFlags; + RGBA_t PolyColor; + RGBA_t TintColor; + RGBA_t FadeColor; + FLightInfo LightInfo; // jimita 14032019 }; typedef struct FSurfaceInfo FSurfaceInfo; +#define GL_DEFAULTMIX 0x00000000 +#define GL_DEFAULTFOG 0xFF000000 + //Hurdler: added for backward compatibility enum hwdsetspecialstate { HWD_SET_MODEL_LIGHTING = 1, - HWD_SET_FOG_MODE, - HWD_SET_FOG_COLOR, - HWD_SET_FOG_DENSITY, + HWD_SET_SHADERS, HWD_SET_TEXTUREFILTERMODE, HWD_SET_TEXTUREANISOTROPICMODE, HWD_NUMSTATE @@ -229,6 +224,15 @@ enum hwdsetspecialstate typedef enum hwdsetspecialstate hwdspecialstate_t; +// Lactozilla: Shader info +// Generally set at the start of the frame. +enum hwdshaderinfo +{ + HWD_SHADERINFO_LEVELTIME = 1, +}; + +typedef enum hwdshaderinfo hwdshaderinfo_t; + enum hwdfiltermode { HWD_SET_TEXTUREFILTER_POINTSAMPLED, diff --git a/src/hardware/hw_dll.h b/src/hardware/hw_dll.h index 3fa5852d8..d22c8c312 100644 --- a/src/hardware/hw_dll.h +++ b/src/hardware/hw_dll.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 2005 by Sonic Team Junior. // -// Copyright (C) 2005 by SRB2 Jr. Team. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_dll.h /// \brief Win32 DLL and Shared Objects API definitions #ifndef __HWR_DLL_H__ @@ -54,8 +47,6 @@ #endif #endif -typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR; - // ========================================================================== // MATHS // ========================================================================== @@ -63,7 +54,7 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR; // Constants #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360 -void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/; +void GL_DBG_Printf(const char *format, ...) /*FUNCPRINTF*/; #ifdef _WINDOWS BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index d01331765..3d20cd9b0 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_draw.c /// \brief miscellaneous drawing (mainly 2d) #ifdef __GNUC__ @@ -23,6 +17,7 @@ #include "../doomdef.h" #ifdef HWRENDER +#include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" @@ -43,9 +38,6 @@ #define O_BINARY 0 #endif -float gr_patch_scalex; -float gr_patch_scaley; - #if defined(_MSC_VER) #pragma pack(1) #endif @@ -65,9 +57,6 @@ typedef struct #if defined(_MSC_VER) #pragma pack() #endif -typedef UINT8 GLRGB[3]; - -#define BLENDMODE PF_Translucent static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229,255}; static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; @@ -121,12 +110,12 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = gpatch->max_s; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -356,19 +345,19 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t if (option & V_FLIP) { - v[0].sow = v[3].sow = gpatch->max_s; - v[2].sow = v[1].sow = 0.0f; + v[0].s = v[3].s = gpatch->max_s; + v[2].s = v[1].s = 0.0f; } else { - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = gpatch->max_s; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = gpatch->max_s; } - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = gpatch->max_t; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -379,11 +368,11 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t if (alphalevel) { FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; - else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; + Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; + if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; + else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -514,19 +503,19 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; + v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; if (sx + w > SHORT(gpatch->width)) - v[2].sow = v[1].sow = gpatch->max_s; + v[2].s = v[1].s = gpatch->max_s; else - v[2].sow = v[1].sow = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; + v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; - v[0].tow = v[1].tow = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; + v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; if (sy + h > SHORT(gpatch->height)) - v[2].tow = v[3].tow = gpatch->max_t; + v[2].t = v[3].t = gpatch->max_t; else - v[2].tow = v[3].tow = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; + v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; - flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; + flags = PF_Translucent|PF_NoDepthTest; if (option & V_WRAPX) flags |= PF_ForceWrapX; @@ -537,11 +526,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal if (alphalevel) { FSurfaceInfo Surf; - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - if (alphalevel == 13) Surf.FlatColor.s.alpha = softwaretranstogl_lo[st_translucency]; - else if (alphalevel == 14) Surf.FlatColor.s.alpha = softwaretranstogl[st_translucency]; - else if (alphalevel == 15) Surf.FlatColor.s.alpha = softwaretranstogl_hi[st_translucency]; - else Surf.FlatColor.s.alpha = softwaretranstogl[10-alphalevel]; + Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; + if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; + else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } @@ -569,10 +558,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0; - v[2].sow = v[1].sow = patch->max_s; - v[0].tow = v[1].tow = 0; - v[2].tow = v[3].tow = patch->max_t; + v[0].s = v[3].s = 0; + v[2].s = v[1].s = patch->max_s; + v[0].t = v[1].t = 0; + v[2].t = v[3].t = patch->max_t; //Hurdler: Boris, the same comment as above... but maybe for pics @@ -581,7 +570,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) // But then, the question is: why not 0 instead of PF_Masked ? // or maybe PF_Environment ??? (like what I said above) // BP: PF_Environment don't change anything ! and 0 is undifined - HWD.pfnDrawPolygon(NULL, v, 4, BLENDMODE | PF_NoDepthTest | PF_Clip | PF_NoZClip); + HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip); } // ========================================================================== @@ -644,10 +633,10 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; // flat is 64x64 lod and texture offsets are [0.0, 1.0] - v[0].sow = v[3].sow = (float)((x & flatflag)/dflatsize); - v[2].sow = v[1].sow = (float)(v[0].sow + w/dflatsize); - v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize); - v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize); + v[0].s = v[3].s = (float)((x & flatflag)/dflatsize); + v[2].s = v[1].s = (float)(v[0].s + w/dflatsize); + v[0].t = v[1].t = (float)((y & flatflag)/dflatsize); + v[2].t = v[3].t = (float)(v[0].t + h/dflatsize); HWR_LiterallyGetFlat(flatlumpnum); @@ -679,20 +668,20 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) v[2].y = v[3].y = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 0.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; if (color & 0xFF00) // Do COLORMAP fade. { - Surf.FlatColor.rgba = UINT2RGBA(0x01010160); - Surf.FlatColor.s.alpha = (strength*8); + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); } else // Do TRANSMAP** fade. { - Surf.FlatColor.rgba = V_GetColor(color).rgba; - Surf.FlatColor.s.alpha = softwaretranstogl[strength]; + Surf.PolyColor.rgba = V_GetColor(color).rgba; + Surf.PolyColor.s.alpha = softwaretranstogl[strength]; } HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -850,24 +839,22 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac 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; //; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = 1.0f; if (actualcolor & 0xFF00) // Do COLORMAP fade. { - Surf.FlatColor.rgba = UINT2RGBA(0x01010160); - Surf.FlatColor.s.alpha = (strength*8); + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); } else // Do TRANSMAP** fade. { - Surf.FlatColor.rgba = V_GetColor(actualcolor).rgba; - Surf.FlatColor.s.alpha = softwaretranstogl[strength]; + Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba; + Surf.PolyColor.s.alpha = softwaretranstogl[strength]; } HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -888,13 +875,13 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) v[2].y = v[3].y = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 0.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; - Surf.FlatColor.rgba = UINT2RGBA(color); - Surf.FlatColor.s.alpha = 0x80; + Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.s.alpha = 0x80; HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -904,7 +891,11 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight) { FOutVector v[4]; FSurfaceInfo Surf; - INT32 height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway + INT32 height; + if (boxheight < 0) + height = -boxheight; + else + height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway // setup some neat-o translucency effect @@ -914,13 +905,13 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight) v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height); v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 1.0f; - v[2].tow = v[3].tow = 0.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; - Surf.FlatColor.rgba = UINT2RGBA(color); - Surf.FlatColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software + Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -1232,17 +1223,15 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 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; //; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = 1.0f; - Surf.FlatColor.rgba = UINT2RGBA(actualcolor); - Surf.FlatColor.s.alpha = 0x80; + Surf.PolyColor.rgba = UINT2RGBA(actualcolor); + Surf.PolyColor.s.alpha = 0x80; HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -1412,16 +1401,14 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) 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; //; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = 0.0f; - v[2].sow = v[1].sow = 1.0f; - v[0].tow = v[1].tow = 0.0f; - v[2].tow = v[3].tow = 1.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = 1.0f; - Surf.FlatColor = V_GetColor(color); + Surf.PolyColor = V_GetColor(color); HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_NoTexture|PF_NoDepthTest); diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 3314fb015..2e4ea10cc 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_drv.h /// \brief imports/exports for the 3D hardware low-level interface API #ifndef __HWR_DRV_H__ @@ -32,7 +25,7 @@ // STANDARD DLL EXPORTS // ========================================================================== -EXPORT boolean HWRAPI(Init) (I_Error_t ErrorFunction); +EXPORT boolean HWRAPI(Init) (void); #ifndef HAVE_SDL EXPORT void HWRAPI(Shutdown) (void); #endif @@ -43,10 +36,12 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray); EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); 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(UpdateTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -55,14 +50,11 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); -EXPORT INT32 HWRAPI(GetRenderVersion) (void); -#define SCREENVERTS 10 -EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(StartScreenWipe) (void); EXPORT void HWRAPI(EndScreenWipe) (void); @@ -71,6 +63,20 @@ EXPORT void HWRAPI(DrawIntermissionBG) (void); EXPORT void HWRAPI(MakeScreenTexture) (void); EXPORT void HWRAPI(MakeScreenFinalTexture) (void); EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); + +#define SCREENVERTS 10 +EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); + +// jimita +EXPORT boolean HWRAPI(LoadShaders) (void); +EXPORT void HWRAPI(KillShaders) (void); +EXPORT void HWRAPI(SetShader) (int shader); +EXPORT void HWRAPI(UnSetShader) (void); + +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); +EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); +EXPORT boolean HWRAPI(InitCustomShaders) (void); + // ========================================================================== // HWR DRIVER OBJECT, FOR CLIENT PROGRAM // ========================================================================== @@ -84,10 +90,12 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; + DrawIndexedTriangles pfnDrawIndexedTriangles; RenderSkyDome pfnRenderSkyDome; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; + UpdateTexture pfnUpdateTexture; ReadRect pfnReadRect; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; @@ -96,7 +104,6 @@ struct hwdriver_s CreateModelVBOs pfnCreateModelVBOs; SetTransform pfnSetTransform; GetTextureUsed pfnGetTextureUsed; - GetRenderVersion pfnGetRenderVersion; #ifdef _WINDOWS GetModeList pfnGetModeList; #endif @@ -112,13 +119,19 @@ struct hwdriver_s MakeScreenTexture pfnMakeScreenTexture; MakeScreenFinalTexture pfnMakeScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture; + + LoadShaders pfnLoadShaders; + KillShaders pfnKillShaders; + SetShader pfnSetShader; + UnSetShader pfnUnSetShader; + + SetShaderInfo pfnSetShaderInfo; + LoadCustomShader pfnLoadCustomShader; + InitCustomShaders pfnInitCustomShaders; }; extern struct hwdriver_s hwdriver; -//Hurdler: 16/10/99: added for OpenGL gamma correction -//extern RGBA_t gamma_correction; - #define HWD hwdriver #endif //not defined _CREATE_DLL_ diff --git a/src/hardware/hw_glide.h b/src/hardware/hw_glide.h index bf91229ef..d0eeebaeb 100644 --- a/src/hardware/hw_glide.h +++ b/src/hardware/hw_glide.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_glide.h /// \brief Declaration needed by Glide renderer /// !!! To be replaced by our own def in the future !!! @@ -25,26 +18,6 @@ typedef unsigned long FxU32; typedef long FxI32; -typedef FxI32 GrAspectRatio_t; -#define GR_ASPECT_LOG2_8x1 3 /* 8W x 1H */ -#define GR_ASPECT_LOG2_4x1 2 /* 4W x 1H */ -#define GR_ASPECT_LOG2_2x1 1 /* 2W x 1H */ -#define GR_ASPECT_LOG2_1x1 0 /* 1W x 1H */ -#define GR_ASPECT_LOG2_1x2 -1 /* 1W x 2H */ -#define GR_ASPECT_LOG2_1x4 -2 /* 1W x 4H */ -#define GR_ASPECT_LOG2_1x8 -3 /* 1W x 8H */ - -typedef FxI32 GrLOD_t; -#define GR_LOD_LOG2_256 0x8 -#define GR_LOD_LOG2_128 0x7 -#define GR_LOD_LOG2_64 0x6 -#define GR_LOD_LOG2_32 0x5 -#define GR_LOD_LOG2_16 0x4 -#define GR_LOD_LOG2_8 0x3 -#define GR_LOD_LOG2_4 0x2 -#define GR_LOD_LOG2_2 0x1 -#define GR_LOD_LOG2_1 0x0 - typedef FxI32 GrTextureFormat_t; #define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */ #define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */ @@ -59,11 +32,6 @@ typedef FxI32 GrTextureFormat_t; typedef struct { -#ifdef GLIDE_API_COMPATIBILITY - GrLOD_t smallLodLog2; - GrLOD_t largeLodLog2; - GrAspectRatio_t aspectRatioLog2; -#endif GrTextureFormat_t format; void *data; } GrTexInfo; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index a2bf79817..861c2f382 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_glob.h /// \brief globals (shared data & code) for hw_ modules #ifndef _HWR_GLOB_H_ @@ -118,11 +111,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- -extern float gr_patch_scalex; -extern float gr_patch_scaley; - -extern consvar_t cv_grrounddown; // on/off - extern INT32 patchformat; extern INT32 textureformat; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 3d1316a2f..b2139d5ee 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_light.c /// \brief Corona/Dynamic/Static lighting add on by Hurdler /// !!! Under construction !!! @@ -879,19 +873,19 @@ void HWR_WallLighting(FOutVector *wlVerts) #endif for (i = 0; i < 4; i++) { - wlVerts[i].sow = (float)(0.5f + d[i]*s); - wlVerts[i].tow = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f); + wlVerts[i].s = (float)(0.5f + d[i]*s); + wlVerts[i].t = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f); } HWR_SetLight(); - Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); + Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); #ifdef DL_HIGH_QUALITY - Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha); #endif // next state is null so fade out with alpha if (dynlights->mo[j]->state->nextstate == S_NULL) - Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha); HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS); @@ -948,19 +942,19 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) #endif for (i = 0; i < nrClipVerts; i++) { - clVerts[i].sow = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s; - clVerts[i].tow = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f; + clVerts[i].s = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s; + clVerts[i].t = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f; } HWR_SetLight(); - Surf.FlatColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); + Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); #ifdef DL_HIGH_QUALITY - Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha); #endif // next state is null so fade out with alpha if ((dynlights->mo[j]->state->nextstate == S_NULL)) - Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); + Surf.PolyColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha); HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS); @@ -1027,11 +1021,11 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr) // more realistique corona ! if (cz >= 255*8+250) return; - Surf.FlatColor.rgba = p_lspr->corona_color; + Surf.PolyColor.rgba = p_lspr->corona_color; if (cz > 250.0f) - Surf.FlatColor.s.alpha = 0xff-((int)cz-250)/8; + Surf.PolyColor.s.alpha = 0xff-((int)cz-250)/8; else - Surf.FlatColor.s.alpha = 0xff; + Surf.PolyColor.s.alpha = 0xff; // do not be hide by sprite of the light itself ! cz = cz - 2.0f; @@ -1043,19 +1037,19 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr) // car comme l'offset est minime sa ce voit pas ! light[0].x = cx-size; light[0].z = cz; light[0].y = cy-size*1.33f+p_lspr->light_yoffset; - light[0].sow = 0.0f; light[0].tow = 0.0f; + light[0].s = 0.0f; light[0].t = 0.0f; light[1].x = cx+size; light[1].z = cz; light[1].y = cy-size*1.33f+p_lspr->light_yoffset; - light[1].sow = 1.0f; light[1].tow = 0.0f; + light[1].s = 1.0f; light[1].t = 0.0f; light[2].x = cx+size; light[2].z = cz; light[2].y = cy+size*1.33f+p_lspr->light_yoffset; - light[2].sow = 1.0f; light[2].tow = 1.0f; + light[2].s = 1.0f; light[2].t = 1.0f; light[3].x = cx-size; light[3].z = cz; light[3].y = cy+size*1.33f+p_lspr->light_yoffset; - light[3].sow = 0.0f; light[3].tow = 1.0f; + light[3].s = 0.0f; light[3].t = 1.0f; HWR_GetPic(coronalumpnum); /// \todo use different coronas @@ -1101,11 +1095,11 @@ void HWR_DrawCoronas(void) // more realistique corona ! if (cz >= 255*8+250) continue; - Surf.FlatColor.rgba = p_lspr->corona_color; + Surf.PolyColor.rgba = p_lspr->corona_color; if (cz > 250.0f) - Surf.FlatColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8)); + Surf.PolyColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8)); else - Surf.FlatColor.s.alpha = 0xff; + Surf.PolyColor.s.alpha = 0xff; switch (p_lspr->type) { @@ -1113,7 +1107,7 @@ void HWR_DrawCoronas(void) size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ? break; case ROCKET_SPR: - Surf.FlatColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff); + Surf.PolyColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff); // don't need a break case CORONA_SPR: size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ? @@ -1133,19 +1127,19 @@ void HWR_DrawCoronas(void) light[0].x = cx-size; light[0].z = cz; light[0].y = cy-size*1.33f; - light[0].sow = 0.0f; light[0].tow = 0.0f; + light[0].s = 0.0f; light[0].t = 0.0f; light[1].x = cx+size; light[1].z = cz; light[1].y = cy-size*1.33f; - light[1].sow = 1.0f; light[1].tow = 0.0f; + light[1].s = 1.0f; light[1].t = 0.0f; light[2].x = cx+size; light[2].z = cz; light[2].y = cy+size*1.33f; - light[2].sow = 1.0f; light[2].tow = 1.0f; + light[2].s = 1.0f; light[2].t = 1.0f; light[3].x = cx-size; light[3].z = cz; light[3].y = cy+size*1.33f; - light[3].sow = 0.0f; light[3].tow = 1.0f; + light[3].s = 0.0f; light[3].t = 1.0f; HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona); } @@ -1254,11 +1248,6 @@ static void HWR_SetLight(void) lightmappatch.height = 128; lightmappatch.mipmap->width = 128; lightmappatch.mipmap->height = 128; -#ifdef GLIDE_API_COMPATIBILITY - lightmappatch.mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_128; - lightmappatch.mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_128; - lightmappatch.mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! } HWD.pfnSetTexture(lightmappatch.mipmap); diff --git a/src/hardware/hw_light.h b/src/hardware/hw_light.h index 2733cc698..3b12f9c87 100644 --- a/src/hardware/hw_light.h +++ b/src/hardware/hw_light.h @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_light.h /// \brief Dynamic lighting & coronas add on by Hurdler #ifndef _HW_LIGHTS_ diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index df5119814..b89ffe9e6 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_main.c /// \brief hardware renderer, using the standard HardWareRender driver DLL for SRB2 #include @@ -24,6 +18,7 @@ #include "hw_glob.h" #include "hw_light.h" #include "hw_drv.h" +#include "hw_batching.h" #include "../i_video.h" // for rendermode == render_glide #include "../v_video.h" @@ -51,7 +46,6 @@ #define R_FAKEFLOORS #define HWPRECIP -#define SORTING //#define POLYSKY // ========================================================================== @@ -70,175 +64,12 @@ static void HWR_ProjectSprite(mobj_t *thing); static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif -#ifdef SORTING -void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); -#else -static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, fixed_t fixedheight, - INT32 lightlevel, INT32 alpha, sector_t *FOFSector); -static void HWR_Render3DWater(void); -static void HWR_RenderTransparentWalls(void); -#endif -static void HWR_FoggingOn(void); -static UINT32 atohex(const char *s); boolean drawsky = true; -/* - * lookuptable for lightvalues - * calculated as follow: - * floatlight = (1.0-exp((light^3)*gamma)) / (1.0-exp(1.0*gamma)); - * gamma=-0,2;-2,0;-4,0;-6,0;-8,0 - * light = 0,0 .. 1,0 - */ -static const float lighttable[5][256] = -{ - { - 0.00000f,0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00001f,0.00002f,0.00003f,0.00004f, - 0.00006f,0.00008f,0.00010f,0.00013f,0.00017f,0.00020f,0.00025f,0.00030f,0.00035f,0.00041f, - 0.00048f,0.00056f,0.00064f,0.00073f,0.00083f,0.00094f,0.00106f,0.00119f,0.00132f,0.00147f, - 0.00163f,0.00180f,0.00198f,0.00217f,0.00237f,0.00259f,0.00281f,0.00305f,0.00331f,0.00358f, - 0.00386f,0.00416f,0.00447f,0.00479f,0.00514f,0.00550f,0.00587f,0.00626f,0.00667f,0.00710f, - 0.00754f,0.00800f,0.00848f,0.00898f,0.00950f,0.01003f,0.01059f,0.01117f,0.01177f,0.01239f, - 0.01303f,0.01369f,0.01437f,0.01508f,0.01581f,0.01656f,0.01734f,0.01814f,0.01896f,0.01981f, - 0.02069f,0.02159f,0.02251f,0.02346f,0.02444f,0.02544f,0.02647f,0.02753f,0.02862f,0.02973f, - 0.03088f,0.03205f,0.03325f,0.03448f,0.03575f,0.03704f,0.03836f,0.03971f,0.04110f,0.04252f, - 0.04396f,0.04545f,0.04696f,0.04851f,0.05009f,0.05171f,0.05336f,0.05504f,0.05676f,0.05852f, - 0.06031f,0.06214f,0.06400f,0.06590f,0.06784f,0.06981f,0.07183f,0.07388f,0.07597f,0.07810f, - 0.08027f,0.08248f,0.08473f,0.08702f,0.08935f,0.09172f,0.09414f,0.09659f,0.09909f,0.10163f, - 0.10421f,0.10684f,0.10951f,0.11223f,0.11499f,0.11779f,0.12064f,0.12354f,0.12648f,0.12946f, - 0.13250f,0.13558f,0.13871f,0.14188f,0.14511f,0.14838f,0.15170f,0.15507f,0.15850f,0.16197f, - 0.16549f,0.16906f,0.17268f,0.17635f,0.18008f,0.18386f,0.18769f,0.19157f,0.19551f,0.19950f, - 0.20354f,0.20764f,0.21179f,0.21600f,0.22026f,0.22458f,0.22896f,0.23339f,0.23788f,0.24242f, - 0.24702f,0.25168f,0.25640f,0.26118f,0.26602f,0.27091f,0.27587f,0.28089f,0.28596f,0.29110f, - 0.29630f,0.30156f,0.30688f,0.31226f,0.31771f,0.32322f,0.32879f,0.33443f,0.34013f,0.34589f, - 0.35172f,0.35761f,0.36357f,0.36960f,0.37569f,0.38185f,0.38808f,0.39437f,0.40073f,0.40716f, - 0.41366f,0.42022f,0.42686f,0.43356f,0.44034f,0.44718f,0.45410f,0.46108f,0.46814f,0.47527f, - 0.48247f,0.48974f,0.49709f,0.50451f,0.51200f,0.51957f,0.52721f,0.53492f,0.54271f,0.55058f, - 0.55852f,0.56654f,0.57463f,0.58280f,0.59105f,0.59937f,0.60777f,0.61625f,0.62481f,0.63345f, - 0.64217f,0.65096f,0.65984f,0.66880f,0.67783f,0.68695f,0.69615f,0.70544f,0.71480f,0.72425f, - 0.73378f,0.74339f,0.75308f,0.76286f,0.77273f,0.78268f,0.79271f,0.80283f,0.81304f,0.82333f, - 0.83371f,0.84417f,0.85472f,0.86536f,0.87609f,0.88691f,0.89781f,0.90880f,0.91989f,0.93106f, - 0.94232f,0.95368f,0.96512f,0.97665f,0.98828f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00007f,0.00010f, - 0.00014f,0.00019f,0.00024f,0.00031f,0.00038f,0.00047f,0.00057f,0.00069f,0.00081f,0.00096f, - 0.00112f,0.00129f,0.00148f,0.00170f,0.00193f,0.00218f,0.00245f,0.00274f,0.00306f,0.00340f, - 0.00376f,0.00415f,0.00456f,0.00500f,0.00547f,0.00597f,0.00649f,0.00704f,0.00763f,0.00825f, - 0.00889f,0.00957f,0.01029f,0.01104f,0.01182f,0.01264f,0.01350f,0.01439f,0.01532f,0.01630f, - 0.01731f,0.01836f,0.01945f,0.02058f,0.02176f,0.02298f,0.02424f,0.02555f,0.02690f,0.02830f, - 0.02974f,0.03123f,0.03277f,0.03436f,0.03600f,0.03768f,0.03942f,0.04120f,0.04304f,0.04493f, - 0.04687f,0.04886f,0.05091f,0.05301f,0.05517f,0.05738f,0.05964f,0.06196f,0.06434f,0.06677f, - 0.06926f,0.07181f,0.07441f,0.07707f,0.07979f,0.08257f,0.08541f,0.08831f,0.09126f,0.09428f, - 0.09735f,0.10048f,0.10368f,0.10693f,0.11025f,0.11362f,0.11706f,0.12056f,0.12411f,0.12773f, - 0.13141f,0.13515f,0.13895f,0.14281f,0.14673f,0.15072f,0.15476f,0.15886f,0.16303f,0.16725f, - 0.17153f,0.17587f,0.18028f,0.18474f,0.18926f,0.19383f,0.19847f,0.20316f,0.20791f,0.21272f, - 0.21759f,0.22251f,0.22748f,0.23251f,0.23760f,0.24274f,0.24793f,0.25318f,0.25848f,0.26383f, - 0.26923f,0.27468f,0.28018f,0.28573f,0.29133f,0.29697f,0.30266f,0.30840f,0.31418f,0.32001f, - 0.32588f,0.33179f,0.33774f,0.34374f,0.34977f,0.35585f,0.36196f,0.36810f,0.37428f,0.38050f, - 0.38675f,0.39304f,0.39935f,0.40570f,0.41207f,0.41847f,0.42490f,0.43136f,0.43784f,0.44434f, - 0.45087f,0.45741f,0.46398f,0.47057f,0.47717f,0.48379f,0.49042f,0.49707f,0.50373f,0.51041f, - 0.51709f,0.52378f,0.53048f,0.53718f,0.54389f,0.55061f,0.55732f,0.56404f,0.57075f,0.57747f, - 0.58418f,0.59089f,0.59759f,0.60429f,0.61097f,0.61765f,0.62432f,0.63098f,0.63762f,0.64425f, - 0.65086f,0.65746f,0.66404f,0.67060f,0.67714f,0.68365f,0.69015f,0.69662f,0.70307f,0.70948f, - 0.71588f,0.72224f,0.72857f,0.73488f,0.74115f,0.74739f,0.75359f,0.75976f,0.76589f,0.77199f, - 0.77805f,0.78407f,0.79005f,0.79599f,0.80189f,0.80774f,0.81355f,0.81932f,0.82504f,0.83072f, - 0.83635f,0.84194f,0.84747f,0.85296f,0.85840f,0.86378f,0.86912f,0.87441f,0.87964f,0.88482f, - 0.88995f,0.89503f,0.90005f,0.90502f,0.90993f,0.91479f,0.91959f,0.92434f,0.92903f,0.93366f, - 0.93824f,0.94276f,0.94723f,0.95163f,0.95598f,0.96027f,0.96451f,0.96868f,0.97280f,0.97686f, - 0.98086f,0.98481f,0.98869f,0.99252f,0.99629f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00008f,0.00013f,0.00018f, - 0.00025f,0.00033f,0.00042f,0.00054f,0.00067f,0.00083f,0.00101f,0.00121f,0.00143f,0.00168f, - 0.00196f,0.00227f,0.00261f,0.00299f,0.00339f,0.00383f,0.00431f,0.00483f,0.00538f,0.00598f, - 0.00661f,0.00729f,0.00802f,0.00879f,0.00961f,0.01048f,0.01140f,0.01237f,0.01340f,0.01447f, - 0.01561f,0.01680f,0.01804f,0.01935f,0.02072f,0.02215f,0.02364f,0.02520f,0.02682f,0.02850f, - 0.03026f,0.03208f,0.03397f,0.03594f,0.03797f,0.04007f,0.04225f,0.04451f,0.04684f,0.04924f, - 0.05172f,0.05428f,0.05691f,0.05963f,0.06242f,0.06530f,0.06825f,0.07129f,0.07441f,0.07761f, - 0.08089f,0.08426f,0.08771f,0.09125f,0.09487f,0.09857f,0.10236f,0.10623f,0.11019f,0.11423f, - 0.11836f,0.12257f,0.12687f,0.13125f,0.13571f,0.14027f,0.14490f,0.14962f,0.15442f,0.15931f, - 0.16427f,0.16932f,0.17445f,0.17966f,0.18496f,0.19033f,0.19578f,0.20130f,0.20691f,0.21259f, - 0.21834f,0.22417f,0.23007f,0.23605f,0.24209f,0.24820f,0.25438f,0.26063f,0.26694f,0.27332f, - 0.27976f,0.28626f,0.29282f,0.29944f,0.30611f,0.31284f,0.31962f,0.32646f,0.33334f,0.34027f, - 0.34724f,0.35426f,0.36132f,0.36842f,0.37556f,0.38273f,0.38994f,0.39718f,0.40445f,0.41174f, - 0.41907f,0.42641f,0.43378f,0.44116f,0.44856f,0.45598f,0.46340f,0.47084f,0.47828f,0.48573f, - 0.49319f,0.50064f,0.50809f,0.51554f,0.52298f,0.53042f,0.53784f,0.54525f,0.55265f,0.56002f, - 0.56738f,0.57472f,0.58203f,0.58932f,0.59658f,0.60381f,0.61101f,0.61817f,0.62529f,0.63238f, - 0.63943f,0.64643f,0.65339f,0.66031f,0.66717f,0.67399f,0.68075f,0.68746f,0.69412f,0.70072f, - 0.70726f,0.71375f,0.72017f,0.72653f,0.73282f,0.73905f,0.74522f,0.75131f,0.75734f,0.76330f, - 0.76918f,0.77500f,0.78074f,0.78640f,0.79199f,0.79751f,0.80295f,0.80831f,0.81359f,0.81880f, - 0.82393f,0.82898f,0.83394f,0.83883f,0.84364f,0.84836f,0.85301f,0.85758f,0.86206f,0.86646f, - 0.87078f,0.87502f,0.87918f,0.88326f,0.88726f,0.89118f,0.89501f,0.89877f,0.90245f,0.90605f, - 0.90957f,0.91301f,0.91638f,0.91966f,0.92288f,0.92601f,0.92908f,0.93206f,0.93498f,0.93782f, - 0.94059f,0.94329f,0.94592f,0.94848f,0.95097f,0.95339f,0.95575f,0.95804f,0.96027f,0.96244f, - 0.96454f,0.96658f,0.96856f,0.97049f,0.97235f,0.97416f,0.97591f,0.97760f,0.97924f,0.98083f, - 0.98237f,0.98386f,0.98530f,0.98669f,0.98803f,0.98933f,0.99058f,0.99179f,0.99295f,0.99408f, - 0.99516f,0.99620f,0.99721f,0.99817f,0.99910f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00005f,0.00008f,0.00012f,0.00019f,0.00026f, - 0.00036f,0.00048f,0.00063f,0.00080f,0.00099f,0.00122f,0.00148f,0.00178f,0.00211f,0.00249f, - 0.00290f,0.00335f,0.00386f,0.00440f,0.00500f,0.00565f,0.00636f,0.00711f,0.00793f,0.00881f, - 0.00975f,0.01075f,0.01182f,0.01295f,0.01416f,0.01543f,0.01678f,0.01821f,0.01971f,0.02129f, - 0.02295f,0.02469f,0.02652f,0.02843f,0.03043f,0.03252f,0.03469f,0.03696f,0.03933f,0.04178f, - 0.04433f,0.04698f,0.04973f,0.05258f,0.05552f,0.05857f,0.06172f,0.06498f,0.06834f,0.07180f, - 0.07537f,0.07905f,0.08283f,0.08672f,0.09072f,0.09483f,0.09905f,0.10337f,0.10781f,0.11236f, - 0.11701f,0.12178f,0.12665f,0.13163f,0.13673f,0.14193f,0.14724f,0.15265f,0.15817f,0.16380f, - 0.16954f,0.17538f,0.18132f,0.18737f,0.19351f,0.19976f,0.20610f,0.21255f,0.21908f,0.22572f, - 0.23244f,0.23926f,0.24616f,0.25316f,0.26023f,0.26739f,0.27464f,0.28196f,0.28935f,0.29683f, - 0.30437f,0.31198f,0.31966f,0.32740f,0.33521f,0.34307f,0.35099f,0.35896f,0.36699f,0.37506f, - 0.38317f,0.39133f,0.39952f,0.40775f,0.41601f,0.42429f,0.43261f,0.44094f,0.44929f,0.45766f, - 0.46604f,0.47443f,0.48283f,0.49122f,0.49962f,0.50801f,0.51639f,0.52476f,0.53312f,0.54146f, - 0.54978f,0.55807f,0.56633f,0.57457f,0.58277f,0.59093f,0.59905f,0.60713f,0.61516f,0.62314f, - 0.63107f,0.63895f,0.64676f,0.65452f,0.66221f,0.66984f,0.67739f,0.68488f,0.69229f,0.69963f, - 0.70689f,0.71407f,0.72117f,0.72818f,0.73511f,0.74195f,0.74870f,0.75536f,0.76192f,0.76839f, - 0.77477f,0.78105f,0.78723f,0.79331f,0.79930f,0.80518f,0.81096f,0.81664f,0.82221f,0.82768f, - 0.83305f,0.83832f,0.84347f,0.84853f,0.85348f,0.85832f,0.86306f,0.86770f,0.87223f,0.87666f, - 0.88098f,0.88521f,0.88933f,0.89334f,0.89726f,0.90108f,0.90480f,0.90842f,0.91194f,0.91537f, - 0.91870f,0.92193f,0.92508f,0.92813f,0.93109f,0.93396f,0.93675f,0.93945f,0.94206f,0.94459f, - 0.94704f,0.94941f,0.95169f,0.95391f,0.95604f,0.95810f,0.96009f,0.96201f,0.96386f,0.96564f, - 0.96735f,0.96900f,0.97059f,0.97212f,0.97358f,0.97499f,0.97634f,0.97764f,0.97888f,0.98007f, - 0.98122f,0.98231f,0.98336f,0.98436f,0.98531f,0.98623f,0.98710f,0.98793f,0.98873f,0.98949f, - 0.99021f,0.99090f,0.99155f,0.99218f,0.99277f,0.99333f,0.99387f,0.99437f,0.99486f,0.99531f, - 0.99575f,0.99616f,0.99654f,0.99691f,0.99726f,0.99759f,0.99790f,0.99819f,0.99847f,0.99873f, - 0.99897f,0.99920f,0.99942f,0.99963f,0.99982f,1.00000f - }, - { - 0.00000f,0.00000f,0.00000f,0.00001f,0.00003f,0.00006f,0.00010f,0.00017f,0.00025f,0.00035f, - 0.00048f,0.00064f,0.00083f,0.00106f,0.00132f,0.00163f,0.00197f,0.00237f,0.00281f,0.00330f, - 0.00385f,0.00446f,0.00513f,0.00585f,0.00665f,0.00751f,0.00845f,0.00945f,0.01054f,0.01170f, - 0.01295f,0.01428f,0.01569f,0.01719f,0.01879f,0.02048f,0.02227f,0.02415f,0.02614f,0.02822f, - 0.03042f,0.03272f,0.03513f,0.03765f,0.04028f,0.04303f,0.04589f,0.04887f,0.05198f,0.05520f, - 0.05855f,0.06202f,0.06561f,0.06933f,0.07318f,0.07716f,0.08127f,0.08550f,0.08987f,0.09437f, - 0.09900f,0.10376f,0.10866f,0.11369f,0.11884f,0.12414f,0.12956f,0.13512f,0.14080f,0.14662f, - 0.15257f,0.15865f,0.16485f,0.17118f,0.17764f,0.18423f,0.19093f,0.19776f,0.20471f,0.21177f, - 0.21895f,0.22625f,0.23365f,0.24117f,0.24879f,0.25652f,0.26435f,0.27228f,0.28030f,0.28842f, - 0.29662f,0.30492f,0.31329f,0.32175f,0.33028f,0.33889f,0.34756f,0.35630f,0.36510f,0.37396f, - 0.38287f,0.39183f,0.40084f,0.40989f,0.41897f,0.42809f,0.43723f,0.44640f,0.45559f,0.46479f, - 0.47401f,0.48323f,0.49245f,0.50167f,0.51088f,0.52008f,0.52927f,0.53843f,0.54757f,0.55668f, - 0.56575f,0.57479f,0.58379f,0.59274f,0.60164f,0.61048f,0.61927f,0.62799f,0.63665f,0.64524f, - 0.65376f,0.66220f,0.67056f,0.67883f,0.68702f,0.69511f,0.70312f,0.71103f,0.71884f,0.72655f, - 0.73415f,0.74165f,0.74904f,0.75632f,0.76348f,0.77053f,0.77747f,0.78428f,0.79098f,0.79756f, - 0.80401f,0.81035f,0.81655f,0.82264f,0.82859f,0.83443f,0.84013f,0.84571f,0.85117f,0.85649f, - 0.86169f,0.86677f,0.87172f,0.87654f,0.88124f,0.88581f,0.89026f,0.89459f,0.89880f,0.90289f, - 0.90686f,0.91071f,0.91445f,0.91807f,0.92157f,0.92497f,0.92826f,0.93143f,0.93450f,0.93747f, - 0.94034f,0.94310f,0.94577f,0.94833f,0.95081f,0.95319f,0.95548f,0.95768f,0.95980f,0.96183f, - 0.96378f,0.96565f,0.96744f,0.96916f,0.97081f,0.97238f,0.97388f,0.97532f,0.97669f,0.97801f, - 0.97926f,0.98045f,0.98158f,0.98266f,0.98369f,0.98467f,0.98560f,0.98648f,0.98732f,0.98811f, - 0.98886f,0.98958f,0.99025f,0.99089f,0.99149f,0.99206f,0.99260f,0.99311f,0.99359f,0.99404f, - 0.99446f,0.99486f,0.99523f,0.99559f,0.99592f,0.99623f,0.99652f,0.99679f,0.99705f,0.99729f, - 0.99751f,0.99772f,0.99792f,0.99810f,0.99827f,0.99843f,0.99857f,0.99871f,0.99884f,0.99896f, - 0.99907f,0.99917f,0.99926f,0.99935f,0.99943f,0.99951f,0.99958f,0.99964f,0.99970f,0.99975f, - 0.99980f,0.99985f,0.99989f,0.99993f,0.99997f,1.00000f - } -}; - -#define gld_CalcLightLevel(lightlevel) (lighttable[1][max(min((lightlevel),255),0)]) - // ========================================================================== // VIEW GLOBALS // ========================================================================== @@ -311,153 +142,199 @@ static float gr_viewsin, gr_viewcos; static float gr_viewludsin, gr_viewludcos; // look up down kik test static float gr_fovlud; +static angle_t gr_aimingangle; +static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox); + +// Render stats +int rs_hw_nodesorttime = 0; +int rs_hw_nodedrawtime = 0; +int rs_hw_spritesorttime = 0; +int rs_hw_spritedrawtime = 0; + +// Render stats for batching +int rs_hw_numpolys = 0; +int rs_hw_numverts = 0; +int rs_hw_numcalls = 0; +int rs_hw_numshaders = 0; +int rs_hw_numtextures = 0; +int rs_hw_numpolyflags = 0; +int rs_hw_numcolors = 0; +int rs_hw_batchsorttime = 0; +int rs_hw_batchdrawtime = 0; + +boolean gr_shadersavailable = true; + + // ========================================================================== -// LIGHT stuffs +// Lighting // ========================================================================== -static UINT8 lightleveltonumlut[256]; - -// added to SRB2's sector lightlevel to make things a bit brighter (sprites/walls/planes) -FUNCMATH UINT8 LightLevelToLum(INT32 l) +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap) { - return (UINT8)(255*gld_CalcLightLevel(l)); + RGBA_t poly_color, tint_color, fade_color; + + poly_color.rgba = 0xFFFFFFFF; + tint_color.rgba = (colormap != NULL) ? (UINT32)colormap->rgba : GL_DEFAULTMIX; + fade_color.rgba = (colormap != NULL) ? (UINT32)colormap->fadergba : GL_DEFAULTFOG; + + // Crappy backup coloring if you can't do shaders + if (!cv_grshaders.value || !gr_shadersavailable) + { + // be careful, this may get negative for high lightlevel values. + float tint_alpha, fade_alpha; + float red, green, blue; + + red = (float)poly_color.s.red; + green = (float)poly_color.s.green; + blue = (float)poly_color.s.blue; + + // 48 is just an arbritrary value that looked relatively okay. + tint_alpha = (float)(sqrt(tint_color.s.alpha) * 48) / 255.0f; + + // 8 is roughly the brightness of the "close" color in Software, and 16 the brightness of the "far" color. + // 8 is too bright for dark levels, and 16 is too dark for bright levels. + // 12 is the compromise value. It doesn't look especially good anywhere, but it's the most balanced. + // (Also, as far as I can tell, fade_color's alpha is actually not used in Software, so we only use light level.) + fade_alpha = (float)(sqrt(255-light_level) * 12) / 255.0f; + + // Clamp the alpha values + tint_alpha = min(max(tint_alpha, 0.0f), 1.0f); + fade_alpha = min(max(fade_alpha, 0.0f), 1.0f); + + red = (tint_color.s.red * tint_alpha) + (red * (1.0f - tint_alpha)); + green = (tint_color.s.green * tint_alpha) + (green * (1.0f - tint_alpha)); + blue = (tint_color.s.blue * tint_alpha) + (blue * (1.0f - tint_alpha)); + + red = (fade_color.s.red * fade_alpha) + (red * (1.0f - fade_alpha)); + green = (fade_color.s.green * fade_alpha) + (green * (1.0f - fade_alpha)); + blue = (fade_color.s.blue * fade_alpha) + (blue * (1.0f - fade_alpha)); + + poly_color.s.red = (UINT8)red; + poly_color.s.green = (UINT8)green; + poly_color.s.blue = (UINT8)blue; + } + + Surface->PolyColor.rgba = poly_color.rgba; + Surface->TintColor.rgba = tint_color.rgba; + Surface->FadeColor.rgba = fade_color.rgba; + Surface->LightInfo.light_level = light_level; + Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0; + Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31; } -static inline void InitLumLut(void) -{ - INT32 i, k = 0; - for (i = 0; i < 256; i++) - { - if (i > 128) - k += 2; - else - k = 1; - lightleveltonumlut[i] = (UINT8)(k); - } -} - -//#define FOGFACTOR 300 //was 600 >> Covered by cv_grfogdensity -#define NORMALFOG 0x00000000 -#define FADEFOG 0x19000000 -#define CALCFOGDENSITY(x) ((float)((5220.0f*(1.0f/((x)/41.0f+1.0f)))-(5220.0f*(1.0f/(255.0f/41.0f+1.0f))))) // Approximate fog calculation based off of software walls -#define CALCFOGDENSITYFLOOR(x) ((float)((40227.0f*(1.0f/((x)/11.0f+1.0f)))-(40227.0f*(1.0f/(255.0f/11.0f+1.0f))))) // Approximate fog calculation based off of software floors -#define CALCLIGHT(x,y) ((float)(x)*((y)/255.0f)) -UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane) -{ - RGBA_t realcolor, fogcolor, surfcolor; - INT32 alpha, fogalpha; - - (void)fogblockpoly; - - // Don't go out of bounds - if (light < 0) - light = 0; - else if (light > 255) - light = 255; - - realcolor.rgba = color; - fogcolor.rgba = fadecolor; - - alpha = (realcolor.s.alpha*255)/25; - fogalpha = (fogcolor.s.alpha*255)/25; - - if (cv_grfog.value && cv_grsoftwarefog.value) // Only do this when fog is on, software fog mode is on, and the poly is not from a fog block - { - // Modulate the colors by alpha. - realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red)); - realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green)); - realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue)); - - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.red,255)); - surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.green,255)); - surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),255)+CALCLIGHT(realcolor.s.blue,255)); - surfcolor.s.alpha = 0xFF; - - // Modulate the colors by alpha. - fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red)); - fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green)); - fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue)); - } - else - { - // Modulate the colors by alpha. - realcolor.s.red = (UINT8)(CALCLIGHT(alpha,realcolor.s.red)); - realcolor.s.green = (UINT8)(CALCLIGHT(alpha,realcolor.s.green)); - realcolor.s.blue = (UINT8)(CALCLIGHT(alpha,realcolor.s.blue)); - - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.red,light)); - surfcolor.s.green = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.green,light)); - surfcolor.s.blue = (UINT8)(CALCLIGHT((0xFF-alpha),light)+CALCLIGHT(realcolor.s.blue,light)); - - // Modulate the colors by alpha. - fogcolor.s.red = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.red)); - fogcolor.s.green = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.green)); - fogcolor.s.blue = (UINT8)(CALCLIGHT(fogalpha,fogcolor.s.blue)); - - // Set the surface colors and further modulate the colors by light. - surfcolor.s.red = surfcolor.s.red+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.red,(255-light)))); - surfcolor.s.green = surfcolor.s.green+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.green,(255-light)))); - surfcolor.s.blue = surfcolor.s.blue+((UINT8)(CALCLIGHT((0xFF-fogalpha),(255-light))+CALCLIGHT(fogcolor.s.blue,(255-light)))); - surfcolor.s.alpha = 0xFF; - } - - if(cv_grfog.value) - { - if (cv_grsoftwarefog.value) - { - fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light))); - fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light))); - fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light))); - - // Set the fog options. - if (cv_grsoftwarefog.value == 1 && plane) // With floors, software draws them way darker for their distance - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITYFLOOR(light))); - else // everything else is drawn like walls - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(CALCFOGDENSITY(light))); - } - else - { - fogcolor.s.red = (UINT8)((CALCLIGHT(fogcolor.s.red,(255-light)))+(CALCLIGHT(realcolor.s.red,light))); - fogcolor.s.green = (UINT8)((CALCLIGHT(fogcolor.s.green,(255-light)))+(CALCLIGHT(realcolor.s.green,light))); - fogcolor.s.blue = (UINT8)((CALCLIGHT(fogcolor.s.blue,(255-light)))+(CALCLIGHT(realcolor.s.blue,light))); - - fogalpha = (UINT8)((CALCLIGHT(fogalpha,(255-light)))+(CALCLIGHT(alpha,light))); - - // Set the fog options. - light = (UINT8)(CALCLIGHT(light,(255-fogalpha))); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, (INT32)(cv_grfogdensity.value-(cv_grfogdensity.value*(float)light/255.0f))); - } - - HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, (fogcolor.s.red*0x10000)+(fogcolor.s.green*0x100)+fogcolor.s.blue); - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1); - } - return surfcolor.rgba; -} - - -static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this can work +UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work { RGBA_t realcolor, surfcolor; INT32 alpha; - // Don't go out of bounds - if (light < 0) - light = 0; - else if (light > 255) - light = 255; + realcolor.rgba = (colormap != NULL) ? colormap->rgba : GL_DEFAULTMIX; - realcolor.rgba = color; + if (cv_grshaders.value && gr_shadersavailable) + { + surfcolor.s.alpha = (255 - light); + } + else + { + light = light - (255 - light); - alpha = (realcolor.s.alpha*255)/25; + // Don't go out of bounds + if (light < 0) + light = 0; + else if (light > 255) + light = 255; - // 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; + alpha = (realcolor.s.alpha*255)/25; + + // 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; } +static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) +{ + INT16 finallight = lightnum; + + if (cv_grfakecontrast.value != 0) + { + const UINT8 contrast = 8; + fixed_t extralight = 0; + + if (cv_grfakecontrast.value == 2) // Smooth setting + { + extralight = (-(contrast<> FRACBITS; + } + else + { + if (v1y == v2y) + extralight = -contrast; + else if (v1x == v2x) + extralight = contrast; + } + + if (extralight != 0) + { + finallight += extralight; + + if (finallight < 0) + finallight = 0; + if (finallight > 255) + finallight = 255; + } + } + + return (FUINT)finallight; +} + +static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta) +{ + INT16 finallight = lightnum; + + if (cv_grfakecontrast.value != 0 && cv_grslopecontrast.value != 0) + { + const UINT8 contrast = 8; + fixed_t extralight = 0; + + if (cv_grfakecontrast.value == 2) // Smooth setting + { + fixed_t dirmul = abs(FixedDiv(AngleFixed(dir) - (180<> FRACBITS; + } + else + { + dir = ((dir + ANGLE_45) / ANGLE_90) * ANGLE_90; + + if (dir == ANGLE_180) + extralight = -contrast; + else if (dir == 0) + extralight = contrast; + + if (delta >= FRACUNIT/2) + extralight *= 2; + } + + if (extralight != 0) + { + finallight += extralight; + + if (finallight < 0) + finallight = 0; + if (finallight > 255) + finallight = 255; + } + } + + return (FUINT)finallight; +} + // ========================================================================== // FLOOR/CEILING GENERATION FROM SUBSECTORS // ========================================================================== @@ -467,8 +344,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c // -----------------+ // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ -static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, - FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap) +static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -489,6 +365,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + int shader; + // no convex poly were generated for this subsector if (!xsub->planepoly) return; @@ -521,13 +399,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool if (nrPlaneVerts < 3) //not even a triangle ? return; - // This check is so inconsistent between functions, it hurts. - if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size - { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX); - return; - } - // Allocate plane-vertex buffer if we need to if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts) { @@ -578,7 +449,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } } else // set no texture - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); // reference point for flat texture coord for each vertex around the polygon flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); @@ -616,9 +487,18 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } } + if (angle) // Only needs to be done if there's an altered angle { - angle = InvAngle(angle)>>ANGLETOFINESHIFT; + + angle = (InvAngle(angle)+ANGLE_180)>>ANGLETOFINESHIFT; + + // This needs to be done so that it scrolls in a different direction after rotation like software + /*tempxsow = FLOAT_TO_FIXED(scrollx); + tempytow = FLOAT_TO_FIXED(scrolly); + scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); + scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));*/ + // This needs to be done so everything aligns after rotation // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does tempxsow = FLOAT_TO_FIXED(flatxref); @@ -631,24 +511,24 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool /* Hurdler: add scrolling texture on floor/ceiling */\ if (texflat)\ {\ - vert->sow = (float)((vx) / fflatwidth) + scrollx;\ - vert->tow = -(float)((vy) / fflatheight) + scrolly;\ + vert->s = (float)((vx) / fflatwidth) + scrollx;\ + vert->t = -(float)((vy) / fflatheight) + scrolly;\ }\ else\ {\ - vert->sow = (float)(((vx) / fflatwidth) - flatxref + scrollx);\ - vert->tow = (float)(flatyref - ((vy) / fflatheight) + scrolly);\ + vert->s = (float)(((vx) / fflatwidth) - flatxref + scrollx);\ + vert->t = (float)(flatyref - ((vy) / fflatheight) + scrolly);\ }\ \ /* Need to rotate before translate */\ if (angle) /* Only needs to be done if there's an altered angle */\ {\ - tempxsow = FLOAT_TO_FIXED(vert->sow);\ - tempytow = FLOAT_TO_FIXED(vert->tow);\ + tempxsow = FLOAT_TO_FIXED(vert->s);\ + tempytow = FLOAT_TO_FIXED(vert->t);\ if (texflat)\ tempytow = -tempytow;\ - vert->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ - vert->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ + vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ + vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ }\ \ vert->x = (vx);\ @@ -665,39 +545,27 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++) SETUP3DVERT(v3d, pv->x, pv->y); - // only useful for flat coloured triangles - //Surf.FlatColor = 0xff804020; + if (slope) + lightlevel = HWR_CalcSlopeLight(lightlevel, R_PointToAngle2(0, 0, slope->normal.x, slope->normal.y), abs(slope->zdelta)); - // use different light tables - // for horizontal / vertical / diagonal - // note: try to get the same visual feel as the original - Surf.FlatColor.s.red = Surf.FlatColor.s.green = - Surf.FlatColor.s.blue = LightLevelToLum(lightlevel); // Don't take from the frontsector, or the game will crash - - if (planecolormap) - { - if (fogplane) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, true, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); - } - else - { - if (fogplane) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, true, false); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); - } + HWR_Lighting(&Surf, lightlevel, planecolormap); if (PolyFlags & (PF_Translucent|PF_Fog)) { - Surf.FlatColor.s.alpha = (UINT8)alpha; - PolyFlags |= PF_Modulated|PF_Clip; + Surf.PolyColor.s.alpha = (UINT8)alpha; + PolyFlags |= PF_Modulated; } else - PolyFlags |= PF_Masked|PF_Modulated|PF_Clip; + PolyFlags |= PF_Masked|PF_Modulated; - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags); + if (PolyFlags & PF_Fog) + shader = 6; // fog shader + else if (PolyFlags & PF_Ripple) + shader = 5; // water shader + else + shader = 1; // floor shader + + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); if (subsector) { @@ -766,7 +634,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool horizonpts[4].y = gr_viewz; // Draw - HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags); + HWR_ProcessPolygon(&Surf, horizonpts, 6, PolyFlags, shader, true); } } } @@ -811,8 +679,8 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) v3d = planeVerts; for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) { - v3d->sow = 0.0f; - v3d->tow = 0.0f; + v3d->s = 0.0f; + v3d->t = 0.0f; v3d->x = pv->x; v3d->y = height; v3d->z = pv->y; @@ -835,13 +703,10 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) #ifdef WALLSPLATS static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) { - FOutVector trVerts[4], *wv; - wallVert3D wallVerts[4]; - wallVert3D *pwallVerts; + FOutVector wallVerts[4]; wallsplat_t *splat; GLPatch_t *gpatch; fixed_t i; - FSurfaceInfo pSurf2; // seg bbox fixed_t segbbox[4]; @@ -879,141 +744,64 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) wallVerts[3].s = wallVerts[3].t = wallVerts[2].s = wallVerts[0].t = 0.0f; wallVerts[1].s = wallVerts[1].t = wallVerts[2].t = wallVerts[0].s = 1.0f; - // transform - wv = trVerts; - pwallVerts = wallVerts; - for (i = 0; i < 4; i++,wv++,pwallVerts++) - { - wv->x = pwallVerts->x; - wv->z = pwallVerts->z; - wv->y = pwallVerts->y; - - // Kalaron: TOW and SOW needed to be switched - wv->sow = pwallVerts->t; - wv->tow = pwallVerts->s; - } - M_Memcpy(&pSurf2,pSurf,sizeof (FSurfaceInfo)); switch (splat->flags & SPLATDRAWMODE_MASK) { case SPLATDRAWMODE_OPAQUE : - pSurf2.FlatColor.s.alpha = 0xff; + pSurf.PolyColor.s.alpha = 0xff; i = PF_Translucent; break; case SPLATDRAWMODE_TRANS : - pSurf2.FlatColor.s.alpha = 128; + pSurf.PolyColor.s.alpha = 128; i = PF_Translucent; break; case SPLATDRAWMODE_SHADE : - pSurf2.FlatColor.s.alpha = 0xff; + pSurf.PolyColor.s.alpha = 0xff; i = PF_Substractive; break; } - HWD.pfnDrawPolygon(&pSurf2, trVerts, 4, i|PF_Modulated|PF_Clip|PF_Decal); + HWD.pfnSetShader(2); // wall shader + HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal); } } #endif -// ========================================================================== -// WALL GENERATION FROM SUBSECTOR SEGS -// ========================================================================== - - FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) { switch (transtablenum) { - case tr_trans10 : pSurf->FlatColor.s.alpha = 0xe6;return PF_Translucent; - case tr_trans20 : pSurf->FlatColor.s.alpha = 0xcc;return PF_Translucent; - case tr_trans30 : pSurf->FlatColor.s.alpha = 0xb3;return PF_Translucent; - case tr_trans40 : pSurf->FlatColor.s.alpha = 0x99;return PF_Translucent; - case tr_trans50 : pSurf->FlatColor.s.alpha = 0x80;return PF_Translucent; - case tr_trans60 : pSurf->FlatColor.s.alpha = 0x66;return PF_Translucent; - case tr_trans70 : pSurf->FlatColor.s.alpha = 0x4c;return PF_Translucent; - case tr_trans80 : pSurf->FlatColor.s.alpha = 0x33;return PF_Translucent; - case tr_trans90 : pSurf->FlatColor.s.alpha = 0x19;return PF_Translucent; + case tr_trans10 : pSurf->PolyColor.s.alpha = 0xe6;return PF_Translucent; + case tr_trans20 : pSurf->PolyColor.s.alpha = 0xcc;return PF_Translucent; + case tr_trans30 : pSurf->PolyColor.s.alpha = 0xb3;return PF_Translucent; + case tr_trans40 : pSurf->PolyColor.s.alpha = 0x99;return PF_Translucent; + case tr_trans50 : pSurf->PolyColor.s.alpha = 0x80;return PF_Translucent; + case tr_trans60 : pSurf->PolyColor.s.alpha = 0x66;return PF_Translucent; + case tr_trans70 : pSurf->PolyColor.s.alpha = 0x4c;return PF_Translucent; + case tr_trans80 : pSurf->PolyColor.s.alpha = 0x33;return PF_Translucent; + case tr_trans90 : pSurf->PolyColor.s.alpha = 0x19;return PF_Translucent; } return PF_Translucent; } -// v1,v2 : the start & end vertices along the original wall segment, that may have been -// clipped so that only a visible portion of the wall seg is drawn. -// floorheight, ceilingheight : depend on wall upper/lower/middle, comes from the sectors. +static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); -static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo * pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); +// ========================================================================== +// Wall generation from subsector segs +// ========================================================================== -// -----------------+ -// HWR_ProjectWall : -// -----------------+ -/* - wallVerts order is : - 3--2 - | /| - |/ | - 0--1 -*/ -static void HWR_ProjectWall(wallVert3D * wallVerts, - FSurfaceInfo * pSurf, - FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) +// +// HWR_ProjectWall +// +static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { - FOutVector trVerts[4]; - FOutVector *wv; + HWR_Lighting(pSurf, lightlevel, wallcolormap); - // transform - wv = trVerts; - // it sounds really stupid to do this conversion with the new T&L code - // we should directly put the right information in the right structure - // wallVerts3D seems ok, doesn't need FOutVector - // also remove the light copy - - // More messy to unwrap, but it's also quicker, uses less memory. - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - wv++; wallVerts++; - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - - if (wallcolormap) - { - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, false, false); - } - else - { - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); - } - - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blendmode|PF_Modulated|PF_Occlude|PF_Clip); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, 2, false); // wall shader #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); #endif -#ifdef ALAM_LIGHTING - //Hurdler: TDOD: do static lighting using gr_curline->lm - HWR_WallLighting(trVerts); - - //Hurdler: for better dynamic light in dark area, we should draw the light first - // and then the wall all that with the right blending func - //HWD.pfnDrawPolygon(pSurf, trVerts, 4, PF_Additive|PF_Modulated|PF_Occlude|PF_Clip); -#endif } // ========================================================================== @@ -1055,38 +843,10 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) } #endif -static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) -{ - INT16 finallight = lightnum; - - if (cv_grfakecontrast.value != 0) - { - const UINT8 contrast = 8; - fixed_t extralight = 0; - - if (v1y == v2y) - extralight = -contrast; - else if (v1x == v2x) - extralight = contrast; - - if (extralight != 0) - { - finallight += extralight; - - if (finallight < 0) - finallight = 0; - if (finallight > 255) - finallight = 255; - } - } - - return (FUINT)finallight; -} - // // HWR_SplitWall // -static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) +static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts @@ -1111,7 +871,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; + const UINT8 alpha = Surf->PolyColor.s.alpha; FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; @@ -1129,10 +889,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, for (i = 0; i < sector->numlights; i++) { - if (endtop < endrealbot && top < realbot) + if (endtop < endrealbot && top < realbot) return; - // 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)) @@ -1210,7 +969,8 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (endbot < endrealbot) endbot = endrealbot; - Surf->FlatColor.s.alpha = alpha; + + Surf->PolyColor.s.alpha = alpha; wallVerts[3].t = pegt + ((realtop - top) * pegmul); wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); @@ -1239,7 +999,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (endtop <= endrealbot && top <= realbot) return; - Surf->FlatColor.s.alpha = alpha; + Surf->PolyColor.s.alpha = alpha; wallVerts[3].t = pegt + ((realtop - top) * pegmul); wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); @@ -1262,35 +1022,31 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, // HWR_DrawSkyWall // Draw walls into the depth buffer so that anything behind is culled properly -static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf) +static void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) { - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); // no texture wallVerts[3].t = wallVerts[2].t = 0; wallVerts[0].t = wallVerts[1].t = 0; wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = 0; // this no longer sets top/bottom coords, this should be done before caling the function - HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL); + HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_NoTexture, 255, NULL); // PF_Invisible so it's not drawn into the colour buffer // PF_NoTexture for no texture // PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer } // -// HWR_StoreWallRange +// HWR_ProcessSeg // A portion or all of a wall segment will be drawn, from startfrac to endfrac, // where 0 is the start of the segment, 1 the end of the segment // Anything between means the wall segment has been clipped with solidsegs, // reducing wall overdraw to a minimum // -#ifdef NEWCLIP static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom -#else -static void HWR_StoreWallRange(double startfrac, double endfrac) -#endif { - wallVert3D wallVerts[4]; + FOutVector wallVerts[4]; v2d_t vs, ve; // start, end vertices of 2d line (view from above) fixed_t worldtop, worldbottom; @@ -1309,11 +1065,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) extracolormap_t *colormap; FSurfaceInfo Surf; -#ifndef NEWCLIP - if (startfrac > endfrac) - return; -#endif - gr_sidedef = gr_curline->sidedef; gr_linedef = gr_curline->linedef; @@ -1345,35 +1096,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) wallVerts[0].z = wallVerts[3].z = vs.y; wallVerts[2].x = wallVerts[1].x = ve.x; wallVerts[2].z = wallVerts[1].z = ve.y; - wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f; + // x offset the texture { - // x offset the texture fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset; - -#ifndef NEWCLIP - // clip texture s start/end coords with solidsegs - if (startfrac > 0.0f && startfrac < 1.0f) - cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac); - else -#endif - cliplow = (float)texturehpeg; - -#ifndef NEWCLIP - if (endfrac > 0.0f && endfrac < 1.0f) - cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac); - else -#endif - cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); + cliplow = (float)texturehpeg; + cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); } lightnum = HWR_CalcWallLight(gr_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = gr_frontsector->extra_colormap; if (gr_frontsector) - { - Surf.FlatColor.s.alpha = 255; - } + Surf.PolyColor.s.alpha = 255; if (gr_backsector) { @@ -1762,7 +1497,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { if (gr_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn { - Surf.FlatColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode + Surf.PolyColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode blendmode = PF_Masked; } else @@ -1782,16 +1517,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); - - // If there is a colormap change, remove it. -/* if (!(Surf.FlatColor.s.red + Surf.FlatColor.s.green + Surf.FlatColor.s.blue == Surf.FlatColor.s.red/3) - { - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; - Surf.FlatColor.rgba = 0xffffffff; - }*/ } -#if 1 // Sky culling // No longer so much a mess as before! if (!gr_curline->polyseg) // Don't do it for polyobjects @@ -1818,13 +1545,12 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } } } -#endif } else { // Single sided line... Deal only with the middletexture (if one exists) gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); - if (gr_midtexture && gr_linedef->special != HORIZONSPECIAL) // Ignore horizon line for OGL + if (gr_midtexture && gr_linedef->special != 41) // (Ignore horizon line for OGL) { { fixed_t texturevpeg; @@ -1898,7 +1624,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) //Hurdler: 3d-floors test -#ifdef R_FAKEFLOORS if (gr_frontsector && gr_backsector && gr_frontsector->tag != gr_backsector->tag && (gr_backsector->ffloors || gr_frontsector->ffloors)) { ffloor_t * rover; @@ -2016,15 +1741,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); 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); - } - else - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); - } + 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, &Surf, rover->flags, rover); @@ -2038,7 +1755,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; - Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } if (gr_frontsector->numlights) @@ -2124,14 +1841,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); 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); - } - else - { - Surf.FlatColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel,NORMALFOG); - } + 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, &Surf, rover->flags, rover); @@ -2145,7 +1855,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; - Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } if (gr_backsector->numlights) @@ -2161,7 +1871,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } } } -#endif //Hurdler: end of 3d-floors test } @@ -2976,7 +2685,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; - fixed_t tempxsow, tempytow; + fixed_t tempxs, tempyt; size_t nrPlaneVerts; static FOutVector *planeVerts = NULL; @@ -3045,7 +2754,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, } } else // set no texture - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); // reference point for flat texture coord for each vertex around the polygon flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth); @@ -3088,17 +2797,17 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, if (angle) // Only needs to be done if there's an altered angle { // This needs to be done so that it scrolls in a different direction after rotation like software - tempxsow = FLOAT_TO_FIXED(scrollx); - tempytow = FLOAT_TO_FIXED(scrolly); - scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + tempxs = FLOAT_TO_FIXED(scrollx); + tempyt = FLOAT_TO_FIXED(scrolly); + scrollx = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + scrolly = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle)))); // This needs to be done so everything aligns after rotation // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does - tempxsow = FLOAT_TO_FIXED(flatxref); - tempytow = FLOAT_TO_FIXED(flatyref); - flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + tempxs = FLOAT_TO_FIXED(flatxref); + tempyt = FLOAT_TO_FIXED(flatyref); + flatxref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + flatyref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle)))); } for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) @@ -3107,24 +2816,24 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, // Means the flat is offset based on the original vertex locations if (texflat) { - v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; - v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; + v3d->s = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; + v3d->t = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; } else { - v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); - v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); + v3d->s = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); + v3d->t = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { - tempxsow = FLOAT_TO_FIXED(v3d->sow); - tempytow = FLOAT_TO_FIXED(v3d->tow); + tempxs = FLOAT_TO_FIXED(v3d->s); + tempyt = FLOAT_TO_FIXED(v3d->t); if (texflat) - tempytow = -tempytow; - v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); + tempyt = -tempyt; + v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + v3d->t = (FIXED_TO_FLOAT(-FixedMul(tempxs, FINESINE(angle)) - FixedMul(tempyt, FINECOSINE(angle)))); } v3d->x = FIXED_TO_FLOAT(polysector->vertices[i]->x); @@ -3133,20 +2842,17 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, } - if (planecolormap) - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); - else - Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); + HWR_Lighting(&Surf, lightlevel, planecolormap); if (blendmode & PF_Translucent) { - Surf.FlatColor.s.alpha = (UINT8)alpha; + Surf.PolyColor.s.alpha = (UINT8)alpha; blendmode |= PF_Modulated|PF_Occlude|PF_Clip; } else blendmode |= PF_Masked|PF_Modulated|PF_Clip; - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, 1, false); // floor shader } static void HWR_AddPolyObjectPlanes(void) @@ -3180,7 +2886,7 @@ static void HWR_AddPolyObjectPlanes(void) memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { @@ -3203,7 +2909,7 @@ static void HWR_AddPolyObjectPlanes(void) memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight, - (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); + (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap)); } else { @@ -3351,7 +3057,7 @@ static void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, false, floorcolormap); + PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, floorcolormap); } } else @@ -3373,7 +3079,7 @@ static void HWR_Subsector(size_t num) // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, false, ceilingcolormap); + PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, ceilingcolormap); } } else @@ -3419,13 +3125,9 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); - if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); - else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - - HWR_AddTransparentFloor(NULL, + HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, @@ -3436,28 +3138,21 @@ static void HWR_Subsector(size_t num) 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 - HWR_Add3DWater(&levelflats[*rover->bottompic], - &extrasubsectors[num], - *rover->bottomheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1, rover->master->frontsector); -#else + HWR_AddTransparentFloor(&levelflats[*rover->bottompic], &extrasubsectors[num], false, *rover->bottomheight, *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, + rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, false, *gr_frontsector->lightlist[light].extra_colormap); -#endif } else { HWR_GetLevelFlat(&levelflats[*rover->bottompic]); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], - rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); + 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], + rover->master->frontsector, 255, *gr_frontsector->lightlist[light].extra_colormap); } } @@ -3475,13 +3170,9 @@ static void HWR_Subsector(size_t num) UINT8 alpha; light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); - if (rover->master->frontsector->extra_colormap) - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba); - else - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG); - - HWR_AddTransparentFloor(NULL, + HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, @@ -3492,29 +3183,21 @@ static void HWR_Subsector(size_t num) else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); -#ifndef SORTING - HWR_Add3DWater(&levelflats[*rover->toppic], - &extrasubsectors[num], - *rover->topheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1, rover->master->frontsector); -#else + HWR_AddTransparentFloor(&levelflats[*rover->toppic], &extrasubsectors[num], true, *rover->topheight, *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, PF_Translucent, + rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, false, *gr_frontsector->lightlist[light].extra_colormap); -#endif - } else { HWR_GetLevelFlat(&levelflats[*rover->toppic]); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], - rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap); + 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], + rover->master->frontsector, 255, *gr_frontsector->lightlist[light].extra_colormap); } } } @@ -3536,6 +3219,9 @@ static void HWR_Subsector(size_t num) po = (polyobj_t *)(po->link.next); } + // for render stats + rs_numpolyobjects += numpolys; + // Sort polyobjects R_SortPolyObjects(sub); @@ -3641,6 +3327,8 @@ static void HWR_RenderBSPNode(INT32 bspnum) // Decide which side the view point is on INT32 side; + + rs_numbspcalls++; // Found a subsector? if (bspnum & NF_SUBSECTOR) @@ -3853,13 +3541,12 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v return false; } -static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale) +static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) { GLPatch_t *gpatch; FOutVector shadowVerts[4]; FSurfaceInfo sSurf; float fscale; float fx; float fy; float offset; - UINT8 lightlevel = 255; extracolormap_t *colormap = NULL; UINT8 i; SINT8 flip = P_MobjFlip(thing); @@ -3903,10 +3590,18 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale else offset = (float)(SHORT(gpatch->height)/2); - shadowVerts[0].x = shadowVerts[3].x = fx - offset; - shadowVerts[2].x = shadowVerts[1].x = fx + offset; - shadowVerts[0].z = shadowVerts[1].z = fy - offset; - shadowVerts[3].z = shadowVerts[2].z = fy + offset; + shadowVerts[2].x = shadowVerts[3].x = fx + offset; + shadowVerts[1].x = shadowVerts[0].x = fx - offset; + shadowVerts[1].z = shadowVerts[2].z = fy - offset; + shadowVerts[0].z = shadowVerts[3].z = fy + offset; + + for (i = 0; i < 4; i++) + { + float oldx = shadowVerts[i].x; + float oldy = shadowVerts[i].z; + shadowVerts[i].x = fx + ((oldx - fx) * gr_viewcos) - ((oldy - fy) * gr_viewsin); + shadowVerts[i].z = fy + ((oldx - fx) * gr_viewsin) + ((oldy - fy) * gr_viewcos); + } if (groundslope) { @@ -3922,57 +3617,29 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale shadowVerts[i].y = FIXED_TO_FLOAT(groundz) + flip * 0.05f; } - if (spr->flip) - { - shadowVerts[0].sow = shadowVerts[3].sow = gpatch->max_s; - shadowVerts[2].sow = shadowVerts[1].sow = 0; - } - else - { - shadowVerts[0].sow = shadowVerts[3].sow = 0; - shadowVerts[2].sow = shadowVerts[1].sow = gpatch->max_s; - } + shadowVerts[0].s = shadowVerts[3].s = 0; + shadowVerts[2].s = shadowVerts[1].s = gpatch->max_s; - // flip the texture coords (look familiar?) - if (spr->vflip) - { - shadowVerts[3].tow = shadowVerts[2].tow = gpatch->max_t; - shadowVerts[0].tow = shadowVerts[1].tow = 0; - } - else - { - shadowVerts[3].tow = shadowVerts[2].tow = 0; - shadowVerts[0].tow = shadowVerts[1].tow = gpatch->max_t; - } + shadowVerts[3].t = shadowVerts[2].t = 0; + shadowVerts[0].t = shadowVerts[1].t = gpatch->max_t; if (thing->subsector->sector->numlights) { light = R_GetPlaneLight(thing->subsector->sector, groundz, false); // Always use the light at the top instead of whatever I was doing before - if (*thing->subsector->sector->lightlist[light].lightlevel > 255) - lightlevel = 255; - else - lightlevel = *thing->subsector->sector->lightlist[light].lightlevel; - if (*thing->subsector->sector->lightlist[light].extra_colormap) colormap = *thing->subsector->sector->lightlist[light].extra_colormap; } else { - lightlevel = thing->subsector->sector->lightlevel; - if (thing->subsector->sector->extra_colormap) colormap = thing->subsector->sector->extra_colormap; } - if (colormap) - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); - else - sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + HWR_Lighting(&sSurf, 0, colormap); + sSurf.PolyColor.s.alpha = alpha; - sSurf.FlatColor.s.alpha = alpha; - - HWD.pfnDrawPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, 3, false); // sprite shader } // This is expecting a pointer to an array containing 4 wallVerts for a sprite @@ -4024,7 +3691,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) INT32 i; float realtop, realbot, top, bot; - float towtop, towbot, towmult; + float ttop, tbot, tmult; float bheight; float realheight, heightmult; const sector_t *sector = spr->mobj->subsector->sector; @@ -4065,25 +3732,25 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (spr->flip) { - baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s; - baseWallVerts[2].sow = baseWallVerts[1].sow = 0; + baseWallVerts[0].s = baseWallVerts[3].s = gpatch->max_s; + baseWallVerts[2].s = baseWallVerts[1].s = 0; } else { - baseWallVerts[0].sow = baseWallVerts[3].sow = 0; - baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s; + baseWallVerts[0].s = baseWallVerts[3].s = 0; + baseWallVerts[2].s = baseWallVerts[1].s = gpatch->max_s; } // flip the texture coords (look familiar?) if (spr->vflip) { - baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t; - baseWallVerts[0].tow = baseWallVerts[1].tow = 0; + baseWallVerts[3].t = baseWallVerts[2].t = gpatch->max_t; + baseWallVerts[0].t = baseWallVerts[1].t = 0; } else { - baseWallVerts[3].tow = baseWallVerts[2].tow = 0; - baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t; + baseWallVerts[3].t = baseWallVerts[2].t = 0; + baseWallVerts[0].t = baseWallVerts[1].t = gpatch->max_t; } // if it has a dispoffset, push it a little towards the camera @@ -4101,9 +3768,9 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) realtop = top = baseWallVerts[3].y; realbot = bot = baseWallVerts[0].y; - towtop = baseWallVerts[3].tow; - towbot = baseWallVerts[0].tow; - towmult = (towbot - towtop) / (top - bot); + ttop = baseWallVerts[3].t; + tbot = baseWallVerts[0].t; + tmult = (tbot - ttop) / (top - bot); endrealtop = endtop = baseWallVerts[2].y; endrealbot = endbot = baseWallVerts[1].y; @@ -4115,12 +3782,12 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (!cv_translucency.value) // translucency disabled { - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } else if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4131,11 +3798,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) // 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; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - alpha = Surf.FlatColor.s.alpha; + alpha = Surf.PolyColor.s.alpha; // Start with the lightlevel and colormap from the top of the sprite lightlevel = *list[sector->numlights - 1].lightlevel; @@ -4197,10 +3864,10 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (endbot < endrealbot) endbot = endrealbot; - 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].t = ttop + ((realtop - top) * tmult); + wallVerts[2].t = ttop + ((endrealtop - endtop) * tmult); + wallVerts[0].t = ttop + ((realtop - bot) * tmult); + wallVerts[1].t = ttop + ((endrealtop - endbot) * tmult); wallVerts[3].y = top; wallVerts[2].y = endtop; @@ -4231,14 +3898,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; } - 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); + HWR_Lighting(&Surf, lightlevel, colormap); - Surf.FlatColor.s.alpha = alpha; + Surf.PolyColor.s.alpha = alpha; - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader top = bot; endtop = endbot; @@ -4250,24 +3914,21 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) return; // If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite - 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].t = ttop + ((realtop - top) * tmult); + wallVerts[2].t = ttop + ((endrealtop - endtop) * tmult); + wallVerts[0].t = ttop + ((realtop - bot) * tmult); + wallVerts[1].t = ttop + ((endrealtop - endbot) * tmult); wallVerts[3].y = top; wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; - 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); + HWR_Lighting(&Surf, lightlevel, colormap); - Surf.FlatColor.s.alpha = alpha; + Surf.PolyColor.s.alpha = alpha; - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader } // -----------------+ @@ -4337,21 +3998,21 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (spr->flip) { - wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s; - wallVerts[2].sow = wallVerts[1].sow = 0; + wallVerts[0].s = wallVerts[3].s = gpatch->max_s; + wallVerts[2].s = wallVerts[1].s = 0; }else{ - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + wallVerts[0].s = wallVerts[3].s = 0; + wallVerts[2].s = wallVerts[1].s = 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; + wallVerts[3].t = wallVerts[2].t = gpatch->max_t; + wallVerts[0].t = wallVerts[1].t = 0; }else{ - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + wallVerts[3].t = wallVerts[2].t = 0; + wallVerts[0].t = wallVerts[1].t = gpatch->max_t; } // cache the patch in the graphics card memory @@ -4385,22 +4046,19 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (!(spr->mobj->frame & FF_FULLBRIGHT)) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; - 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); + HWR_Lighting(&Surf, lightlevel, colormap); } { FBITFIELD blend = 0; if (!cv_translucency.value) // translucency disabled { - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } else if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4411,11 +4069,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // 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; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader } } @@ -4456,11 +4114,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // Let dispoffset work first since this adjust each vertex HWR_RotateSpritePolyToAim(spr, wallVerts, true); - wallVerts[0].sow = wallVerts[3].sow = 0; - wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s; + wallVerts[0].s = wallVerts[3].s = 0; + wallVerts[2].s = wallVerts[1].s = gpatch->max_s; - wallVerts[3].tow = wallVerts[2].tow = 0; - wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t; + wallVerts[3].t = wallVerts[2].t = 0; + wallVerts[0].t = wallVerts[1].t = gpatch->max_t; // cache the patch in the graphics card memory //12/12/99: Hurdler: same comment as above (for md2) @@ -4494,15 +4152,12 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) colormap = sector->extra_colormap; } - 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); + HWR_Lighting(&Surf, lightlevel, colormap); } if (spr->mobj->flags2 & MF2_SHADOW) { - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; blend = PF_Translucent; } else if (spr->mobj->frame & FF_TRANSMASK) @@ -4513,11 +4168,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) // 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; + Surf.PolyColor.s.alpha = 0xFF; blend = PF_Translucent|PF_Occlude; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader } #endif @@ -4620,14 +4275,11 @@ static void HWR_SortVisSprites(void) // middle texture. This is used for sorting with sprites. typedef struct { - wallVert3D wallVerts[4]; + FOutVector wallVerts[4]; FSurfaceInfo Surf; INT32 texnum; FBITFIELD blend; INT32 drawcount; -#ifndef SORTING - fixed_t fixedheight; -#endif boolean fogwall; INT32 lightlevel; extracolormap_t *wallcolormap; // Doing the lighting in HWR_RenderWall now for correct fog after sorting @@ -4636,7 +4288,7 @@ typedef struct static wallinfo_t *wallinfo = NULL; static size_t numwalls = 0; // a list of transparent walls to be drawn -static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); +void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); #define MAX_TRANSPARENTWALL 256 @@ -4675,9 +4327,6 @@ typedef struct static size_t numpolyplanes = 0; // a list of transparent poyobject floors to be drawn static polyplaneinfo_t *polyplaneinfo = NULL; -#ifndef SORTING -size_t numfloors = 0; -#else //Hurdler: 3D water sutffs typedef struct gr_drawnode_s { @@ -4695,8 +4344,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, - fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -4727,8 +4375,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, - fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) +void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -4777,6 +4424,8 @@ static void HWR_CreateDrawNodes(void) // If true, swap the draw order. boolean shift = false; + + rs_hw_nodesorttime = I_GetTimeMicros(); for (i = 0; i < numplanes; i++, p++) { @@ -4795,6 +4444,8 @@ static void HWR_CreateDrawNodes(void) sortnode[p].wall = &wallinfo[i]; sortindex[p] = p; } + + rs_numdrawnodes = p; // p is the number of stuff to sort @@ -4897,8 +4548,14 @@ static void HWR_CreateDrawNodes(void) } //i++ } // loop++ - HWD.pfnSetTransform(&atransform); + rs_hw_nodesorttime = I_GetTimeMicros() - rs_hw_nodesorttime; + + rs_hw_nodedrawtime = I_GetTimeMicros(); + // Okay! Let's draw it all! Woo! + HWD.pfnSetTransform(&atransform); + HWD.pfnSetShader(0); + for (i = 0; i < p; i++) { if (sortnode[sortindex[i]].plane) @@ -4909,7 +4566,7 @@ static void HWR_CreateDrawNodes(void) if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat); HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); + sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { @@ -4929,6 +4586,8 @@ static void HWR_CreateDrawNodes(void) sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap); } } + + rs_hw_nodedrawtime = I_GetTimeMicros() - rs_hw_nodedrawtime; numwalls = 0; numplanes = 0; @@ -4939,18 +4598,17 @@ static void HWR_CreateDrawNodes(void) Z_Free(sortindex); } -#endif - // -------------------------------------------------------------------------- // Draw all vissprites // -------------------------------------------------------------------------- -#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(void) { if (gr_visspritecount > 0) { gr_vissprite_t *spr; + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value); // draw all vissprites back to front for (spr = gr_vsprsortedhead.next; @@ -4965,7 +4623,7 @@ static void HWR_DrawSprites(void) { if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value) { - HWR_DrawDropShadow(spr->mobj, spr, spr->mobj->shadowscale); + HWR_DrawDropShadow(spr->mobj, spr->mobj->shadowscale); } if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) @@ -4990,9 +4648,10 @@ static void HWR_DrawSprites(void) } } } + + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, 0); } } -#endif // -------------------------------------------------------------------------- // HWR_AddSprites @@ -5486,7 +5145,7 @@ static void HWR_DrawSkyBackground(player_t *player) //04/01/2000: Hurdler: added for T&L // It should replace all other gr_viewxxx when finished - dometransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + HWR_SetTransformAiming(&dometransform, player, false); dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); if (*type == postimg_flip) @@ -5547,8 +5206,8 @@ static void HWR_DrawSkyBackground(player_t *player) dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left - v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f) + v[0].s = v[3].s = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[2].s = v[1].s = v[0].s + (1.0f/dimensionmultiply); // right (or left + 1.0f) // use +angle and -1.0f above instead if you wanted old backwards behavior // Y @@ -5566,13 +5225,13 @@ static void HWR_DrawSkyBackground(player_t *player) if (atransform.flip) { // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously - v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top - v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) + v[3].t = v[2].t = -(0.5f-(0.5f/dimensionmultiply)); // top + v[0].t = v[1].t = v[3].t - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) } else { - v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom - v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) + v[0].t = v[1].t = -(0.5f-(0.5f/dimensionmultiply)); // bottom + v[3].t = v[2].t = v[0].t - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) } angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; @@ -5580,16 +5239,18 @@ static void HWR_DrawSkyBackground(player_t *player) if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa { angle = InvAngle(angle); - v[3].tow = v[2].tow += ((float) angle / angleturn); - v[0].tow = v[1].tow += ((float) angle / angleturn); + v[3].t = v[2].t += ((float) angle / angleturn); + v[0].t = v[1].t += ((float) angle / angleturn); } else { - v[3].tow = v[2].tow -= ((float) angle / angleturn); - v[0].tow = v[1].tow -= ((float) angle / angleturn); + v[3].t = v[2].t -= ((float) angle / angleturn); + v[0].t = v[1].t -= ((float) angle / angleturn); } + HWD.pfnSetShader(7); // sky shader HWD.pfnDrawPolygon(NULL, v, 4, 0); + HWD.pfnSetShader(0); } } @@ -5653,6 +5314,28 @@ void HWR_SetViewSize(void) HWD.pfnFlushScreenTextures(); } +// Set view aiming, for the sky dome, the skybox, +// and the normal view, all with a single function. +static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox) +{ + // 1 = always on + // 2 = chasecam only + if (cv_grshearing.value == 1 || (cv_grshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))) + { + fixed_t fixedaiming = AIMINGTODY(aimingangle); + trans->viewaiming = FIXED_TO_FLOAT(fixedaiming); + trans->shearing = true; + gr_aimingangle = 0; + } + else + { + trans->shearing = false; + gr_aimingangle = aimingangle; + } + + trans->anglex = (float)(gr_aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); +} + // ========================================================================== // Same as rendering the player view, but from the skybox object // ========================================================================== @@ -5705,16 +5388,16 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) gr_viewsin = FIXED_TO_FLOAT(viewsin); gr_viewcos = FIXED_TO_FLOAT(viewcos); - gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(aimingangle>>ANGLETOFINESHIFT)); - gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(aimingangle>>ANGLETOFINESHIFT)); - //04/01/2000: Hurdler: added for T&L // It should replace all other gr_viewxxx when finished memset(&atransform, 0x00, sizeof(FTransform)); - atransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + HWR_SetTransformAiming(&atransform, player, true); atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gr_aimingangle>>ANGLETOFINESHIFT)); + gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(gr_aimingangle>>ANGLETOFINESHIFT)); + if (*type == postimg_flip) atransform.flip = true; else @@ -5726,6 +5409,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) atransform.scalex = 1; atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; + atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails if (player->viewrollangle != 0) @@ -5741,14 +5425,6 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) //------------------------------------------------------------------------ HWR_ClearView(); -if (0) -{ // I don't think this is ever used. - if (cv_grfog.value) - HWR_FoggingOn(); // First of all, turn it on, set the default user settings too - else - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off -} - if (drawsky) HWR_DrawSkyBackground(player); @@ -5757,13 +5433,12 @@ if (0) HWR_ClearSprites(); -#ifdef SORTING drawcount = 0; -#endif + #ifdef NEWCLIP if (rendermode == render_opengl) { - angle_t a1 = gld_FrustumAngle(); + angle_t a1 = gld_FrustumAngle(gr_aimingangle); gld_clipper_Clear(); gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); #ifdef HAVE_SPHEREFRUSTRUM @@ -5778,8 +5453,15 @@ if (0) // Actually it only works on Walls and Planes HWD.pfnSetTransform(&atransform); + // Reset the shader state. + HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); + HWD.pfnSetShader(0); + validcount++; + if (cv_grbatching.value) + HWR_StartBatching(); + HWR_RenderBSPNode((INT32)numnodes-1); #ifndef NEWCLIP @@ -5790,14 +5472,14 @@ if (0) viewangle = localaiming2; // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) + if ((gr_aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //left dup_viewangle += ANGLE_90; - if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) + if (((INT32)gr_aimingangle > ANGLE_45 || (INT32)gr_aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //back @@ -5811,6 +5493,9 @@ if (0) } #endif + if (cv_grbatching.value) + HWR_RenderBatches(); + // Check for new console commands. NetUpdate(); @@ -5821,39 +5506,21 @@ if (0) #endif // Draw MD2 and sprites -#ifdef SORTING HWR_SortVisSprites(); -#endif - -#ifdef SORTING HWR_DrawSprites(); -#endif + #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? HWR_DrawCoronas(); #endif -#ifdef SORTING if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything { HWR_CreateDrawNodes(); } -#else - if (numfloors || numwalls) - { - HWD.pfnSetTransform(&atransform); - if (numfloors) - HWR_Render3DWater(); - if (numwalls) - HWR_RenderTransparentWalls(); - } -#endif HWD.pfnSetTransform(NULL); - - // put it off for menus etc - if (cv_grfog.value) - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); + HWD.pfnUnSetShader(); // Check for new console commands. NetUpdate(); @@ -5885,6 +5552,9 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) ClearColor.blue = 0.0f; ClearColor.alpha = 1.0f; + if (cv_grshaders.value) + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime. + if (viewnumber == 0) // Only do it if it's the first screen being rendered HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. @@ -5931,16 +5601,16 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) gr_viewsin = FIXED_TO_FLOAT(viewsin); gr_viewcos = FIXED_TO_FLOAT(viewcos); - gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(aimingangle>>ANGLETOFINESHIFT)); - gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(aimingangle>>ANGLETOFINESHIFT)); - //04/01/2000: Hurdler: added for T&L // It should replace all other gr_viewxxx when finished memset(&atransform, 0x00, sizeof(FTransform)); - atransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + HWR_SetTransformAiming(&atransform, player, false); atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gr_aimingangle>>ANGLETOFINESHIFT)); + gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(gr_aimingangle>>ANGLETOFINESHIFT)); + if (*type == postimg_flip) atransform.flip = true; else @@ -5952,6 +5622,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) atransform.scalex = 1; atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; + atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails if (player->viewrollangle != 0) @@ -5967,14 +5638,6 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) //------------------------------------------------------------------------ HWR_ClearView(); // Clears the depth buffer and resets the view I believe -if (0) -{ // I don't think this is ever used. - if (cv_grfog.value) - HWR_FoggingOn(); // First of all, turn it on, set the default user settings too - else - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); // Turn it off -} - if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox HWR_DrawSkyBackground(player); @@ -5983,13 +5646,12 @@ if (0) HWR_ClearSprites(); -#ifdef SORTING drawcount = 0; -#endif + #ifdef NEWCLIP if (rendermode == render_opengl) { - angle_t a1 = gld_FrustumAngle(); + angle_t a1 = gld_FrustumAngle(gr_aimingangle); gld_clipper_Clear(); gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); #ifdef HAVE_SPHEREFRUSTRUM @@ -6004,8 +5666,19 @@ if (0) // Actually it only works on Walls and Planes HWD.pfnSetTransform(&atransform); + // Reset the shader state. + HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); + HWD.pfnSetShader(0); + + rs_numbspcalls = 0; + rs_numpolyobjects = 0; + rs_bsptime = I_GetTimeMicros(); + validcount++; + if (cv_grbatching.value) + HWR_StartBatching(); + HWR_RenderBSPNode((INT32)numnodes-1); #ifndef NEWCLIP @@ -6016,14 +5689,14 @@ if (0) viewangle = localaiming2; // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) + if ((gr_aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //left dup_viewangle += ANGLE_90; - if (((INT32)aimingangle > ANGLE_45 || (INT32)aimingangle<-ANGLE_45)) + if (((INT32)gr_aimingangle > ANGLE_45 || (INT32)gr_aimingangle<-ANGLE_45)) { HWR_ClearClipSegs(); HWR_RenderBSPNode((INT32)numnodes-1); //back @@ -6037,6 +5710,11 @@ if (0) } #endif + rs_bsptime = I_GetTimeMicros() - rs_bsptime; + + if (cv_grbatching.value) + HWR_RenderBatches(); + // Check for new console commands. NetUpdate(); @@ -6047,39 +5725,29 @@ if (0) #endif // Draw MD2 and sprites -#ifdef SORTING + rs_numsprites = gr_visspritecount; + rs_hw_spritesorttime = I_GetTimeMicros(); HWR_SortVisSprites(); -#endif - -#ifdef SORTING + rs_hw_spritesorttime = I_GetTimeMicros() - rs_hw_spritesorttime; + rs_hw_spritedrawtime = I_GetTimeMicros(); HWR_DrawSprites(); -#endif + rs_hw_spritedrawtime = I_GetTimeMicros() - rs_hw_spritedrawtime; + #ifdef NEWCORONAS //Hurdler: they must be drawn before translucent planes, what about gl fog? HWR_DrawCoronas(); #endif -#ifdef SORTING + rs_numdrawnodes = 0; + rs_hw_nodesorttime = 0; + rs_hw_nodedrawtime = 0; if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything { HWR_CreateDrawNodes(); } -#else - if (numfloors || numpolyplanes || numwalls) - { - HWD.pfnSetTransform(&atransform); - if (numfloors) - HWR_Render3DWater(); - if (numwalls) - HWR_RenderTransparentWalls(); - } -#endif HWD.pfnSetTransform(NULL); - - // put it off for menus etc - if (cv_grfog.value) - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 0); + HWD.pfnUnSetShader(); HWR_DoPostProcessor(player); @@ -6091,60 +5759,16 @@ if (0) HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE); } -// ========================================================================== -// FOG -// ========================================================================== - -/// \author faB - -static UINT32 atohex(const char *s) -{ - INT32 iCol; - const char *sCol; - char cCol; - INT32 i; - - if (strlen(s)<6) - return 0; - - iCol = 0; - sCol = s; - for (i = 0; i < 6; i++, sCol++) - { - iCol <<= 4; - cCol = *sCol; - if (cCol >= '0' && cCol <= '9') - iCol |= cCol - '0'; - else - { - if (cCol >= 'F') - cCol -= 'a' - 'A'; - if (cCol >= 'A' && cCol <= 'F') - iCol = iCol | (cCol - 'A' + 10); - } - } - //CONS_Debug(DBG_RENDER, "col %x\n", iCol); - return iCol; -} - -static void HWR_FoggingOn(void) -{ - HWD.pfnSetSpecialState(HWD_SET_FOG_COLOR, atohex(cv_grfogcolor.string)); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); - HWD.pfnSetSpecialState(HWD_SET_FOG_MODE, 1); -} - // ========================================================================== // 3D ENGINE COMMANDS // ========================================================================== -static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}}; static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}}; +static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}}; +static CV_PossibleValue_t grshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}}; -static void CV_grmodellighting_OnChange(void); static void CV_grfiltermode_OnChange(void); static void CV_granisotropic_OnChange(void); -static void CV_grfogdensity_OnChange(void); static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, @@ -6154,10 +5778,8 @@ static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA {0, NULL}}; CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; +consvar_t cv_grshaders = {"gr_shaders", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef ALAM_LIGHTING consvar_t cv_grdynamiclighting = {"gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6168,15 +5790,13 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0, NULL, 0, consvar_t cv_grmodels = {"gr_models", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grmodelinterpolation = {"gr_modelinterpolation", "Sometimes", CV_SAVE, grmodelinterpolation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_grmodellighting_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grshearing = {"gr_shearing", "Off", CV_SAVE, grshearing_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfakecontrast = {"gr_fakecontrast", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned, - CV_grfogdensity_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grfakecontrast = {"gr_fakecontrast", "Smooth", CV_SAVE, grfakecontrast_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_grslopecontrast = {"gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_SAVE|CV_CALL, grfiltermode_cons_t, CV_grfiltermode_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -6186,17 +5806,7 @@ consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL, granisotro 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_grmodellighting_OnChange(void) -{ - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value); -} - -static void CV_grfogdensity_OnChange(void) -{ - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); -} +consvar_t cv_grbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static void CV_grfiltermode_OnChange(void) { @@ -6215,11 +5825,6 @@ void HWR_AddCommands(void) { CV_RegisterVar(&cv_fovchange); - CV_RegisterVar(&cv_grfogdensity); - CV_RegisterVar(&cv_grfogcolor); - CV_RegisterVar(&cv_grfog); - CV_RegisterVar(&cv_grsoftwarefog); - #ifdef ALAM_LIGHTING CV_RegisterVar(&cv_grstaticlighting); CV_RegisterVar(&cv_grdynamiclighting); @@ -6234,11 +5839,15 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_grskydome); CV_RegisterVar(&cv_grspritebillboarding); CV_RegisterVar(&cv_grfakecontrast); + CV_RegisterVar(&cv_grshearing); + CV_RegisterVar(&cv_grshaders); CV_RegisterVar(&cv_grfiltermode); - CV_RegisterVar(&cv_grrounddown); CV_RegisterVar(&cv_grcorrecttricks); CV_RegisterVar(&cv_grsolvetjoin); + + CV_RegisterVar(&cv_renderstats); + CV_RegisterVar(&cv_grbatching); #ifndef NEWCLIP CV_RegisterVar(&cv_grclipwalls); @@ -6263,17 +5872,12 @@ void HWR_Startup(void) { static boolean startupdone = false; - // setup GLPatch_t scaling - gr_patch_scalex = (float)(1.0f / vid.width); - gr_patch_scaley = (float)(1.0f / vid.height); - - // initalze light lut translation - InitLumLut(); - // do this once if (!startupdone) { + INT32 i; CONS_Printf("HWR_Startup()...\n"); + HWR_InitPolyPool(); HWR_AddSessionCommands(); HWR_InitTextureCache(); @@ -6281,6 +5885,12 @@ void HWR_Startup(void) #ifdef ALAM_LIGHTING HWR_InitLight(); #endif + + // read every custom shader + for (i = 0; i < numwadfiles; i++) + HWR_ReadShaders(i, (wadfiles[i]->type == RET_PK3)); + if (!HWR_LoadShaders()) + gr_shadersavailable = false; } if (rendermode == render_opengl) @@ -6295,8 +5905,6 @@ void HWR_Startup(void) void HWR_Switch(void) { // Set special states from CVARs - HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value); - HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); } @@ -6336,106 +5944,7 @@ void transform(float *cx, float *cy, float *cz) *cx *= gr_fovlud; } - -//Hurdler: 3D Water stuff -#ifndef SORTING - -#define MAX_3DWATER 512 - -static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, - fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector) -{ - static size_t allocedplanes = 0; - - // Force realloc if buffer has been freed - if (!planeinfo) - allocedplanes = 0; - - if (allocedplanes < numfloors + 1) - { - allocedplanes += MAX_3DWATER; - Z_Realloc(planeinfo, allocedplanes * sizeof (*planeinfo), PU_LEVEL, &planeinfo); - } - planeinfo[numfloors].fixedheight = fixedheight; - planeinfo[numfloors].lightlevel = lightlevel; - planeinfo[numfloors].levelflat = levelflat; - planeinfo[numfloors].xsub = xsub; - planeinfo[numfloors].alpha = alpha; - planeinfo[numfloors].FOFSector = FOFSector; - numfloors++; -} - -#define DIST_PLANE(i) ABS(planeinfo[(i)].fixedheight-dup_viewz) - -static void HWR_QuickSortPlane(INT32 start, INT32 finish) -{ - INT32 left = start; - INT32 right = finish; - INT32 starterval = (INT32)((right+left)/2); //pick a starter - - planeinfo_t temp; - - //'sort of sort' the two halves of the data list about starterval - while (right > left); - { - while (DIST_PLANE(left) < DIST_PLANE(starterval)) left++; //attempt to find a bigger value on the left - while (DIST_PLANE(right) > DIST_PLANE(starterval)) right--; //attempt to find a smaller value on the right - - if (left < right) //if we haven't gone too far - { - //switch them - M_Memcpy(&temp, &planeinfo[left], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[left], &planeinfo[right], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[right], &temp, sizeof (planeinfo_t)); - //move the bounds - left++; - right--; - } - } - - if (start < right) HWR_QuickSortPlane(start, right); - if (left < finish) HWR_QuickSortPlane(left, finish); -} - -static void HWR_Render3DWater(void) -{ - size_t i; - - //bubble sort 3D Water for correct alpha blending - { - boolean permut = true; - while (permut) - { - size_t j; - for (j = 0, permut= false; j < numfloors-1; j++) - { - if (ABS(planeinfo[j].fixedheight-dup_viewz) < ABS(planeinfo[j+1].fixedheight-dup_viewz)) - { - planeinfo_t temp; - M_Memcpy(&temp, &planeinfo[j+1], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[j+1], &planeinfo[j], sizeof (planeinfo_t)); - M_Memcpy(&planeinfo[j], &temp, sizeof (planeinfo_t)); - permut = true; - } - } - } - } -#if 0 //thanks epat, but it's goes looping forever on CTF map Silver Cascade Zone - HWR_QuickSortPlane(0, numplanes-1); -#endif - - gr_frontsector = NULL; //Hurdler: gr_fronsector is no longer valid - for (i = 0; i < numfloors; i++) - { - HWR_GetLevelFlat(planeinfo[i].levelflat); - HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].levelflat, - planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap); - } - numfloors = 0; -} -#endif - -static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) +void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { static size_t allocedwalls = 0; @@ -6453,103 +5962,43 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I M_Memcpy(&wallinfo[numwalls].Surf, pSurf, sizeof (FSurfaceInfo)); wallinfo[numwalls].texnum = texnum; wallinfo[numwalls].blend = blend; -#ifdef SORTING wallinfo[numwalls].drawcount = drawcount++; -#endif wallinfo[numwalls].fogwall = fogwall; wallinfo[numwalls].lightlevel = lightlevel; wallinfo[numwalls].wallcolormap = wallcolormap; numwalls++; } -#ifndef SORTING -static void HWR_RenderTransparentWalls(void) +void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { - size_t i; + FBITFIELD blendmode = blend; + UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha - /*{ // sorting is disbale for now, do it! - INT32 permut = 1; - while (permut) - { - INT32 j; - for (j = 0, permut = 0; j < numwalls-1; j++) - { - if (ABS(wallinfo[j].fixedheight-dup_viewz) < ABS(wallinfo[j+1].fixedheight-dup_viewz)) - { - wallinfo_t temp; - M_Memcpy(&temp, &wallinfo[j+1], sizeof (wallinfo_t)); - M_Memcpy(&wallinfo[j+1], &wallinfo[j], sizeof (wallinfo_t)); - M_Memcpy(&wallinfo[j], &temp, sizeof (wallinfo_t)); - permut = 1; - } - } - } - }*/ - - for (i = 0; i < numwalls; i++) - { - HWR_GetTexture(wallinfo[i].texnum); - HWR_RenderWall(wallinfo[i].wallVerts, &wallinfo[i].Surf, wallinfo[i].blend, wallinfo[i].wall->fogwall, wallinfo[i].wall->lightlevel, wallinfo[i].wall->wallcolormap); - } - numwalls = 0; -} -#endif - -static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) -{ - FOutVector trVerts[4]; - UINT8 i; - FOutVector *wv; - UINT8 alpha; - - // transform - wv = trVerts; - // it sounds really stupid to do this conversion with the new T&L code - // we should directly put the right information in the right structure - // wallVerts3D seems ok, doesn't need FOutVector - // also remove the light copy - for (i = 0; i < 4; i++, wv++, wallVerts++) - { - wv->sow = wallVerts->s; - wv->tow = wallVerts->t; - wv->x = wallVerts->x; - wv->y = wallVerts->y; - wv->z = wallVerts->z; - } - - alpha = pSurf->FlatColor.s.alpha; // retain the alpha + int shader; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting - if (wallcolormap) - { - if (fogwall) - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, true, false); - else - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, wallcolormap->rgba, wallcolormap->fadergba, false, false); - } - else - { - if (fogwall) - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, true, false); - else - pSurf->FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); - } + HWR_Lighting(pSurf, lightlevel, wallcolormap); - pSurf->FlatColor.s.alpha = alpha; // put the alpha back after lighting + pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting + + shader = 2; // wall shader if (blend & PF_Environment) - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip|PF_Occlude); // PF_Occlude must be used for solid objects - else - HWD.pfnDrawPolygon(pSurf, trVerts, 4, blend|PF_Modulated|PF_Clip); // No PF_Occlude means overlapping (incorrect) transparency + blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects + + if (fogwall) + { + blendmode |= PF_Fog; + shader = 6; // fog shader + } + + blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency + + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false); #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); - -#ifdef ALAM_LIGHTING - //Hurdler: TODO: do static lighting using gr_curline->lm - HWR_WallLighting(trVerts); -#endif #endif } @@ -6562,6 +6011,8 @@ void HWR_DoPostProcessor(player_t *player) { postimg_t *type; + HWD.pfnUnSetShader(); + if (splitscreen && player == &players[secondarydisplayplayer]) type = &postimgtype2; else @@ -6581,13 +6032,13 @@ void HWR_DoPostProcessor(player_t *player) // This won't change if the flash palettes are changed unfortunately, but it works for its purpose if (player->flashpal == PAL_NUKE) { - Surf.FlatColor.s.red = 0xff; - Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0x7F; // The nuke palette is kind of pink-ish + Surf.PolyColor.s.red = 0xff; + Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0x7F; // The nuke palette is kind of pink-ish } else - Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = 0xff; + Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - Surf.FlatColor.s.alpha = 0xc0; // match software mode + Surf.PolyColor.s.alpha = 0xc0; // match software mode HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip); } @@ -6634,7 +6085,8 @@ void HWR_DoPostProcessor(player_t *player) } } HWD.pfnPostImgRedraw(v); - disStart += 1; + if (!(paused || P_AutoPause())) + disStart += 1; // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) @@ -6721,4 +6173,161 @@ void HWR_DrawScreenFinalTexture(int width, int height) HWD.pfnDrawScreenFinalTexture(width, height); } +// jimita 18032019 +typedef struct +{ + char type[16]; + INT32 id; +} shaderxlat_t; + +static inline UINT16 HWR_CheckShader(UINT16 wadnum) +{ + UINT16 i; + lumpinfo_t *lump_p; + + lump_p = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name, "SHADERS", 7) == 0) + return i; + + return INT16_MAX; +} + +boolean HWR_LoadShaders(void) +{ + return HWD.pfnInitCustomShaders(); +} + +void HWR_ReadShaders(UINT16 wadnum, boolean PK3) +{ + UINT16 lump; + char *shaderdef, *line; + char *stoken; + char *value; + size_t size; + int linenum = 1; + int shadertype = 0; + int i; + + #define SHADER_TYPES 7 + shaderxlat_t shaderxlat[SHADER_TYPES] = + { + {"Flat", 1}, + {"WallTexture", 2}, + {"Sprite", 3}, + {"Model", 4}, + {"WaterRipple", 5}, + {"Fog", 6}, + {"Sky", 7}, + }; + + lump = HWR_CheckShader(wadnum); + if (lump == INT16_MAX) + return; + + shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + line = Z_Malloc(size+1, PU_STATIC, NULL); + M_Memcpy(line, shaderdef, size); + line[size] = '\0'; + + stoken = strtok(line, "\r\n "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); + goto skip_field; + } + + if (!stricmp(stoken, "GLSL")) + { + value = strtok(NULL, "\r\n "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_lump; + } + + if (!stricmp(value, "VERTEX")) + shadertype = 1; + else if (!stricmp(value, "FRAGMENT")) + shadertype = 2; + +skip_lump: + stoken = strtok(NULL, "\r\n "); + linenum++; + } + else + { + value = strtok(NULL, "\r\n= "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_field; + } + + if (!shadertype) + { + CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + Z_Free(line); + return; + } + + for (i = 0; i < SHADER_TYPES; i++) + { + if (!stricmp(shaderxlat[i].type, stoken)) + { + size_t shader_size; + char *shader_source; + char *shader_lumpname; + UINT16 shader_lumpnum; + + if (PK3) + { + shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL); + strcpy(shader_lumpname, "Shaders/sh_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0); + } + else + { + shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL); + strcpy(shader_lumpname, "SH_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0); + } + + if (shader_lumpnum == INT16_MAX) + { + CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); + Z_Free(shader_lumpname); + continue; + } + + shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum); + shader_source = Z_Malloc(shader_size, PU_STATIC, NULL); + W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source); + + HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2)); + + Z_Free(shader_source); + Z_Free(shader_lumpname); + } + } + +skip_field: + stoken = strtok(NULL, "\r\n= "); + linenum++; + } + } + + Z_Free(line); + return; +} + #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ec5362194..21bd7ddb3 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,20 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_main.h /// \brief 3D render mode functions #ifndef __HWR_MAIN_H__ @@ -73,8 +66,11 @@ void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); // This stuff is put here so MD2's can use them -UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); -FUNCMATH UINT8 LightLevelToLum(INT32 l); +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); +UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work + +void HWR_ReadShaders(UINT16 wadnum, boolean PK3); +boolean HWR_LoadShaders(void); extern CV_PossibleValue_t granisotropicmode_cons_t[]; @@ -84,21 +80,23 @@ extern consvar_t cv_grstaticlighting; extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronasize; #endif + +extern consvar_t cv_grshaders; extern consvar_t cv_grmodels; extern consvar_t cv_grmodelinterpolation; extern consvar_t cv_grmodellighting; -extern consvar_t cv_grfog; -extern consvar_t cv_grfogcolor; -extern consvar_t cv_grfogdensity; -extern consvar_t cv_grsoftwarefog; extern consvar_t cv_grfiltermode; extern consvar_t cv_granisotropicmode; extern consvar_t cv_grcorrecttricks; extern consvar_t cv_fovchange; extern consvar_t cv_grsolvetjoin; +extern consvar_t cv_grshearing; extern consvar_t cv_grspritebillboarding; extern consvar_t cv_grskydome; extern consvar_t cv_grfakecontrast; +extern consvar_t cv_grslopecontrast; + +extern consvar_t cv_grbatching; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; @@ -108,4 +106,24 @@ extern float gr_viewwindowx, gr_basewindowcentery; extern fixed_t *hwbbox; extern FTransform atransform; + +// Render stats +extern int rs_hw_nodesorttime; +extern int rs_hw_nodedrawtime; +extern int rs_hw_spritesorttime; +extern int rs_hw_spritedrawtime; + +// Render stats for batching +extern int rs_hw_numpolys; +extern int rs_hw_numverts; +extern int rs_hw_numcalls; +extern int rs_hw_numshaders; +extern int rs_hw_numtextures; +extern int rs_hw_numpolyflags; +extern int rs_hw_numcolors; +extern int rs_hw_batchsorttime; +extern int rs_hw_batchdrawtime; + +extern boolean gr_shadersavailable; + #endif diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index e4ea26d86..76c7f89b4 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,23 +1,16 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief MD2 Handling +/// \file hw_md2.c +/// \brief 3D Model Handling /// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch) - #ifdef __GNUC__ #include #endif @@ -400,13 +393,6 @@ static void md2_loadTexture(md2_t *model) V_CubeApply(&image->s.red, &image->s.green, &image->s.blue); image++; } - -#ifdef GLIDE_API_COMPATIBILITY - // not correct! - grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif } HWD.pfnSetTexture(grpatch->mipmap); } @@ -455,13 +441,6 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->height = (INT16)h; grpatch->mipmap->width = (UINT16)w; grpatch->mipmap->height = (UINT16)h; - -#ifdef GLIDE_API_COMPATIBILITY - // not correct! - grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; -#endif } HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary @@ -949,11 +928,19 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, blendcolor = V_GetColor(translation[firsti]); + if (secondi >= translen) + mul = 0; + if (mul > 0) // If it's 0, then we only need the first color. { - if (secondi >= translen) // blend to black +#if 0 + if (secondi >= translen) + { + // blend to black nextcolor = V_GetColor(31); + } else +#endif nextcolor = V_GetColor(translation[secondi]); // Find difference between points @@ -1188,15 +1175,14 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t boolean HWR_DrawModel(gr_vissprite_t *spr) { - FSurfaceInfo Surf; + md2_t *md2; char filename[64]; INT32 frame = 0; INT32 nextFrame = -1; UINT8 spr2 = 0; FTransform p; - md2_t *md2; - UINT8 color[4]; + FSurfaceInfo Surf; if (!cv_grmodels.value) return false; @@ -1235,13 +1221,10 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) colormap = sector->extra_colormap; } - 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); + HWR_Lighting(&Surf, lightlevel, colormap); } else - Surf.FlatColor.rgba = 0xFFFFFFFF; + Surf.PolyColor.rgba = 0xFFFFFFFF; // Look at HWR_ProjectSprite for more { @@ -1263,11 +1246,11 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) //durs = tics; if (spr->mobj->flags2 & MF2_SHADOW) - Surf.FlatColor.s.alpha = 0x40; + Surf.PolyColor.s.alpha = 0x40; else if (spr->mobj->frame & FF_TRANSMASK) HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); else - Surf.FlatColor.s.alpha = 0xFF; + Surf.PolyColor.s.alpha = 0xFF; // dont forget to enabled the depth test because we can't do this like // before: polygons models are not sorted @@ -1512,11 +1495,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) } #endif - color[0] = Surf.FlatColor.s.red; - color[1] = Surf.FlatColor.s.green; - color[2] = Surf.FlatColor.s.blue; - color[3] = Surf.FlatColor.s.alpha; - // SRB2CBTODO: MD2 scaling support finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); @@ -1525,7 +1503,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) p.mirror = atransform.mirror; // from Kart #endif - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color); + HWD.pfnSetShader(4); // model shader + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf); } return true; diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 3bbe30053..faa91caee 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -1,21 +1,14 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief MD2 Handling +/// \file hw_md2.h +/// \brief 3D Model Handling /// Inspired from md2.h by Mete Ciragan (mete@swissquake.ch) #ifndef _HW_MD2_H_ diff --git a/src/hardware/hws_data.h b/src/hardware/hws_data.h index b890d976b..a8607ac67 100644 --- a/src/hardware/hws_data.h +++ b/src/hardware/hws_data.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 2005 by Sonic Team Junior. // -// Copyright (C) 2005 by SRB2 Jr. Team. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hws_data.h /// \brief 3D sound definitions #ifndef __HWS_DATA_H__ diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index e4a71734b..c9bf60144 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -206,7 +206,7 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth if (iLastPFD) { - DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n"); + GL_DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n"); } // set the pixel format only if different than the current @@ -215,17 +215,17 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth else iLastPFD = iPFD; - DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n", + GL_DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n", WantColorBits, WantStencilBits, WantDepthBits); nPixelFormat = ChoosePixelFormat(hDC, &pfd); if (nPixelFormat == 0) - DBG_Printf("ChoosePixelFormat() FAILED\n"); + GL_DBG_Printf("ChoosePixelFormat() FAILED\n"); if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0) { - DBG_Printf("SetPixelFormat() FAILED\n"); + GL_DBG_Printf("SetPixelFormat() FAILED\n"); return 0; } @@ -243,7 +243,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN); UNREFERENCED_PARAMETER(pcurrentmode); - DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", + GL_DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", lvid->width, lvid->height, lvid->bpp*8, WantFullScreen ? "fullscreen" : "windowed"); @@ -301,7 +301,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) hDC = GetDC(hWnd); if (!hDC) { - DBG_Printf("GetDC() FAILED\n"); + GL_DBG_Printf("GetDC() FAILED\n"); return 0; } @@ -321,12 +321,12 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) hGLRC = pwglCreateContext(hDC); if (!hGLRC) { - DBG_Printf("pwglCreateContext() FAILED\n"); + GL_DBG_Printf("pwglCreateContext() FAILED\n"); return 0; } if (!pwglMakeCurrent(hDC, hGLRC)) { - DBG_Printf("wglMakeCurrent() FAILED\n"); + GL_DBG_Printf("wglMakeCurrent() FAILED\n"); return 0; } } @@ -337,15 +337,15 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) //BP: why don't we make it earlier ? //Hurdler: we cannot do that before intialising gl context renderer = (LPCSTR)pglGetString(GL_RENDERER); - DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR)); - DBG_Printf("Renderer : %s\n", renderer); - DBG_Printf("Version : %s\n", pglGetString(GL_VERSION)); - DBG_Printf("Extensions : %s\n", gl_extensions); + GL_DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR)); + GL_DBG_Printf("Renderer : %s\n", renderer); + GL_DBG_Printf("Version : %s\n", pglGetString(GL_VERSION)); + GL_DBG_Printf("Extensions : %s\n", gl_extensions); // BP: disable advenced feature that don't work on somes hardware // Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04 if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD; - DBG_Printf("oglflags : 0x%X\n", oglflags); + GL_DBG_Printf("oglflags : 0x%X\n", oglflags); #ifdef USE_WGL_SWAP if (isExtAvailable("WGL_EXT_swap_control",gl_extensions)) @@ -386,7 +386,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) // -----------------+ static void UnSetRes(void) { - DBG_Printf("UnSetRes()\n"); + GL_DBG_Printf("UnSetRes()\n"); pwglMakeCurrent(hDC, NULL); pwglDeleteContext(hGLRC); @@ -437,7 +437,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) video_modes[iMode].misc = 0; video_modes[iMode].name = malloc(12 * sizeof (CHAR)); sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight); - DBG_Printf ("Mode: %s\n", video_modes[iMode].name); + GL_DBG_Printf ("Mode: %s\n", video_modes[iMode].name); video_modes[iMode].width = Tmp.dmPelsWidth; video_modes[iMode].height = Tmp.dmPelsHeight; video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8; @@ -474,7 +474,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) HDC bpphdc; INT32 iBitsPerPel; - DBG_Printf ("HWRAPI GetModeList()\n"); + GL_DBG_Printf ("HWRAPI GetModeList()\n"); bpphdc = GetDC(NULL); // on obtient le bpp actuel iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL); @@ -490,7 +490,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) video_modes[i].misc = 0; video_modes[i].name = malloc(12 * sizeof (CHAR)); sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]); - DBG_Printf ("Mode: %s\n", video_modes[i].name); + GL_DBG_Printf ("Mode: %s\n", video_modes[i].name); video_modes[i].width = res[i][0]; video_modes[i].height = res[i][1]; video_modes[i].bytesperpixel = iBitsPerPel/8; @@ -511,9 +511,9 @@ EXPORT void HWRAPI(Shutdown) (void) #ifdef DEBUG_TO_FILE long nb_centiemes; - DBG_Printf ("HWRAPI Shutdown()\n"); + GL_DBG_Printf ("HWRAPI Shutdown()\n"); nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC; - DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n", + GL_DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n", nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes); #endif @@ -530,7 +530,7 @@ EXPORT void HWRAPI(Shutdown) (void) } FreeLibrary(GLU32); FreeLibrary(OGL32); - DBG_Printf ("HWRAPI Shutdown(DONE)\n"); + GL_DBG_Printf ("HWRAPI Shutdown(DONE)\n"); } // -----------------+ @@ -543,7 +543,7 @@ EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl) #else UNREFERENCED_PARAMETER(waitvbl); #endif - // DBG_Printf ("FinishUpdate()\n"); + // GL_DBG_Printf ("FinishUpdate()\n"); #ifdef DEBUG_TO_FILE if ((++nb_frames)==2) // on ne commence pas � la premi�re frame my_clock = clock(); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 73f6a4044..41ec703bc 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2020 by Sonic Team Junior. // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file r_opengl.c /// \brief OpenGL API for Sonic Robo Blast 2 #if defined (_WIN32) @@ -64,10 +56,6 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; -#if 0 -static GLuint pal_col = 0; -static FRGBAFloat const_pal_col; -#endif static FBITFIELD CurrentPolyFlags; static FTextureInfo *gr_cachetail = NULL; @@ -83,14 +71,16 @@ static GLboolean MipMap = GL_FALSE; static GLint min_filter = GL_LINEAR; static GLint mag_filter = GL_LINEAR; static GLint anisotropic_filter = 0; -static boolean model_lighting = true; +static boolean model_lighting = false; +const GLubyte *gl_version = NULL; +const GLubyte *gl_renderer = NULL; const GLubyte *gl_extensions = NULL; //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) -static GLfloat modelMatrix[16]; -static GLfloat projMatrix[16]; -static GLint viewport[4]; +static GLfloat modelMatrix[16]; +static GLfloat projMatrix[16]; +static GLint viewport[4]; // 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 @@ -100,9 +90,10 @@ static GLuint screentexture = 0; static GLuint startScreenWipe = 0; static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; -#if 0 -GLuint screentexture = FIRST_TEX_AVAIL; -#endif + +// Lactozilla: Set shader programs and uniforms +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { @@ -140,31 +131,82 @@ static const GLfloat byte2float[256] = { 0.972549f, 0.976471f, 0.980392f, 0.984314f, 0.988235f, 0.992157f, 0.996078f, 1.000000f }; -float byteasfloat(UINT8 fbyte) -{ - return (float)(byte2float[fbyte]*2.0f); -} - -static I_Error_t I_Error_GL = NULL; - // -----------------+ -// DBG_Printf : Output error messages to debug log if DEBUG_TO_FILE is defined, +// GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, // : else do nothing // Returns : // -----------------+ -FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) + +#ifdef DEBUG_TO_FILE +FILE *gllogstream; +#endif + +FUNCPRINTF void GL_DBG_Printf(const char *format, ...) { #ifdef DEBUG_TO_FILE - char str[4096] = ""; + char str[4096] = ""; va_list arglist; - va_start (arglist, lpFmt); - vsnprintf (str, 4096, lpFmt, arglist); - va_end (arglist); - if (gllogstream) - fwrite(str, strlen(str), 1, gllogstream); + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + + fwrite(str, strlen(str), 1, gllogstream); #else - (void)lpFmt; + (void)format; +#endif +} + +// -----------------+ +// GL_MSG_Warning : Raises a warning. +// : +// Returns : +// -----------------+ + +static void GL_MSG_Warning(const char *format, ...) +{ + char str[4096] = ""; + va_list arglist; + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_WARNING, "%s", str); +#endif +#ifdef DEBUG_TO_FILE + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); +#endif +} + +// -----------------+ +// GL_MSG_Error : Raises an error. +// : +// Returns : +// -----------------+ + +static void GL_MSG_Error(const char *format, ...) +{ + char str[4096] = ""; + va_list arglist; + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_ERROR, "%s", str); +#endif +#ifdef DEBUG_TO_FILE + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); #endif } @@ -219,6 +261,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglLightfv glLightfv #define pglLightModelfv glLightModelfv #define pglMaterialfv glMaterialfv +#define pglMateriali glMateriali /* Raster functions */ #define pglPixelStorei glPixelStorei @@ -228,10 +271,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D - -/* Fog */ -#define pglFogf glFogf -#define pglFogfv glFogfv +#define pglTexSubImage2D glTexSubImage2D /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -248,7 +288,6 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) /* Miscellaneous */ typedef void (APIENTRY * PFNglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); static PFNglClearColor pglClearColor; -//glClear typedef void (APIENTRY * PFNglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); static PFNglColorMask pglColorMask; typedef void (APIENTRY * PFNglAlphaFunc) (GLenum func, GLclampf ref); @@ -267,8 +306,6 @@ typedef void (APIENTRY * PFNglDisable) (GLenum cap); static PFNglDisable pglDisable; typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params); static PFNglGetFloatv pglGetFloatv; -//glGetIntegerv -//glGetString /* Depth Buffer */ typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth); @@ -329,6 +366,8 @@ typedef void (APIENTRY * PFNglLightModelfv) (GLenum pname, GLfloat *params); static PFNglLightModelfv pglLightModelfv; typedef void (APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *params); static PFNglMaterialfv pglMaterialfv; +typedef void (APIENTRY * PFNglMateriali) (GLint face, GLenum pname, GLint param); +static PFNglMateriali pglMateriali; /* Raster functions */ typedef void (APIENTRY * PFNglPixelStorei) (GLenum pname, GLint param); @@ -343,12 +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; - -/* Fog */ -typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); -static PFNglFogf pglFogf; -typedef void (APIENTRY * PFNglFogfv) (GLenum pname, const GLfloat *params); -static PFNglFogfv pglFogfv; +typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexSubImage2D pglTexSubImage2D; /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -424,7 +459,7 @@ boolean SetupGLfunc(void) func = GetGLFunc(#proc); \ if (!func) \ { \ - DBG_Printf("failed to get OpenGL function: %s", #proc); \ + GL_MSG_Warning("failed to get OpenGL function: %s", #proc); \ } \ GETOPENGLFUNC(pglClearColor, glClearColor) @@ -442,22 +477,23 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv) GETOPENGLFUNC(pglGetString, glGetString) - GETOPENGLFUNC(pglClearDepth , glClearDepth) - GETOPENGLFUNC(pglDepthFunc , glDepthFunc) - GETOPENGLFUNC(pglDepthMask , glDepthMask) - GETOPENGLFUNC(pglDepthRange , glDepthRange) + GETOPENGLFUNC(pglClearDepth, glClearDepth) + GETOPENGLFUNC(pglDepthFunc, glDepthFunc) + GETOPENGLFUNC(pglDepthMask, glDepthMask) + GETOPENGLFUNC(pglDepthRange, glDepthRange) - GETOPENGLFUNC(pglMatrixMode , glMatrixMode) - GETOPENGLFUNC(pglViewport , glViewport) - GETOPENGLFUNC(pglPushMatrix , glPushMatrix) - GETOPENGLFUNC(pglPopMatrix , glPopMatrix) - GETOPENGLFUNC(pglLoadIdentity , glLoadIdentity) - GETOPENGLFUNC(pglMultMatrixf , glMultMatrixf) - GETOPENGLFUNC(pglRotatef , glRotatef) - GETOPENGLFUNC(pglScalef , glScalef) - GETOPENGLFUNC(pglTranslatef , glTranslatef) + GETOPENGLFUNC(pglMatrixMode, glMatrixMode) + GETOPENGLFUNC(pglViewport, glViewport) + GETOPENGLFUNC(pglPushMatrix, glPushMatrix) + GETOPENGLFUNC(pglPopMatrix, glPopMatrix) + GETOPENGLFUNC(pglLoadIdentity, glLoadIdentity) + GETOPENGLFUNC(pglMultMatrixf, glMultMatrixf) + GETOPENGLFUNC(pglRotatef, glRotatef) + GETOPENGLFUNC(pglScalef, glScalef) + GETOPENGLFUNC(pglTranslatef, glTranslatef) GETOPENGLFUNC(pglColor4ubv, glColor4ubv) + GETOPENGLFUNC(pglVertexPointer, glVertexPointer) GETOPENGLFUNC(pglNormalPointer, glNormalPointer) GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) @@ -467,39 +503,329 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglEnableClientState, glEnableClientState) GETOPENGLFUNC(pglDisableClientState, glDisableClientState) - GETOPENGLFUNC(pglShadeModel , glShadeModel) + GETOPENGLFUNC(pglShadeModel, glShadeModel) GETOPENGLFUNC(pglLightfv, glLightfv) - GETOPENGLFUNC(pglLightModelfv , glLightModelfv) - GETOPENGLFUNC(pglMaterialfv , glMaterialfv) + GETOPENGLFUNC(pglLightModelfv, glLightModelfv) + GETOPENGLFUNC(pglMaterialfv, glMaterialfv) + GETOPENGLFUNC(pglMateriali, glMateriali) - GETOPENGLFUNC(pglPixelStorei , glPixelStorei) - GETOPENGLFUNC(pglReadPixels , glReadPixels) + GETOPENGLFUNC(pglPixelStorei, glPixelStorei) + GETOPENGLFUNC(pglReadPixels, glReadPixels) - GETOPENGLFUNC(pglTexEnvi , glTexEnvi) - GETOPENGLFUNC(pglTexParameteri , glTexParameteri) - GETOPENGLFUNC(pglTexImage2D , glTexImage2D) + GETOPENGLFUNC(pglTexEnvi, glTexEnvi) + GETOPENGLFUNC(pglTexParameteri, glTexParameteri) + GETOPENGLFUNC(pglTexImage2D, glTexImage2D) + GETOPENGLFUNC(pglTexSubImage2D, glTexSubImage2D) - GETOPENGLFUNC(pglFogf , glFogf) - GETOPENGLFUNC(pglFogfv , glFogfv) + GETOPENGLFUNC(pglGenTextures, glGenTextures) + GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) + GETOPENGLFUNC(pglBindTexture, glBindTexture) - GETOPENGLFUNC(pglGenTextures , glGenTextures) - GETOPENGLFUNC(pglDeleteTextures , glDeleteTextures) - GETOPENGLFUNC(pglBindTexture , glBindTexture) - - GETOPENGLFUNC(pglCopyTexImage2D , glCopyTexImage2D) - GETOPENGLFUNC(pglCopyTexSubImage2D , glCopyTexSubImage2D) + GETOPENGLFUNC(pglCopyTexImage2D, glCopyTexImage2D) + GETOPENGLFUNC(pglCopyTexSubImage2D, glCopyTexSubImage2D) #undef GETOPENGLFUNC - pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); - #endif return true; } -// This has to be done after the context is created so the version number can be obtained -// This is stupid -- even some of the oldest usable OpenGL hardware today supports 1.3-level featureset. -boolean SetupGLFunc13(void) +static boolean gl_allowshaders = false; +static boolean gl_shadersenabled = false; + +#ifdef GL_SHADERS +typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); +typedef void (APIENTRY *PFNglShaderSource) (GLuint, GLsizei, const GLchar**, GLint*); +typedef void (APIENTRY *PFNglCompileShader) (GLuint); +typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*); +typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); +typedef void (APIENTRY *PFNglDeleteShader) (GLuint); +typedef GLuint (APIENTRY *PFNglCreateProgram) (void); +typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint); +typedef void (APIENTRY *PFNglLinkProgram) (GLuint); +typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); +typedef void (APIENTRY *PFNglUseProgram) (GLuint); +typedef void (APIENTRY *PFNglUniform1i) (GLint, GLint); +typedef void (APIENTRY *PFNglUniform1f) (GLint, GLfloat); +typedef void (APIENTRY *PFNglUniform2f) (GLint, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform3f) (GLint, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform4f) (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY *PFNglUniform1fv) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY *PFNglUniform2fv) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY *PFNglUniform3fv) (GLint, GLsizei, const GLfloat*); +typedef GLint (APIENTRY *PFNglGetUniformLocation) (GLuint, const GLchar*); + +static PFNglCreateShader pglCreateShader; +static PFNglShaderSource pglShaderSource; +static PFNglCompileShader pglCompileShader; +static PFNglGetShaderiv pglGetShaderiv; +static PFNglGetShaderInfoLog pglGetShaderInfoLog; +static PFNglDeleteShader pglDeleteShader; +static PFNglCreateProgram pglCreateProgram; +static PFNglAttachShader pglAttachShader; +static PFNglLinkProgram pglLinkProgram; +static PFNglGetProgramiv pglGetProgramiv; +static PFNglUseProgram pglUseProgram; +static PFNglUniform1i pglUniform1i; +static PFNglUniform1f pglUniform1f; +static PFNglUniform2f pglUniform2f; +static PFNglUniform3f pglUniform3f; +static PFNglUniform4f pglUniform4f; +static PFNglUniform1fv pglUniform1fv; +static PFNglUniform2fv pglUniform2fv; +static PFNglUniform3fv pglUniform3fv; +static PFNglGetUniformLocation pglGetUniformLocation; + +#define MAXSHADERS 16 +#define MAXSHADERPROGRAMS 16 + +// 18032019 +static char *gl_customvertexshaders[MAXSHADERS]; +static char *gl_customfragmentshaders[MAXSHADERS]; +static GLuint gl_currentshaderprogram = 0; +static boolean gl_shaderprogramchanged = true; + +// 13062019 +typedef enum +{ + // lighting + gluniform_poly_color, + gluniform_tint_color, + gluniform_fade_color, + gluniform_lighting, + gluniform_fade_start, + gluniform_fade_end, + + // misc. (custom shaders) + gluniform_leveltime, + + gluniform_max, +} gluniform_t; + +typedef struct gl_shaderprogram_s +{ + GLuint program; + boolean custom; + GLint uniforms[gluniform_max+1]; +} gl_shaderprogram_t; +static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; + +// Shader info +static INT32 shader_leveltime = 0; + +// ======================== +// Fragment shader macros +// ======================== + +// +// GLSL Software fragment shader +// + +#define GLSL_DOOM_COLORMAP \ + "float R_DoomColormap(float light, float z)\n" \ + "{\n" \ + "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ + "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ + "float startmap = (15.0 - lightnum) * 4.0;\n" \ + "float scale = 160.0 / (lightz + 1.0);\n" \ + "return startmap - scale * 0.5;\n" \ + "}\n" + +#define GLSL_DOOM_LIGHT_EQUATION \ + "float R_DoomLightingEquation(float light)\n" \ + "{\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ + "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ + "}\n" + +#define GLSL_SOFTWARE_TINT_EQUATION \ + "if (tint_color.a > 0.0) {\n" \ + "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ + "float strength = sqrt(9.0 * tint_color.a);\n" \ + "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ + "}\n" + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(lighting);\n" \ + "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ + "float fs = fade_start / 31.0;\n" \ + "float fe = fade_end / 31.0;\n" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "final_color = mix(final_color, fade_color, darkness);\n" + +#define GLSL_SOFTWARE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Water surface shader +// +// Mostly guesstimated, rather than the rest being built off Software science. +// Still needs to distort things underneath/around the water... +// + +#define GLSL_WATER_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + "uniform float leveltime;\n" \ + "const float freq = 0.025;\n" \ + "const float amp = 0.025;\n" \ + "const float speed = 2.0;\n" \ + "const float pi = 3.14159;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ + "float a = -pi * (z * freq) + (leveltime * speed);\n" \ + "float sdistort = sin(a) * amp;\n" \ + "float cdistort = cos(a) * amp;\n" \ + "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +#define GLSL_FOG_FRAGMENT_SHADER \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 base_color = gl_Color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// GLSL generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +static const char *fragment_shaders[] = { + // Default fragment shader + GLSL_DEFAULT_FRAGMENT_SHADER, + + // Floor fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Wall fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Sprite fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Model fragment shader + GLSL_SOFTWARE_FRAGMENT_SHADER, + + // Water fragment shader + GLSL_WATER_FRAGMENT_SHADER, + + // Fog fragment shader + GLSL_FOG_FRAGMENT_SHADER, + + // Sky fragment shader + "uniform sampler2D tex;\n" + "void main(void) {\n" + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" + "}\0", + + NULL, +}; + +// ====================== +// Vertex shader macros +// ====================== + +// +// GLSL generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +static const char *vertex_shaders[] = { + // Default vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Floor vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Wall vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Sprite vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Model vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Water vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Fog vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + // Sky vertex shader + GLSL_DEFAULT_VERTEX_SHADER, + + NULL, +}; + +#endif // GL_SHADERS + +void SetupGLFunc4(void) { pglActiveTexture = GetGLFunc("glActiveTexture"); pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); @@ -512,15 +838,266 @@ boolean SetupGLFunc13(void) pglBufferData = GetGLFunc("glBufferData"); pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); +#ifdef GL_SHADERS + pglCreateShader = GetGLFunc("glCreateShader"); + pglShaderSource = GetGLFunc("glShaderSource"); + pglCompileShader = GetGLFunc("glCompileShader"); + pglGetShaderiv = GetGLFunc("glGetShaderiv"); + pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog"); + pglDeleteShader = GetGLFunc("glDeleteShader"); + pglCreateProgram = GetGLFunc("glCreateProgram"); + pglAttachShader = GetGLFunc("glAttachShader"); + pglLinkProgram = GetGLFunc("glLinkProgram"); + pglGetProgramiv = GetGLFunc("glGetProgramiv"); + pglUseProgram = GetGLFunc("glUseProgram"); + pglUniform1i = GetGLFunc("glUniform1i"); + pglUniform1f = GetGLFunc("glUniform1f"); + pglUniform2f = GetGLFunc("glUniform2f"); + pglUniform3f = GetGLFunc("glUniform3f"); + pglUniform4f = GetGLFunc("glUniform4f"); + pglUniform1fv = GetGLFunc("glUniform1fv"); + pglUniform2fv = GetGLFunc("glUniform2fv"); + pglUniform3fv = GetGLFunc("glUniform3fv"); + pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); +#endif + + // GLU + pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); +} + +// jimita +EXPORT boolean HWRAPI(LoadShaders) (void) +{ +#ifdef GL_SHADERS + GLuint gl_vertShader, gl_fragShader; + GLint i, result; + + if (!pglUseProgram) return false; + + gl_customvertexshaders[0] = NULL; + gl_customfragmentshaders[0] = NULL; + + for (i = 0; vertex_shaders[i] && fragment_shaders[i]; i++) + { + gl_shaderprogram_t *shader; + const GLchar* vert_shader = vertex_shaders[i]; + const GLchar* frag_shader = fragment_shaders[i]; + boolean custom = ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0)); + + // 18032019 + if (gl_customvertexshaders[i]) + vert_shader = gl_customvertexshaders[i]; + if (gl_customfragmentshaders[i]) + frag_shader = gl_customfragmentshaders[i]; + + if (i >= MAXSHADERS) + break; + if (i >= MAXSHADERPROGRAMS) + break; + + shader = &gl_shaderprograms[i]; + shader->program = 0; + shader->custom = custom; + + // + // Load and compile vertex shader + // + gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); + if (!gl_vertShader) + { + GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i); + continue; + } + + pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); + pglCompileShader(gl_vertShader); + + // check for compile errors + pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + GLchar* infoLog; + GLint logLength; + + pglGetShaderiv(gl_vertShader, GL_INFO_LOG_LENGTH, &logLength); + + infoLog = malloc(logLength); + pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog); + + GL_MSG_Error("LoadShaders: Error compiling vertex shader %d\n%s", i, infoLog); + continue; + } + + // + // Load and compile fragment shader + // + gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); + if (!gl_fragShader) + { + GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i); + continue; + } + + pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); + pglCompileShader(gl_fragShader); + + // check for compile errors + pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + GLchar* infoLog; + GLint logLength; + + pglGetShaderiv(gl_fragShader, GL_INFO_LOG_LENGTH, &logLength); + + infoLog = malloc(logLength); + pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog); + + GL_MSG_Error("LoadShaders: Error compiling fragment shader %d\n%s", i, infoLog); + continue; + } + + shader->program = pglCreateProgram(); + pglAttachShader(shader->program, gl_vertShader); + pglAttachShader(shader->program, gl_fragShader); + pglLinkProgram(shader->program); + + // check link status + pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); + + // delete the shader objects + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + + // couldn't link? + if (result != GL_TRUE) + { + shader->program = 0; + shader->custom = false; + GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i); + continue; + } + + // 13062019 +#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); + + // lighting + shader->uniforms[gluniform_poly_color] = GETUNI("poly_color"); + shader->uniforms[gluniform_tint_color] = GETUNI("tint_color"); + shader->uniforms[gluniform_fade_color] = GETUNI("fade_color"); + shader->uniforms[gluniform_lighting] = GETUNI("lighting"); + shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); + shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); + + // misc. (custom shaders) + shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); + +#undef GETUNI + } +#endif return true; } +// +// Shader info +// Those are given to the uniforms. +// + +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) +{ +#ifdef GL_SHADERS + switch (info) + { + case HWD_SHADERINFO_LEVELTIME: + shader_leveltime = value; + break; + default: + break; + } +#else + (void)info; + (void)value; +#endif +} + +// +// Custom shader loading +// +EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment) +{ +#ifdef GL_SHADERS + if (!pglUseProgram) return; + if (number < 1 || number > MAXSHADERS) + I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS); + + if (fragment) + { + gl_customfragmentshaders[number] = malloc(size+1); + strncpy(gl_customfragmentshaders[number], shader, size); + gl_customfragmentshaders[number][size] = 0; + } + else + { + gl_customvertexshaders[number] = malloc(size+1); + strncpy(gl_customvertexshaders[number], shader, size); + gl_customvertexshaders[number][size] = 0; + } +#else + (void)number; + (void)shader; + (void)size; + (void)fragment; +#endif +} + +EXPORT boolean HWRAPI(InitCustomShaders) (void) +{ +#ifdef GL_SHADERS + KillShaders(); + return LoadShaders(); +#endif +} + +EXPORT void HWRAPI(SetShader) (int shader) +{ +#ifdef GL_SHADERS + if (gl_allowshaders) + { + if ((GLuint)shader != gl_currentshaderprogram) + { + gl_currentshaderprogram = shader; + gl_shaderprogramchanged = true; + } + gl_shadersenabled = true; + return; + } +#else + (void)shader; +#endif + gl_shadersenabled = false; +} + +EXPORT void HWRAPI(UnSetShader) (void) +{ +#ifdef GL_SHADERS + gl_shadersenabled = false; + gl_currentshaderprogram = 0; + if (!pglUseProgram) return; + pglUseProgram(0); +#endif +} + +EXPORT void HWRAPI(KillShaders) (void) +{ + // unused......................... +} + // -----------------+ // SetNoTexture : Disable texture // -----------------+ static void SetNoTexture(void) { - // Set small white texture. + // Disable texture. if (tex_downloaded != NOTEXTURE_NUM) { if (NOTEXTURE_NUM == 0) @@ -542,7 +1119,7 @@ static void GLPerspective(GLfloat fovy, GLfloat aspect) const GLfloat zNear = NEAR_CLIPPING_PLANE; const GLfloat zFar = FAR_CLIPPING_PLANE; const GLfloat radians = (GLfloat)(fovy / 2.0f * M_PIl / 180.0f); - const GLfloat sine = sinf(radians); + const GLfloat sine = sin(radians); const GLfloat deltaZ = zFar - zNear; GLfloat cotangent; @@ -605,7 +1182,7 @@ static void GLProject(GLfloat objX, GLfloat objY, GLfloat objZ, // -----------------+ void SetModelView(GLint w, GLint h) { -// DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)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) @@ -615,9 +1192,6 @@ void SetModelView(GLint w, GLint h) screen_height = h; pglViewport(0, 0, w, h); -#ifdef GL_ACCUM_BUFFER_BIT - pglClear(GL_ACCUM_BUFFER_BIT); -#endif pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); @@ -643,7 +1217,7 @@ void SetStates(void) GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; #endif -// DBG_Printf("SetStates()\n"); +// GL_DBG_Printf("SetStates()\n"); // Hurdler: not necessary, is it? pglShadeModel(GL_SMOOTH); // iterate vertice colors @@ -668,7 +1242,7 @@ void SetStates(void) pglDepthRange(0.0f, 1.0f); pglDepthFunc(GL_LEQUAL); - // this set CurrentPolyFlags to the acctual configuration + // this set CurrentPolyFlags to the actual configuration CurrentPolyFlags = 0xffffffff; SetBlend(0); @@ -680,10 +1254,7 @@ void SetStates(void) //pglEnable(GL_CULL_FACE); //pglCullFace(GL_FRONT); - //glFogi(GL_FOG_MODE, GL_EXP); - //pglHint(GL_FOG_HINT, GL_FASTEST); - //pglFogfv(GL_FOG_COLOR, fogcolor); - //pglFogf(GL_FOG_DENSITY, 0.0005f); + pglDisable(GL_FOG); // Lighting for models #ifdef GL_LIGHT_MODEL_AMBIENT @@ -704,7 +1275,7 @@ void SetStates(void) // -----------------+ void Flush(void) { - //DBG_Printf ("HWR_Flush()\n"); + //GL_DBG_Printf ("HWR_Flush()\n"); while (gr_cachehead) { @@ -751,10 +1322,8 @@ INT32 isExtAvailable(const char *extension, const GLubyte *start) // Init : Initialise the OpenGL interface API // Returns : // -----------------+ -EXPORT boolean HWRAPI(Init) (I_Error_t FatalErrorFunction) +EXPORT boolean HWRAPI(Init) (void) { - I_Error_GL = FatalErrorFunction; - DBG_Printf ("%s %s\n", DRIVER_STRING, VERSIONSTRING); return LoadGL(); } @@ -764,7 +1333,7 @@ EXPORT boolean HWRAPI(Init) (I_Error_t FatalErrorFunction) // -----------------+ EXPORT void HWRAPI(ClearMipMapCache) (void) { - // DBG_Printf ("HWR_Flush(exe)\n"); + // GL_DBG_Printf ("HWR_Flush(exe)\n"); Flush(); } @@ -778,7 +1347,7 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 * dst_data) { INT32 i; - // DBG_Printf ("ReadRect()\n"); + // GL_DBG_Printf ("ReadRect()\n"); if (dst_stride == width*3) { GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1); @@ -826,7 +1395,7 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, // -----------------+ EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip) { - // DBG_Printf ("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy); + // GL_DBG_Printf ("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy); pglViewport(minx, screen_height-maxy, maxx-minx, maxy-miny); NEAR_CLIPPING_PLANE = nearclip; @@ -850,7 +1419,7 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat * ClearColor) { - // DBG_Printf ("ClearBuffer(%d)\n", alpha); + // GL_DBG_Printf ("ClearBuffer(%d)\n", alpha); GLbitfield ClearMask = 0; if (ColorMask) @@ -885,7 +1454,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, F2DCoord * v2, RGBA_t Color) { - // DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); + // GL_DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); GLfloat p[12]; GLfloat dx, dy; GLfloat angle; @@ -1028,7 +1597,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) else #endif if (PolyFlags & PF_Modulated) - { // mix texture colour with Surface->FlatColor + { // mix texture colour with Surface->PolyColor pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else @@ -1067,6 +1636,207 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) CurrentPolyFlags = PolyFlags; } +// -----------------+ +// UpdateTexture : Updates the texture data. +// -----------------+ +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *pTexInfo) +{ + // Download a mipmap + boolean updatemipmap = true; + static RGBA_t tex[2048*2048]; + const GLvoid *ptex = tex; + INT32 w, h; + GLuint texnum = 0; + + if (!pTexInfo->downloaded) + { + pglGenTextures(1, &texnum); + pTexInfo->downloaded = texnum; + updatemipmap = false; + } + else + texnum = pTexInfo->downloaded; + + //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data); + + w = pTexInfo->width; + h = pTexInfo->height; + + if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || + (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && + (pTexInfo->flags & TF_CHROMAKEYED)) + { + tex[w*j+i].s.red = 0; + 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 + { + tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; + tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; + tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; + tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; + } + + pImgData++; + + if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) + { + if (!(pTexInfo->flags & TF_CHROMAKEYED)) + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + + } + } + } + else if (pTexInfo->grInfo.format == GR_RGBA) + { + // corona test : passed as ARGB 8888, which is not in glide formats + // Hurdler: not used for coronas anymore, just for dynamic lighting + ptex = pTexInfo->grInfo.data; + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = *pImgData; + tex[w*j+i].s.green = *pImgData; + tex[w*j+i].s.blue = *pImgData; + pImgData++; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't + tex[w*j+i].s.green = 255; + tex[w*j+i].s.blue = 255; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else + GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); + + // the texture number was already generated by pglGenTextures + pglBindTexture(GL_TEXTURE_2D, texnum); + tex_downloaded = texnum; + + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } + + if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + else + { + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + // Control the mipmap level of detail + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + + if (pTexInfo->flags & TF_WRAPX) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_S); + + if (pTexInfo->flags & TF_WRAPY) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_T); + + if (maximumAnisotropy) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); +} // -----------------+ // SetTexture : The mipmap becomes the current texture source @@ -1088,179 +1858,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } else { - // Download a mipmap - static RGBA_t tex[2048*2048]; - const GLvoid *ptex = tex; - INT32 w, h; - GLuint texnum = 0; - - pglGenTextures(1, &texnum); - //DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data); - - w = pTexInfo->width; - h = pTexInfo->height; - - if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || - (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && - (pTexInfo->flags & TF_CHROMAKEYED)) - { - tex[w*j+i].s.red = 0; - 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 - { - tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; - tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; - tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; - tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; - } - - pImgData++; - - if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) - { - if (!(pTexInfo->flags & TF_CHROMAKEYED)) - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - - } - } - } - else if (pTexInfo->grInfo.format == GR_RGBA) - { - // corona test : passed as ARGB 8888, which is not in glide formats - // Hurdler: not used for coronas anymore, just for dynamic lighting - ptex = pTexInfo->grInfo.data; - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = *pImgData; - tex[w*j+i].s.green = *pImgData; - tex[w*j+i].s.blue = *pImgData; - pImgData++; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't - tex[w*j+i].s.green = 255; - tex[w*j+i].s.blue = 255; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else - DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); - - // the texture number was already generated by pglGenTextures - pglBindTexture(GL_TEXTURE_2D, texnum); - pTexInfo->downloaded = texnum; - tex_downloaded = texnum; - - // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues - if (pTexInfo->flags & TF_TRANSPARENT) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - else - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); - } - - if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else - { - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - // Control the mipmap level of detail - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - - if (pTexInfo->flags & TF_WRAPX) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_S); - - if (pTexInfo->flags & TF_WRAPY) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_T); - - if (maximumAnisotropy) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); - + UpdateTexture(pTexInfo); pTexInfo->nextmipmap = NULL; if (gr_cachetail) { // insertion at the tail @@ -1272,32 +1870,132 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } - -// -----------------+ -// DrawPolygon : Render a polygon, set the texture, set render mode -// -----------------+ -EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, - //FTextureInfo *pTexInfo, - FOutVector *pOutVerts, - FUINT iNumPts, - FBITFIELD PolyFlags) +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) { - FUINT i; - FUINT j; +#ifdef GL_SHADERS + if (gl_shadersenabled && pglUseProgram) + { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (shader->program) + { + if (gl_shaderprogramchanged) + { + pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); + gl_shaderprogramchanged = false; + } + Shader_SetUniforms(Surface, poly, tint, fade); + return shader; + } + else + pglUseProgram(0); + } +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; +#endif + return NULL; +} + +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +{ +#ifdef GL_SHADERS + if (gl_shadersenabled) + { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (!shader->program) + return; + + #define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + #define UNIFORM_2(uniform, a, b, function) \ + if (uniform != -1) \ + function (uniform, a, b); + + #define UNIFORM_3(uniform, a, b, c, function) \ + if (uniform != -1) \ + function (uniform, a, b, c); + + #define UNIFORM_4(uniform, a, b, c, d, function) \ + if (uniform != -1) \ + function (uniform, a, b, c, d); + + // polygon + UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); + if (Surface != NULL) + { + UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); + } + UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); + + #undef UNIFORM_1 + #undef UNIFORM_2 + #undef UNIFORM_3 + #undef UNIFORM_4 + } +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; +#endif +} + +// code that is common between DrawPolygon and DrawIndexedTriangles +// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching +static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) +{ + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD)) PolyFlags &= ~(PF_NoDepthTest|PF_Corona); SetBlend(PolyFlags); //TODO: inline (#pragma..) - // If Modulated, mix the surface colour to the texture - if ((CurrentPolyFlags & PF_Modulated) && pSurf) - pglColor4ubv((GLubyte*)&pSurf->FlatColor.s); + // PolyColor + if (pSurf) + { + // If Modulated, mix the surface colour to the texture + if (CurrentPolyFlags & PF_Modulated) + { + // Poly color + poly.red = byte2float[pSurf->PolyColor.s.red]; + poly.green = byte2float[pSurf->PolyColor.s.green]; + poly.blue = byte2float[pSurf->PolyColor.s.blue]; + poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; + + pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + } + + // Tint color + tint.red = byte2float[pSurf->TintColor.s.red]; + tint.green = byte2float[pSurf->TintColor.s.green]; + tint.blue = byte2float[pSurf->TintColor.s.blue]; + tint.alpha = byte2float[pSurf->TintColor.s.alpha]; + + // Fade color + fade.red = byte2float[pSurf->FadeColor.s.red]; + fade.green = byte2float[pSurf->FadeColor.s.green]; + fade.blue = byte2float[pSurf->FadeColor.s.blue]; + fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; + } // this test is added for new coronas' code (without depth buffer) // I think I should do a separate function for drawing coronas, so it will be a little faster if (PolyFlags & PF_Corona) // check to see if we need to draw the corona { + FUINT i; + FUINT j; + //rem: all 8 (or 8.0f) values are hard coded: it can be changed to a higher value GLfloat buf[8][8]; GLfloat cx, cy, cz; @@ -1314,18 +2012,18 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, // I dont know if this is slow or not GLProject(cx, cy, cz, &px, &py, &pz); - //DBG_Printf("Projection: (%f, %f, %f)\n", px, py, pz); + //GL_DBG_Printf("Projection: (%f, %f, %f)\n", px, py, pz); if ((pz < 0.0l) || - (px < -8.0l) || - (py < viewport[1]-8.0l) || - (px > viewport[2]+8.0l) || - (py > viewport[1]+viewport[3]+8.0l)) + (px < -8.0l) || + (py < viewport[1]-8.0l) || + (px > viewport[2]+8.0l) || + (py > viewport[1]+viewport[3]+8.0l)) return; // the damned slow glReadPixels functions :( pglReadPixels((INT32)px-4, (INT32)py, 8, 8, GL_DEPTH_COMPONENT, GL_FLOAT, buf); - //DBG_Printf("DepthBuffer: %f %f\n", buf[0][0], buf[3][3]); + //GL_DBG_Printf("DepthBuffer: %f %f\n", buf[0][0], buf[3][3]); for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) @@ -1338,24 +2036,34 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, if (py > viewport[1]+viewport[3]-4) scalef -= (GLfloat)(8*(4-(viewport[1]+viewport[3]-py))); scalef /= 64; - //DBG_Printf("Scale factor: %f\n", scalef); + //GL_DBG_Printf("Scale factor: %f\n", scalef); if (scalef < 0.05f) return; // GLubyte c[4]; - c[0] = pSurf->FlatColor.s.red; - c[1] = pSurf->FlatColor.s.green; - c[2] = pSurf->FlatColor.s.blue; + c[0] = pSurf->PolyColor.s.red; + c[1] = pSurf->PolyColor.s.green; + c[2] = pSurf->PolyColor.s.blue; - alpha = byte2float[pSurf->FlatColor.s.alpha]; + alpha = byte2float[pSurf->PolyColor.s.alpha]; alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) c[3] = (unsigned char)(alpha * 255); pglColor4ubv(c); } + Shader_Load(pSurf, &poly, &tint, &fade); +} + +// -----------------+ +// DrawPolygon : Render a polygon, set the texture, set render mode +// -----------------+ +EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags) +{ + PreparePolygon(pSurf, pOutVerts, PolyFlags); + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].sow); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); if (PolyFlags & PF_RemoveYWrap) @@ -1368,6 +2076,17 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, Clamp2D(GL_TEXTURE_WRAP_T); } +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray) +{ + PreparePolygon(pSurf, pOutVerts, PolyFlags); + + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawElements(GL_TRIANGLES, iNumPts, GL_UNSIGNED_INT, IndexArray); + + // the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it? +} + typedef struct vbo_vertex_s { float x, y, z; @@ -1630,46 +2349,16 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) model_lighting = Value; break; - case HWD_SET_FOG_COLOR: - { - GLfloat fogcolor[4]; - - fogcolor[0] = byte2float[((Value>>16)&0xff)]; - fogcolor[1] = byte2float[((Value>>8)&0xff)]; - fogcolor[2] = byte2float[((Value)&0xff)]; - fogcolor[3] = 0x0; - pglFogfv(GL_FOG_COLOR, fogcolor); - break; - } - - case HWD_SET_FOG_DENSITY: - pglFogf(GL_FOG_DENSITY, Value*1200/(500*1000000.0f)); - break; - - case HWD_SET_FOG_MODE: - if (Value) + case HWD_SET_SHADERS: + switch (Value) { - pglEnable(GL_FOG); - // experimental code - /* - switch (Value) - { - case 1: - glFogi(GL_FOG_MODE, GL_LINEAR); - pglFogf(GL_FOG_START, -1000.0f); - pglFogf(GL_FOG_END, 2000.0f); - break; - case 2: - glFogi(GL_FOG_MODE, GL_EXP); - break; - case 3: - glFogi(GL_FOG_MODE, GL_EXP2); - break; - } - */ + case 1: + gl_allowshaders = true; + break; + default: + gl_allowshaders = false; + break; } - else - pglDisable(GL_FOG); break; case HWD_SET_TEXTUREFILTERMODE: @@ -1926,10 +2615,11 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) #define BUFFER_OFFSET(i) ((void*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) { - GLfloat ambient[4]; - GLfloat diffuse[4]; + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; float pol = 0.0f; float scalex, scaley, scalez; @@ -1938,8 +2628,12 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 int i; - // Because Otherwise, scaling the screen negatively vertically breaks the lighting + // Because otherwise, scaling the screen negatively vertically breaks the lighting GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; +#ifdef GL_LIGHT_MODEL_AMBIENT + GLfloat ambient[4]; + GLfloat diffuse[4]; +#endif // Affect input model scaling scale *= 0.5f; @@ -1960,16 +2654,23 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pol = 0.0f; } - if (color) + poly.red = byte2float[Surface->PolyColor.s.red]; + poly.green = byte2float[Surface->PolyColor.s.green]; + poly.blue = byte2float[Surface->PolyColor.s.blue]; + poly.alpha = byte2float[Surface->PolyColor.s.alpha]; + +#ifdef GL_LIGHT_MODEL_AMBIENT + if (model_lighting && (!gl_shadersenabled)) // doesn't work with shaders anyway { - ambient[0] = (color[0]/255.0f); - ambient[1] = (color[1]/255.0f); - ambient[2] = (color[2]/255.0f); - ambient[3] = (color[3]/255.0f); - diffuse[0] = (color[0]/255.0f); - diffuse[1] = (color[1]/255.0f); - diffuse[2] = (color[2]/255.0f); - diffuse[3] = (color[3]/255.0f); + ambient[0] = poly.red; + ambient[1] = poly.green; + ambient[2] = poly.blue; + ambient[3] = poly.alpha; + + diffuse[0] = poly.red; + diffuse[1] = poly.green; + diffuse[2] = poly.blue; + diffuse[3] = poly.alpha; if (ambient[0] > 0.75f) ambient[0] = 0.75f; @@ -1977,7 +2678,31 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 ambient[1] = 0.75f; if (ambient[2] > 0.75f) ambient[2] = 0.75f; + + pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); + pglShadeModel(GL_SMOOTH); + + pglEnable(GL_LIGHTING); + pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); + pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); } +#endif + else + pglColor4ubv((GLubyte*)&Surface->PolyColor.s); + + SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated); + + tint.red = byte2float[Surface->TintColor.s.red]; + tint.green = byte2float[Surface->TintColor.s.green]; + tint.blue = byte2float[Surface->TintColor.s.blue]; + tint.alpha = byte2float[Surface->TintColor.s.alpha]; + + fade.red = byte2float[Surface->FadeColor.s.red]; + fade.green = byte2float[Surface->FadeColor.s.green]; + fade.blue = byte2float[Surface->FadeColor.s.blue]; + fade.alpha = byte2float[Surface->FadeColor.s.alpha]; + + Shader_Load(Surface, &poly, &tint, &fade); pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); @@ -2006,31 +2731,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } #endif - if (model_lighting) - { - pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); - pglShadeModel(GL_SMOOTH); - } - - if (color) - { -#ifdef GL_LIGHT_MODEL_AMBIENT - if (model_lighting) - { - pglEnable(GL_LIGHTING); - pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); - pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); - } - else -#endif - pglColor4ubv((GLubyte*)color); - - if (color[3] < 255) - SetBlend(PF_Translucent|PF_Modulated|PF_Clip); - else - SetBlend(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); @@ -2091,13 +2791,12 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 { short *vertPtr; char *normPtr; - int j; + int j = 0; // Dangit, I soooo want to do this in a GLSL shader... AllocLerpTinyBuffer(mesh->numVertices * sizeof(short) * 3); vertPtr = vertTinyBuffer; normPtr = normTinyBuffer; - j = 0; for (j = 0; j < mesh->numVertices * 3; j++) { @@ -2168,19 +2867,24 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglDisableClientState(GL_NORMAL_ARRAY); pglPopMatrix(); // should be the same as glLoadIdentity - if (color) - pglDisable(GL_LIGHTING); - pglShadeModel(GL_FLAT); pglDisable(GL_CULL_FACE); pglDisable(GL_NORMALIZE); + +#ifdef GL_LIGHT_MODEL_AMBIENT + if (model_lighting && (!gl_shadersenabled)) + { + pglDisable(GL_LIGHTING); + pglShadeModel(GL_FLAT); + } +#endif } // -----------------+ -// HWRAPI DrawMD2 : Draw an MD2 model with glcommands +// HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, color); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface); } // -----------------+ @@ -2189,8 +2893,11 @@ EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, EXPORT void HWRAPI(SetTransform) (FTransform *stransform) { static boolean special_splitscreen; + boolean shearing = false; float used_fov; + pglLoadIdentity(); + if (stransform) { used_fov = stransform->fovxangle; @@ -2212,6 +2919,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglTranslatef(-stransform->x, -stransform->z, -stransform->y); special_splitscreen = stransform->splitscreen; + shearing = stransform->shearing; } else { @@ -2222,6 +2930,15 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); + // jimita 14042019 + // Simulate Software's y-shearing + // https://zdoom.org/wiki/Y-shearing + if (shearing) + { + float fdy = stransform->viewaiming * 2; + pglTranslatef(0.0f, -fdy/BASEVIDHEIGHT, 0.0f); + } + if (special_splitscreen) { used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI; @@ -2234,6 +2951,7 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglMatrixMode(GL_MODELVIEW); pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) + } EXPORT INT32 HWRAPI(GetTextureUsed) (void) @@ -2265,11 +2983,6 @@ EXPORT INT32 HWRAPI(GetTextureUsed) (void) return res; } -EXPORT INT32 HWRAPI(GetRenderVersion) (void) -{ - return VERSION; -} - EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) { INT32 x, y; @@ -2307,6 +3020,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglVertexPointer(3, GL_FLOAT, 0, blackBack); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); for(x=0;xtypeoflevel); else if (fastcmp(field,"nextlevel")) lua_pushinteger(L, header->nextlevel); + else if (fastcmp(field,"marathonnext")) + lua_pushinteger(L, header->marathonnext); else if (fastcmp(field,"keywords")) lua_pushstring(L, header->keywords); else if (fastcmp(field,"musname")) diff --git a/src/lua_script.c b/src/lua_script.c index 374294d6e..a295256da 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -167,7 +167,10 @@ int LUA_PushGlobals(lua_State *L, const char *word) lua_pushboolean(L, splitscreen); return 1; } else if (fastcmp(word,"gamecomplete")) { - lua_pushboolean(L, gamecomplete); + lua_pushboolean(L, (gamecomplete != 0)); + return 1; + } else if (fastcmp(word,"marathonmode")) { + lua_pushinteger(L, marathonmode); return 1; } else if (fastcmp(word,"devparm")) { lua_pushboolean(L, devparm); @@ -197,6 +200,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"spstage_start")) { lua_pushinteger(L, spstage_start); return 1; + } else if (fastcmp(word,"spmarathon_start")) { + lua_pushinteger(L, spmarathon_start); + return 1; } else if (fastcmp(word,"sstage_start")) { lua_pushinteger(L, sstage_start); return 1; diff --git a/src/m_menu.c b/src/m_menu.c index fc25621e5..f684354a5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -183,6 +183,7 @@ static tic_t keydown = 0; static void M_GoBack(INT32 choice); static void M_StopMessage(INT32 choice); +static boolean stopstopmessage = false; #ifndef NONET static void M_HandleServerPage(INT32 choice); @@ -253,6 +254,7 @@ static void M_ConfirmTeamScramble(INT32 choice); static void M_ConfirmTeamChange(INT32 choice); static void M_SecretsMenu(INT32 choice); static void M_SetupChoosePlayer(INT32 choice); +static UINT8 M_SetupChoosePlayerDirect(INT32 choice); static void M_QuitSRB2(INT32 choice); menu_t SP_MainDef, OP_MainDef; menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; @@ -273,9 +275,14 @@ static void M_ModeAttackEndGame(INT32 choice); static void M_SetGuestReplay(INT32 choice); static void M_HandleChoosePlayerMenu(INT32 choice); static void M_ChoosePlayer(INT32 choice); +static void M_MarathonLiveEventBackup(INT32 choice); +static void M_Marathon(INT32 choice); +static void M_HandleMarathonChoosePlayer(INT32 choice); +static void M_StartMarathon(INT32 choice); menu_t SP_LevelStatsDef; static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef; static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef; +static menu_t SP_MarathonDef; // Multiplayer static void M_SetupMultiPlayer(INT32 choice); @@ -317,8 +324,11 @@ static void M_VideoOptions(INT32 choice); menu_t OP_VideoOptionsDef, OP_VideoModeDef, OP_ColorOptionsDef; #ifdef HWRENDER static void M_OpenGLOptionsMenu(void); -menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef; -#endif +menu_t OP_OpenGLOptionsDef; +#ifdef ALAM_LIGHTING +menu_t OP_OpenGLLightingDef; +#endif // ALAM_LIGHTING +#endif // HWRENDER menu_t OP_SoundOptionsDef; menu_t OP_SoundAdvancedDef; @@ -355,6 +365,7 @@ static void M_DrawLoad(void); static void M_DrawLevelStats(void); static void M_DrawTimeAttackMenu(void); static void M_DrawNightsAttackMenu(void); +static void M_DrawMarathon(void); static void M_DrawSetupChoosePlayerMenu(void); static void M_DrawControlsDefMenu(void); static void M_DrawCameraOptionsMenu(void); @@ -365,9 +376,6 @@ static void M_DrawVideoMode(void); static void M_DrawColorMenu(void); static void M_DrawScreenshotMenu(void); static void M_DrawMonitorToggles(void); -#ifdef HWRENDER -static void M_OGL_DrawFogMenu(void); -#endif #ifndef NONET static void M_DrawConnectMenu(void); static void M_DrawMPMainMenu(void); @@ -391,9 +399,6 @@ static boolean M_CancelConnect(void); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); -#ifdef HWRENDER -static void M_HandleFogColor(INT32 choice); -#endif static void M_HandleVideoMode(INT32 choice); static void M_ResetCvars(void); @@ -477,6 +482,13 @@ static consvar_t cv_dummylives = {"dummylives", "0", CV_HIDEN, liveslimit_cons_t static consvar_t cv_dummycontinues = {"dummycontinues", "0", CV_HIDEN, contlimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL}; +CV_PossibleValue_t marathon_cons_t[] = {{0, "Standard"}, {1, "Live Event Backup"}, {2, "Ultimate"}, {0, NULL}}; +CV_PossibleValue_t loadless_cons_t[] = {{0, "Realtime"}, {1, "In-game"}, {0, NULL}}; + +consvar_t cv_dummymarathon = {"dummymarathon", "Standard", CV_HIDEN, marathon_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_dummycutscenes = {"dummycutscenes", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_dummyloadless = {"dummyloadless", "Realtime", CV_HIDEN, loadless_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + // ========================================================================== // ORGANIZATION START. // ========================================================================== @@ -747,9 +759,10 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { - {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 84}, - {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 92}, - {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 100}, + {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76}, + {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84}, + {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92}, + {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Marathon Run", M_Marathon, 100}, {IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108}, {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116} }; @@ -759,6 +772,7 @@ enum sploadgame, sprecordattack, spnightsmode, + spmarathon, sptutorial, spstatistics }; @@ -904,6 +918,25 @@ enum nastart }; +// Marathon +static menuitem_t SP_MarathonMenu[] = +{ + {IT_STRING|IT_KEYHANDLER, NULL, "Character", M_HandleMarathonChoosePlayer, 90}, + {IT_STRING|IT_CVAR, NULL, "Category", &cv_dummymarathon, 100}, + {IT_STRING|IT_CVAR, NULL, "Timer", &cv_dummyloadless, 110}, + {IT_STRING|IT_CVAR, NULL, "Cutscenes", &cv_dummycutscenes, 120}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartMarathon, 130}, +}; + +enum +{ + marathonplayer, + marathonultimate, + marathonloadless, + marathoncutscenes, + marathonstart +}; + // Statistics static menuitem_t SP_LevelStatsMenu[] = { @@ -1413,22 +1446,23 @@ static menuitem_t OP_OpenGLOptionsMenu[] = { {IT_HEADER, NULL, "3D Models", NULL, 0}, {IT_STRING|IT_CVAR, NULL, "Models", &cv_grmodels, 12}, - {IT_STRING|IT_CVAR, NULL, "Model interpolation", &cv_grmodelinterpolation, 22}, - {IT_STRING|IT_CVAR, NULL, "Model lighting", &cv_grmodellighting, 32}, + {IT_STRING|IT_CVAR, NULL, "Frame interpolation", &cv_grmodelinterpolation, 22}, + {IT_STRING|IT_CVAR, NULL, "Ambient lighting", &cv_grmodellighting, 32}, {IT_HEADER, NULL, "General", NULL, 51}, - {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 63}, - {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 73}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 83}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,93}, + {IT_STRING|IT_CVAR, NULL, "Shaders", &cv_grshaders, 63}, + {IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_grshearing, 73}, + {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 83}, - {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, - {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 124}, + {IT_HEADER, NULL, "Miscellaneous", NULL, 102}, + {IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 114}, + {IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_grfiltermode, 124}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 134}, #ifdef ALAM_LIGHTING - {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 134}, + {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 144}, #endif #if defined (_WINDOWS) && (!((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL))) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 144}, + {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 154}, #endif }; @@ -1440,15 +1474,8 @@ static menuitem_t OP_OpenGLLightingMenu[] = {IT_STRING|IT_CVAR, NULL, "Dynamic lighting", &cv_grdynamiclighting, 20}, {IT_STRING|IT_CVAR, NULL, "Static lighting", &cv_grstaticlighting, 30}, }; -#endif +#endif // ALAM_LIGHTING -static menuitem_t OP_OpenGLFogMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Fog", &cv_grfog, 10}, - {IT_STRING|IT_KEYHANDLER, NULL, "Fog color", M_HandleFogColor, 20}, - {IT_STRING|IT_CVAR, NULL, "Fog density", &cv_grfogdensity, 30}, - {IT_STRING|IT_CVAR, NULL, "Software Fog",&cv_grsoftwarefog,40}, -}; #endif static menuitem_t OP_SoundOptionsMenu[] = @@ -1911,6 +1938,18 @@ static menu_t SP_NightsGhostDef = NULL }; +static menu_t SP_MarathonDef = +{ + MTREE2(MN_SP_MAIN, MN_SP_MARATHON), + "M_ATTACK", // temporary + sizeof(SP_MarathonMenu)/sizeof(menuitem_t), + &MainDef, // Doesn't matter. + SP_MarathonMenu, + M_DrawMarathon, + 32, 40, + 0, + NULL +}; menu_t SP_PlayerDef = { @@ -2195,20 +2234,9 @@ menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE( menu_t OP_OpenGLLightingDef = DEFAULTMENUSTYLE( MTREE4(MN_OP_MAIN, MN_OP_VIDEO, MN_OP_OPENGL, MN_OP_OPENGL_LIGHTING), "M_VIDEO", OP_OpenGLLightingMenu, &OP_OpenGLOptionsDef, 60, 40); -#endif -menu_t OP_OpenGLFogDef = -{ - MTREE4(MN_OP_MAIN, MN_OP_VIDEO, MN_OP_OPENGL, MN_OP_OPENGL_FOG), - "M_VIDEO", - sizeof (OP_OpenGLFogMenu)/sizeof (menuitem_t), - &OP_OpenGLOptionsDef, - OP_OpenGLFogMenu, - M_OGL_DrawFogMenu, - 60, 40, - 0, - NULL -}; -#endif +#endif // ALAM_LIGHTING +#endif // HWRENDER + menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE( MTREE2(MN_OP_MAIN, MN_OP_DATA), "M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); @@ -2527,6 +2555,8 @@ void M_InitMenuPresTables(void) strncpy(menupres[i].musname, "_recat", 7); else if (i == MN_SP_NIGHTSATTACK) strncpy(menupres[i].musname, "_nitat", 7); + else if (i == MN_SP_MARATHON) + strncpy(menupres[i].musname, "spec8", 6); else if (i == MN_SP_PLAYER || i == MN_SR_PLAYER) strncpy(menupres[i].musname, "_chsel", 7); else if (i == MN_SR_SOUNDTEST) @@ -3021,7 +3051,7 @@ static void M_GoBack(INT32 choice) netgame = multiplayer = false; } - if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) + if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef || currentMenu == &SP_MarathonDef)) { // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. @@ -3406,11 +3436,14 @@ boolean M_Responder(event_t *ev) { if (currentMenu->menuitems[itemOn].alphaKey != MM_EVENTHANDLER) { - if (ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER) + if (ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER || ch == KEY_DEL) { if (routine) routine(ch); - M_StopMessage(0); + if (stopstopmessage) + stopstopmessage = false; + else + M_StopMessage(0); noFurtherInput = true; return true; } @@ -3660,7 +3693,7 @@ void M_StartControlPanel(void) { INT32 numlives = 2; - SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); if (&players[consoleplayer]) { @@ -3678,10 +3711,10 @@ void M_StartControlPanel(void) } // We can always use level select though. :33 - SPauseMenu[spause_levelselect].status = (gamecomplete) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_levelselect].status = (gamecomplete == 1) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // And emblem hints. - SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // Shift up Pandora's Box if both pandora and levelselect are active /*if (SPauseMenu[spause_pandora].status != (IT_DISABLED) @@ -3862,6 +3895,9 @@ void M_Init(void) CV_RegisterVar(&cv_dummylives); CV_RegisterVar(&cv_dummycontinues); CV_RegisterVar(&cv_dummymares); + CV_RegisterVar(&cv_dummymarathon); + CV_RegisterVar(&cv_dummyloadless); + CV_RegisterVar(&cv_dummycutscenes); quitmsg[QUITMSG] = M_GetText("Eggman's tied explosives\nto your girlfriend, and\nwill activate them if\nyou press the 'Y' key!\nPress 'N' to save her!\n\n(Press 'Y' to quit)"); quitmsg[QUITMSG1] = M_GetText("What would Tails say if\nhe saw you quitting the game?\n\n(Press 'Y' to quit)"); @@ -6324,8 +6360,8 @@ static char *M_AddonsHeaderPath(void) static void M_AddonsClearName(INT32 choice) { + (void)choice; CLEARNAME; - M_StopMessage(choice); } // returns whether to do message draw @@ -6357,7 +6393,7 @@ static boolean M_AddonsRefresh(void) if (message) { - M_StartMessage(message,M_AddonsClearName,MM_EVENTHANDLER); + M_StartMessage(message,M_AddonsClearName,MM_NOTHING); return true; } @@ -6862,6 +6898,11 @@ static void M_RetryResponse(INT32 ch) static void M_Retry(INT32 choice) { (void)choice; + if (marathonmode) + { + M_RetryResponse(KEY_ENTER); + return; + } M_StartMessage(M_GetText("Retry this act from the last starpost?\n\n(Press 'Y' to confirm)\n"),M_RetryResponse,MM_YESNO); } @@ -8016,6 +8057,16 @@ static void M_SinglePlayerMenu(INT32 choice) SP_MainMenu[sptutorial].status = tutorialmap ? IT_CALL|IT_STRING : IT_NOTHING|IT_DISABLED; + // If the FIRST stage immediately leads to the ending, or itself (which gets converted to the title screen in G_DoCompleted for marathonmode only), there's no point in having this option on the menu. You should use Record Attack in that circumstance, although if marathonnext is set this behaviour can be overridden if you make some weird mod that requires multiple playthroughs of the same map in sequence and has some in-level mechanism to break the cycle. + if (!M_SecretUnlocked(SECRET_RECORDATTACK) // also if record attack is locked + || (mapheaderinfo[spmarathon_start-1] + && !mapheaderinfo[spmarathon_start-1]->marathonnext + && (mapheaderinfo[spmarathon_start-1]->nextlevel == spmarathon_start + || mapheaderinfo[spmarathon_start-1]->nextlevel >= 1100))) + SP_MainMenu[spmarathon].status = IT_NOTHING|IT_DISABLED; + else + SP_MainMenu[spmarathon].status = IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED; + M_SetupNextMenu(&SP_MainDef); } @@ -8106,7 +8157,7 @@ static void M_StartTutorial(INT32 choice) emeralds = 0; memset(&luabanks, 0, sizeof(luabanks)); M_ClearMenus(true); - gamecomplete = false; + gamecomplete = 0; cursaveslot = 0; G_DeferedInitNew(false, G_BuildMapName(tutorialmap), 0, false, false); } @@ -8869,7 +8920,7 @@ static void M_CacheCharacterSelect(void) { INT32 i, skinnum; - for (i = 0; i < 32; i++) + for (i = 0; i < MAXSKINS; i++) { if (!description[i].used) continue; @@ -8881,7 +8932,7 @@ static void M_CacheCharacterSelect(void) } } -static void M_SetupChoosePlayer(INT32 choice) +static UINT8 M_SetupChoosePlayerDirect(INT32 choice) { INT32 skinnum; UINT8 i; @@ -8892,7 +8943,7 @@ static void M_SetupChoosePlayer(INT32 choice) if (!mapheaderinfo[startmap-1] || mapheaderinfo[startmap-1]->forcecharacter[0] == '\0') { - for (i = 0; i < 32; i++) // Handle charsels, availability, and unlocks. + for (i = 0; i < MAXSKINS; i++) // Handle charsels, availability, and unlocks. { if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. { @@ -8900,7 +8951,7 @@ static void M_SetupChoosePlayer(INT32 choice) if (and) { char firstskin[SKINNAMESIZE+1]; - if (mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS) // skip tagteam characters for NiGHTS levels + if (mapheaderinfo[startmap-1] && mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS) // skip tagteam characters for NiGHTS levels continue; strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); firstskin[(and - description[i].skinname)] = '\0'; @@ -8937,14 +8988,36 @@ static void M_SetupChoosePlayer(INT32 choice) if (firstvalid == lastvalid) // We're being forced into a specific character, so might as well just skip it. { - M_ChoosePlayer(firstvalid); - return; + return firstvalid; } // One last bit of order we can't do in the iteration above. description[firstvalid].prev = lastvalid; description[lastvalid].next = firstvalid; + if (!allowed) + { + char_on = firstvalid; + if (startchar > 0 && startchar < MAXSKINS) + { + INT16 workchar = startchar; + while (workchar--) + char_on = description[char_on].next; + } + } + + return MAXSKINS; +} + +static void M_SetupChoosePlayer(INT32 choice) +{ + UINT8 skinset = M_SetupChoosePlayerDirect(choice); + if (skinset != MAXSKINS) + { + M_ChoosePlayer(skinset); + return; + } + M_ChangeMenuMusic("_chsel", true); /* the menus suck -James */ @@ -8959,16 +9032,6 @@ static void M_SetupChoosePlayer(INT32 choice) SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); - if (!allowed) - { - char_on = firstvalid; - if (startchar > 0 && startchar < 32) - { - INT16 workchar = startchar; - while (workchar--) - char_on = description[char_on].next; - } - } // finish scrolling the menu char_scroll = 0; @@ -9027,6 +9090,10 @@ static void M_HandleChoosePlayerMenu(INT32 choice) case KEY_ENTER: S_StartSound(NULL, sfx_menu1); + char_scroll = 0; // finish scrolling the menu + M_DrawSetupChoosePlayerMenu(); // draw the finally selected character one last time for the fadeout + // Is this a hack? + charseltimer = 0; M_ChoosePlayer(char_on); break; @@ -9266,7 +9333,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Chose the player you want to use Tails 03-02-2002 static void M_ChoosePlayer(INT32 choice) { - boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT); + boolean ultmode = (currentMenu == &SP_MarathonDef) ? (cv_dummymarathon.value == 2) : (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT); UINT8 skinnum; // skip this if forcecharacter or no characters available @@ -9278,11 +9345,6 @@ static void M_ChoosePlayer(INT32 choice) // M_SetupChoosePlayer didn't call us directly, that means we've been properly set up. else { - char_scroll = 0; // finish scrolling the menu - M_DrawSetupChoosePlayerMenu(); // draw the finally selected character one last time for the fadeout - // Is this a hack? - charseltimer = 0; - skinnum = description[choice].skinnum[0]; if ((botingame = (description[choice].skinnum[1] != -1))) { @@ -9296,11 +9358,11 @@ static void M_ChoosePlayer(INT32 choice) M_ClearMenus(true); - if (startmap != spstage_start) + if (!marathonmode && startmap != spstage_start) cursaveslot = 0; //lastmapsaved = 0; - gamecomplete = false; + gamecomplete = 0; G_DeferedInitNew(ultmode, G_BuildMapName(startmap), skinnum, false, fromlevelselect); COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this @@ -10299,6 +10361,368 @@ static void M_ModeAttackEndGame(INT32 choice) Nextmap_OnChange(); } +static void M_MarathonLiveEventBackup(INT32 choice) +{ + if (choice == 'y' || choice == KEY_ENTER) + { + marathonmode = MA_INIT; + G_LoadGame(MARATHONSLOT, 0); + cursaveslot = MARATHONSLOT; + if (!(marathonmode & MA_RUNNING)) + marathonmode = 0; + return; + } + + M_StopMessage(0); + stopstopmessage = true; + + if (choice == KEY_DEL) + { + if (FIL_FileExists(liveeventbackup)) // just in case someone deleted it while we weren't looking. + remove(liveeventbackup); + BwehHehHe(); + M_StartMessage("Live event backup erased.\n",M_Marathon,MM_NOTHING); + return; + } + + M_Marathon(-1); +} + +// Going to Marathon menu... +static void M_Marathon(INT32 choice) +{ + UINT8 skinset; + INT32 mapnum = 0; + + if (choice != -1 && FIL_FileExists(liveeventbackup)) + { + M_StartMessage(\ + "\x82Live event backup detected.\n\x80\ + Do you want to resurrect the last run?\n\ + (Fs in chat if we crashed on stream.)\n\ + \n\ + Press 'Y' or 'Enter' to resume,\n\ + 'Del' to delete, or any other\n\ + key to continue to Marathon Run.",M_MarathonLiveEventBackup,MM_YESNO); + return; + } + + fromlevelselect = false; + + startmap = spmarathon_start; + CV_SetValue(&cv_newgametype, GT_COOP); // Graue 09-08-2004 + + skinset = M_SetupChoosePlayerDirect(-1); + + SP_MarathonMenu[marathonplayer].status = (skinset == MAXSKINS) ? IT_KEYHANDLER|IT_STRING : IT_NOTHING|IT_DISABLED; + + while (mapnum < NUMMAPS) + { + if (mapheaderinfo[mapnum]) + { + if (mapheaderinfo[mapnum]->cutscenenum || mapheaderinfo[mapnum]->precutscenenum) + break; + } + mapnum++; + } + + SP_MarathonMenu[marathoncutscenes].status = (mapnum < NUMMAPS) ? IT_CVAR|IT_STRING : IT_NOTHING|IT_DISABLED; + + M_ChangeMenuMusic("spec8", true); + + SP_MarathonDef.prevMenu = &MainDef; + G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching + titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please + M_SetupNextMenu(&SP_MarathonDef); + itemOn = marathonstart; // "Start" is selected. + recatkdrawtimer = 50-8; + char_scroll = 0; +} + +static void M_HandleMarathonChoosePlayer(INT32 choice) +{ + INT32 selectval; + + if (keydown > 1) + return; + + switch (choice) + { + case KEY_DOWNARROW: + M_NextOpt(); + break; + case KEY_UPARROW: + M_PrevOpt(); + break; + + case KEY_LEFTARROW: + if ((selectval = description[char_on].prev) == char_on) + return; + char_on = selectval; + break; + case KEY_RIGHTARROW: + if ((selectval = description[char_on].next) == char_on) + return; + char_on = selectval; + break; + + case KEY_ESCAPE: + noFurtherInput = true; + M_GoBack(0); + return; + + default: + return; + } + S_StartSound(NULL, sfx_menu1); +} + +static void M_StartMarathon(INT32 choice) +{ + (void)choice; + marathontime = 0; + marathonmode = MA_RUNNING|MA_INIT; + if (cv_dummymarathon.value == 1) + cursaveslot = MARATHONSLOT; + if (!cv_dummycutscenes.value) + marathonmode |= MA_NOCUTSCENES; + if (cv_dummyloadless.value) + marathonmode |= MA_INGAME; + M_ChoosePlayer(char_on); +} + +// Drawing function for Marathon menu +void M_DrawMarathon(void) +{ + INT32 i, x, y, cursory = 0, cnt, soffset = 0, w; + UINT16 dispstatus; + consvar_t *cv; + const char *cvstring; + char *work; + angle_t fa; + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy; + + // lactozilla: the renderer changed so recache patches + if (needpatchrecache) + M_CacheCharacterSelect(); + + curbgxspeed = 0; + curbgyspeed = 18; + + M_ChangeMenuMusic("spec8", true); // Eww, but needed for when user hits escape during demo playback + + V_DrawFill(-diffx, -diffy, diffx+(BASEVIDWIDTH-190)/2, yspan, 158); + V_DrawFill((BASEVIDWIDTH-190)/2, -diffy, 190, yspan, 31); + V_DrawFill((BASEVIDWIDTH+190)/2, -diffy, diffx+(BASEVIDWIDTH-190)/2, yspan, 158); + //M_DrawRecordAttackForeground(); + if (curfadevalue) + V_DrawFadeScreen(0xFF00, curfadevalue); + + x = (((BASEVIDWIDTH-82)/2)+11)<>ANGLETOFINESHIFT) & FINEMASK; + y -= (10*FINECOSINE(fa)); + + recatkdrawtimer++; + + soffset = cnt = (recatkdrawtimer%50); + if (!useBlackRock) + { + if (cnt > 8) + cnt = 8; + V_DrawFixedPatch(x+(6< 8) + { + cnt = 8; + V_DrawFixedPatch(x, y, FRACUNIT, V_TRANSLUCENT, W_CachePatchName("ENDEGRK5", PU_PATCH), NULL); + } + else + { + V_DrawFixedPatch(x, y, FRACUNIT, cnt<= 160) + col = 253; + V_DrawFill(((BASEVIDWIDTH-190)/2)-cursory-w, -diffy, w, yspan, col); + V_DrawFill(((BASEVIDWIDTH+190)/2)+cursory, -diffy, w, yspan, col); + cursory += w; + w *= 2; + } + } + + w = char_scroll + (((8-cnt)*(8-cnt))<<(FRACBITS-5)); + if (soffset == 50-1) + w += FRACUNIT/2; + + { + patch_t *fg = W_CachePatchName("RECATKFG", PU_PATCH); + INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2)); + INT32 height = (SHORT(fg->height)/2); + char patchname[7] = "CEMGx0"; + + dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain. + dupz = ((dupz>>FRACBITS) % height); + y = height/2; + while (y+dupz >= -diffy) + y -= height; + while (y-2-dupz < maxy) + { + V_DrawFixedPatch(((BASEVIDWIDTH-190)<<(FRACBITS-1)), (y-2-dupz)<>ANGLETOFINESHIFT) & FINEMASK; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + (60*FINESINE(fa)); + y = ((BASEVIDHEIGHT+16-20)<<(FRACBITS-1)) - (60*FINECOSINE(fa)); + w += (360<>FRACBITS) % height); + y = dupz+(height/4); + x = 105+dupz; + while (y >= -diffy) + { + x -= height; + y -= height; + } + while (y-dupz < maxy && x < (xspan/2)) + { + V_DrawFill((BASEVIDWIDTH/2)-x-height, -diffy, height, diffy+y+height, 153); + V_DrawFill((BASEVIDWIDTH/2)+x, (maxy-y)-height, height, height+y, 153); + y += height; + x += height; + } + } + + if (!soffset) + { + char_scroll += (360<= 360< (10*TICRATE)) + recatkdrawtimer -= (10*TICRATE); + } + + //M_DrawMenuTitle(); + + // draw menu (everything else goes on top of it) + // Sadly we can't just use generic mode menus because we need some extra hacks + x = currentMenu->x; + y = currentMenu->y; + + dispstatus = (currentMenu->menuitems[marathonplayer].status & IT_DISPLAY); + if (dispstatus == IT_STRING || dispstatus == IT_WHITESTRING) + { + soffset = 68; + if (description[char_on].charpic->width >= 256) + V_DrawTinyScaledPatch(224, 120, 0, description[char_on].charpic); + else + V_DrawSmallScaledPatch(224, 120, 0, description[char_on].charpic); + } + else + soffset = 0; + + for (i = 0; i < currentMenu->numitems; ++i) + { + dispstatus = (currentMenu->menuitems[i].status & IT_DISPLAY); + if (dispstatus != IT_STRING && dispstatus != IT_WHITESTRING) + continue; + + y = currentMenu->y+currentMenu->menuitems[i].alphaKey; + if (i == itemOn) + cursory = y; + + V_DrawString(x, y, (dispstatus == IT_WHITESTRING) ? V_YELLOWMAP : 0 , currentMenu->menuitems[i].text); + + cv = NULL; + cvstring = NULL; + work = NULL; + if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_CVAR) + { + cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + cvstring = cv->string; + } + else if (i == marathonplayer) + { + if (description[char_on].displayname[0]) + { + work = Z_StrDup(description[char_on].displayname); + cnt = 0; + while (work[cnt]) + { + if (work[cnt] == '\n') + work[cnt] = ' '; + cnt++; + } + cvstring = work; + } + else + cvstring = description[char_on].skinname; + } + + // Cvar specific handling + if (cvstring) + { + INT32 flags = V_YELLOWMAP; + if (cv == &cv_dummymarathon && cv->value == 2) // ultimate_selectable + flags = V_REDMAP; + + // Should see nothing but strings + if (cv == &cv_dummymarathon && cv->value == 1) + { + w = V_ThinStringWidth(cvstring, 0); + V_DrawThinString(BASEVIDWIDTH - x - soffset - w, y+1, flags, cvstring); + } + else + { + w = V_StringWidth(cvstring, 0); + V_DrawString(BASEVIDWIDTH - x - soffset - w, y, flags, cvstring); + } + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - w - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } + if (work) + Z_Free(work); + } + } + + // DRAW THE SKULL CURSOR + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_PATCH)); + V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); + + // Draw press ESC to exit string on main record attack menu + V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit")); +} + // ======== // END GAME // ======== @@ -12780,6 +13204,7 @@ void M_QuitResponse(INT32 ch) if (!(netgame || cv_debug)) { S_ResetCaptions(); + marathonmode = 0; mrand = M_RandomKey(sizeof(quitsounds)/sizeof(INT32)); if (quitsounds[mrand]) S_StartSound(NULL, quitsounds[mrand]); @@ -12803,85 +13228,3 @@ static void M_QuitSRB2(INT32 choice) (void)choice; M_StartMessage(quitmsg[M_RandomKey(NUM_QUITMESSAGES)], M_QuitResponse, MM_YESNO); } - -#ifdef HWRENDER -// ===================================================================== -// OpenGL specific options -// ===================================================================== - -#define FOG_COLOR_ITEM 1 -// =================== -// M_OGL_DrawFogMenu() -// =================== -static void M_OGL_DrawFogMenu(void) -{ - INT32 mx, my; - - mx = currentMenu->x; - my = currentMenu->y; - M_DrawGenericMenu(); // use generic drawer for cursor, items and title - V_DrawString(BASEVIDWIDTH - mx - V_StringWidth(cv_grfogcolor.string, 0), - my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, V_YELLOWMAP, cv_grfogcolor.string); - // blink cursor on FOG_COLOR_ITEM if selected - if (itemOn == FOG_COLOR_ITEM && skullAnimCounter < 4) - V_DrawCharacter(BASEVIDWIDTH - mx, - my + currentMenu->menuitems[FOG_COLOR_ITEM].alphaKey, '_' | 0x80,false); -} - -//=================== -// M_HandleFogColor() -//=================== -static void M_HandleFogColor(INT32 choice) -{ - size_t i, l; - char temp[8]; - boolean exitmenu = false; // exit to previous menu and send name change - - switch (choice) - { - case KEY_DOWNARROW: - S_StartSound(NULL, sfx_menu1); - itemOn++; - break; - - case KEY_UPARROW: - S_StartSound(NULL, sfx_menu1); - itemOn--; - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_BACKSPACE: - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp)-1; - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[i + 6 - l] = temp[i]; - break; - - default: - if ((choice >= '0' && choice <= '9') || (choice >= 'a' && choice <= 'f') - || (choice >= 'A' && choice <= 'F')) - { - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp); - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[5 - i] = temp[l - i]; - cv_grfogcolor.zstring[5] = (char)choice; - } - break; - } - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} -#endif diff --git a/src/m_menu.h b/src/m_menu.h index cce5a6a6c..221f1fd3f 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -61,6 +61,8 @@ typedef enum MN_SP_NIGHTS_REPLAY, MN_SP_NIGHTS_GHOST, + MN_SP_MARATHON, + // Multiplayer MN_MP_MAIN, MN_MP_SPLITSCREEN, // SplitServer @@ -92,8 +94,6 @@ typedef enum MN_OP_COLOR, MN_OP_OPENGL, MN_OP_OPENGL_LIGHTING, - MN_OP_OPENGL_FOG, - MN_OP_OPENGL_COLOR, MN_OP_SOUND, @@ -419,6 +419,7 @@ extern INT16 char_on, startchar; #define MAXSAVEGAMES 31 #define NOSAVESLOT 0 //slot where Play Without Saving appears +#define MARATHONSLOT 420 // just has to be nonzero, but let's use one that'll show up as an obvious error if something goes wrong while not using our existing saves #define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he diff --git a/src/p_enemy.c b/src/p_enemy.c index 146c8f1aa..578874574 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5106,9 +5106,11 @@ void A_SignPlayer(mobj_t *actor) INT32 locvar2 = var2; skin_t *skin = NULL; mobj_t *ov; - UINT16 facecolor, signcolor = (UINT16)locvar2; + UINT16 facecolor, signcolor = 0; UINT32 signframe = states[actor->info->raisestate].frame; + facecolor = signcolor = (UINT16)locvar2; + if (LUA_CallAction("A_SignPlayer", actor)) return; diff --git a/src/p_saveg.c b/src/p_saveg.c index 85c4c4f75..b4d7ef838 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3808,10 +3808,10 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) if (mapoverride != 0) { gamemap = mapoverride; - gamecomplete = true; + gamecomplete = 1; } else - gamecomplete = false; + gamecomplete = 0; // gamemap changed; we assume that its map header is always valid, // so make it so diff --git a/src/p_setup.c b/src/p_setup.c index 84e89d746..ffb68b1b0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -344,6 +344,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->actnum = 0; mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->nextlevel = (INT16)(i + 1); + mapheaderinfo[num]->marathonnext = 0; mapheaderinfo[num]->startrings = 0; mapheaderinfo[num]->sstimer = 90; mapheaderinfo[num]->ssspheres = 1; @@ -3308,7 +3309,7 @@ static boolean CanSaveLevel(INT32 mapnum) // Any levels that have the savegame flag can save normally. // If the game is complete for this save slot, then any level can save! // On the other side of the spectrum, if lastmaploaded is 0, then the save file has only just been created and needs to save ASAP! - return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || gamecomplete || !lastmaploaded); + return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || (gamecomplete != 0) || marathonmode || !lastmaploaded); } static void P_RunSpecialStageWipe(void) diff --git a/src/p_tick.c b/src/p_tick.c index 55b545856..1f1331856 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -755,6 +755,9 @@ void P_PreTicker(INT32 frames) postimgtype = postimgtype2 = postimg_none; + if (marathonmode & MA_INGAME) + marathonmode |= MA_INIT; + for (framecnt = 0; framecnt < frames; ++framecnt) { P_MapStart(); @@ -799,4 +802,7 @@ void P_PreTicker(INT32 frames) P_MapEnd(); } + + if (marathonmode & MA_INGAME) + marathonmode &= ~MA_INIT; } diff --git a/src/p_user.c b/src/p_user.c index e07ddaec5..f21da1564 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8578,7 +8578,7 @@ static void P_MovePlayer(player_t *player) } #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none && cv_fovchange.value) + if (rendermode == render_opengl && cv_fovchange.value) { fixed_t speed; const fixed_t runnyspeed = 20*FRACUNIT; @@ -9988,9 +9988,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (camorbit) //Sev here, I'm guessing this is where orbital cam lives { - if (rendermode == render_opengl) +#ifdef HWRENDER + if (rendermode == render_opengl && !cv_grshearing.value) distxy = FixedMul(dist, FINECOSINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)); else +#endif distxy = dist; distz = -FixedMul(dist, FINESINE((focusaiming>>ANGLETOFINESHIFT) & FINEMASK)) + slopez; } diff --git a/src/r_bsp.c b/src/r_bsp.c index 60291da0f..a430ef040 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -798,6 +798,9 @@ static void R_AddPolyObjects(subsector_t *sub) po = (polyobj_t *)(po->link.next); } + // for render stats + rs_numpolyobjects += numpolys; + // sort polyobjects R_SortPolyObjects(sub); @@ -1235,6 +1238,9 @@ void R_RenderBSPNode(INT32 bspnum) { node_t *bsp; INT32 side; + + rs_numbspcalls++; + while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? { bsp = &nodes[bspnum]; diff --git a/src/r_data.c b/src/r_data.c index 831e75bef..b72214996 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -242,9 +242,10 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph fullalpha = 0xFF; alpha = (UINT8)fullalpha; - // if the background pixel is empty, match software and don't blend anything + // if the background pixel is empty, + // match software and don't blend anything if (!background.s.alpha) - output.rgba = 0; + output.s.alpha = 0; else { UINT8 beta = (0xFF - alpha); diff --git a/src/r_main.c b/src/r_main.c index e47bb06e3..cf7360804 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -33,6 +33,8 @@ #include "z_zone.h" #include "m_random.h" // quake camera shake #include "r_portal.h" +#include "r_main.h" +#include "i_system.h" // I_GetTimeMicros #ifdef HWRENDER #include "hardware/hw_main.h" @@ -97,6 +99,22 @@ lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Hack to support extra boom colormaps. extracolormap_t *extra_colormaps = NULL; +// Render stats +int rs_prevframetime = 0; +int rs_rendercalltime = 0; +int rs_swaptime = 0; + +int rs_bsptime = 0; + +int rs_sw_portaltime = 0; +int rs_sw_planetime = 0; +int rs_sw_maskedtime = 0; + +int rs_numbspcalls = 0; +int rs_numsprites = 0; +int rs_numdrawnodes = 0; +int rs_numpolyobjects = 0; + static CV_PossibleValue_t drawdist_cons_t[] = { {256, "256"}, {512, "512"}, {768, "768"}, {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, @@ -147,6 +165,8 @@ consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_renderstats = {"renderstats", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + void SplitScreen_OnChange(void) { if (!cv_debug && netgame) @@ -900,11 +920,6 @@ void R_ExecuteSetViewSize(void) R_InitTextureMapping(); -#ifdef HWRENDER - if (rendermode != render_soft) - HWR_InitTextureMapping(); -#endif - // thing clipping for (i = 0; i < viewwidth; i++) screenheightarray[i] = (INT16)viewheight; @@ -1038,29 +1053,34 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) // R_SetupFrame // -// WARNING: a should be unsigned but to add with 2048, it isn't! -#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)/fovtan) - // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) static void R_SetupFreelook(void) { INT32 dy = 0; + + // clip it in the case we are looking a hardware 90 degrees full aiming + // (lmps, network and use F12...) + if (rendermode == render_soft +#ifdef HWRENDER + || cv_grshearing.value +#endif + ) + { + G_SoftwareClipAimingPitch((INT32 *)&aimingangle); + } + if (rendermode == render_soft) { - // clip it in the case we are looking a hardware 90 degrees full aiming - // (lmps, network and use F12...) - G_SoftwareClipAimingPitch((INT32 *)&aimingangle); - dy = AIMINGTODY(aimingangle) * viewwidth/BASEVIDWIDTH; + dy = (AIMINGTODY(aimingangle)>>FRACBITS) * viewwidth/BASEVIDWIDTH; yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)]; } + centery = (viewheight/2) + dy; centeryfrac = centery<climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) + chasecam = true; // force chasecam on + else if (player->spectator) // no spectator chasecam + chasecam = false; // force chasecam off + + return chasecam; +} + +boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox) +{ + boolean chasecam = R_ViewpointHasChasecam(player); + + // cut-away view stuff + if (player->awayviewtics || skybox) + return chasecam; + // use outside cam view + else if (!player->spectator && chasecam) + return true; + + // use the player's eyes view + return false; +} + static void R_PortalFrame(portal_t *portal) { viewx = portal->viewx; @@ -1410,7 +1462,11 @@ void R_RenderPlayerView(player_t *player) mytotal = 0; ProfZeroTimer(); #endif + rs_numbspcalls = rs_numpolyobjects = rs_numdrawnodes = 0; + rs_bsptime = I_GetTimeMicros(); R_RenderBSPNode((INT32)numnodes - 1); + rs_bsptime = I_GetTimeMicros() - rs_bsptime; + rs_numsprites = visspritecount; #ifdef TIMING RDMSR(0x10, &mycount); mytotal += mycount; // 64bit add @@ -1428,6 +1484,7 @@ void R_RenderPlayerView(player_t *player) Portal_AddSkyboxPortals(); // Portal rendering. Hijacks the BSP traversal. + rs_sw_portaltime = I_GetTimeMicros(); if (portal_base) { portal_t *portal; @@ -1467,15 +1524,20 @@ void R_RenderPlayerView(player_t *player) Portal_Remove(portal); } } + rs_sw_portaltime = I_GetTimeMicros() - rs_sw_portaltime; + rs_sw_planetime = I_GetTimeMicros(); R_DrawPlanes(); #ifdef FLOORSPLATS R_DrawVisibleFloorSplats(); #endif + rs_sw_planetime = I_GetTimeMicros() - rs_sw_planetime; // draw mid texture and sprite // And now 3D floors/sides! + rs_sw_maskedtime = I_GetTimeMicros(); R_DrawMasked(masks, nummasks); + rs_sw_maskedtime = I_GetTimeMicros() - rs_sw_maskedtime; free(masks); } diff --git a/src/r_main.h b/src/r_main.h index 0a48df412..99a25d86e 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -26,7 +26,10 @@ extern INT32 centerx, centery; extern fixed_t centerxfrac, centeryfrac; extern fixed_t projection, projectiony; -extern fixed_t fovtan; // field of view +extern fixed_t fovtan; + +// WARNING: a should be unsigned but to add with 2048, it isn't! +#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160), fovtan) extern size_t validcount, linecount, loopcount, framecount; @@ -71,6 +74,25 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); +// Render stats + +extern consvar_t cv_renderstats; + +extern int rs_prevframetime;// time when previous frame was rendered +extern int rs_rendercalltime; +extern int rs_swaptime; + +extern int rs_bsptime; + +extern int rs_sw_portaltime; +extern int rs_sw_planetime; +extern int rs_sw_maskedtime; + +extern int rs_numbspcalls; +extern int rs_numsprites; +extern int rs_numdrawnodes; +extern int rs_numpolyobjects; + // // REFRESH - the actual rendering functions. // @@ -104,10 +126,13 @@ void R_SetViewSize(void); // do it (sometimes explicitly called) void R_ExecuteSetViewSize(void); +void R_SetupFrame(player_t *player); void R_SkyboxFrame(player_t *player); -void R_SetupFrame(player_t *player); -// Called by G_Drawer. +boolean R_ViewpointHasChasecam(player_t *player); +boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox); + +// Called by D_Display. void R_RenderPlayerView(player_t *player); // add commands related to engine, at game startup diff --git a/src/r_things.c b/src/r_things.c index 228c86a64..de5eb208f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2505,6 +2505,8 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link) node->thickseg = NULL; node->ffloor = NULL; node->sprite = NULL; + + rs_numdrawnodes++; return node; } diff --git a/src/screen.c b/src/screen.c index e01d1a81a..e7ff9e735 100644 --- a/src/screen.c +++ b/src/screen.c @@ -622,3 +622,51 @@ void SCR_ClosedCaptions(void) va("%c [%s]", dot, (closedcaptions[i].s->caption[0] ? closedcaptions[i].s->caption : closedcaptions[i].s->name))); } } + +void SCR_DisplayMarathonInfo(void) +{ + INT32 flags = V_SNAPTOBOTTOM; + static tic_t entertic, oldentertics = 0, antisplice[2] = {48,0}; + const char *str; +#if 0 // eh, this probably isn't going to be a problem + if (((signed)marathontime) < 0) + { + flags |= V_REDMAP; + str = "No waiting out the clock to submit a bogus time."; + } + else +#endif + { + entertic = I_GetTime(); + if (gamecomplete) + flags |= V_YELLOWMAP; + else if (marathonmode & MA_INGAME) + ; // see also G_Ticker + else if (marathonmode & MA_INIT) + marathonmode &= ~MA_INIT; + else + marathontime += entertic - oldentertics; + + // Create a sequence of primes such that their LCM is nice and big. +#define PRIMEV1 13 +#define PRIMEV2 17 // I can't believe it! I'm on TV! + antisplice[0] += (entertic - oldentertics)*PRIMEV2; + antisplice[0] %= PRIMEV1*((vid.width/vid.dupx)+1); + antisplice[1] += (entertic - oldentertics)*PRIMEV1; + antisplice[1] %= PRIMEV1*((vid.width/vid.dupx)+1); + str = va("%i:%02i:%02i.%02i", + G_TicsToHours(marathontime), + G_TicsToMinutes(marathontime, false), + G_TicsToSeconds(marathontime), + G_TicsToCentiseconds(marathontime)); + oldentertics = entertic; + } + V_DrawFill((antisplice[0]/PRIMEV1)-1, BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTOLEFT); + V_DrawFill((antisplice[0]/PRIMEV1), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTOLEFT|31); + V_DrawFill(BASEVIDWIDTH-((antisplice[1]/PRIMEV1)-1), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTORIGHT); + V_DrawFill(BASEVIDWIDTH-((antisplice[1]/PRIMEV1)), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTORIGHT|31); +#undef PRIMEV1 +#undef PRIMEV2 + V_DrawPromptBack(-8, cons_backcolor.value); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-8, flags, str); +} diff --git a/src/screen.h b/src/screen.h index ddbd499bb..91ec175f4 100644 --- a/src/screen.h +++ b/src/screen.h @@ -206,5 +206,6 @@ FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); void SCR_DisplayTicRate(void); void SCR_ClosedCaptions(void); void SCR_DisplayLocalPing(void); +void SCR_DisplayMarathonInfo(void); #undef DNWH #endif //__SCREEN_H__ diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 6a55ac2d6..c24104b92 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -220,6 +220,7 @@ + @@ -370,6 +371,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 89ba1b588..2f0aec7ca 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -219,6 +219,9 @@ Hw_Hardware + + Hw_Hardware + Hw_Hardware @@ -636,6 +639,9 @@ Hw_Hardware + + Hw_Hardware + Hw_Hardware diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 5f040023a..416c8d2f5 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -75,14 +75,17 @@ void *hwSym(const char *funcName,void *handle) void *funcPointer = NULL; #ifdef HWRENDER if (0 == strcmp("SetPalette", funcName)) - funcPointer = &OglSdlSetPalette; + funcPointer = &OglSdlSetPalette; + GETFUNC(Init); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); + GETFUNC(DrawIndexedTriangles); GETFUNC(RenderSkyDome); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); + GETFUNC(UpdateTexture); GETFUNC(ReadRect); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); @@ -91,7 +94,6 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(DrawModel); GETFUNC(CreateModelVBOs); GETFUNC(SetTransform); - GETFUNC(GetRenderVersion); GETFUNC(PostImgRedraw); GETFUNC(FlushScreenTextures); GETFUNC(StartScreenWipe); @@ -101,6 +103,16 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(MakeScreenTexture); GETFUNC(MakeScreenFinalTexture); GETFUNC(DrawScreenFinalTexture); + + GETFUNC(LoadShaders); + GETFUNC(KillShaders); + GETFUNC(SetShader); + GETFUNC(UnSetShader); + + GETFUNC(SetShaderInfo); + GETFUNC(LoadCustomShader); + GETFUNC(InitCustomShaders); + #else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) return funcPointer; //&FinishUpdate; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e358308b4..27e015ef7 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -54,6 +54,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif +#if defined (_WIN32) +DWORD TimeFunction(int requested_frequency); +#else +int TimeFunction(int requested_frequency); +#endif + #include #ifdef _WIN32 #include @@ -2063,9 +2069,11 @@ static p_timeGetTime pfntimeGetTime = NULL; // but lower precision on Windows NT // --------- -tic_t I_GetTime(void) +DWORD TimeFunction(int requested_frequency) { - tic_t newtics = 0; + DWORD newtics = 0; + // this var acts as a multiplier if sub-millisecond precision is asked but is not available + int excess_frequency = requested_frequency / 1000; if (!starttickcount) // high precision timer { @@ -2085,7 +2093,7 @@ tic_t I_GetTime(void) if (frequency.LowPart && QueryPerformanceCounter(&currtime)) { - newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * NEWTICRATE + newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * requested_frequency / frequency.QuadPart); } else if (pfntimeGetTime) @@ -2093,11 +2101,19 @@ tic_t I_GetTime(void) currtime.LowPart = pfntimeGetTime(); if (!basetime.LowPart) basetime.LowPart = currtime.LowPart; - newtics = ((currtime.LowPart - basetime.LowPart)/(1000/NEWTICRATE)); + if (requested_frequency > 1000) + newtics = currtime.LowPart - basetime.LowPart * excess_frequency; + else + newtics = (currtime.LowPart - basetime.LowPart)/(1000/requested_frequency); } } else - newtics = (GetTickCount() - starttickcount)/(1000/NEWTICRATE); + { + if (requested_frequency > 1000) + newtics = (GetTickCount() - starttickcount) * excess_frequency; + else + newtics = (GetTickCount() - starttickcount)/(1000/requested_frequency); + } return newtics; } @@ -2119,7 +2135,9 @@ static void I_ShutdownTimer(void) // I_GetTime // returns time in 1/TICRATE second tics // -tic_t I_GetTime (void) + +// millisecond precision only +int TimeFunction(int requested_frequency) { static Uint64 basetime = 0; Uint64 ticks = SDL_GetTicks(); @@ -2129,14 +2147,24 @@ tic_t I_GetTime (void) ticks -= basetime; - ticks = (ticks*TICRATE); + ticks = (ticks*requested_frequency); ticks = (ticks/1000); - return (tic_t)ticks; + return ticks; } #endif +tic_t I_GetTime(void) +{ + return TimeFunction(NEWTICRATE); +} + +int I_GetTimeMicros(void) +{ + return TimeFunction(1000000); +} + // //I_StartupTimer // diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index a3c913b9c..01194a02f 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -358,11 +358,7 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) case SDL_SCANCODE_RGUI: return KEY_RIGHTWIN; default: break; } -#ifdef HWRENDER - DBG_Printf("Unknown incoming scancode: %d, represented %c\n", - code, - SDL_GetKeyName(SDL_GetKeyFromScancode(code))); -#endif + return 0; } @@ -1206,6 +1202,9 @@ void I_FinishUpdate(void) if (I_SkipFrame()) return; + if (marathonmode) + SCR_DisplayMarathonInfo(); + // draw captions if enabled if (cv_closedcaptioning.value) SCR_ClosedCaptions(); @@ -1482,6 +1481,7 @@ void VID_CheckGLLoaded(rendermode_t oldrender) #ifdef HWRENDER if (vid_opengl_state == -1) // Well, it didn't work the first time anyway. { + CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); rendermode = oldrender; if (chosenrendermode == render_opengl) // fallback to software rendermode = render_soft; @@ -1830,10 +1830,12 @@ void VID_StartupOpenGL(void) HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL); HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); + HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); @@ -1843,7 +1845,6 @@ void VID_StartupOpenGL(void) HWD.pfnDrawModel = hwSym("DrawModel",NULL); HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); - HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); @@ -1854,14 +1855,16 @@ void VID_StartupOpenGL(void) HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - // check gl renderer lib - if (HWD.pfnGetRenderVersion() != VERSION) - { - CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable!\nBe sure you have installed SRB2 properly.\n")); - vid_opengl_state = -1; - } - else - vid_opengl_state = HWD.pfnInit(I_Error) ? 1 : -1; // let load the OpenGL library + HWD.pfnLoadShaders = hwSym("LoadShaders",NULL); + HWD.pfnKillShaders = hwSym("KillShaders",NULL); + HWD.pfnSetShader = hwSym("SetShader",NULL); + HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); + + HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); + HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); + HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL); + + vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library if (vid_opengl_state == -1) { diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 8da2126c8..edc69b21d 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -37,6 +37,7 @@ #ifdef HWRENDER #include "../hardware/r_opengl/r_opengl.h" +#include "../hardware/hw_main.h" #include "ogl_sdl.h" #include "../i_system.h" #include "hwsym_sdl.h" @@ -90,15 +91,15 @@ boolean LoadGL(void) const char *OGLLibname = NULL; const char *GLULibname = NULL; - if (M_CheckParm ("-OGLlib") && M_IsNextParm()) + if (M_CheckParm("-OGLlib") && M_IsNextParm()) OGLLibname = M_GetNextParm(); if (SDL_GL_LoadLibrary(OGLLibname) != 0) { CONS_Alert(CONS_ERROR, "Could not load OpenGL Library: %s\n" "Falling back to Software mode.\n", SDL_GetError()); - if (!M_CheckParm ("-OGLlib")) - CONS_Alert(CONS_ERROR, "If you know what is the OpenGL library's name, use -OGLlib\n"); + if (!M_CheckParm("-OGLlib")) + CONS_Printf("If you know what is the OpenGL library's name, use -OGLlib\n"); return 0; } @@ -118,7 +119,7 @@ boolean LoadGL(void) GLULibname = NULL; #endif - if (M_CheckParm ("-GLUlib") && M_IsNextParm()) + if (M_CheckParm("-GLUlib") && M_IsNextParm()) GLULibname = M_GetNextParm(); if (GLULibname) @@ -152,31 +153,29 @@ boolean LoadGL(void) */ boolean OglSdlSurface(INT32 w, INT32 h) { - INT32 cbpp; - const GLvoid *glvendor = NULL, *glrenderer = NULL, *glversion = NULL; + INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; + static boolean first_init = false; - cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; - - glvendor = pglGetString(GL_VENDOR); - // Get info and extensions. - //BP: why don't we make it earlier ? - //Hurdler: we cannot do that before intialising gl context - glrenderer = pglGetString(GL_RENDERER); - glversion = pglGetString(GL_VERSION); - gl_extensions = pglGetString(GL_EXTENSIONS); - - DBG_Printf("Vendor : %s\n", glvendor); - DBG_Printf("Renderer : %s\n", glrenderer); - DBG_Printf("Version : %s\n", glversion); - DBG_Printf("Extensions : %s\n", gl_extensions); oglflags = 0; + if (!first_init) + { + gl_version = pglGetString(GL_VERSION); + gl_renderer = pglGetString(GL_RENDERER); + gl_extensions = pglGetString(GL_EXTENSIONS); + + GL_DBG_Printf("OpenGL %s\n", gl_version); + GL_DBG_Printf("GPU: %s\n", gl_renderer); + GL_DBG_Printf("Extensions: %s\n", gl_extensions); + } + first_init = true; + if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); else maximumAnisotropy = 1; - SetupGLFunc13(); + SetupGLFunc4(); granisotropicmode_cons_t[1].value = maximumAnisotropy; @@ -222,7 +221,7 @@ void OglSdlFinishUpdate(boolean waitvbl) HWR_DrawScreenFinalTexture(realwidth, realheight); } -EXPORT void HWRAPI( OglSdlSetPalette) (RGBA_t *palette) +EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette) { size_t palsize = (sizeof(RGBA_t) * 256); // on a palette change, you have to reload all of the textures diff --git a/src/st_stuff.c b/src/st_stuff.c index 086e80291..621acb489 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -763,7 +763,7 @@ static void ST_drawTime(void) ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon, V_HUDTRANS); // Colon ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2, V_HUDTRANS); // Seconds - if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking) // there's not enough room for tics in splitscreen, don't even bother trying! + if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking || marathonmode) { ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod, V_HUDTRANS); // Period ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2, V_HUDTRANS); // Tics @@ -1450,7 +1450,7 @@ static void ST_drawPowerupHUD(void) // --------- // Let's have a power-like icon to represent finishing the level! - if (stplyr->pflags & PF_FINISHED && cv_exitmove.value) + if (stplyr->pflags & PF_FINISHED && cv_exitmove.value && multiplayer) { finishoffs[q] = ICONSEP; V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, fnshico); diff --git a/src/v_video.c b/src/v_video.c index 2f546dea2..b88c4838b 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -418,7 +418,7 @@ void V_SetPalette(INT32 palettenum) LoadMapPalette(); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_SetPalette(&pLocalPalette[palettenum*256]); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else @@ -432,7 +432,7 @@ void V_SetPaletteLump(const char *pal) { LoadPalette(pal); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_SetPalette(pLocalPalette); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else @@ -529,7 +529,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Why? - if (rendermode != render_soft) + if (rendermode == render_opengl) { HWR_DrawStretchyFixedPatch((GLPatch_t *)patch, x, y, pscale, vscale, scrn, colormap); return; @@ -829,7 +829,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Not this again - if (rendermode != render_soft) + if (rendermode == render_opengl) { HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); return; @@ -1153,7 +1153,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) #ifdef HWRENDER //if (rendermode != render_soft && !con_startup) // Not this again - if (rendermode != render_soft) + if (rendermode == render_opengl) { HWR_DrawFill(x, y, w, h, c); return; @@ -1350,7 +1350,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) return; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { UINT32 hwcolor = V_GetHWConsBackColor(); HWR_DrawConsoleFill(x, y, w, h, c, hwcolor); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. @@ -1547,7 +1547,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U return; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { // ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny @@ -1709,7 +1709,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum) size_t size, lflatsize, flatshift; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { HWR_DrawFlatFill(x, y, w, h, flatnum); return; @@ -1819,7 +1819,7 @@ void V_DrawPatchFill(patch_t *pat) void V_DrawFadeScreen(UINT16 color, UINT8 strength) { #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { HWR_FadeScreenMenuBack(color, strength); return; @@ -1848,7 +1848,7 @@ void V_DrawFadeConsBack(INT32 plines) UINT8 *deststop, *buf; #ifdef HWRENDER // not win32 only 19990829 by Kin - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { UINT32 hwcolor = V_GetHWConsBackColor(); HWR_DrawConsoleBack(hwcolor, plines); @@ -1870,7 +1870,10 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color) if (color >= 256 && color < 512) { - boxheight = ((boxheight * 4) + (boxheight/2)*5); + if (boxheight < 0) + boxheight = -boxheight; + else // 4 lines of space plus gaps between and some leeway + boxheight = ((boxheight * 4) + (boxheight/2)*5); V_DrawFill((BASEVIDWIDTH-(vid.width/vid.dupx))/2, BASEVIDHEIGHT-boxheight, (vid.width/vid.dupx),boxheight, (color-256)|V_SNAPTOBOTTOM); return; } @@ -1881,7 +1884,7 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color) color = cons_backcolor.value; #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { UINT32 hwcolor; switch (color) @@ -1917,8 +1920,11 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color) // heavily simplified -- we don't need to know x or y position, // just the start and stop positions - deststop = screens[0] + vid.rowbytes * vid.height; - buf = deststop - vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5); // 4 lines of space plus gaps between and some leeway + buf = deststop = screens[0] + vid.rowbytes * vid.height; + if (boxheight < 0) + buf += vid.rowbytes * boxheight; + else // 4 lines of space plus gaps between and some leeway + buf -= vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5); for (; buf < deststop; ++buf) *buf = promptbgmap[*buf]; } @@ -3506,8 +3512,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param) INT32 height, yoffset; #ifdef HWRENDER - // draw a hardware converted patch - if (rendermode != render_soft && rendermode != render_none) + if (rendermode != render_soft) return; #endif diff --git a/src/w_wad.c b/src/w_wad.c index af9f9a7c0..9af661b57 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -848,6 +848,15 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) wadfiles[numwadfiles] = wadfile; numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded +#ifdef HWRENDER + // Read shaders from file + if (rendermode == render_opengl && (vid_opengl_state == 1)) + { + HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3)); + HWR_LoadShaders(); + } +#endif // HWRENDER + // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. switch (wadfile->type) { @@ -1632,21 +1641,6 @@ boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr) return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); } -void W_FlushCachedPatches(void) -{ - if (needpatchflush) - { - Z_FreeTag(PU_CACHE); - Z_FreeTag(PU_PATCH); - Z_FreeTag(PU_HUDGFX); - Z_FreeTag(PU_HWRPATCHINFO); - Z_FreeTag(PU_HWRMODELTEXTURE); - Z_FreeTag(PU_HWRCACHE); - Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRMODELTEXTURE_UNLOCKED); - } - needpatchflush = false; -} - // ========================================================================== // W_CacheLumpName // ========================================================================== @@ -1674,9 +1668,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { lumpcache_t *lumpcache = NULL; - if (needpatchflush) - W_FlushCachedPatches(); - if (!TestValidLump(wad, lump)) return NULL; @@ -1727,9 +1718,6 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) GLPatch_t *grPatch; #endif - if (needpatchflush) - W_FlushCachedPatches(); - if (!TestValidLump(wad, lump)) return NULL; @@ -1778,7 +1766,7 @@ void W_UnlockCachedPatch(void *patch) // The hardware code does its own memory management, as its patches // have different lifetimes from software's. #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_UnlockCachedPatch((GLPatch_t*)patch); else #endif diff --git a/src/w_wad.h b/src/w_wad.h index 88b542fca..fddc65529 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -210,7 +210,6 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag); void W_UnlockCachedPatch(void *patch); -void W_FlushCachedPatches(void); void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 986eb32dc..3f6c5e290 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -106,6 +106,7 @@ static loadfunc_t hwdFuncTable[] = { {"SetBlend@4", &hwdriver.pfnSetBlend}, {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, {"SetTexture@4", &hwdriver.pfnSetTexture}, + {"UpdateTexture@4", &hwdriver.pfnUpdateTexture}, {"ReadRect@24", &hwdriver.pfnReadRect}, {"GClipRect@20", &hwdriver.pfnGClipRect}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, @@ -120,7 +121,7 @@ static loadfunc_t hwdFuncTable[] = { {"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures}, {"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe}, {"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe}, - {"DoScreenWipe@4", &hwdriver.pfnDoScreenWipe}, + {"DoScreenWipe@0", &hwdriver.pfnDoScreenWipe}, {"DrawIntermissionBG@0",&hwdriver.pfnDrawIntermissionBG}, {"MakeScreenTexture@0", &hwdriver.pfnMakeScreenTexture}, {"MakeScreenFinalTexture@0", &hwdriver.pfnMakeScreenFinalTexture}, @@ -137,6 +138,7 @@ static loadfunc_t hwdFuncTable[] = { {"SetBlend", &hwdriver.pfnSetBlend}, {"ClearBuffer", &hwdriver.pfnClearBuffer}, {"SetTexture", &hwdriver.pfnSetTexture}, + {"UpdateTexture", &hwdriver.pfnUpdateTexture}, {"ReadRect", &hwdriver.pfnReadRect}, {"GClipRect", &hwdriver.pfnGClipRect}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 5fa219586..0f1144a84 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -366,6 +366,9 @@ void I_FinishUpdate(void) if (I_SkipFrame()) return; + if (marathonmode) + SCR_DisplayMarathonInfo(); + // draw captions if enabled if (cv_closedcaptioning.value) SCR_ClosedCaptions(); diff --git a/src/y_inter.c b/src/y_inter.c index 2fe0de605..c32182518 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -392,7 +392,7 @@ dontdrawbg: if (gottoken) // first to be behind everything else Y_IntermissionTokenDrawer(); - if (!splitscreen) + if (!splitscreen) // there's not enough room in splitscreen, don't even bother trying! { // draw score ST_DrawPatchFromHud(HUD_SCORE, sboscore); @@ -414,7 +414,7 @@ dontdrawbg: ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds - if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking) // there's not enough room for tics in splitscreen, don't even bother trying! + if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking || marathonmode) { ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics @@ -1004,7 +1004,7 @@ void Y_Ticker(void) { INT32 i; UINT32 oldscore = data.coop.score; - boolean skip = false; + boolean skip = (marathonmode) ? true : false; boolean anybonuses = false; if (!intertic) // first time only @@ -1080,7 +1080,7 @@ void Y_Ticker(void) { INT32 i; UINT32 oldscore = data.spec.score; - boolean skip = false, super = false, anybonuses = false; + boolean skip = (marathonmode) ? true : false, super = false, anybonuses = false; if (!intertic) // first time only { diff --git a/src/z_zone.c b/src/z_zone.c index 96dcd0cba..2387a1143 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -499,17 +499,14 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) // Utility functions // ----------------- -// for renderer switching, free a bunch of stuff +// for renderer switching boolean needpatchflush = false; boolean needpatchrecache = false; // flush all patches from memory -// (also frees memory tagged with PU_CACHE) -// (which are not necessarily patches but I don't care) void Z_FlushCachedPatches(void) { CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); - Z_FreeTag(PU_CACHE); Z_FreeTag(PU_PATCH); Z_FreeTag(PU_HUDGFX); Z_FreeTag(PU_HWRPATCHINFO); @@ -808,7 +805,7 @@ static void Command_Memfree_f(void) sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10)); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10));