- implement Eternity-Style flat and horizon portals. Not tested yet due to lack of material to work with.

This commit is contained in:
Christoph Oelckers 2016-01-11 15:07:58 +01:00
parent ab1bf2bca3
commit ef7bcb3a66
7 changed files with 1426 additions and 1263 deletions

View file

@ -45,6 +45,7 @@
#include "c_dispatch.h" #include "c_dispatch.h"
#include "doomstat.h" #include "doomstat.h"
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "r_sky.h"
#include "gl/system/gl_interface.h" #include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h" #include "gl/system/gl_framebuffer.h"
@ -533,7 +534,7 @@ void GLPortal::EndFrame()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Renders one sky portal without a stencil. // Renders one sky portal without a stencil.
// In more complex scenes using a stencil for skies can severly stall // In more complex scenes using a stencil for skies can severely stall
// the GPU and there's rarely more than one sky visible at a time. // the GPU and there's rarely more than one sky visible at a time.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1080,6 +1081,69 @@ void GLHorizonPortal::DrawContents()
gl_RenderState.EnableTextureMatrix(false); gl_RenderState.EnableTextureMatrix(false);
PortalAll.Unclock(); PortalAll.Unclock();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
// Eternity-style horizon portal
//
// To the rest of the engine these masquerade as a skybox portal
// Internally they need to draw two horizon or sky portals
// and will use the respective classes to achieve that.
//
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void GLEEHorizonPortal::DrawContents()
{
PortalAll.Clock();
if (origin->Sector->GetTexture(sector_t::floor) == skyflatnum ||
origin->Sector->GetTexture(sector_t::ceiling) == skyflatnum)
{
GLSkyInfo skyinfo;
skyinfo.init(origin->Sector->sky, 0);
GLSkyPortal sky(&skyinfo, true);
sky.DrawContents();
}
if (origin->Sector->GetTexture(sector_t::ceiling) != skyflatnum)
{
GLHorizonInfo horz;
horz.plane.GetFromSector(origin->Sector, true);
horz.lightlevel = gl_ClampLight(origin->Sector->GetCeilingLight());
horz.colormap = origin->Sector->ColorMap;
if (origin->flags & MF_FLOAT)
{
horz.plane.texheight = viewz + abs(horz.plane.texheight);
}
GLHorizonPortal ceil(&horz, true);
ceil.DrawContents();
}
if (origin->Sector->GetTexture(sector_t::floor) != skyflatnum)
{
GLHorizonInfo horz;
horz.plane.GetFromSector(origin->Sector, false);
horz.lightlevel = gl_ClampLight(origin->Sector->GetFloorLight());
horz.colormap = origin->Sector->ColorMap;
if (origin->flags & MF_FLOAT)
{
horz.plane.texheight = viewz - abs(horz.plane.texheight);
}
GLHorizonPortal floor(&horz, true);
floor.DrawContents();
}
} }
const char *GLSkyPortal::GetName() { return "Sky"; } const char *GLSkyPortal::GetName() { return "Sky"; }
@ -1088,3 +1152,5 @@ const char *GLSectorStackPortal::GetName() { return "Sectorstack"; }
const char *GLPlaneMirrorPortal::GetName() { return "Planemirror"; } const char *GLPlaneMirrorPortal::GetName() { return "Planemirror"; }
const char *GLMirrorPortal::GetName() { return "Mirror"; } const char *GLMirrorPortal::GetName() { return "Mirror"; }
const char *GLHorizonPortal::GetName() { return "Horizon"; } const char *GLHorizonPortal::GetName() { return "Horizon"; }
const char *GLEEHorizonPortal::GetName() { return "EEHorizon"; }

View file

