diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b1811eb45..c79452bb5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6194,7 +6194,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) } // note: sets viewangle, viewx, viewy, viewz - R_SetupFrame(player, false); // This can stay false because it is only used to set viewsky in r_main.c, which isn't used here + R_SetupFrame(player); // copy view cam position for local use dup_viewx = viewx; diff --git a/src/p_setup.c b/src/p_setup.c index 0602865a9..af4f1f9dd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3147,7 +3147,6 @@ boolean P_SetupLevel(boolean skipprecip) savedata.lives = 0; } - skyVisible = skyVisible1 = skyVisible2 = true; // assume the skybox is visible on level load. if (loadprecip) // uglier hack { // to make a newly loaded level start on the second frame. INT32 buf = gametic % BACKUPTICS; diff --git a/src/r_bsp.c b/src/r_bsp.c index 5643e777e..58d69ddf4 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -15,6 +15,7 @@ #include "g_game.h" #include "r_local.h" #include "r_state.h" +#include "r_portal.h" // Add seg portals #include "r_splats.h" #include "p_local.h" // camera diff --git a/src/r_main.c b/src/r_main.c index cab0490bf..c9513e390 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -66,8 +66,6 @@ size_t loopcount; fixed_t viewx, viewy, viewz; angle_t viewangle, aimingangle; fixed_t viewcos, viewsin; -boolean viewsky, skyVisible; -boolean skyVisible1, skyVisible2; // saved values of skyVisible for P1 and P2, for splitscreen sector_t *viewsector; player_t *viewplayer; @@ -739,7 +737,7 @@ static void R_SetupFreelook(void) #undef AIMINGTODY -void R_SetupFrame(player_t *player, boolean skybox) +void R_SetupFrame(player_t *player) { camera_t *thiscam; boolean chasecam = false; @@ -769,7 +767,6 @@ void R_SetupFrame(player_t *player, boolean skybox) else if (!chasecam) thiscam->chase = false; - viewsky = !skybox; if (player->awayviewtics) { // cut-away view stuff @@ -858,7 +855,6 @@ void R_SkyboxFrame(player_t *player) thiscam = &camera; // cut-away view stuff - viewsky = true; viewmobj = skyboxmo[0]; #ifdef PARANOIA if (!viewmobj) @@ -1022,9 +1018,6 @@ static void R_PortalFrame(portal_t *portal) void R_RenderPlayerView(player_t *player) { - portal_t *portal; - const boolean skybox = (skyboxmo[0] && cv_skybox.value); - if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1 { if (cv_homremoval.value == 1) @@ -1033,37 +1026,7 @@ void R_RenderPlayerView(player_t *player) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 32+(timeinmap&15)); } - // load previous saved value of skyVisible for the player - if (splitscreen && player == &players[secondarydisplayplayer]) - skyVisible = skyVisible2; - else - skyVisible = skyVisible1; - - Portal_InitList(); - - if (skybox && skyVisible) - { - R_SkyboxFrame(player); - - R_ClearClipSegs(); - R_ClearDrawSegs(); - R_ClearPlanes(); - R_ClearSprites(); -#ifdef FLOORSPLATS - R_ClearVisibleFloorSplats(); -#endif - - R_RenderBSPNode((INT32)numnodes - 1); - R_ClipSprites(); - R_DrawPlanes(); -#ifdef FLOORSPLATS - R_DrawVisibleFloorSplats(); -#endif - R_DrawMasked(); - } - - R_SetupFrame(player, skybox); - skyVisible = false; + R_SetupFrame(player); framecount++; validcount++; @@ -1075,6 +1038,7 @@ void R_RenderPlayerView(player_t *player) #ifdef FLOORSPLATS R_ClearVisibleFloorSplats(); #endif + Portal_InitList(); // check for new console commands. NetUpdate(); @@ -1086,7 +1050,9 @@ void R_RenderPlayerView(player_t *player) mytotal = 0; ProfZeroTimer(); #endif + R_RenderBSPNode((INT32)numnodes - 1); + R_ClipSprites(); #ifdef TIMING RDMSR(0x10, &mycount); @@ -1096,9 +1062,15 @@ void R_RenderPlayerView(player_t *player) #endif //profile stuff --------------------------------------------------------- + // Add skybox portals caused by sky visplanes. + if (cv_skybox.value) + Portal_AddSkyboxPortals(); + // Portal rendering. Hijacks the BSP traversal. if (portal_base) { + portal_t *portal; + for(portal = portal_base; portal; portal = portal_base) { portalrender = portal->pass; // Recursiveness depth. @@ -1135,16 +1107,6 @@ void R_RenderPlayerView(player_t *player) // draw mid texture and sprite // And now 3D floors/sides! R_DrawMasked(); - - // Check for new console commands. - NetUpdate(); - - // save value to skyVisible1 or skyVisible2 - // this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa - if (splitscreen && player == &players[secondarydisplayplayer]) - skyVisible2 = skyVisible; - else - skyVisible1 = skyVisible; } // ========================================================================= diff --git a/src/r_main.h b/src/r_main.h index 6ae5aa221..1d82a01b9 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -94,7 +94,7 @@ void R_ExecuteSetViewSize(void); void R_SkyboxFrame(player_t *player); -void R_SetupFrame(player_t *player, boolean skybox); +void R_SetupFrame(player_t *player); // Called by G_Drawer. void R_RenderPlayerView(player_t *player); diff --git a/src/r_plane.c b/src/r_plane.c index 5cd9b26b5..18e5fda52 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -23,6 +23,8 @@ #include "r_state.h" #include "r_splats.h" // faB(21jan):testing #include "r_sky.h" +#include "r_portal.h" + #include "v_video.h" #include "w_wad.h" #include "z_zone.h" @@ -679,16 +681,6 @@ static void R_DrawSkyPlane(visplane_t *pl) INT32 x; INT32 angle; - // If we're not supposed to draw the sky (e.g. for skyboxes), don't do anything! - // This probably utterly ruins sky rendering for FOFs and polyobjects, unfortunately - if (!viewsky) - { - // Mark that the sky was visible here for next tic - // (note: this is a hack and it sometimes can cause HOMs to appear for a tic IIRC) - skyVisible = true; - return; - } - // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) // (that is, unless we'll need to switch drawers in future for some reason) wallcolfunc = walldrawerfunc; @@ -1186,3 +1178,31 @@ void R_PlaneBounds(visplane_t *plane) plane->high = hi; plane->low = low; } + +/** Creates portals for the currently existing sky visplanes. + * The visplanes are also removed and cleared from the list. + */ +void Portal_AddSkyboxPortals (void) +{ + visplane_t *pl; + INT32 i; + UINT16 count = 0; + + for (i = 0; i < MAXVISPLANES; i++, pl++) + { + for (pl = visplanes[i]; pl; pl = pl->next) + { + if (pl->picnum == skyflatnum) + { + Portal_AddSkybox(pl); + + pl->minx = 0; + pl->maxx = -1; + + count++; + } + } + } + + CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count); +} diff --git a/src/r_plane.h b/src/r_plane.h index bdfc40058..c101e3218 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -120,4 +120,6 @@ typedef struct planemgr_s extern visffloor_t ffloor[MAXFFLOORS]; extern INT32 numffloors; + +void Portal_AddSkyboxPortals (void); #endif diff --git a/src/r_portal.c b/src/r_portal.c index 2675ae968..15efc79ba 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -13,7 +13,9 @@ #include "r_portal.h" #include "r_plane.h" -#include "r_main.h" // viewheight, viewwidth +#include "r_main.h" +#include "doomstat.h" +#include "p_spec.h" // Skybox viewpoints #include "z_zone.h" UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */ @@ -39,7 +41,7 @@ void Portal_InitList (void) * the function is called, so it is useful for converting one-sided * lines into portals. */ -void Portal_ClipStoreFromRange (portal_t* portal) +void Portal_ClipRange (portal_t* portal) { INT32 start = portal->start; INT32 end = portal->end; @@ -179,9 +181,80 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con portal->clipline = line2; - Portal_ClipStoreFromRange(portal); + Portal_ClipRange(portal); portalline = true; // this tells R_StoreWallRange that curline is a portal seg } +/** Store the clipping window for a portal using a visplane. + * + * Since visplanes top/bottom windows work in an identical way, + * it can just be copied almost directly. + */ +static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal) +{ + INT16 start = portal->start; + INT16 end = portal->end; + INT32 i; + for (i = 0; i < end - start; i++) + { + portal->ceilingclip[i] = plane->top[i + start]; + portal->floorclip[i] = plane->bottom[i + start] + 1; + } +} + +extern INT32 viewwidth; + +/** Creates a skybox portal out of a visplane. + * + * Applies the necessary offsets and rotation to give + * a depth illusion to the skybox. + */ +void Portal_AddSkybox (const visplane_t* plane) +{ + INT16 start = plane->minx; + INT16 end = plane->maxx + 1; + mapheader_t *mh; + portal_t* portal; + + if (!(start < end)) + return; + + portal = Portal_Add(start, end); + + Portal_ClipVisplane(plane, portal); + + portal->viewx = skyboxmo[0]->x; + portal->viewy = skyboxmo[0]->y; + portal->viewz = skyboxmo[0]->z; + portal->viewangle = viewangle + skyboxmo[0]->angle; + + mh = mapheaderinfo[gamemap-1]; + + // If a relative viewpoint exists, offset the viewpoint. + if (skyboxmo[1]) + { + fixed_t x = 0, y = 0; + + if (mh->skybox_scalex > 0) + x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex; + else if (mh->skybox_scalex < 0) + x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex; + + if (mh->skybox_scaley > 0) + y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley; + else if (mh->skybox_scaley < 0) + y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley; + + portal->viewx += x; + portal->viewy += y; + } + + if (mh->skybox_scalez > 0) + portal->viewz += viewz / mh->skybox_scalez; + else if (mh->skybox_scalez < 0) + portal->viewz += viewz * -mh->skybox_scalez; + + portal->clipline = -1; +} diff --git a/src/r_portal.h b/src/r_portal.h index 8df3db415..9426aaf6a 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -12,9 +12,9 @@ /// \brief Software renderer portal struct, functions, linked list extern. #include "r_data.h" +#include "r_plane.h" // visplanes - -/** Portal structure. +/** Portal structure for the software renderer. */ typedef struct portal_s { @@ -44,6 +44,7 @@ extern UINT8 portalrender; void Portal_InitList (void); void Portal_Remove (portal_t* portal); void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); +void Portal_AddSkybox (const visplane_t* plane); -void Portal_ClipStoreFromRange (portal_t* portal); +void Portal_ClipRange (portal_t* portal); void Portal_ClipApply (const portal_t* portal); diff --git a/src/r_state.h b/src/r_state.h index 9c8ce51d6..4959b55bc 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -80,8 +80,6 @@ extern side_t *sides; // extern fixed_t viewx, viewy, viewz; extern angle_t viewangle, aimingangle; -extern boolean viewsky, skyVisible; -extern boolean skyVisible1, skyVisible2; // saved values of skyVisible for P1 and P2, for splitscreen extern sector_t *viewsector; extern player_t *viewplayer; extern UINT8 portalrender;