- 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
parent ab16cbe298
commit 70d30feb4c
5 changed files with 147 additions and 158 deletions

View file

@ -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 )

View file

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

View file

@ -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);

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;
}

View file

@ -16,6 +16,8 @@ class OpenGLFrameBuffer : public SystemGLFrameBuffer
{
typedef SystemGLFrameBuffer Super;
void RenderTextureView(FCanvasTexture* tex, AActor* Viewpoint, double FOV);
public:
explicit OpenGLFrameBuffer() {}