// //--------------------------------------------------------------------------- // // 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_system.h" #include "gi.h" #include "m_png.h" #include "doomstat.h" #include "r_data/r_interpolate.h" #include "r_utility.h" #include "d_player.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 "hwrenderer/utility/hw_cvars.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" //----------------------------------------------------------------------------- // // Renders one viewpoint in a scene // //----------------------------------------------------------------------------- sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen) { auto& RenderState = *screen->RenderState(); R_SetupFrame(mainvp, r_viewwindow, camera); if (mainview && toscreen) screen->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; screen->FirstEye(); for (int eye_ix = 0; eye_ix < eyeCount; ++eye_ix) { const auto& eye = vrmode->mEyes[eye_ix]; screen->SetViewportRects(bounds); if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao { bool useSSAO = (gl_ssao != 0); screen->SetSceneRenderTarget(useSSAO); RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); RenderState.EnableDrawBuffers(RenderState.GetPassDrawBufferCount(), true); } auto di = HWDrawInfo::StartDrawInfo(mainvp.ViewLevel, nullptr, mainvp, nullptr); auto& vp = di->Viewpoint; di->Set3DViewport(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(RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); di->ProcessScene(toscreen); if (mainview) { PostProcess.Clock(); if (toscreen) di->EndDrawScene(mainvp.sector, RenderState); // do not call this for camera textures. if (RenderState.GetPassType() == GBUFFER_PASS) // Turn off ssao draw buffers { RenderState.SetPassType(NORMAL_PASS); RenderState.EnableDrawBuffers(1); } screen->PostProcessScene(false, cm, [&]() { di->DrawEndScene2D(mainvp.sector, RenderState); }); PostProcess.Unclock(); } di->EndDrawInfo(); if (eyeCount - eye_ix > 1) screen->NextEye(eyeCount); } return mainvp.sector; }