diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c391b83b5..d035e752e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1288,7 +1288,8 @@ include_directories( . ../libraries/glslang/glslang/Public ../libraries/glslang/spirv ${CMAKE_BINARY_DIR}/libraries/gdtoa - ${SYSTEM_SOURCES_DIR} ) + ${SYSTEM_SOURCES_DIR} +) add_dependencies( zdoom revision_check ) diff --git a/src/rendering/gl/renderer/gl_renderer.cpp b/src/rendering/gl/renderer/gl_renderer.cpp index 5858ae938..79713ae75 100644 --- a/src/rendering/gl/renderer/gl_renderer.cpp +++ b/src/rendering/gl/renderer/gl_renderer.cpp @@ -62,12 +62,9 @@ #include "texturemanager.h" EXTERN_CVAR(Int, screenblocks) -EXTERN_CVAR(Bool, cl_capfps) extern bool NoInterpolateView; -void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown); - namespace OpenGLRenderer { @@ -217,78 +214,6 @@ void FGLRenderer::UpdateShadowMap() } } -//----------------------------------------------------------------------------- -// -// renders the view -// -//----------------------------------------------------------------------------- - -sector_t *FGLRenderer::RenderView(player_t* player) -{ - gl_RenderState.SetVertexBuffer(screen->mVertexData); - screen->mVertexData->Reset(); - sector_t *retsec; - - if (!V_IsHardwareRenderer()) - { - if (swdrawer == nullptr) swdrawer = new SWSceneDrawer; - retsec = swdrawer->RenderView(player); - } - else - { - hw_ClearFakeFlat(); - - iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0; - - checkBenchActive(); - - // reset statistics counters - ResetProfilingData(); - - // Get this before everything else - if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; - else r_viewpoint.TicFrac = I_GetTimeFrac(); - - screen->mLights->Clear(); - screen->mViewpoints->Clear(); - - // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. - bool saved_niv = NoInterpolateView; - NoInterpolateView = false; - - // Shader start time does not need to be handled per level. Just use the one from the camera to render from. - if (player->camera) - gl_RenderState.CheckTimer(player->camera->Level->ShaderStartTime); - // prepare all camera textures that have been used in the last frame. - // This must be done for all levels, not just the primary one! - for (auto Level : AllLevels()) - { - Level->canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov) - { - RenderTextureView(camtex, camera, fov); - }); - } - NoInterpolateView = saved_niv; - - - // now render the main view - float fovratio; - float ratio = r_viewwindow.WidescreenRatio; - if (r_viewwindow.WidescreenRatio >= 1.3f) - { - fovratio = 1.333333f; - } - else - { - fovratio = ratio; - } - - retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); - } - All.Unclock(); - return retsec; -} - //=========================================================================== // // @@ -309,83 +234,6 @@ void FGLRenderer::BindToFrameBuffer(FTexture *tex) BaseLayer->BindToFrameBuffer(tex->GetWidth(), tex->GetHeight()); } -//=========================================================================== -// -// Camera texture rendering -// -//=========================================================================== - -void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV) -{ - // This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene. - - float ratio = tex->aspectRatio; - - StartOffscreen(); - BindToFrameBuffer(tex); - - IntRect bounds; - bounds.left = bounds.top = 0; - bounds.width = FHardwareTexture::GetTexDimension(tex->GetWidth()); - bounds.height = FHardwareTexture::GetTexDimension(tex->GetHeight()); - - FRenderViewpoint texvp; - RenderViewpoint(texvp, Viewpoint, &bounds, FOV, ratio, ratio, false, false); - - EndOffscreen(); - - tex->SetUpdated(true); - static_cast(screen)->camtexcount++; -} - -//=========================================================================== -// -// Render the view to a savegame picture -// -//=========================================================================== - -void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height) -{ - IntRect bounds; - bounds.left = 0; - bounds.top = 0; - bounds.width = width; - bounds.height = height; - - // we must be sure the GPU finished reading from the buffer before we fill it with new data. - glFinish(); - - // Switch to render buffers dimensioned for the savepic - mBuffers = mSaveBuffers; - - hw_ClearFakeFlat(); - gl_RenderState.SetVertexBuffer(screen->mVertexData); - screen->mVertexData->Reset(); - screen->mLights->Clear(); - screen->mViewpoints->Clear(); - - // This shouldn't overwrite the global viewpoint even for a short time. - FRenderViewpoint savevp; - sector_t *viewsector = RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false); - glDisable(GL_STENCIL_TEST); - gl_RenderState.SetNoSoftLightLevel(); - CopyToBackbuffer(&bounds, false); - - // strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers - glFinish(); - - int numpixels = width * height; - uint8_t * scr = (uint8_t *)M_Malloc(numpixels * 3); - glReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr); - - DoWriteSavePic(file, SS_RGB, scr, width, height, viewsector, true); - M_Free(scr); - - // Switch back the screen render buffers - screen->SetViewportRects(nullptr); - mBuffers = mScreenBuffers; -} - //=========================================================================== // // diff --git a/src/rendering/gl/renderer/gl_renderer.h b/src/rendering/gl/renderer/gl_renderer.h index bf59a5532..3dde0195c 100644 --- a/src/rendering/gl/renderer/gl_renderer.h +++ b/src/rendering/gl/renderer/gl_renderer.h @@ -89,9 +89,6 @@ public: void DrawPresentTexture(const IntRect &box, bool applyGamma); void Flush(); void Draw2D(F2DDrawer *data); - void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); - void WriteSavePic(player_t *player, FileWriter *file, int width, int height); - sector_t *RenderView(player_t *player); void BeginFrame(); sector_t *RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); diff --git a/src/rendering/gl/system/gl_framebuffer.cpp b/src/rendering/gl/system/gl_framebuffer.cpp index 0a8770b1e..961f807fe 100644 --- a/src/rendering/gl/system/gl_framebuffer.cpp +++ b/src/rendering/gl/system/gl_framebuffer.cpp @@ -30,6 +30,7 @@ #include "v_video.h" #include "m_png.h" #include "templates.h" +#include "i_time.h" #include "gl_interface.h" #include "gl/system/gl_framebuffer.h" @@ -40,18 +41,25 @@ #include "hwrenderer/utility/hw_vrmodes.h" #include "hwrenderer/models/hw_models.h" #include "hwrenderer/scene/hw_skydome.h" +#include "hwrenderer/scene/hw_fakeflat.h" #include "hwrenderer/data/hw_viewpointbuffer.h" #include "hwrenderer/dynlights/hw_lightbuffer.h" #include "gl/shaders/gl_shaderprogram.h" #include "gl_debug.h" #include "r_videoscale.h" #include "gl_buffers.h" +#include "swrenderer/r_swscene.h" #include "hwrenderer/data/flatvertices.h" EXTERN_CVAR (Bool, vid_vsync) EXTERN_CVAR(Bool, r_drawvoxels) EXTERN_CVAR(Int, gl_tonemap) +EXTERN_CVAR(Bool, cl_capfps) + +void DoWriteSavePic(FileWriter* file, ESSType ssformat, uint8_t* scr, int width, int height, sector_t* viewsector, bool upsidedown); + +extern bool NoInterpolateView; void gl_LoadExtensions(); void gl_PrintStartupLog(); @@ -193,9 +201,79 @@ void OpenGLFrameBuffer::Update() void OpenGLFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height) { if (!V_IsHardwareRenderer()) + { Super::WriteSavePic(player, file, width, height); + } else if (GLRenderer != nullptr) - GLRenderer->WriteSavePic(player, file, width, height); + { + IntRect bounds; + bounds.left = 0; + bounds.top = 0; + bounds.width = width; + bounds.height = height; + + // we must be sure the GPU finished reading from the buffer before we fill it with new data. + glFinish(); + + // Switch to render buffers dimensioned for the savepic + GLRenderer->mBuffers = GLRenderer->mSaveBuffers; + + hw_ClearFakeFlat(); + gl_RenderState.SetVertexBuffer(screen->mVertexData); + screen->mVertexData->Reset(); + screen->mLights->Clear(); + screen->mViewpoints->Clear(); + + // This shouldn't overwrite the global viewpoint even for a short time. + FRenderViewpoint savevp; + sector_t* viewsector = GLRenderer->RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false); + glDisable(GL_STENCIL_TEST); + gl_RenderState.SetNoSoftLightLevel(); + GLRenderer->CopyToBackbuffer(&bounds, false); + + // strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers + glFinish(); + + int numpixels = width * height; + uint8_t* scr = (uint8_t*)M_Malloc(numpixels * 3); + glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, scr); + + DoWriteSavePic(file, SS_RGB, scr, width, height, viewsector, true); + M_Free(scr); + + // Switch back the screen render buffers + screen->SetViewportRects(nullptr); + GLRenderer->mBuffers = GLRenderer->mScreenBuffers; + } +} + +//=========================================================================== +// +// Camera texture rendering +// +//=========================================================================== + +void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture* tex, AActor* Viewpoint, double FOV) +{ + // This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene. + + float ratio = tex->aspectRatio; + + GLRenderer->StartOffscreen(); + GLRenderer->BindToFrameBuffer(tex); + + IntRect bounds; + bounds.left = bounds.top = 0; + bounds.width = FHardwareTexture::GetTexDimension(tex->GetWidth()); + bounds.height = FHardwareTexture::GetTexDimension(tex->GetHeight()); + + FRenderViewpoint texvp; + GLRenderer->RenderViewpoint(texvp, Viewpoint, &bounds, FOV, ratio, ratio, false, false); + + GLRenderer->EndOffscreen(); + + tex->SetUpdated(true); + static_cast(screen)->camtexcount++; } //=========================================================================== @@ -207,7 +285,70 @@ void OpenGLFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int wid sector_t *OpenGLFrameBuffer::RenderView(player_t *player) { if (GLRenderer != nullptr) - return GLRenderer->RenderView(player); + { + gl_RenderState.SetVertexBuffer(screen->mVertexData); + screen->mVertexData->Reset(); + sector_t* retsec; + + if (!V_IsHardwareRenderer()) + { + if (GLRenderer->swdrawer == nullptr) GLRenderer->swdrawer = new SWSceneDrawer; + retsec = GLRenderer->swdrawer->RenderView(player); + } + else + { + hw_ClearFakeFlat(); + + iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0; + + checkBenchActive(); + + // reset statistics counters + ResetProfilingData(); + + // Get this before everything else + if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; + else r_viewpoint.TicFrac = I_GetTimeFrac(); + + screen->mLights->Clear(); + screen->mViewpoints->Clear(); + + // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. + bool saved_niv = NoInterpolateView; + NoInterpolateView = false; + + // Shader start time does not need to be handled per level. Just use the one from the camera to render from. + if (player->camera) + gl_RenderState.CheckTimer(player->camera->Level->ShaderStartTime); + // prepare all camera textures that have been used in the last frame. + // This must be done for all levels, not just the primary one! + for (auto Level : AllLevels()) + { + Level->canvasTextureInfo.UpdateAll([&](AActor* camera, FCanvasTexture* camtex, double fov) + { + RenderTextureView(camtex, camera, fov); + }); + } + NoInterpolateView = saved_niv; + + + // now render the main view + float fovratio; + float ratio = r_viewwindow.WidescreenRatio; + if (r_viewwindow.WidescreenRatio >= 1.3f) + { + fovratio = 1.333333f; + } + else + { + fovratio = ratio; + } + + retsec = GLRenderer->RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); + } + All.Unclock(); + return retsec; + } return nullptr; } diff --git a/src/rendering/gl/system/gl_framebuffer.h b/src/rendering/gl/system/gl_framebuffer.h index 7578103fb..ec780dd38 100644 --- a/src/rendering/gl/system/gl_framebuffer.h +++ b/src/rendering/gl/system/gl_framebuffer.h @@ -16,6 +16,8 @@ class OpenGLFrameBuffer : public SystemGLFrameBuffer { typedef SystemGLFrameBuffer Super; + void RenderTextureView(FCanvasTexture* tex, AActor* Viewpoint, double FOV); + public: explicit OpenGLFrameBuffer() {}