This shouldn't be in the hardware independent interface because the semantics on OpenGL and Vulkan are too different, so a common implementation is not possible. Most bind calls were in the GL interface anyway, so these no longer pass through hardware independent code. This also moves the bind calls in the shadowmap code into the GL interface - these never did anything useful in Vulkan and aren't needed there. Last but not least, this moves the legacy buffer binding handling into FGLRenderState and performs the initial binding for the light buffer in a more suitable place so that this doesn't have to pollute the render state.
227 lines
7.5 KiB
C++
227 lines
7.5 KiB
C++
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// 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/
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
/*
|
|
** gl_scene.cpp
|
|
** manages the rendering of the player's view
|
|
**
|
|
*/
|
|
|
|
#include "gl_load/gl_system.h"
|
|
#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"
|
|
#include "serializer.h"
|
|
#include "g_levellocals.h"
|
|
#include "actorinlines.h"
|
|
#include "r_data/models/models.h"
|
|
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
|
#include "hwrenderer/utility/hw_clock.h"
|
|
#include "hwrenderer/data/flatvertices.h"
|
|
|
|
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
|
#include "gl_load/gl_interface.h"
|
|
#include "gl/system/gl_framebuffer.h"
|
|
#include "gl/system/gl_debug.h"
|
|
#include "hwrenderer/utility/hw_cvars.h"
|
|
#include "gl/renderer/gl_renderstate.h"
|
|
#include "gl/renderer/gl_renderbuffers.h"
|
|
#include "hwrenderer/data/hw_viewpointbuffer.h"
|
|
#include "hwrenderer/scene/hw_clipper.h"
|
|
#include "hwrenderer/scene/hw_portal.h"
|
|
#include "hwrenderer/utility/hw_vrmodes.h"
|
|
#include "gl/renderer/gl_renderer.h"
|
|
#include "gl/system/gl_buffers.h"
|
|
|
|
//==========================================================================
|
|
//
|
|
// 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)
|
|
|
|
EXTERN_CVAR (Bool, cl_capfps)
|
|
EXTERN_CVAR (Bool, r_deathcamera)
|
|
EXTERN_CVAR (Float, r_visibility)
|
|
EXTERN_CVAR (Bool, r_drawvoxels)
|
|
|
|
|
|
namespace OpenGLRenderer
|
|
{
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// 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 FGLRenderer::DrawScene(HWDrawInfo *di, int drawmode)
|
|
{
|
|
static int recursion=0;
|
|
static int ssao_portals_available = 0;
|
|
const auto &vp = di->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 = true;
|
|
ssao_portals_available--;
|
|
}
|
|
|
|
if (vp.camera != nullptr)
|
|
{
|
|
ActorRenderFlags savedflags = vp.camera->renderflags;
|
|
di->CreateScene(drawmode == DM_MAINVIEW);
|
|
vp.camera->renderflags = savedflags;
|
|
}
|
|
else
|
|
{
|
|
di->CreateScene(false);
|
|
}
|
|
|
|
glDepthMask(true);
|
|
if (!gl_no_skyclear) screen->mPortalState->RenderFirstSkyPortal(recursion, di, gl_RenderState);
|
|
|
|
di->RenderScene(gl_RenderState);
|
|
|
|
if (applySSAO && gl_RenderState.GetPassType() == GBUFFER_PASS)
|
|
{
|
|
gl_RenderState.EnableDrawBuffers(1);
|
|
GLRenderer->AmbientOccludeScene(di->VPUniforms.mProjectionMatrix.get()[5]);
|
|
glViewport(screen->mSceneViewport.left, screen->mSceneViewport.top, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
|
GLRenderer->mBuffers->BindSceneFB(true);
|
|
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
|
|
gl_RenderState.Apply();
|
|
screen->mViewpoints->Bind(gl_RenderState, di->vpIndex);
|
|
}
|
|
|
|
// Handle all portals after rendering the opaque objects but before
|
|
// doing all translucent stuff
|
|
recursion++;
|
|
screen->mPortalState->EndFrame(di, gl_RenderState);
|
|
recursion--;
|
|
di->RenderTranslucent(gl_RenderState);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Renders one viewpoint in a scene
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen)
|
|
{
|
|
R_SetupFrame (mainvp, r_viewwindow, camera);
|
|
|
|
if (mainview && toscreen)
|
|
UpdateShadowMap();
|
|
|
|
// Update the attenuation flag of all light defaults for each viewpoint.
|
|
// This function will only do something if the setting differs.
|
|
FLightDefaults::SetAttenuationForLevel(!!(camera->Level->flags3 & LEVEL3_ATTENUATE));
|
|
|
|
// Render (potentially) multiple views for stereo 3d
|
|
// Fixme. The view offsetting should be done with a static table and not require setup of the entire render state for the mode.
|
|
auto vrmode = VRMode::GetVRMode(mainview && toscreen);
|
|
const int eyeCount = vrmode->mEyeCount;
|
|
mBuffers->CurrentEye() = 0; // always begin at zero, in case eye count changed
|
|
for (int eye_ix = 0; eye_ix < eyeCount; ++eye_ix)
|
|
{
|
|
const auto &eye = vrmode->mEyes[mBuffers->CurrentEye()];
|
|
screen->SetViewportRects(bounds);
|
|
|
|
if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao
|
|
{
|
|
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();
|
|
}
|
|
|
|
|
|
auto di = HWDrawInfo::StartDrawInfo(mainvp.ViewLevel, nullptr, mainvp, nullptr);
|
|
auto &vp = di->Viewpoint;
|
|
|
|
di->Set3DViewport(gl_RenderState);
|
|
di->SetViewArea();
|
|
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)
|
|
|
|
// Stereo mode specific perspective projection
|
|
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio);
|
|
// Stereo mode specific viewpoint adjustment
|
|
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees);
|
|
di->SetupView(gl_RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
|
|
|
// std::function until this can be done better in a cross-API fashion.
|
|
di->ProcessScene(toscreen, [&](HWDrawInfo *di, int mode) {
|
|
DrawScene(di, mode);
|
|
});
|
|
|
|
if (mainview)
|
|
{
|
|
PostProcess.Clock();
|
|
if (toscreen) di->EndDrawScene(mainvp.sector, gl_RenderState); // do not call this for camera textures.
|
|
|
|
if (gl_RenderState.GetPassType() == GBUFFER_PASS) // Turn off ssao draw buffers
|
|
{
|
|
gl_RenderState.SetPassType(NORMAL_PASS);
|
|
gl_RenderState.EnableDrawBuffers(1);
|
|
}
|
|
|
|
mBuffers->BlitSceneToTexture(); // Copy the resulting scene to the current post process texture
|
|
|
|
PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector, gl_RenderState); });
|
|
PostProcess.Unclock();
|
|
}
|
|
di->EndDrawInfo();
|
|
if (eyeCount - eye_ix > 1)
|
|
mBuffers->NextEye(eyeCount);
|
|
}
|
|
|
|
return mainvp.sector;
|
|
}
|
|
|
|
}
|