@ -70,11 +70,13 @@ struct GLSkyInfo
{ {
return !!memcmp(this, &inf, sizeof(*this)); return !!memcmp(this, &inf, sizeof(*this));
} }
void init(int sky1, PalEntry fadecolor);
}; };
extern UniqueList<GLSkyInfo> UniqueSkies; extern UniqueList<GLSkyInfo> UniqueSkies;
extern UniqueList<GLHorizonInfo> UniqueHorizons; extern UniqueList<GLHorizonInfo> UniqueHorizons;
extern UniqueList<secplane_t> UniquePlaneMirrors; extern UniqueList<secplane_t> UniquePlaneMirrors;
struct GLEEHorizonPortal;
class GLPortal class GLPortal
{ {
@ -110,7 +112,7 @@ protected:
TArray<GLWall> lines; TArray<GLWall> lines;
int level; int level;
GLPortal() { portals.Push(this); } GLPortal(bool local = false) { if (!local) portals.Push(this); }
virtual ~GLPortal() { } virtual ~GLPortal() { }
bool Start(bool usestencil, bool doquery); bool Start(bool usestencil, bool doquery);
@ -215,6 +217,7 @@ public:
struct GLSkyPortal : public GLPortal struct GLSkyPortal : public GLPortal
{ {
GLSkyInfo * origin; GLSkyInfo * origin;
friend struct GLEEHorizonPortal;
protected: protected:
virtual void DrawContents(); virtual void DrawContents();
@ -226,7 +229,8 @@ protected:
public: public:
GLSkyPortal(GLSkyInfo * pt) GLSkyPortal(GLSkyInfo * pt, bool local = false)
: GLPortal(local)
{ {
origin=pt; origin=pt;
} }
@ -281,6 +285,7 @@ public:
struct GLHorizonPortal : public GLPortal struct GLHorizonPortal : public GLPortal
{ {
GLHorizonInfo * origin; GLHorizonInfo * origin;
friend struct GLEEHorizonPortal;
protected: protected:
virtual void DrawContents(); virtual void DrawContents();
@ -291,7 +296,28 @@ protected:
public: public:
GLHorizonPortal(GLHorizonInfo * pt) GLHorizonPortal(GLHorizonInfo * pt, bool local = false)
: GLPortal(local)
{
origin=pt;
}
};
struct GLEEHorizonPortal : public GLPortal
{
AActor * origin;
protected:
virtual void DrawContents();
virtual void * GetSource() const { return origin; }
virtual bool NeedDepthBuffer() { return false; }
virtual bool NeedCap() { return false; }
virtual const char *GetName();
public:
GLEEHorizonPortal(AActor *pt)
{ {
origin=pt; origin=pt;
} }

View file

@ -63,6 +63,72 @@ enum
}; };
//==========================================================================
//
// Set up the skyinfo struct
//
//==========================================================================
void GLSkyInfo::init(int sky1, PalEntry FadeColor)
{
memset(this, 0, sizeof(*this));
if ((sky1 & PL_SKYFLAT) && (sky1 & (PL_SKYFLAT - 1)))
{
const line_t *l = &lines[(sky1&(PL_SKYFLAT - 1)) - 1];
const side_t *s = l->sidedef[0];
int pos;
if (level.flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid())
{
pos = side_t::bottom;
}
else
{
pos = side_t::top;
}
FTextureID texno = s->GetTexture(pos);
texture[0] = FMaterial::ValidateTexture(texno, false, true);
if (!texture[0] || texture[0]->tex->UseType == FTexture::TEX_Null) goto normalsky;
skytexno1 = texno;
x_offset[0] = ANGLE_TO_FLOAT(s->GetTextureXOffset(pos));
y_offset = FIXED2FLOAT(s->GetTextureYOffset(pos));
mirrored = !l->args[2];
}
else
{
normalsky:
if (level.flags&LEVEL_DOUBLESKY)
{
texture[1] = FMaterial::ValidateTexture(sky1texture, false, true);
x_offset[1] = GLRenderer->mSky1Pos;
doublesky = true;
}
if ((level.flags&LEVEL_SWAPSKIES || (sky1 == PL_SKYFLAT) || (level.flags&LEVEL_DOUBLESKY)) &&
sky2texture != sky1texture) // If both skies are equal use the scroll offset of the first!
{
texture[0] = FMaterial::ValidateTexture(sky2texture, false, true);
skytexno1 = sky2texture;
sky2 = true;
x_offset[0] = GLRenderer->mSky2Pos;
}
else if (!doublesky)
{
texture[0] = FMaterial::ValidateTexture(sky1texture, false, true);
skytexno1 = sky1texture;
x_offset[0] = GLRenderer->mSky1Pos;
}
}
if (skyfog > 0)
{
fadecolor = FadeColor;
fadecolor.a = 0;
}
else fadecolor = 0;
}
//========================================================================== //==========================================================================
// //
// Calculate sky texture // Calculate sky texture
@ -92,63 +158,7 @@ void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect)
} }
else else
{ {
int sky1 = sector->sky; skyinfo.init(sector->sky, Colormap.FadeColor);
memset(&skyinfo, 0, sizeof(skyinfo));
if ((sky1 & PL_SKYFLAT) && (sky1 & (PL_SKYFLAT-1)))
{
const line_t *l = &lines[(sky1&(PL_SKYFLAT-1))-1];
const side_t *s = l->sidedef[0];
int pos;
if (level.flags & LEVEL_SWAPSKIES && s->GetTexture(side_t::bottom).isValid())
{
pos = side_t::bottom;
}
else
{
pos = side_t::top;
}
FTextureID texno = s->GetTexture(pos);
skyinfo.texture[0] = FMaterial::ValidateTexture(texno, false, true);
if (!skyinfo.texture[0] || skyinfo.texture[0]->tex->UseType == FTexture::TEX_Null) goto normalsky;
skyinfo.skytexno1 = texno;
skyinfo.x_offset[0] = ANGLE_TO_FLOAT(s->GetTextureXOffset(pos));
skyinfo.y_offset = FIXED2FLOAT(s->GetTextureYOffset(pos));
skyinfo.mirrored = !l->args[2];
}
else
{
normalsky:
if (level.flags&LEVEL_DOUBLESKY)
{
skyinfo.texture[1]=FMaterial::ValidateTexture(sky1texture, false, true);
skyinfo.x_offset[1] = GLRenderer->mSky1Pos;
skyinfo.doublesky = true;
}
if ((level.flags&LEVEL_SWAPSKIES || (sky1==PL_SKYFLAT) || (level.flags&LEVEL_DOUBLESKY)) &&
sky2texture!=sky1texture) // If both skies are equal use the scroll offset of the first!
{
skyinfo.texture[0]=FMaterial::ValidateTexture(sky2texture, false, true);
skyinfo.skytexno1=sky2texture;
skyinfo.sky2 = true;
skyinfo.x_offset[0] = GLRenderer->mSky2Pos;
}
else
{
skyinfo.texture[0]=FMaterial::ValidateTexture(sky1texture, false, true);
skyinfo.skytexno1=sky1texture;
skyinfo.x_offset[0] = GLRenderer->mSky1Pos;
}
}
if (skyfog>0)
{
skyinfo.fadecolor=Colormap.FadeColor;
skyinfo.fadecolor.a=0;
}
else skyinfo.fadecolor=0;
type = RENDERWALL_SKY; type = RENDERWALL_SKY;
sky=UniqueSkies.Get(&skyinfo); sky=UniqueSkies.Get(&skyinfo);
} }
@ -194,7 +204,7 @@ void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex
{ {
if (fs->GetTexture(sector_t::ceiling)==skyflatnum) if (fs->GetTexture(sector_t::ceiling)==skyflatnum)
{ {
if ((bs->special&0xff) == NoSkyDraw) return; if (bs->special == NoSkyDraw) return;
if (bs->GetTexture(sector_t::ceiling)==skyflatnum) if (bs->GetTexture(sector_t::ceiling)==skyflatnum)
{ {
// if the back sector is closed the sky must be drawn! // if the back sector is closed the sky must be drawn!
@ -285,7 +295,7 @@ void GLWall::SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,ver
{ {
if (fs->GetTexture(sector_t::floor)==skyflatnum) if (fs->GetTexture(sector_t::floor)==skyflatnum)
{ {
if ((bs->special&0xff) == NoSkyDraw) return; if (bs->special == NoSkyDraw) return;
FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::bottom)); FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::bottom));
// For lower skies the normal logic only applies to walls with no lower texture! // For lower skies the normal logic only applies to walls with no lower texture!

View file

@ -177,7 +177,12 @@ void GLWall::PutWall(bool translucent)
case RENDERWALL_SKYBOX: case RENDERWALL_SKYBOX:
portal = GLPortal::FindPortal(skybox); portal = GLPortal::FindPortal(skybox);
if (!portal) portal=new GLSkyboxPortal(skybox); if (!portal)
{
// either a regulat skybox or an Eternity-style horizon
if (skybox->flags7 & MF7_HANDLENODELAY) portal = new GLEEHorizonPortal(skybox);
else portal = new GLSkyboxPortal(skybox);
}
portal->AddLine(this); portal->AddLine(this);
break; break;

View file

@ -65,6 +65,7 @@
// State. // State.
#include "r_state.h" #include "r_state.h"
#include "r_sky.h"
#include "c_console.h" #include "c_console.h"
@ -986,7 +987,7 @@ void P_SetupPortals()
} }
} }
inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t alpha) inline void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, fixed_t alpha)
{ {
// plane: 0=floor, 1=ceiling, 2=both // plane: 0=floor, 1=ceiling, 2=both
if (plane > 0) if (plane > 0)
@ -996,6 +997,8 @@ inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t
sector->CeilingSkyBox = portal; sector->CeilingSkyBox = portal;
if (sector->GetAlpha(sector_t::ceiling) == OPAQUE) if (sector->GetAlpha(sector_t::ceiling) == OPAQUE)
sector->SetAlpha(sector_t::ceiling, alpha); sector->SetAlpha(sector_t::ceiling, alpha);
if (!portal->bAlways) sector->SetTexture(sector_t::ceiling, skyflatnum);
} }
} }
if (plane == 2 || plane == 0) if (plane == 2 || plane == 0)
@ -1006,6 +1009,8 @@ inline void SetPortal(sector_t *sector, int plane, AStackPoint *portal, fixed_t
} }
if (sector->GetAlpha(sector_t::floor) == OPAQUE) if (sector->GetAlpha(sector_t::floor) == OPAQUE)
sector->SetAlpha(sector_t::floor, alpha); sector->SetAlpha(sector_t::floor, alpha);
if (!portal->bAlways) sector->SetTexture(sector_t::floor, skyflatnum);
} }
} }
@ -1076,6 +1081,47 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
} }
void P_SpawnHorizon(line_t *line)
{
ASkyViewpoint *origin = Spawn<ASkyViewpoint>(0, 0, 0, NO_REPLACE);
origin->Sector = line->frontsector;
origin->flags7 |= MF7_HANDLENODELAY; // mark as 'special'
if (line->args[1] == 3) origin->flags |= MF_FLOAT; // well, it actually does 'float'... :P
int s;
FSectorTagIterator itr(line->args[0]);
while ((s = itr.Next()) >= 0)
{
SetPortal(&sectors[s], line->args[2], origin, 0);
}
for (int j=0;j<numlines;j++)
{
// Check if this portal needs to be copied to other sectors
// This must be done here to ensure that it gets done only after the portal is set up
if (lines[j].special == Sector_SetPortal &&
lines[j].args[1] == 1 &&
(lines[j].args[2] == line->args[2] || lines[j].args[2] == 3) &&
lines[j].args[3] == line->args[0])
{
if (lines[j].args[0] == 0)
{
SetPortal(lines[j].frontsector, line->args[2], origin, 0);
}
else
{
FSectorTagIterator itr(lines[j].args[0]);
while ((s = itr.Next()) >= 0)
{
SetPortal(&sectors[s], line->args[2], origin, 0);
}
}
}
}
}
// //
// P_SetSectorDamage // P_SetSectorDamage
// //
@ -1408,6 +1454,8 @@ void P_SpawnSpecials (void)
// - 0: normal (handled here) // - 0: normal (handled here)
// - 1: copy (handled by the portal they copy) // - 1: copy (handled by the portal they copy)
// - 2: EE-style skybox (handled by the camera object) // - 2: EE-style skybox (handled by the camera object)
// - 3: EE-style flat portal (HW renderer only for now)
// - 4: EE-style horizon portal (HW renderer only for now)
// other values reserved for later use // other values reserved for later use
// arg 2 = 0:floor, 1:ceiling, 2:both // arg 2 = 0:floor, 1:ceiling, 2:both
// arg 3 = 0: anchor, 1: reference line // arg 3 = 0: anchor, 1: reference line
@ -1416,6 +1464,10 @@ void P_SpawnSpecials (void)
{ {
P_SpawnPortal(&lines[i], lines[i].args[0], lines[i].args[2], lines[i].args[4]); P_SpawnPortal(&lines[i], lines[i].args[0], lines[i].args[2], lines[i].args[4]);
} }
else if (lines[i].args[1] == 3 || lines[i].args[1] == 4)
{
P_SpawnHorizon(&lines[i]);
}
break; break;
// [RH] ZDoom Static_Init settings // [RH] ZDoom Static_Init settings

