- moved the render interface functions out of FGLRenderer into OpenGLFrameBuffer.

These need some consolidation among the backends, and the additional indirection in the OpenGL backend made it harder than necessary.
This commit is contained in:
Christoph Oelckers 2020-04-24 15:52:31 +02:00
commit 70d30feb4c
5 changed files with 147 additions and 158 deletions

View file

@ -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<OpenGLFrameBuffer*>(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;
}