2016-09-14 18:01:13 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Copyright(C) 2004-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/
|
|
|
|
//
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
2013-06-23 07:49:34 +00:00
|
|
|
/*
|
|
|
|
** gl_scene.cpp
|
|
|
|
** manages the rendering of the player's view
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
2018-05-16 21:34:52 +00:00
|
|
|
#include "gl_load/gl_system.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gi.h"
|
|
|
|
#include "m_png.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "g_level.h"
|
|
|
|
#include "r_data/r_interpolate.h"
|
|
|
|
#include "r_utility.h"
|
|
|
|
#include "d_player.h"
|
|
|
|
#include "p_effect.h"
|
|
|
|
#include "sbar.h"
|
|
|
|
#include "po_man.h"
|
|
|
|
#include "p_local.h"
|
2016-09-23 23:47:44 +00:00
|
|
|
#include "serializer.h"
|
2017-01-08 17:45:30 +00:00
|
|
|
#include "g_levellocals.h"
|
2018-04-16 07:02:48 +00:00
|
|
|
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-08-01 18:59:39 +00:00
|
|
|
#include "gl/dynlights/gl_lightbuffer.h"
|
2018-05-16 21:21:21 +00:00
|
|
|
#include "gl_load/gl_interface.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/system/gl_framebuffer.h"
|
2018-04-25 18:33:55 +00:00
|
|
|
#include "hwrenderer/utility/hw_cvars.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/renderer/gl_lightdata.h"
|
|
|
|
#include "gl/renderer/gl_renderstate.h"
|
2016-07-26 19:27:02 +00:00
|
|
|
#include "gl/renderer/gl_renderbuffers.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/data/gl_vertexbuffer.h"
|
2018-04-23 20:18:13 +00:00
|
|
|
#include "hwrenderer/scene/hw_clipper.h"
|
2018-06-23 11:25:23 +00:00
|
|
|
#include "hwrenderer/scene/hw_portal.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/scene/gl_drawinfo.h"
|
|
|
|
#include "gl/scene/gl_portal.h"
|
2015-10-31 00:51:35 +00:00
|
|
|
#include "gl/stereo3d/gl_stereo3d.h"
|
2018-06-12 12:47:05 +00:00
|
|
|
#include "hwrenderer/utility/scoped_view_shifter.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CVARs
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
CVAR(Bool, gl_texture, true, 0)
|
|
|
|
CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
|
|
CVAR(Float, gl_mask_threshold, 0.5f,CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
|
|
CVAR(Float, gl_mask_sprite_threshold, 0.5f,CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
2014-08-30 13:34:14 +00:00
|
|
|
CVAR(Bool, gl_sort_textures, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
EXTERN_CVAR (Bool, cl_capfps)
|
|
|
|
EXTERN_CVAR (Bool, r_deathcamera)
|
2017-07-09 17:01:34 +00:00
|
|
|
EXTERN_CVAR (Float, r_visibility)
|
2017-07-30 14:44:49 +00:00
|
|
|
EXTERN_CVAR (Bool, r_drawvoxels)
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
|
2018-06-21 18:54:34 +00:00
|
|
|
void FDrawInfo::ApplyVPUniforms()
|
2015-10-31 00:51:35 +00:00
|
|
|
{
|
2018-06-21 18:54:34 +00:00
|
|
|
VPUniforms.CalcDependencies();
|
2018-06-21 19:36:12 +00:00
|
|
|
GLRenderer->mShaderManager->ApplyMatrices(&VPUniforms, NORMAL_PASS);
|
2018-06-22 20:45:05 +00:00
|
|
|
|
|
|
|
if (!(gl.flags & RFL_NO_CLIP_PLANES))
|
|
|
|
{
|
2018-06-22 21:49:39 +00:00
|
|
|
if (VPUniforms.mClipHeightDirection != 0.f || VPUniforms.mClipLine.X > -10000000.0f)
|
2018-06-22 20:45:05 +00:00
|
|
|
{
|
|
|
|
glEnable(GL_CLIP_DISTANCE0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glDisable(GL_CLIP_DISTANCE0);
|
|
|
|
}
|
|
|
|
}
|
2015-10-31 00:51:35 +00:00
|
|
|
}
|
|
|
|
|
2018-06-22 21:49:39 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// CreateScene
|
|
|
|
//
|
|
|
|
// creates the draw lists for the current scene
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2018-06-20 09:17:38 +00:00
|
|
|
void FDrawInfo::CreateScene()
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2018-06-20 09:17:38 +00:00
|
|
|
const auto &vp = Viewpoint;
|
|
|
|
angle_t a1 = FrustumAngle();
|
|
|
|
mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1);
|
2017-03-11 23:19:20 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
// reset the portal manager
|
2018-06-23 11:25:23 +00:00
|
|
|
GLRenderer->mPortalState.StartFrame();
|
2017-03-13 20:16:37 +00:00
|
|
|
PO_LinkToSubsectors();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
ProcessAll.Clock();
|
|
|
|
|
|
|
|
// clip the scene and fill the drawlists
|
|
|
|
Bsp.Clock();
|
2016-08-29 08:43:03 +00:00
|
|
|
GLRenderer->mVBO->Map();
|
2018-04-29 15:36:51 +00:00
|
|
|
GLRenderer->mLights->Begin();
|
|
|
|
|
2018-05-21 22:27:39 +00:00
|
|
|
// Give the DrawInfo the viewpoint in fixed point because that's what the nodes are.
|
2018-06-20 09:17:38 +00:00
|
|
|
viewx = FLOAT2FIXED(vp.Pos.X);
|
|
|
|
viewy = FLOAT2FIXED(vp.Pos.Y);
|
2018-05-21 22:27:39 +00:00
|
|
|
|
2016-04-17 08:39:29 +00:00
|
|
|
validcount++; // used for processing sidedefs only once by the renderer.
|
2018-05-21 08:49:24 +00:00
|
|
|
|
2018-06-20 09:17:38 +00:00
|
|
|
mShadowMap = &GLRenderer->mShadowMap;
|
2018-04-28 22:09:44 +00:00
|
|
|
|
2018-06-20 09:17:38 +00:00
|
|
|
RenderBSPNode (level.HeadNode());
|
|
|
|
PreparePlayerSprites(vp.sector, in_area);
|
2018-05-04 21:11:37 +00:00
|
|
|
|
2018-04-30 21:06:48 +00:00
|
|
|
// Process all the sprites on the current portal's back side which touch the portal.
|
2018-06-23 11:51:19 +00:00
|
|
|
if (mCurrentPortal != nullptr) mCurrentPortal->RenderAttached(this);
|
2013-06-23 07:49:34 +00:00
|
|
|
Bsp.Unclock();
|
|
|
|
|
2018-04-02 21:42:45 +00:00
|
|
|
// 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.
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2018-06-20 09:17:38 +00:00
|
|
|
HandleMissingTextures(in_area); // Missing upper/lower textures
|
|
|
|
HandleHackedSubsectors(); // open sector hacks for deep water
|
|
|
|
ProcessSectorStacks(in_area); // merge visplanes of sector stacks
|
2018-04-29 15:36:51 +00:00
|
|
|
GLRenderer->mLights->Finish();
|
2016-08-29 08:43:03 +00:00
|
|
|
GLRenderer->mVBO->Unmap();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
ProcessAll.Unclock();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// RenderScene
|
|
|
|
//
|
|
|
|
// Draws the current draw lists for the non GLSL renderer
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2018-06-20 09:17:38 +00:00
|
|
|
void FDrawInfo::RenderScene(int recursion)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2018-06-20 09:17:38 +00:00
|
|
|
const auto &vp = Viewpoint;
|
2013-06-23 07:49:34 +00:00
|
|
|
RenderAll.Clock();
|
|
|
|
|
2013-09-03 12:05:41 +00:00
|
|
|
glDepthMask(true);
|
2018-06-23 11:25:23 +00:00
|
|
|
if (!gl_no_skyclear) GLRenderer->mPortalState.RenderFirstSkyPortal(recursion, this);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
gl_RenderState.EnableFog(true);
|
|
|
|
gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
|
|
|
|
|
2014-08-30 13:34:14 +00:00
|
|
|
if (gl_sort_textures)
|
|
|
|
{
|
2018-06-20 09:17:38 +00:00
|
|
|
drawlists[GLDL_PLAINWALLS].SortWalls();
|
|
|
|
drawlists[GLDL_PLAINFLATS].SortFlats();
|
|
|
|
drawlists[GLDL_MASKEDWALLS].SortWalls();
|
|
|
|
drawlists[GLDL_MASKEDFLATS].SortFlats();
|
|
|
|
drawlists[GLDL_MASKEDWALLSOFS].SortWalls();
|
2014-08-30 13:34:14 +00:00
|
|
|
}
|
2014-08-19 12:18:21 +00:00
|
|
|
|
|
|
|
// if we don't have a persistently mapped buffer, we have to process all the dynamic lights up front,
|
|
|
|
// so that we don't have to do repeated map/unmap calls on the buffer.
|
2018-06-20 09:17:38 +00:00
|
|
|
if (gl.lightmethod == LM_DEFERRED && level.HasDynamicLights && !isFullbrightScene())
|
2014-08-19 12:18:21 +00:00
|
|
|
{
|
|
|
|
GLRenderer->mLights->Begin();
|
2018-06-20 09:17:38 +00:00
|
|
|
drawlists[GLDL_PLAINFLATS].DrawFlats(this, GLPASS_LIGHTSONLY);
|
|
|
|
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, GLPASS_LIGHTSONLY);
|
|
|
|
drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, GLPASS_LIGHTSONLY);
|
|
|
|
drawlists[GLDL_TRANSLUCENT].Draw(this, GLPASS_LIGHTSONLY, true);
|
2014-08-19 12:18:21 +00:00
|
|
|
GLRenderer->mLights->Finish();
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
// Part 1: solid geometry. This is set up so that there are no transparent parts
|
2013-09-03 12:05:41 +00:00
|
|
|
glDepthFunc(GL_LESS);
|
2014-07-14 19:14:43 +00:00
|
|
|
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
|
2014-08-19 12:18:21 +00:00
|
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2018-06-08 17:12:06 +00:00
|
|
|
int pass = GLPASS_ALL;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
gl_RenderState.EnableTexture(gl_texture);
|
2014-07-15 18:49:21 +00:00
|
|
|
gl_RenderState.EnableBrightmap(true);
|
2018-06-20 09:17:38 +00:00
|
|
|
drawlists[GLDL_PLAINWALLS].DrawWalls(this, pass);
|
|
|
|
drawlists[GLDL_PLAINFLATS].DrawFlats(this, pass);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
|
2014-07-15 18:49:21 +00:00
|
|
|
// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
|
2013-06-23 07:49:34 +00:00
|
|
|
if (!gl_texture)
|
|
|
|
{
|
|
|
|
gl_RenderState.EnableTexture(true);
|
|
|
|
gl_RenderState.SetTextureMode(TM_MASK);
|
|
|
|
}
|
2014-07-14 19:14:43 +00:00
|
|
|
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
|
2018-06-20 09:17:38 +00:00
|
|
|
drawlists[GLDL_MASKEDWALLS].DrawWalls(this, pass);
|
|
|
|
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, pass);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
// Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use.
|
2018-06-20 09:17:38 +00:00
|
|
|
if (drawlists[GLDL_MASKEDWALLSOFS].Size() > 0)
|
2014-07-15 19:16:59 +00:00
|
|
|
{
|
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glPolygonOffset(-1.0f, -128.0f);
|
2018-06-20 09:17:38 +00:00
|
|
|
drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(this, pass);
|
2014-07-15 19:16:59 +00:00
|
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glPolygonOffset(0, 0);
|
|
|
|
}
|
|
|
|
|
2018-06-20 09:17:38 +00:00
|
|
|
drawlists[GLDL_MODELS].Draw(this, pass);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
// Part 4: Draw decals (not a real pass)
|
2013-09-03 12:05:41 +00:00
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glPolygonOffset(-1.0f, -128.0f);
|
|
|
|
glDepthMask(false);
|
2018-06-20 09:17:38 +00:00
|
|
|
DrawDecals();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
gl_RenderState.SetTextureMode(TM_MODULATE);
|
|
|
|
|
2013-09-03 12:05:41 +00:00
|
|
|
glDepthMask(true);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Push bleeding floor/ceiling textures back a little in the z-buffer
|
|
|
|
// so they don't interfere with overlapping mid textures.
|
2013-09-03 12:05:41 +00:00
|
|
|
glPolygonOffset(1.0f, 128.0f);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-08-19 12:18:21 +00:00
|
|
|
// Part 5: flood all the gaps with the back sector's flat texture
|
|
|
|
// This will always be drawn like GLDL_PLAIN, depending on the fog settings
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2013-09-03 12:05:41 +00:00
|
|
|
glDepthMask(false); // don't write to Z-buffer!
|
2013-08-18 13:41:52 +00:00
|
|
|
gl_RenderState.EnableFog(true);
|
2014-07-14 19:14:43 +00:00
|
|
|
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
|
2013-08-18 13:41:52 +00:00
|
|
|
gl_RenderState.BlendFunc(GL_ONE,GL_ZERO);
|
2018-06-20 09:17:38 +00:00
|
|
|
DrawUnhandledMissingTextures();
|
2013-09-03 12:05:41 +00:00
|
|
|
glDepthMask(true);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2013-09-03 12:05:41 +00:00
|
|
|
glPolygonOffset(0.0f, 0.0f);
|
|
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
2013-06-23 07:49:34 +00:00
|
|
|
RenderAll.Unclock();
|
2014-08-30 12:33:06 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// RenderTranslucent
|
|
|
|
//
|
|
|
|
// Draws the current draw lists for the non GLSL renderer
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2018-06-20 09:17:38 +00:00
|
|
|
void FDrawInfo::RenderTranslucent()
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
RenderAll.Clock();
|
|
|
|
|
|
|
|
// final pass: translucent stuff
|
2014-07-14 19:14:43 +00:00
|
|
|
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
|
2013-06-23 07:49:34 +00:00
|
|
|
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
gl_RenderState.EnableBrightmap(true);
|
2018-06-20 09:17:38 +00:00
|
|
|
drawlists[GLDL_TRANSLUCENTBORDER].Draw(this, GLPASS_TRANSLUCENT);
|
2018-06-02 21:08:42 +00:00
|
|
|
glDepthMask(false);
|
2018-06-20 09:17:38 +00:00
|
|
|
DrawSorted(GLDL_TRANSLUCENT);
|
2013-06-23 07:49:34 +00:00
|
|
|
gl_RenderState.EnableBrightmap(false);
|
|
|
|
|
|
|
|
|
2014-07-14 19:14:43 +00:00
|
|
|
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f);
|
2018-04-27 18:18:52 +00:00
|
|
|
glDepthMask(true);
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
RenderAll.Unclock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// gl_drawscene - this function renders the scene from the current
|
2018-04-01 20:26:57 +00:00
|
|
|
// viewpoint, including mirrors and skyboxes and other portals
|
2013-06-23 07:49:34 +00:00
|
|
|
// It is assumed that the GLPortal::EndFrame returns with the
|
|
|
|
// stencil, z-buffer and the projection matrix intact!
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
void FDrawInfo::DrawScene(int drawmode)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
static int recursion=0;
|
2016-09-24 18:09:40 +00:00
|
|
|
static int ssao_portals_available = 0;
|
2018-06-20 09:38:45 +00:00
|
|
|
const auto &vp = Viewpoint;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-10-22 19:35:49 +00:00
|
|
|
bool applySSAO = false;
|
2016-10-21 22:09:06 +00:00
|
|
|
if (drawmode == DM_MAINVIEW)
|
2016-10-22 19:35:49 +00:00
|
|
|
{
|
|
|
|
ssao_portals_available = gl_ssao_portals;
|
|
|
|
applySSAO = true;
|
|
|
|
}
|
2016-10-21 22:09:06 +00:00
|
|
|
else if (drawmode == DM_OFFSCREEN)
|
2016-10-22 19:35:49 +00:00
|
|
|
{
|
2016-10-21 22:09:06 +00:00
|
|
|
ssao_portals_available = 0;
|
2016-10-22 19:35:49 +00:00
|
|
|
}
|
2017-03-11 16:20:06 +00:00
|
|
|
else if (drawmode == DM_PORTAL && ssao_portals_available > 0)
|
2016-10-22 19:35:49 +00:00
|
|
|
{
|
|
|
|
applySSAO = true;
|
|
|
|
ssao_portals_available--;
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2018-06-19 21:16:22 +00:00
|
|
|
if (vp.camera != nullptr)
|
2016-06-18 10:14:20 +00:00
|
|
|
{
|
2018-06-19 21:16:22 +00:00
|
|
|
ActorRenderFlags savedflags = vp.camera->renderflags;
|
2018-06-20 09:38:45 +00:00
|
|
|
CreateScene();
|
2018-06-19 21:16:22 +00:00
|
|
|
vp.camera->renderflags = savedflags;
|
2016-06-18 10:14:20 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-06-20 09:38:45 +00:00
|
|
|
CreateScene();
|
2016-06-18 10:14:20 +00:00
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
RenderScene(recursion);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-10-22 19:35:49 +00:00
|
|
|
if (applySSAO && gl_RenderState.GetPassType() == GBUFFER_PASS)
|
2016-09-21 00:04:56 +00:00
|
|
|
{
|
2016-10-21 22:09:06 +00:00
|
|
|
gl_RenderState.EnableDrawBuffers(1);
|
2018-06-21 18:54:34 +00:00
|
|
|
GLRenderer->AmbientOccludeScene(VPUniforms.mProjectionMatrix.get()[5]);
|
2017-03-12 11:03:54 +00:00
|
|
|
GLRenderer->mBuffers->BindSceneFB(true);
|
2016-10-21 22:09:06 +00:00
|
|
|
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
2016-09-21 00:04:56 +00:00
|
|
|
gl_RenderState.Apply();
|
2018-06-21 18:54:34 +00:00
|
|
|
ApplyVPUniforms();
|
2016-09-21 00:04:56 +00:00
|
|
|
}
|
2016-09-03 02:29:50 +00:00
|
|
|
|
2018-04-01 20:26:57 +00:00
|
|
|
// Handle all portals after rendering the opaque objects but before
|
2013-06-23 07:49:34 +00:00
|
|
|
// doing all translucent stuff
|
|
|
|
recursion++;
|
2018-06-23 11:25:23 +00:00
|
|
|
GLRenderer->mPortalState.EndFrame(this);
|
2013-06-23 07:49:34 +00:00
|
|
|
recursion--;
|
2018-06-20 09:38:45 +00:00
|
|
|
RenderTranslucent();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Draws player sprites and color blend
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
void FDrawInfo::EndDrawScene(sector_t * viewsector)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-07-26 20:26:17 +00:00
|
|
|
gl_RenderState.EnableFog(false);
|
|
|
|
|
2018-05-04 21:11:37 +00:00
|
|
|
// [BB] HUD models need to be rendered here.
|
2018-05-21 15:52:03 +00:00
|
|
|
const bool renderHUDModel = IsHUDModelForPlayerAvailable( players[consoleplayer].camera->player );
|
2013-06-23 07:49:34 +00:00
|
|
|
if ( renderHUDModel )
|
|
|
|
{
|
|
|
|
// [BB] The HUD model should be drawn over everything else already drawn.
|
2013-09-03 12:05:41 +00:00
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
2018-06-20 09:38:45 +00:00
|
|
|
DrawPlayerSprites(true);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
2013-09-03 12:05:41 +00:00
|
|
|
glDisable(GL_STENCIL_TEST);
|
2018-06-20 09:38:45 +00:00
|
|
|
glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height);
|
2016-09-20 00:06:52 +00:00
|
|
|
|
2018-06-16 11:47:24 +00:00
|
|
|
// Restore standard rendering state
|
|
|
|
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
gl_RenderState.ResetColor();
|
|
|
|
gl_RenderState.EnableTexture(true);
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
2018-01-06 04:11:12 +00:00
|
|
|
}
|
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
void FDrawInfo::DrawEndScene2D(sector_t * viewsector)
|
2018-01-06 04:11:12 +00:00
|
|
|
{
|
2018-05-21 15:52:03 +00:00
|
|
|
const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
|
2018-01-06 04:11:12 +00:00
|
|
|
|
2018-04-29 20:30:52 +00:00
|
|
|
// This should be removed once all 2D stuff is really done through the 2D interface.
|
2018-06-21 18:54:34 +00:00
|
|
|
VPUniforms.mViewMatrix.loadIdentity();
|
|
|
|
VPUniforms.mProjectionMatrix.ortho(0, screen->GetWidth(), screen->GetHeight(), 0, -1.0f, 1.0f);
|
|
|
|
ApplyVPUniforms();
|
2018-04-30 19:42:36 +00:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_MULTISAMPLE);
|
|
|
|
|
2018-04-29 20:30:52 +00:00
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
DrawPlayerSprites(false);
|
2018-05-04 21:11:37 +00:00
|
|
|
|
2016-09-01 15:14:51 +00:00
|
|
|
gl_RenderState.SetSoftLightLevel(-1);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
// Restore standard rendering state
|
|
|
|
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2014-05-11 20:57:42 +00:00
|
|
|
gl_RenderState.ResetColor();
|
2013-06-23 07:49:34 +00:00
|
|
|
gl_RenderState.EnableTexture(true);
|
2013-09-03 12:05:41 +00:00
|
|
|
glDisable(GL_SCISSOR_TEST);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// R_RenderView - renders one view - either the screen or a camera texture
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
void FDrawInfo::ProcessScene(bool toscreen)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
|
2018-06-23 11:25:23 +00:00
|
|
|
GLRenderer->mPortalState.BeginScene();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
int mapsection = R_PointInSubsector(Viewpoint.Pos)->mapsection;
|
|
|
|
CurrentMapSections.Set(mapsection);
|
|
|
|
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-06-20 10:57:41 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// sets 3D viewport and initial state
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void FGLRenderer::Set3DViewport(bool mainview)
|
|
|
|
{
|
|
|
|
if (mainview && buffersActive)
|
|
|
|
{
|
|
|
|
bool useSSAO = (gl_ssao != 0);
|
|
|
|
mBuffers->BindSceneFB(useSSAO);
|
|
|
|
gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
|
|
|
|
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
|
|
|
gl_RenderState.Apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
glClearColor(mSceneClearColor[0], mSceneClearColor[1], mSceneClearColor[2], 1.0f);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
|
|
|
|
const auto &bounds = screen->mSceneViewport;
|
|
|
|
glViewport(bounds.left, bounds.top, bounds.width, bounds.height);
|
|
|
|
glScissor(bounds.left, bounds.top, bounds.width, bounds.height);
|
|
|
|
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
|
|
|
|
glEnable(GL_MULTISAMPLE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_STENCIL_TEST);
|
|
|
|
glStencilFunc(GL_ALWAYS,0,~0); // default stencil
|
|
|
|
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
|
|
|
|
}
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Renders one viewpoint in a scene
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2018-06-20 10:57:41 +00:00
|
|
|
sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen)
|
2018-06-20 08:47:03 +00:00
|
|
|
{
|
2018-06-19 21:16:22 +00:00
|
|
|
R_SetupFrame (mainvp, r_viewwindow, camera);
|
2014-12-31 11:04:55 +00:00
|
|
|
|
2018-06-20 08:47:03 +00:00
|
|
|
// Render (potentially) multiple views for stereo 3d
|
2015-10-31 00:51:35 +00:00
|
|
|
float viewShift[3];
|
2016-09-03 14:54:17 +00:00
|
|
|
const s3d::Stereo3DMode& stereo3dMode = mainview && toscreen? s3d::Stereo3DMode::getCurrentMode() : s3d::Stereo3DMode::getMonoMode();
|
2015-10-31 00:51:35 +00:00
|
|
|
stereo3dMode.SetUp();
|
2015-12-31 14:36:37 +00:00
|
|
|
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
|
2015-10-31 00:51:35 +00:00
|
|
|
{
|
2018-06-24 08:47:42 +00:00
|
|
|
const auto eye = stereo3dMode.getEyePose(eye_ix);
|
2015-12-31 14:36:37 +00:00
|
|
|
eye->SetUp();
|
2018-06-03 11:59:40 +00:00
|
|
|
screen->SetViewportRects(bounds);
|
2017-03-12 11:51:26 +00:00
|
|
|
Set3DViewport(mainview);
|
2018-05-21 20:04:29 +00:00
|
|
|
|
2018-06-21 18:54:34 +00:00
|
|
|
FDrawInfo *di = FDrawInfo::StartDrawInfo(mainvp, nullptr);
|
2018-06-19 21:16:22 +00:00
|
|
|
auto vp = di->Viewpoint;
|
2018-05-21 20:04:29 +00:00
|
|
|
di->SetViewArea();
|
2018-06-19 21:16:22 +00:00
|
|
|
auto cm = di->SetFullbrightFlags(mainview ? vp.camera->player : nullptr);
|
|
|
|
di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint)
|
2018-05-21 20:04:29 +00:00
|
|
|
|
2015-10-31 00:51:35 +00:00
|
|
|
// Stereo mode specific perspective projection
|
2018-06-21 18:54:34 +00:00
|
|
|
di->VPUniforms.mProjectionMatrix = eye->GetProjection(fov, ratio, fovratio);
|
2016-05-01 15:43:30 +00:00
|
|
|
// Stereo mode specific viewpoint adjustment - temporarily shifts global ViewPos
|
2018-06-19 21:16:22 +00:00
|
|
|
eye->GetViewShift(vp.HWAngles.Yaw.Degrees, viewShift);
|
|
|
|
ScopedViewShifter viewShifter(vp.Pos, viewShift);
|
2018-06-22 19:44:53 +00:00
|
|
|
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
|
|
|
|
2015-10-31 00:51:35 +00:00
|
|
|
|
2018-06-20 09:38:45 +00:00
|
|
|
di->ProcessScene(toscreen);
|
2018-04-29 09:00:34 +00:00
|
|
|
|
2018-06-16 07:37:01 +00:00
|
|
|
if (mainview)
|
2016-07-29 19:31:20 +00:00
|
|
|
{
|
2018-06-20 09:38:45 +00:00
|
|
|
if (toscreen) di->EndDrawScene(mainvp.sector); // do not call this for camera textures.
|
2018-06-20 10:57:41 +00:00
|
|
|
PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector); });
|
2016-07-29 19:31:20 +00:00
|
|
|
}
|
2018-06-19 21:16:22 +00:00
|
|
|
di->EndDrawInfo();
|
2018-06-16 07:37:01 +00:00
|
|
|
if (!stereo3dMode.IsMono())
|
2018-06-20 10:57:41 +00:00
|
|
|
mBuffers->BlitToEyeTexture(eye_ix);
|
2015-10-31 00:51:35 +00:00
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
interpolator.RestoreInterpolations ();
|
2018-06-20 08:47:03 +00:00
|
|
|
return mainvp.sector;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|