View file

@ -1088,6 +1088,7 @@ void R_Subsector (subsector_t *sub)
} }
skybox = frontsector->GetSkyBox(sector_t::ceiling); skybox = frontsector->GetSkyBox(sector_t::ceiling);
if (skybox->flags7 & MF7_HANDLENODELAY) skybox = NULL; // HW renderer only.
ceilingplane = frontsector->ceilingplane.PointOnSide(viewx, viewy, viewz) > 0 || ceilingplane = frontsector->ceilingplane.PointOnSide(viewx, viewy, viewz) > 0 ||
frontsector->GetTexture(sector_t::ceiling) == skyflatnum || frontsector->GetTexture(sector_t::ceiling) == skyflatnum ||
@ -1128,7 +1129,10 @@ void R_Subsector (subsector_t *sub)
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/7/98: Add (x,y) offsets to flats, add deep water check
// killough 3/16/98: add floorlightlevel // killough 3/16/98: add floorlightlevel
// killough 10/98: add support for skies transferred from sidedefs // killough 10/98: add support for skies transferred from sidedefs
skybox = frontsector->GetSkyBox(sector_t::floor); skybox = frontsector->GetSkyBox(sector_t::floor);
if (skybox->flags7 & MF7_HANDLENODELAY) skybox = NULL; // HW renderer only.
floorplane = frontsector->floorplane.PointOnSide(viewx, viewy, viewz) > 0 || // killough 3/7/98 floorplane = frontsector->floorplane.PointOnSide(viewx, viewy, viewz) > 0 || // killough 3/7/98
frontsector->GetTexture(sector_t::floor) == skyflatnum || frontsector->GetTexture(sector_t::floor) == skyflatnum ||
(skybox != NULL && skybox->bAlways) || (skybox != NULL && skybox->bAlways) ||