Add visplane portal creation functionality and use it to replace the skybox rendering.

The skybox rendering process has been replaced with portals instead. Those are generated after the first BSP tree pass by looking for existing sky visplanes at the time, and their windows are used to define new portals.
The skybox portals are still incomplete and cause visual glitches when masked elements are involved.
This commit is contained in:
Nev3r 2019-06-01 21:26:25 +02:00
parent df0a40b3c2
commit 264386f842
10 changed files with 126 additions and 70 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;
}
// =========================================================================

View File

@ -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);

View File

@ -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);
}

View File

@ -120,4 +120,6 @@ typedef struct planemgr_s
extern visffloor_t ffloor[MAXFFLOORS];
extern INT32 numffloors;
void Portal_AddSkyboxPortals (void);
#endif

View File

@ -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;
}

View File

@ -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);

View File

@ -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;