mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 20:20:40 +00:00
- added the DrawInfo class.
This commit is contained in:
parent
e9dd1c104b
commit
af6c6c8ef0
7 changed files with 1954 additions and 9 deletions
|
@ -1075,6 +1075,8 @@ set (PCH_SOURCES
|
|||
core/rendering/scene/hw_walls.cpp
|
||||
core/rendering/render.cpp
|
||||
core/rendering/scene/hw_drawlistadd.cpp
|
||||
core/rendering/scene/hw_drawlist.cpp
|
||||
core/rendering/scene/hw_drawinfo.cpp
|
||||
|
||||
core/console/c_notifybuffer.cpp
|
||||
core/console/d_event.cpp
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include "tarray.h"
|
||||
#include "vectors.h"
|
||||
|
||||
struct FLevelLocals;
|
||||
|
||||
namespace hwrenderer
|
||||
{
|
||||
|
||||
|
|
601
source/core/rendering/scene/hw_drawinfo.cpp
Normal file
601
source/core/rendering/scene/hw_drawinfo.cpp
Normal file
|
@ -0,0 +1,601 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2000-2018 Christoph Oelckers
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_drawinfo.cpp
|
||||
** Basic scene draw info management class
|
||||
**
|
||||
*/
|
||||
|
||||
#include "hw_portal.h"
|
||||
#include "build.h"
|
||||
#include "hw_renderstate.h"
|
||||
#include "hw_drawinfo.h"
|
||||
//#include "models.h"
|
||||
#include "hw_clock.h"
|
||||
#include "hw_cvars.h"
|
||||
#include "hw_viewpointbuffer.h"
|
||||
#include "flatvertices.h"
|
||||
#include "hw_lightbuffer.h"
|
||||
#include "hw_vrmodes.h"
|
||||
#include "hw_clipper.h"
|
||||
#include "v_draw.h"
|
||||
|
||||
EXTERN_CVAR(Float, r_visibility)
|
||||
CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE)
|
||||
CVAR(Bool, gl_sort_textures, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Int, gl_enhanced_nv_stealth, 3, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
CVAR(Bool, gl_texture, true, 0)
|
||||
CVAR(Float, gl_mask_threshold, 0.5f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
CVAR(Float, gl_mask_sprite_threshold, 0.5f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FDrawInfoList
|
||||
{
|
||||
public:
|
||||
TDeletingArray<HWDrawInfo *> mList;
|
||||
|
||||
HWDrawInfo * GetNew();
|
||||
void Release(HWDrawInfo *);
|
||||
};
|
||||
|
||||
|
||||
FDrawInfoList di_list;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Try to reuse the lists as often as possible as they contain resources that
|
||||
// are expensive to create and delete.
|
||||
//
|
||||
// Note: If multithreading gets used, this class needs synchronization.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
HWDrawInfo *FDrawInfoList::GetNew()
|
||||
{
|
||||
if (mList.Size() > 0)
|
||||
{
|
||||
HWDrawInfo *di;
|
||||
mList.Pop(di);
|
||||
return di;
|
||||
}
|
||||
return new HWDrawInfo();
|
||||
}
|
||||
|
||||
void FDrawInfoList::Release(HWDrawInfo * di)
|
||||
{
|
||||
di->ClearBuffers();
|
||||
mList.Push(di);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Sets up a new drawinfo struct
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
HWDrawInfo *HWDrawInfo::StartDrawInfo(HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms)
|
||||
{
|
||||
HWDrawInfo *di = di_list.GetNew();
|
||||
di->StartScene(parentvp, uniforms);
|
||||
return di;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper.
|
||||
static HWDrawInfo * gl_drawinfo; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope.
|
||||
|
||||
void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms)
|
||||
{
|
||||
staticClipper.Clear();
|
||||
mClipper = &staticClipper;
|
||||
|
||||
Viewpoint = parentvp;
|
||||
//lightmode = Level->lightMode;
|
||||
if (uniforms)
|
||||
{
|
||||
VPUniforms = *uniforms;
|
||||
// The clip planes will never be inherited from the parent drawinfo.
|
||||
VPUniforms.mClipLine.X = -1000001.f;
|
||||
VPUniforms.mClipHeight = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
VPUniforms.mProjectionMatrix.loadIdentity();
|
||||
VPUniforms.mViewMatrix.loadIdentity();
|
||||
VPUniforms.mNormalViewMatrix.loadIdentity();
|
||||
//VPUniforms.mViewHeight = viewheight;
|
||||
VPUniforms.mGlobVis = 1 / 64.f;
|
||||
VPUniforms.mPalLightLevels = numshades | (static_cast<int>(gl_fogmode) << 8) | (5 << 16);
|
||||
|
||||
VPUniforms.mClipLine.X = -10000000.0f;
|
||||
VPUniforms.mShadowmapFilter = gl_shadowmap_filter;
|
||||
}
|
||||
mClipper->SetViewpoint(Viewpoint);
|
||||
|
||||
ClearBuffers();
|
||||
|
||||
for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset();
|
||||
hudsprites.Clear();
|
||||
vpIndex = 0;
|
||||
|
||||
// Fullbright information needs to be propagated from the main view.
|
||||
if (outer != nullptr) FullbrightFlags = outer->FullbrightFlags;
|
||||
else FullbrightFlags = 0;
|
||||
|
||||
outer = gl_drawinfo;
|
||||
gl_drawinfo = this;
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
HWDrawInfo *HWDrawInfo::EndDrawInfo()
|
||||
{
|
||||
assert(this == gl_drawinfo);
|
||||
for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset();
|
||||
gl_drawinfo = outer;
|
||||
di_list.Release(this);
|
||||
if (gl_drawinfo == nullptr)
|
||||
ResetRenderDataAllocator();
|
||||
return gl_drawinfo;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void HWDrawInfo::ClearBuffers()
|
||||
{
|
||||
HandledSubsectors.Clear();
|
||||
spriteindex = 0;
|
||||
|
||||
sector_renderflags.Resize(numsectors);
|
||||
memset(§or_renderflags[0], 0, numsectors * sizeof(sector_renderflags[0]));
|
||||
|
||||
Decals[0].Clear();
|
||||
Decals[1].Clear();
|
||||
|
||||
mClipPortal = nullptr;
|
||||
mCurrentPortal = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// R_FrustumAngle
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
angle_t HWDrawInfo::FrustumAngle()
|
||||
{
|
||||
float WidescreenRatio = 1.6666f; // fixme - this is a placeholder.
|
||||
float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees);
|
||||
|
||||
// If the pitch is larger than this you can look all around at a FOV of 90°
|
||||
if (tilt > 46.0f) return 0xffffffff;
|
||||
|
||||
// ok, this is a gross hack that barely works...
|
||||
// but at least it doesn't overestimate too much...
|
||||
double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(WidescreenRatio) / 90.0;
|
||||
angle_t a1 = DAngle(floatangle).BAMs();
|
||||
if (a1 >= ANGLE_180) return 0xffffffff;
|
||||
return a1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Setup the modelview matrix
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror)
|
||||
{
|
||||
float mult = mirror ? -1.f : 1.f;
|
||||
float planemult = planemirror ? -1 : 1;// Level->info->pixelstretch : Level->info->pixelstretch;
|
||||
|
||||
VPUniforms.mViewMatrix.loadIdentity();
|
||||
VPUniforms.mViewMatrix.rotate(angles.Roll.Degrees, 0.0f, 0.0f, 1.0f);
|
||||
VPUniforms.mViewMatrix.rotate(angles.Pitch.Degrees, 1.0f, 0.0f, 0.0f);
|
||||
VPUniforms.mViewMatrix.rotate(angles.Yaw.Degrees, 0.0f, mult, 0.0f);
|
||||
VPUniforms.mViewMatrix.translate(vx * mult, -vz * planemult, -vy);
|
||||
VPUniforms.mViewMatrix.scale(-mult, planemult, 1);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// SetupView
|
||||
// Setup the view rotation matrix for the given viewpoint
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void HWDrawInfo::SetupView(FRenderState &state, float vx, float vy, float vz, bool mirror, bool planemirror)
|
||||
{
|
||||
auto &vp = Viewpoint;
|
||||
//vp.SetViewAngle(r_viewwindow); // todo: need to pass in.
|
||||
SetViewMatrix(vp.HWAngles, vx, vy, vz, mirror, planemirror);
|
||||
SetCameraPos(vp.Pos);
|
||||
VPUniforms.CalcDependencies();
|
||||
vpIndex = screen->mViewpoints->SetViewpoint(state, &VPUniforms);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HWPortal * HWDrawInfo::FindPortal(const void * src)
|
||||
{
|
||||
int i = Portals.Size() - 1;
|
||||
|
||||
while (i >= 0 && Portals[i] && Portals[i]->GetSource() != src) i--;
|
||||
return i >= 0 ? Portals[i] : nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HWDecal* HWDrawInfo::AddDecal(bool onmirror)
|
||||
{
|
||||
#if 0
|
||||
auto decal = (HWDecal*)RenderDataAllocator.Alloc(sizeof(HWDecal));
|
||||
Decals[onmirror ? 1 : 0].Push(decal);
|
||||
return decal;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// CreateScene
|
||||
//
|
||||
// creates the draw lists for the current scene
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::CreateScene(bool drawpsprites)
|
||||
{
|
||||
const auto &vp = Viewpoint;
|
||||
angle_t a1 = FrustumAngle();
|
||||
mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1);
|
||||
|
||||
// reset the portal manager
|
||||
portalState.StartFrame();
|
||||
|
||||
ProcessAll.Clock();
|
||||
|
||||
// clip the scene and fill the drawlists
|
||||
screen->mVertexData->Map();
|
||||
screen->mLights->Map();
|
||||
|
||||
//RenderBSP(Level->HeadNode(), drawpsprites);
|
||||
|
||||
// And now the crappy hacks that have to be done to avoid rendering anomalies.
|
||||
// These cannot be multithreaded when the time comes because all these depend
|
||||
// on the global 'validcount' variable.
|
||||
|
||||
screen->mLights->Unmap();
|
||||
screen->mVertexData->Unmap();
|
||||
|
||||
ProcessAll.Unclock();
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// RenderScene
|
||||
//
|
||||
// Draws the current draw lists for the non GLSL renderer
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::RenderScene(FRenderState &state)
|
||||
{
|
||||
const auto &vp = Viewpoint;
|
||||
RenderAll.Clock();
|
||||
|
||||
state.SetDepthMask(true);
|
||||
|
||||
state.EnableFog(true);
|
||||
state.SetRenderStyle(STYLE_Source);
|
||||
|
||||
if (gl_sort_textures)
|
||||
{
|
||||
drawlists[GLDL_PLAINWALLS].SortWalls();
|
||||
drawlists[GLDL_PLAINFLATS].SortFlats();
|
||||
drawlists[GLDL_MASKEDWALLS].SortWalls();
|
||||
drawlists[GLDL_MASKEDFLATS].SortFlats();
|
||||
drawlists[GLDL_MASKEDWALLSOFS].SortWalls();
|
||||
}
|
||||
|
||||
// Part 1: solid geometry. This is set up so that there are no transparent parts
|
||||
state.SetDepthFunc(DF_Less);
|
||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
state.ClearDepthBias();
|
||||
|
||||
state.EnableTexture(gl_texture);
|
||||
state.EnableBrightmap(true);
|
||||
drawlists[GLDL_PLAINWALLS].DrawWalls(this, state, false);
|
||||
drawlists[GLDL_PLAINFLATS].DrawFlats(this, state, false);
|
||||
|
||||
|
||||
// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
|
||||
drawlists[GLDL_MASKEDWALLS].DrawWalls(this, state, false);
|
||||
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false);
|
||||
|
||||
// Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use.
|
||||
if (drawlists[GLDL_MASKEDWALLSOFS].Size() > 0)
|
||||
{
|
||||
state.SetDepthBias(-1, -128);
|
||||
drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(this, state, false);
|
||||
state.ClearDepthBias();
|
||||
}
|
||||
|
||||
drawlists[GLDL_MODELS].Draw(this, state, false);
|
||||
|
||||
state.SetRenderStyle(STYLE_Translucent);
|
||||
|
||||
// Part 4: Draw decals (not a real pass)
|
||||
state.SetDepthFunc(DF_LEqual);
|
||||
DrawDecals(state, Decals[0]);
|
||||
|
||||
RenderAll.Unclock();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// RenderTranslucent
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::RenderTranslucent(FRenderState &state)
|
||||
{
|
||||
RenderAll.Clock();
|
||||
|
||||
// final pass: translucent stuff
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
|
||||
state.SetRenderStyle(STYLE_Translucent);
|
||||
|
||||
state.EnableBrightmap(true);
|
||||
drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, state, true);
|
||||
state.SetDepthMask(false);
|
||||
|
||||
drawlists[GLDL_TRANSLUCENT].DrawSorted(this, state);
|
||||
state.EnableBrightmap(false);
|
||||
|
||||
|
||||
state.AlphaFunc(Alpha_GEqual, 0.5f);
|
||||
state.SetDepthMask(true);
|
||||
|
||||
RenderAll.Unclock();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// RenderTranslucent
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::RenderPortal(HWPortal *p, FRenderState &state, bool usestencil)
|
||||
{
|
||||
auto gp = static_cast<HWPortal *>(p);
|
||||
gp->SetupStencil(this, state, usestencil);
|
||||
auto new_di = StartDrawInfo(this, Viewpoint, &VPUniforms);
|
||||
new_di->mCurrentPortal = gp;
|
||||
state.SetLightIndex(-1);
|
||||
gp->DrawContents(new_di, state);
|
||||
new_di->EndDrawInfo();
|
||||
state.SetVertexBuffer(screen->mVertexData);
|
||||
screen->mViewpoints->Bind(state, vpIndex);
|
||||
gp->RemoveStencil(this, state, usestencil);
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Draws player sprites and color blend
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void HWDrawInfo::EndDrawScene(sectortype * viewsector, FRenderState &state)
|
||||
{
|
||||
state.EnableFog(false);
|
||||
|
||||
#if 0
|
||||
// [BB] HUD models need to be rendered here.
|
||||
const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
|
||||
if (renderHUDModel)
|
||||
{
|
||||
// [BB] The HUD model should be drawn over everything else already drawn.
|
||||
state.Clear(CT_Depth);
|
||||
DrawPlayerSprites(true, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
state.EnableStencil(false);
|
||||
state.SetViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height);
|
||||
|
||||
// Restore standard rendering state
|
||||
state.SetRenderStyle(STYLE_Translucent);
|
||||
state.ResetColor();
|
||||
state.EnableTexture(true);
|
||||
state.SetScissor(0, 0, -1, -1);
|
||||
}
|
||||
|
||||
void HWDrawInfo::DrawEndScene2D(sectortype * viewsector, FRenderState &state)
|
||||
{
|
||||
//const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
|
||||
auto vrmode = VRMode::GetVRMode(true);
|
||||
|
||||
HWViewpointUniforms vp = VPUniforms;
|
||||
vp.mViewMatrix.loadIdentity();
|
||||
vp.mProjectionMatrix = vrmode->GetHUDSpriteProjection();
|
||||
screen->mViewpoints->SetViewpoint(state, &vp);
|
||||
state.EnableDepthTest(false);
|
||||
state.EnableMultisampling(false);
|
||||
|
||||
//DrawPlayerSprites(false, state);
|
||||
|
||||
state.SetNoSoftLightLevel();
|
||||
|
||||
// Restore standard rendering state
|
||||
state.SetRenderStyle(STYLE_Translucent);
|
||||
state.ResetColor();
|
||||
state.EnableTexture(true);
|
||||
state.SetScissor(0, 0, -1, -1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// sets 3D viewport and initial state
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::Set3DViewport(FRenderState &state)
|
||||
{
|
||||
// Always clear all buffers with scissor test disabled.
|
||||
// This is faster on newer hardware because it allows the GPU to skip
|
||||
// reading from slower memory where the full buffers are stored.
|
||||
state.SetScissor(0, 0, -1, -1);
|
||||
state.Clear(CT_Color | CT_Depth | CT_Stencil);
|
||||
|
||||
const auto &bounds = screen->mSceneViewport;
|
||||
state.SetViewport(bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
state.SetScissor(bounds.left, bounds.top, bounds.width, bounds.height);
|
||||
state.EnableMultisampling(true);
|
||||
state.EnableDepthTest(true);
|
||||
state.EnableStencil(true);
|
||||
state.SetStencil(0, SOP_Keep, SF_AllOn);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// gl_drawscene - this function renders the scene from the current
|
||||
// viewpoint, including mirrors and skyboxes and other portals
|
||||
// It is assumed that the HWPortal::EndFrame returns with the
|
||||
// stencil, z-buffer and the projection matrix intact!
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::DrawScene(int drawmode)
|
||||
{
|
||||
static int recursion = 0;
|
||||
static int ssao_portals_available = 0;
|
||||
const auto& vp = Viewpoint;
|
||||
|
||||
bool applySSAO = false;
|
||||
if (drawmode == DM_MAINVIEW)
|
||||
{
|
||||
ssao_portals_available = gl_ssao_portals;
|
||||
applySSAO = true;
|
||||
}
|
||||
else if (drawmode == DM_OFFSCREEN)
|
||||
{
|
||||
ssao_portals_available = 0;
|
||||
}
|
||||
else if (drawmode == DM_PORTAL && ssao_portals_available > 0)
|
||||
{
|
||||
applySSAO = (mCurrentPortal->AllowSSAO()/* || Level->flags3&LEVEL3_SKYBOXAO*/);
|
||||
ssao_portals_available--;
|
||||
}
|
||||
|
||||
CreateScene(false);
|
||||
auto& RenderState = *screen->RenderState();
|
||||
|
||||
RenderState.SetDepthMask(true);
|
||||
if (!gl_no_skyclear) portalState.RenderFirstSkyPortal(recursion, this, RenderState);
|
||||
|
||||
RenderScene(RenderState);
|
||||
|
||||
if (applySSAO && RenderState.GetPassType() == GBUFFER_PASS)
|
||||
{
|
||||
screen->AmbientOccludeScene(VPUniforms.mProjectionMatrix.get()[5]);
|
||||
screen->mViewpoints->Bind(RenderState, vpIndex);
|
||||
}
|
||||
|
||||
// Handle all portals after rendering the opaque objects but before
|
||||
// doing all translucent stuff
|
||||
recursion++;
|
||||
portalState.EndFrame(this, RenderState);
|
||||
recursion--;
|
||||
RenderTranslucent(RenderState);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// R_RenderView - renders one view - either the screen or a camera texture
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::ProcessScene(bool toscreen)
|
||||
{
|
||||
portalState.BeginScene();
|
||||
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
/*
|
||||
void HWDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub)
|
||||
{
|
||||
auto portal = FindPortal(ptg);
|
||||
if (!portal)
|
||||
{
|
||||
portal = new HWSectorStackPortal(&portalState, ptg);
|
||||
Portals.Push(portal);
|
||||
}
|
||||
auto ptl = static_cast<HWSectorStackPortal*>(portal);
|
||||
ptl->AddSubsector(sub);
|
||||
}
|
||||
*/
|
||||
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include "build.h"
|
||||
#include "vectors.h"
|
||||
#include "hw_viewpointuniforms.h"
|
||||
#include "v_video.h"
|
||||
#include "hw_drawlist.h"
|
||||
#include "r_viewpoint.h"
|
||||
|
||||
enum EDrawMode
|
||||
{
|
||||
|
@ -16,7 +18,6 @@ enum EDrawMode
|
|||
};
|
||||
|
||||
struct FSectorPortalGroup;
|
||||
struct FLinePortalSpan;
|
||||
struct FFlatVertex;
|
||||
class HWWall;
|
||||
class HWFlat;
|
||||
|
@ -82,7 +83,6 @@ struct HWDrawInfo
|
|||
int vpIndex;
|
||||
//ELightMode lightmode;
|
||||
|
||||
FLevelLocals *Level;
|
||||
HWDrawInfo * outer = nullptr;
|
||||
int FullbrightFlags;
|
||||
std::atomic<int> spriteindex;
|
||||
|
@ -101,7 +101,6 @@ struct HWDrawInfo
|
|||
TArray<uint8_t> sector_renderflags;
|
||||
|
||||
// This is needed by the BSP traverser.
|
||||
BitArray CurrentMapSections; // this cannot be a single number, because a group of portals with the same displacement may link different sections.
|
||||
fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster.
|
||||
bool multithread;
|
||||
|
||||
|
@ -151,7 +150,7 @@ public:
|
|||
|
||||
HWPortal * FindPortal(const void * src);
|
||||
|
||||
//static HWDrawInfo *StartDrawInfo(FLevelLocals *lev, HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
|
||||
//static HWDrawInfo *StartDrawInfo(HWDrawInfo *parent, FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
|
||||
//void StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
|
||||
void ClearBuffers();
|
||||
HWDrawInfo *EndDrawInfo();
|
||||
|
@ -169,7 +168,6 @@ public:
|
|||
//void GetDynSpriteLight(AActor *self, float x, float y, float z, FLightNode *node, int portalgroup, float *out);
|
||||
//void GetDynSpriteLight(AActor *thing, particle_t *particle, float *out);
|
||||
|
||||
void UpdateCurrentMapSection();
|
||||
void SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
void SetupView(FRenderState &state, float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
angle_t FrustumAngle();
|
||||
|
|
941
source/core/rendering/scene/hw_drawlist.cpp
Normal file
941
source/core/rendering/scene/hw_drawlist.cpp
Normal file
|
@ -0,0 +1,941 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2002-2016 Christoph Oelckers
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** hw_drawlist.cpp
|
||||
** The main container type for draw items.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hw_drawlist.h"
|
||||
#include "flatvertices.h"
|
||||
#include "hw_clock.h"
|
||||
#include "hw_renderstate.h"
|
||||
#include "hw_drawinfo.h"
|
||||
|
||||
FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time.
|
||||
|
||||
void ResetRenderDataAllocator()
|
||||
{
|
||||
RenderDataAllocator.FreeAll();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
class StaticSortNodeArray : public TDeletingArray<SortNode*>
|
||||
{
|
||||
unsigned usecount;
|
||||
public:
|
||||
unsigned Size() { return usecount; }
|
||||
void Clear() { usecount=0; }
|
||||
void Release(int start) { usecount=start; }
|
||||
SortNode * GetNew();
|
||||
};
|
||||
|
||||
|
||||
SortNode * StaticSortNodeArray::GetNew()
|
||||
{
|
||||
if (usecount==TArray<SortNode*>::Size())
|
||||
{
|
||||
Push(new SortNode);
|
||||
}
|
||||
return operator[](usecount++);
|
||||
}
|
||||
|
||||
|
||||
static StaticSortNodeArray SortNodes;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::Reset()
|
||||
{
|
||||
if (sorted) SortNodes.Release(SortNodeStart);
|
||||
sorted=NULL;
|
||||
walls.Clear();
|
||||
flats.Clear();
|
||||
sprites.Clear();
|
||||
drawitems.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
inline void SortNode::UnlinkFromChain()
|
||||
{
|
||||
if (parent) parent->next=next;
|
||||
if (next) next->parent=parent;
|
||||
parent=next=NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
inline void SortNode::Link(SortNode * hook)
|
||||
{
|
||||
if (hook)
|
||||
{
|
||||
parent=hook->parent;
|
||||
hook->parent=this;
|
||||
}
|
||||
next=hook;
|
||||
if (parent) parent->next=this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
inline void SortNode::AddToEqual(SortNode *child)
|
||||
{
|
||||
child->UnlinkFromChain();
|
||||
child->equal=equal;
|
||||
equal=child;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
inline void SortNode::AddToLeft(SortNode * child)
|
||||
{
|
||||
child->UnlinkFromChain();
|
||||
child->Link(left);
|
||||
left=child;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
inline void SortNode::AddToRight(SortNode * child)
|
||||
{
|
||||
child->UnlinkFromChain();
|
||||
child->Link(right);
|
||||
right=child;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::MakeSortList()
|
||||
{
|
||||
SortNode * p, * n, * c;
|
||||
unsigned i;
|
||||
|
||||
SortNodeStart=SortNodes.Size();
|
||||
p=NULL;
|
||||
n=SortNodes.GetNew();
|
||||
for(i=0;i<drawitems.Size();i++)
|
||||
{
|
||||
n->itemindex=(int)i;
|
||||
n->left=n->equal=n->right=NULL;
|
||||
n->parent=p;
|
||||
p=n;
|
||||
if (i!=drawitems.Size()-1)
|
||||
{
|
||||
c=SortNodes.GetNew();
|
||||
n->next=c;
|
||||
n=c;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->next=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
SortNode * HWDrawList::FindSortPlane(SortNode * head)
|
||||
{
|
||||
while (head->next && drawitems[head->itemindex].rendertype!=DrawType_FLAT)
|
||||
head=head->next;
|
||||
if (drawitems[head->itemindex].rendertype==DrawType_FLAT) return head;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
SortNode * HWDrawList::FindSortWall(SortNode * head)
|
||||
{
|
||||
float farthest = -FLT_MAX;
|
||||
float nearest = FLT_MAX;
|
||||
SortNode * best = NULL;
|
||||
SortNode * node = head;
|
||||
float bestdist = FLT_MAX;
|
||||
|
||||
while (node)
|
||||
{
|
||||
HWDrawItem * it = &drawitems[node->itemindex];
|
||||
if (it->rendertype == DrawType_WALL)
|
||||
{
|
||||
float d = walls[it->index]->ViewDistance;
|
||||
if (d > farthest) farthest = d;
|
||||
if (d < nearest) nearest = d;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
if (farthest == INT_MIN) return NULL;
|
||||
node = head;
|
||||
farthest = (farthest + nearest) / 2;
|
||||
while (node)
|
||||
{
|
||||
HWDrawItem * it = &drawitems[node->itemindex];
|
||||
if (it->rendertype == DrawType_WALL)
|
||||
{
|
||||
float di = fabsf(walls[it->index]->ViewDistance - farthest);
|
||||
if (!best || di < bestdist)
|
||||
{
|
||||
best = node;
|
||||
bestdist = di;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Note: sloped planes are a huge problem...
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::SortPlaneIntoPlane(SortNode * head,SortNode * sort)
|
||||
{
|
||||
HWFlat * fh= flats[drawitems[head->itemindex].index];
|
||||
HWFlat * fs= flats[drawitems[sort->itemindex].index];
|
||||
|
||||
if (fh->z==fs->z)
|
||||
head->AddToEqual(sort);
|
||||
else if ( (fh->z<fs->z && fh->ceiling) || (fh->z>fs->z && !fh->ceiling))
|
||||
head->AddToLeft(sort);
|
||||
else
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::SortWallIntoPlane(SortNode * head, SortNode * sort)
|
||||
{
|
||||
HWFlat * fh = flats[drawitems[head->itemindex].index];
|
||||
HWWall * ws = walls[drawitems[sort->itemindex].index];
|
||||
|
||||
bool ceiling = fh->z > SortZ;
|
||||
|
||||
if ((ws->ztop[0] > fh->z || ws->ztop[1] > fh->z) && (ws->zbottom[0] < fh->z || ws->zbottom[1] < fh->z))
|
||||
{
|
||||
// We have to split this wall!
|
||||
|
||||
HWWall *w = NewWall();
|
||||
*w = *ws;
|
||||
|
||||
// Splitting is done in the shader with clip planes, if available
|
||||
if (screen->hwcaps & RFL_NO_CLIP_PLANES)
|
||||
{
|
||||
ws->vertcount = 0; // invalidate current vertices.
|
||||
float newtexv = ws->tcs[HWWall::UPLFT].v + ((ws->tcs[HWWall::LOLFT].v - ws->tcs[HWWall::UPLFT].v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]);
|
||||
|
||||
// I make the very big assumption here that translucent walls in sloped sectors
|
||||
// and 3D-floors never coexist in the same level - If that were the case this
|
||||
// code would become extremely more complicated.
|
||||
if (!ceiling)
|
||||
{
|
||||
ws->ztop[1] = w->zbottom[1] = ws->ztop[0] = w->zbottom[0] = fh->z;
|
||||
ws->tcs[HWWall::UPRGT].v = w->tcs[HWWall::LORGT].v = ws->tcs[HWWall::UPLFT].v = w->tcs[HWWall::LOLFT].v = newtexv;
|
||||
}
|
||||
else
|
||||
{
|
||||
w->ztop[1] = ws->zbottom[1] = w->ztop[0] = ws->zbottom[0] = fh->z;
|
||||
w->tcs[HWWall::UPLFT].v = ws->tcs[HWWall::LOLFT].v = w->tcs[HWWall::UPRGT].v = ws->tcs[HWWall::LORGT].v = newtexv;
|
||||
}
|
||||
}
|
||||
|
||||
SortNode * sort2 = SortNodes.GetNew();
|
||||
memset(sort2, 0, sizeof(SortNode));
|
||||
sort2->itemindex = drawitems.Size() - 1;
|
||||
|
||||
head->AddToLeft(sort);
|
||||
head->AddToRight(sort2);
|
||||
}
|
||||
else if ((ws->zbottom[0] < fh->z && !ceiling) || (ws->ztop[0] > fh->z && ceiling)) // completely on the left side
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort)
|
||||
{
|
||||
HWFlat * fh = flats[drawitems[head->itemindex].index];
|
||||
HWSprite * ss = sprites[drawitems[sort->itemindex].index];
|
||||
|
||||
bool ceiling = fh->z > SortZ;
|
||||
|
||||
auto hiz = ss->z1 > ss->z2 ? ss->z1 : ss->z2;
|
||||
auto loz = ss->z1 < ss->z2 ? ss->z1 : ss->z2;
|
||||
|
||||
if ((hiz > fh->z && loz < fh->z) || ss->modelframe)
|
||||
{
|
||||
// We have to split this sprite
|
||||
HWSprite *s = NewSprite();
|
||||
*s = *ss;
|
||||
|
||||
// Splitting is done in the shader with clip planes, if available.
|
||||
// The fallback here only really works for non-y-billboarded sprites.
|
||||
if (screen->hwcaps & RFL_NO_CLIP_PLANES)
|
||||
{
|
||||
float newtexv = ss->vt + ((ss->vb - ss->vt) / (ss->z2 - ss->z1))*(fh->z - ss->z1);
|
||||
|
||||
if (!ceiling)
|
||||
{
|
||||
ss->z1 = s->z2 = fh->z;
|
||||
ss->vt = s->vb = newtexv;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->z1 = ss->z2 = fh->z;
|
||||
s->vt = ss->vb = newtexv;
|
||||
}
|
||||
}
|
||||
|
||||
SortNode * sort2 = SortNodes.GetNew();
|
||||
memset(sort2, 0, sizeof(SortNode));
|
||||
sort2->itemindex = drawitems.Size() - 1;
|
||||
|
||||
head->AddToLeft(sort);
|
||||
head->AddToRight(sort2);
|
||||
}
|
||||
else if ((ss->z2<fh->z && !ceiling) || (ss->z1>fh->z && ceiling)) // completely on the left side
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
#define MIN_EQ (0.0005f)
|
||||
|
||||
// Lines start-end and fdiv must intersect.
|
||||
inline double CalcIntersectionVertex(HWWall *w1, HWWall * w2)
|
||||
{
|
||||
float ax = w1->glseg.x1, ay = w1->glseg.y1;
|
||||
float bx = w1->glseg.x2, by = w1->glseg.y2;
|
||||
float cx = w2->glseg.x1, cy = w2->glseg.y1;
|
||||
float dx = w2->glseg.x2, dy = w2->glseg.y2;
|
||||
return ((ay - cy)*(dx - cx) - (ax - cx)*(dy - cy)) / ((bx - ax)*(dy - cy) - (by - ay)*(dx - cx));
|
||||
}
|
||||
|
||||
void HWDrawList::SortWallIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sort)
|
||||
{
|
||||
HWWall * wh= walls[drawitems[head->itemindex].index];
|
||||
HWWall * ws= walls[drawitems[sort->itemindex].index];
|
||||
float v1=wh->PointOnSide(ws->glseg.x1,ws->glseg.y1);
|
||||
float v2=wh->PointOnSide(ws->glseg.x2,ws->glseg.y2);
|
||||
|
||||
if (fabs(v1)<MIN_EQ && fabs(v2)<MIN_EQ)
|
||||
{
|
||||
if (ws->type==RENDERWALL_FOGBOUNDARY && wh->type!=RENDERWALL_FOGBOUNDARY)
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
else if (ws->type!=RENDERWALL_FOGBOUNDARY && wh->type==RENDERWALL_FOGBOUNDARY)
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToEqual(sort);
|
||||
}
|
||||
}
|
||||
else if (v1<MIN_EQ && v2<MIN_EQ)
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else if (v1>-MIN_EQ && v2>-MIN_EQ)
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
double r = CalcIntersectionVertex(ws, wh);
|
||||
|
||||
float ix=(float)(ws->glseg.x1+r*(ws->glseg.x2-ws->glseg.x1));
|
||||
float iy=(float)(ws->glseg.y1+r*(ws->glseg.y2-ws->glseg.y1));
|
||||
float iu=(float)(ws->tcs[HWWall::UPLFT].u + r * (ws->tcs[HWWall::UPRGT].u - ws->tcs[HWWall::UPLFT].u));
|
||||
float izt=(float)(ws->ztop[0]+r*(ws->ztop[1]-ws->ztop[0]));
|
||||
float izb=(float)(ws->zbottom[0]+r*(ws->zbottom[1]-ws->zbottom[0]));
|
||||
|
||||
ws->vertcount = 0; // invalidate current vertices.
|
||||
HWWall *w= NewWall();
|
||||
*w = *ws;
|
||||
|
||||
w->glseg.x1=ws->glseg.x2=ix;
|
||||
w->glseg.y1=ws->glseg.y2=iy;
|
||||
w->ztop[0]=ws->ztop[1]=izt;
|
||||
w->zbottom[0]=ws->zbottom[1]=izb;
|
||||
w->tcs[HWWall::LOLFT].u = w->tcs[HWWall::UPLFT].u = ws->tcs[HWWall::LORGT].u = ws->tcs[HWWall::UPRGT].u = iu;
|
||||
ws->MakeVertices(di, false);
|
||||
w->MakeVertices(di, false);
|
||||
|
||||
SortNode * sort2=SortNodes.GetNew();
|
||||
memset(sort2,0,sizeof(SortNode));
|
||||
sort2->itemindex=drawitems.Size()-1;
|
||||
|
||||
if (v1>0)
|
||||
{
|
||||
head->AddToLeft(sort2);
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
head->AddToRight(sort2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
EXTERN_CVAR(Int, gl_billboard_mode)
|
||||
EXTERN_CVAR(Bool, gl_billboard_faces_camera)
|
||||
EXTERN_CVAR(Bool, gl_billboard_particles)
|
||||
|
||||
inline double CalcIntersectionVertex(HWSprite *s, HWWall * w2)
|
||||
{
|
||||
float ax = s->x1, ay = s->y1;
|
||||
float bx = s->x2, by = s->y2;
|
||||
float cx = w2->glseg.x1, cy = w2->glseg.y1;
|
||||
float dx = w2->glseg.x2, dy = w2->glseg.y2;
|
||||
return ((ay - cy)*(dx - cx) - (ax - cx)*(dy - cy)) / ((bx - ax)*(dy - cy) - (by - ay)*(dx - cx));
|
||||
}
|
||||
|
||||
void HWDrawList::SortSpriteIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sort)
|
||||
{
|
||||
HWWall *wh= walls[drawitems[head->itemindex].index];
|
||||
HWSprite * ss= sprites[drawitems[sort->itemindex].index];
|
||||
|
||||
float v1 = wh->PointOnSide(ss->x1, ss->y1);
|
||||
float v2 = wh->PointOnSide(ss->x2, ss->y2);
|
||||
|
||||
if (fabs(v1)<MIN_EQ && fabs(v2)<MIN_EQ)
|
||||
{
|
||||
if (wh->type==RENDERWALL_FOGBOUNDARY)
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToEqual(sort);
|
||||
}
|
||||
}
|
||||
else if (v1<MIN_EQ && v2<MIN_EQ)
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else if (v1>-MIN_EQ && v2>-MIN_EQ)
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool drawWithXYBillboard = false;//
|
||||
|
||||
const bool drawBillboardFacingCamera = gl_billboard_faces_camera;
|
||||
// [Nash] has +ROLLSPRITE
|
||||
const bool rotated = false;//
|
||||
|
||||
// cannot sort them at the moment. This requires more complex splitting.
|
||||
/*
|
||||
if (drawWithXYBillboard || drawBillboardFacingCamera || rotated)
|
||||
{
|
||||
float v1 = wh->PointOnSide(ss->x, ss->y);
|
||||
if (v1 < 0)
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
return;
|
||||
}
|
||||
*/
|
||||
double r=CalcIntersectionVertex(ss, wh);
|
||||
|
||||
float ix=(float)(ss->x1 + r * (ss->x2-ss->x1));
|
||||
float iy=(float)(ss->y1 + r * (ss->y2-ss->y1));
|
||||
float iu=(float)(ss->ul + r * (ss->ur-ss->ul));
|
||||
|
||||
HWSprite *s = NewSprite();
|
||||
*s = *ss;
|
||||
|
||||
s->x1=ss->x2=ix;
|
||||
s->y1=ss->y2=iy;
|
||||
s->ul=ss->ur=iu;
|
||||
|
||||
SortNode * sort2=SortNodes.GetNew();
|
||||
memset(sort2,0,sizeof(SortNode));
|
||||
sort2->itemindex=drawitems.Size()-1;
|
||||
|
||||
if (v1>0)
|
||||
{
|
||||
head->AddToLeft(sort2);
|
||||
head->AddToRight(sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->AddToLeft(sort);
|
||||
head->AddToRight(sort2);
|
||||
}
|
||||
if (screen->BuffersArePersistent())
|
||||
{
|
||||
s->vertexindex = ss->vertexindex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->CreateVertices(di);
|
||||
ss->CreateVertices(di);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
inline int HWDrawList::CompareSprites(SortNode * a,SortNode * b)
|
||||
{
|
||||
HWSprite * s1= sprites[drawitems[a->itemindex].index];
|
||||
HWSprite * s2= sprites[drawitems[b->itemindex].index];
|
||||
|
||||
if (s1->depth < s2->depth) return 1;
|
||||
if (s1->depth > s2->depth) return -1;
|
||||
return reverseSort? s2->index-s1->index : s1->index-s2->index;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
SortNode * HWDrawList::SortSpriteList(SortNode * head)
|
||||
{
|
||||
SortNode * n;
|
||||
int count;
|
||||
unsigned i;
|
||||
|
||||
static TArray<SortNode*> sortspritelist;
|
||||
|
||||
SortNode * parent=head->parent;
|
||||
|
||||
sortspritelist.Clear();
|
||||
for(count=0,n=head;n;n=n->next) sortspritelist.Push(n);
|
||||
std::stable_sort(sortspritelist.begin(), sortspritelist.end(), [=](SortNode *a, SortNode *b)
|
||||
{
|
||||
return CompareSprites(a, b) < 0;
|
||||
});
|
||||
|
||||
for(i=0;i<sortspritelist.Size();i++)
|
||||
{
|
||||
sortspritelist[i]->next=NULL;
|
||||
if (parent) parent->equal=sortspritelist[i];
|
||||
parent=sortspritelist[i];
|
||||
}
|
||||
return sortspritelist[0];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head)
|
||||
{
|
||||
SortNode * node, * sn, * next;
|
||||
|
||||
sn=FindSortPlane(head);
|
||||
if (sn)
|
||||
{
|
||||
if (sn==head) head=head->next;
|
||||
sn->UnlinkFromChain();
|
||||
node=head;
|
||||
head=sn;
|
||||
while (node)
|
||||
{
|
||||
next=node->next;
|
||||
switch(drawitems[node->itemindex].rendertype)
|
||||
{
|
||||
case DrawType_FLAT:
|
||||
SortPlaneIntoPlane(head,node);
|
||||
break;
|
||||
|
||||
case DrawType_WALL:
|
||||
SortWallIntoPlane(head,node);
|
||||
break;
|
||||
|
||||
case DrawType_SPRITE:
|
||||
SortSpriteIntoPlane(head,node);
|
||||
break;
|
||||
}
|
||||
node=next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sn=FindSortWall(head);
|
||||
if (sn)
|
||||
{
|
||||
if (sn==head) head=head->next;
|
||||
sn->UnlinkFromChain();
|
||||
node=head;
|
||||
head=sn;
|
||||
while (node)
|
||||
{
|
||||
next=node->next;
|
||||
switch(drawitems[node->itemindex].rendertype)
|
||||
{
|
||||
case DrawType_WALL:
|
||||
SortWallIntoWall(di, head,node);
|
||||
break;
|
||||
|
||||
case DrawType_SPRITE:
|
||||
SortSpriteIntoWall(di, head, node);
|
||||
break;
|
||||
|
||||
case DrawType_FLAT: break;
|
||||
}
|
||||
node=next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return SortSpriteList(head);
|
||||
}
|
||||
}
|
||||
if (head->left) head->left=DoSort(di, head->left);
|
||||
if (head->right) head->right=DoSort(di, head->right);
|
||||
return sn;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::Sort(HWDrawInfo *di)
|
||||
{
|
||||
reverseSort = false;
|
||||
SortZ = di->Viewpoint.Pos.Z;
|
||||
MakeSortList();
|
||||
sorted = DoSort(di, SortNodes[SortNodeStart]);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Sorting the drawitems first by texture and then by light level
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void HWDrawList::SortWalls()
|
||||
{
|
||||
if (drawitems.Size() > 1)
|
||||
{
|
||||
std::sort(drawitems.begin(), drawitems.end(), [=](const HWDrawItem &a, const HWDrawItem &b) -> bool
|
||||
{
|
||||
HWWall * w1 = walls[a.index];
|
||||
HWWall * w2 = walls[b.index];
|
||||
|
||||
if (w1->texture != w2->texture) return w1->texture < w2->texture;
|
||||
return (w1->flags & 3) < (w2->flags & 3);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void HWDrawList::SortFlats()
|
||||
{
|
||||
if (drawitems.Size() > 1)
|
||||
{
|
||||
std::sort(drawitems.begin(), drawitems.end(), [=](const HWDrawItem &a, const HWDrawItem &b)
|
||||
{
|
||||
HWFlat * w1 = flats[a.index];
|
||||
HWFlat* w2 = flats[b.index];
|
||||
return w1->texture < w2->texture;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
HWWall *HWDrawList::NewWall()
|
||||
{
|
||||
auto wall = (HWWall*)RenderDataAllocator.Alloc(sizeof(HWWall));
|
||||
drawitems.Push(HWDrawItem(DrawType_WALL, walls.Push(wall)));
|
||||
return wall;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
HWFlat *HWDrawList::NewFlat()
|
||||
{
|
||||
auto flat = (HWFlat*)RenderDataAllocator.Alloc(sizeof(HWFlat));
|
||||
drawitems.Push(HWDrawItem(DrawType_FLAT,flats.Push(flat)));
|
||||
return flat;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
HWSprite *HWDrawList::NewSprite()
|
||||
{
|
||||
auto sprite = (HWSprite*)RenderDataAllocator.Alloc(sizeof(HWSprite));
|
||||
drawitems.Push(HWDrawItem(DrawType_SPRITE, sprites.Push(sprite)));
|
||||
return sprite;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::DoDraw(HWDrawInfo *di, FRenderState &state, bool translucent, int i)
|
||||
{
|
||||
switch(drawitems[i].rendertype)
|
||||
{
|
||||
case DrawType_FLAT:
|
||||
{
|
||||
HWFlat * f= flats[drawitems[i].index];
|
||||
RenderFlat.Clock();
|
||||
f->DrawFlat(di, state, translucent);
|
||||
RenderFlat.Unclock();
|
||||
}
|
||||
break;
|
||||
|
||||
case DrawType_WALL:
|
||||
{
|
||||
HWWall * w= walls[drawitems[i].index];
|
||||
RenderWall.Clock();
|
||||
w->DrawWall(di, state, translucent);
|
||||
RenderWall.Unclock();
|
||||
}
|
||||
break;
|
||||
|
||||
case DrawType_SPRITE:
|
||||
{
|
||||
HWSprite * s= sprites[drawitems[i].index];
|
||||
RenderSprite.Clock();
|
||||
s->DrawSprite(di, state, translucent);
|
||||
RenderSprite.Unclock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::Draw(HWDrawInfo *di, FRenderState &state, bool translucent)
|
||||
{
|
||||
for (unsigned i = 0; i < drawitems.Size(); i++)
|
||||
{
|
||||
DoDraw(di, state, translucent, i);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::DrawWalls(HWDrawInfo *di, FRenderState &state, bool translucent)
|
||||
{
|
||||
RenderWall.Clock();
|
||||
for (auto &item : drawitems)
|
||||
{
|
||||
walls[item.index]->DrawWall(di, state, translucent);
|
||||
}
|
||||
RenderWall.Unclock();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::DrawFlats(HWDrawInfo *di, FRenderState &state, bool translucent)
|
||||
{
|
||||
RenderFlat.Clock();
|
||||
for (unsigned i = 0; i<drawitems.Size(); i++)
|
||||
{
|
||||
flats[drawitems[i].index]->DrawFlat(di, state, translucent);
|
||||
}
|
||||
RenderFlat.Unclock();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::DrawSorted(HWDrawInfo *di, FRenderState &state, SortNode * head)
|
||||
{
|
||||
float clipsplit[2];
|
||||
int relation = 0;
|
||||
float z = 0.f;
|
||||
|
||||
state.GetClipSplit(clipsplit);
|
||||
|
||||
if (drawitems[head->itemindex].rendertype == DrawType_FLAT)
|
||||
{
|
||||
z = flats[drawitems[head->itemindex].index]->z;
|
||||
relation = z > di->Viewpoint.Pos.Z ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
// left is further away, i.e. for stuff above viewz its z coordinate higher, for stuff below viewz its z coordinate is lower
|
||||
if (head->left)
|
||||
{
|
||||
if (relation == -1)
|
||||
{
|
||||
state.SetClipSplit(clipsplit[0], z); // render below: set flat as top clip plane
|
||||
}
|
||||
else if (relation == 1)
|
||||
{
|
||||
state.SetClipSplit(z, clipsplit[1]); // render above: set flat as bottom clip plane
|
||||
}
|
||||
DrawSorted(di, state, head->left);
|
||||
state.SetClipSplit(clipsplit);
|
||||
}
|
||||
DoDraw(di, state, true, head->itemindex);
|
||||
if (head->equal)
|
||||
{
|
||||
SortNode * ehead = head->equal;
|
||||
while (ehead)
|
||||
{
|
||||
DoDraw(di, state, true, ehead->itemindex);
|
||||
ehead = ehead->equal;
|
||||
}
|
||||
}
|
||||
// right is closer, i.e. for stuff above viewz its z coordinate is lower, for stuff below viewz its z coordinate is higher
|
||||
if (head->right)
|
||||
{
|
||||
if (relation == 1)
|
||||
{
|
||||
state.SetClipSplit(clipsplit[0], z); // render below: set flat as top clip plane
|
||||
}
|
||||
else if (relation == -1)
|
||||
{
|
||||
state.SetClipSplit(z, clipsplit[1]); // render above: set flat as bottom clip plane
|
||||
}
|
||||
DrawSorted(di, state, head->right);
|
||||
state.SetClipSplit(clipsplit);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void HWDrawList::DrawSorted(HWDrawInfo *di, FRenderState &state)
|
||||
{
|
||||
if (drawitems.Size() == 0) return;
|
||||
|
||||
if (!sorted)
|
||||
{
|
||||
screen->mVertexData->Map();
|
||||
Sort(di);
|
||||
screen->mVertexData->Unmap();
|
||||
}
|
||||
state.ClearClipSplit();
|
||||
state.EnableClipDistance(1, true);
|
||||
state.EnableClipDistance(2, true);
|
||||
DrawSorted(di, state, sorted);
|
||||
state.EnableClipDistance(1, false);
|
||||
state.EnableClipDistance(2, false);
|
||||
state.ClearClipSplit();
|
||||
}
|
||||
|
|
@ -19,7 +19,6 @@ class FMaterial;
|
|||
struct FTexCoordInfo;
|
||||
struct FSectorPortalGroup;
|
||||
struct FFlatVertex;
|
||||
struct FLinePortalSpan;
|
||||
struct FDynLightData;
|
||||
class VSMatrix;
|
||||
struct FSpriteModelFrame;
|
||||
|
@ -171,7 +170,7 @@ public:
|
|||
HWHorizonInfo * horizon; // for horizon information
|
||||
FSectorPortalGroup * portal; // stacked sector portals
|
||||
secplane_t * planemirror; // for plane mirrors
|
||||
FLinePortalSpan *lineportal; // line-to-line portals
|
||||
walltype *lineportal; // line-to-line portals
|
||||
};
|
||||
*/
|
||||
|
||||
|
|
406
source/core/rendering/scene/hw_portal.h
Normal file
406
source/core/rendering/scene/hw_portal.h
Normal file
|
@ -0,0 +1,406 @@
|
|||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
#include "hw_drawinfo.h"
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hw_renderstate.h"
|
||||
#include "hw_material.h"
|
||||
|
||||
class FSkyBox;
|
||||
|
||||
struct HWSkyInfo
|
||||
{
|
||||
float x_offset[2];
|
||||
float y_offset; // doubleskies don't have a y-offset
|
||||
FGameTexture * texture[2];
|
||||
FTextureID skytexno1;
|
||||
bool mirrored;
|
||||
bool doublesky;
|
||||
bool sky2;
|
||||
PalEntry fadecolor;
|
||||
|
||||
bool operator==(const HWSkyInfo & inf)
|
||||
{
|
||||
return !memcmp(this, &inf, sizeof(*this));
|
||||
}
|
||||
bool operator!=(const HWSkyInfo & inf)
|
||||
{
|
||||
return !!memcmp(this, &inf, sizeof(*this));
|
||||
}
|
||||
void init(HWDrawInfo *di, int sky1, PalEntry fadecolor);
|
||||
};
|
||||
|
||||
struct HWHorizonInfo
|
||||
{
|
||||
HWSectorPlane plane;
|
||||
int lightlevel;
|
||||
FColormap colormap;
|
||||
PalEntry specialcolor;
|
||||
};
|
||||
|
||||
struct BoundingRect
|
||||
{
|
||||
double left, top, right, bottom;
|
||||
|
||||
BoundingRect() = default;
|
||||
BoundingRect(bool)
|
||||
{
|
||||
setEmpty();
|
||||
}
|
||||
|
||||
void setEmpty()
|
||||
{
|
||||
left = top = FLT_MAX;
|
||||
bottom = right = -FLT_MAX;
|
||||
}
|
||||
|
||||
bool contains(const BoundingRect& other) const
|
||||
{
|
||||
return left <= other.left && top <= other.top && right >= other.right && bottom >= other.bottom;
|
||||
}
|
||||
|
||||
bool contains(double x, double y) const
|
||||
{
|
||||
return left <= x && top <= y && right >= x && bottom >= y;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool contains(const T& vec) const
|
||||
{
|
||||
return left <= vec.X && top <= vec.Y && right >= vec.X && bottom >= vec.Y;
|
||||
}
|
||||
|
||||
bool intersects(const BoundingRect& other) const
|
||||
{
|
||||
return !(other.left > right ||
|
||||
other.right < left ||
|
||||
other.top > bottom ||
|
||||
other.bottom < top);
|
||||
}
|
||||
|
||||
void Union(const BoundingRect& other)
|
||||
{
|
||||
if (other.left < left) left = other.left;
|
||||
if (other.right > right) right = other.right;
|
||||
if (other.top < top) top = other.top;
|
||||
if (other.bottom > bottom) bottom = other.bottom;
|
||||
}
|
||||
|
||||
double distanceTo(const BoundingRect& other) const
|
||||
{
|
||||
if (intersects(other)) return 0;
|
||||
return std::max(std::min(fabs(left - other.right), fabs(right - other.left)),
|
||||
std::min(fabs(top - other.bottom), fabs(bottom - other.top)));
|
||||
}
|
||||
|
||||
void addVertex(double x, double y)
|
||||
{
|
||||
if (x < left) left = x;
|
||||
if (x > right) right = x;
|
||||
if (y < top) top = y;
|
||||
if (y > bottom) bottom = y;
|
||||
}
|
||||
|
||||
bool operator == (const BoundingRect& other) const
|
||||
{
|
||||
return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct secplane_t
|
||||
{
|
||||
double a, b, c, d, ic;
|
||||
};
|
||||
|
||||
struct FPortalSceneState;
|
||||
|
||||
class HWPortal
|
||||
{
|
||||
friend struct FPortalSceneState;
|
||||
|
||||
enum
|
||||
{
|
||||
STP_Stencil,
|
||||
STP_DepthClear,
|
||||
STP_DepthRestore,
|
||||
STP_AllInOne
|
||||
};
|
||||
|
||||
TArray<unsigned int> mPrimIndices;
|
||||
unsigned int mTopCap = ~0u, mBottomCap = ~0u;
|
||||
|
||||
void DrawPortalStencil(FRenderState &state, int pass);
|
||||
|
||||
public:
|
||||
FPortalSceneState * mState;
|
||||
TArray<HWWall> lines;
|
||||
BoundingRect boundingBox;
|
||||
int planesused = 0;
|
||||
|
||||
HWPortal(FPortalSceneState *s, bool local = false) : mState(s), boundingBox(false)
|
||||
{
|
||||
}
|
||||
virtual ~HWPortal() {}
|
||||
virtual int ClipSeg(walltype *seg, const DVector3 &viewpos) { return PClip_Inside; }
|
||||
virtual int ClipSubsector(sectortype *sub) { return PClip_Inside; }
|
||||
virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; }
|
||||
virtual walltype *ClipLine() { return nullptr; }
|
||||
virtual void * GetSource() const = 0; // GetSource MUST be implemented!
|
||||
virtual const char *GetName() = 0;
|
||||
virtual bool AllowSSAO() { return true; }
|
||||
virtual bool IsSky() { return false; }
|
||||
virtual bool NeedCap() { return true; }
|
||||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0;
|
||||
virtual void RenderAttached(HWDrawInfo *di) {}
|
||||
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
||||
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
||||
|
||||
void AddLine(HWWall * l)
|
||||
{
|
||||
lines.Push(*l);
|
||||
boundingBox.addVertex(l->glseg.x1, l->glseg.y1);
|
||||
boundingBox.addVertex(l->glseg.x2, l->glseg.y2);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct FPortalSceneState
|
||||
{
|
||||
int MirrorFlag = 0;
|
||||
int PlaneMirrorFlag = 0;
|
||||
int renderdepth = 0;
|
||||
|
||||
int PlaneMirrorMode = 0;
|
||||
bool inskybox = 0;
|
||||
|
||||
UniqueList<HWSkyInfo> UniqueSkies;
|
||||
UniqueList<HWHorizonInfo> UniqueHorizons;
|
||||
UniqueList<secplane_t> UniquePlaneMirrors;
|
||||
|
||||
int skyboxrecursion = 0;
|
||||
|
||||
void BeginScene()
|
||||
{
|
||||
UniqueSkies.Clear();
|
||||
UniqueHorizons.Clear();
|
||||
UniquePlaneMirrors.Clear();
|
||||
}
|
||||
|
||||
bool isMirrored() const
|
||||
{
|
||||
return !!((MirrorFlag ^ PlaneMirrorFlag) & 1);
|
||||
}
|
||||
|
||||
void StartFrame();
|
||||
bool RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di, FRenderState &state);
|
||||
void EndFrame(HWDrawInfo *outer_di, FRenderState &state);
|
||||
void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil, HWDrawInfo *outer_di);
|
||||
};
|
||||
|
||||
extern FPortalSceneState portalState;
|
||||
|
||||
|
||||
class HWScenePortalBase : public HWPortal
|
||||
{
|
||||
protected:
|
||||
HWScenePortalBase(FPortalSceneState *state) : HWPortal(state, false)
|
||||
{
|
||||
|
||||
}
|
||||
public:
|
||||
void ClearClipper(HWDrawInfo *di, Clipper *clipper);
|
||||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state)
|
||||
{
|
||||
if (Setup(di, state, di->mClipper))
|
||||
{
|
||||
di->DrawScene(DM_PORTAL);
|
||||
Shutdown(di, state);
|
||||
}
|
||||
else state.ClearScreen();
|
||||
}
|
||||
virtual bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) = 0;
|
||||
virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {}
|
||||
};
|
||||
|
||||
struct HWLinePortal : public HWScenePortalBase
|
||||
{
|
||||
// this must be the same as at the start of line_t, so that we can pass in this structure directly to P_ClipLineToPortal.
|
||||
walltype* line;
|
||||
vec2_t *v1, *v2; // vertices, from v1 to v2
|
||||
DVector2 delta; // precalculated v2 - v1 for side checking
|
||||
|
||||
angle_t angv1, angv2; // for quick comparisons with a line or subsector
|
||||
|
||||
HWLinePortal(FPortalSceneState *state, walltype *line) : HWScenePortalBase(state)
|
||||
{
|
||||
this->line = line;
|
||||
v1 = &line->pos;
|
||||
v2 = &wall[line->point2].pos;
|
||||
CalcDelta();
|
||||
}
|
||||
|
||||
void CalcDelta()
|
||||
{
|
||||
//delta = v2->fPos() - v1->fPos();
|
||||
}
|
||||
|
||||
int ClipSeg(walltype *seg, const DVector3 &viewpos) override;
|
||||
int ClipSubsector(sectortype *sub) override;
|
||||
int ClipPoint(const DVector2 &pos);
|
||||
bool NeedCap() override { return false; }
|
||||
};
|
||||
|
||||
struct HWMirrorPortal : public HWLinePortal
|
||||
{
|
||||
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
void * GetSource() const override { return line; }
|
||||
const char *GetName() override;
|
||||
|
||||
public:
|
||||
|
||||
HWMirrorPortal(FPortalSceneState *state, walltype * line)
|
||||
: HWLinePortal(state, line)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct HWLineToLinePortal : public HWLinePortal
|
||||
{
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
virtual void * GetSource() const override { return line; }
|
||||
virtual const char *GetName() override;
|
||||
virtual walltype *ClipLine() override { return line; }
|
||||
virtual void RenderAttached(HWDrawInfo *di) override;
|
||||
|
||||
public:
|
||||
|
||||
HWLineToLinePortal(FPortalSceneState *state, walltype *ll)
|
||||
: HWLinePortal(state, ll)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct HWSkyboxPortal : public HWScenePortalBase
|
||||
{
|
||||
bool oldclamp;
|
||||
int old_pm;
|
||||
spritetype * portal;
|
||||
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
virtual void * GetSource() const { return portal; }
|
||||
virtual bool IsSky() { return true; }
|
||||
virtual const char *GetName();
|
||||
virtual bool AllowSSAO() override;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
HWSkyboxPortal(FPortalSceneState *state, spritetype * pt) : HWScenePortalBase(state)
|
||||
{
|
||||
portal = pt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct HWSectorStackPortal : public HWScenePortalBase
|
||||
{
|
||||
TArray<sectortype *> sectors;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one.
|
||||
virtual const char *GetName();
|
||||
FSectorPortalGroup *origin;
|
||||
|
||||
public:
|
||||
|
||||
HWSectorStackPortal(FPortalSceneState *state, FSectorPortalGroup *pt) : HWScenePortalBase(state)
|
||||
{
|
||||
origin = pt;
|
||||
}
|
||||
void SetupCoverage(HWDrawInfo *di);
|
||||
void AddSector(sectortype *sub)
|
||||
{
|
||||
sectors.Push(sub);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct HWPlaneMirrorPortal : public HWScenePortalBase
|
||||
{
|
||||
int old_pm;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual const char *GetName();
|
||||
secplane_t * origin;
|
||||
|
||||
public:
|
||||
|
||||
HWPlaneMirrorPortal(FPortalSceneState *state, secplane_t * pt) : HWScenePortalBase(state)
|
||||
{
|
||||
origin = pt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct HWHorizonPortal : public HWPortal
|
||||
{
|
||||
HWHorizonInfo * origin;
|
||||
unsigned int voffset;
|
||||
unsigned int vcount;
|
||||
friend struct HWEEHorizonPortal;
|
||||
|
||||
protected:
|
||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state);
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool NeedDepthBuffer() { return false; }
|
||||
virtual bool NeedCap() { return false; }
|
||||
virtual const char *GetName();
|
||||
|
||||
public:
|
||||
|
||||
HWHorizonPortal(FPortalSceneState *state, HWHorizonInfo * pt, FRenderViewpoint &vp, bool local = false);
|
||||
};
|
||||
|
||||
struct HWSkyPortal : public HWPortal
|
||||
{
|
||||
HWSkyInfo * origin;
|
||||
FSkyVertexBuffer *vertexBuffer;
|
||||
friend struct HWEEHorizonPortal;
|
||||
|
||||
protected:
|
||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state);
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool IsSky() { return true; }
|
||||
virtual bool NeedDepthBuffer() { return false; }
|
||||
virtual const char *GetName();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
HWSkyPortal(FSkyVertexBuffer *vertexbuffer, FPortalSceneState *state, HWSkyInfo * pt, bool local = false)
|
||||
: HWPortal(state, local)
|
||||
{
|
||||
origin = pt;
|
||||
vertexBuffer = vertexbuffer;
|
||||
}
|
||||
|
||||
};
|
Loading…
Reference in a new issue