- another backend update, pulling in the sky renderer.

This commit is contained in:
Christoph Oelckers 2020-05-31 10:24:04 +02:00
parent efa1cd3048
commit 1d15fe63a6
19 changed files with 1197 additions and 126 deletions

View file

@ -39,15 +39,10 @@
#include "filesystem.h"
#include "i_time.h"
#include "cmdlib.h"
#include "m_png.h"
#include "version.h"
#include "texturemanager.h"
#include "model.h"
//#include "hwrenderer/utility/hw_clock.h"
#include "gl_load/gl_interface.h"
#include "gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gamecvars.h"
#include "hw_cvars.h"
#include "gl_debug.h"
#include "gl/renderer/gl_renderer.h"
#include "gl_renderstate.h"
@ -56,18 +51,14 @@
#include "flatvertices.h"
#include "gl_samplers.h"
#include "hw_lightbuffer.h"
//#include "hwrenderer/data/hw_viewpointbuffer.h"
#include "r_videoscale.h"
//#include "r_data/models/models.h"
#include "model.h"
#include "gl_postprocessstate.h"
#include "gl_buffers.h"
#include "gl_hwtexture.h"
#include "build.h"
#include "texturemanager.h"
EXTERN_CVAR(Int, screenblocks)
EXTERN_CVAR(Bool, cl_capfps)
extern bool NoInterpolateView;
namespace OpenGLRenderer
{
@ -195,9 +186,4 @@ void FGLRenderer::BeginFrame()
mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
}
void FGLRenderer::PresentStereo()
{
}
}

View file

@ -78,7 +78,6 @@ public:
void CopyToBackbuffer(const IntRect *bounds, bool applyGamma);
void DrawPresentTexture(const IntRect &box, bool applyGamma);
void Flush();
//void Draw2D(F2DDrawer *data);
void BeginFrame();
bool StartOffscreen();

View file

@ -0,0 +1,388 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2015 Christopher Bruns
// 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_stereo3d.cpp
** Stereoscopic 3D API
**
*/
#include "gl_system.h"
#include "gl/renderer/gl_renderer.h"
#include "gl_renderbuffers.h"
#include "hw_vrmodes.h"
#include "gl/system/gl_framebuffer.h"
#include "gl_postprocessstate.h"
#include "gl/system/gl_framebuffer.h"
#include "gl_shaderprogram.h"
#include "gl_buffers.h"
#include "templates.h"
EXTERN_CVAR(Int, vr_mode)
EXTERN_CVAR(Float, vid_saturation)
EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Int, gl_satformula)
EXTERN_CVAR(Int, gl_dither_bpc)
void UpdateVRModes(bool considerQuadBuffered = true);
namespace OpenGLRenderer
{
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::PresentAnaglyph(bool r, bool g, bool b)
{
mBuffers->BindOutputFB();
ClearBorders();
glColorMask(r, g, b, 1);
mBuffers->BindEyeTexture(0, 0);
DrawPresentTexture(screen->mOutputLetterbox, true);
glColorMask(!r, !g, !b, 1);
mBuffers->BindEyeTexture(1, 0);
DrawPresentTexture(screen->mOutputLetterbox, true);
glColorMask(1, 1, 1, 1);
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::PresentSideBySide()
{
mBuffers->BindOutputFB();
ClearBorders();
// Compute screen regions to use for left and right eye views
int leftWidth = screen->mOutputLetterbox.width / 2;
int rightWidth = screen->mOutputLetterbox.width - leftWidth;
IntRect leftHalfScreen = screen->mOutputLetterbox;
leftHalfScreen.width = leftWidth;
IntRect rightHalfScreen = screen->mOutputLetterbox;
rightHalfScreen.width = rightWidth;
rightHalfScreen.left += leftWidth;
mBuffers->BindEyeTexture(0, 0);
DrawPresentTexture(leftHalfScreen, true);
mBuffers->BindEyeTexture(1, 0);
DrawPresentTexture(rightHalfScreen, true);
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::PresentTopBottom()
{
mBuffers->BindOutputFB();
ClearBorders();
// Compute screen regions to use for left and right eye views
int topHeight = screen->mOutputLetterbox.height / 2;
int bottomHeight = screen->mOutputLetterbox.height - topHeight;
IntRect topHalfScreen = screen->mOutputLetterbox;
topHalfScreen.height = topHeight;
topHalfScreen.top = topHeight;
IntRect bottomHalfScreen = screen->mOutputLetterbox;
bottomHalfScreen.height = bottomHeight;
bottomHalfScreen.top = 0;
mBuffers->BindEyeTexture(0, 0);
DrawPresentTexture(topHalfScreen, true);
mBuffers->BindEyeTexture(1, 0);
DrawPresentTexture(bottomHalfScreen, true);
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::prepareInterleavedPresent(FPresentShaderBase& shader)
{
mBuffers->BindOutputFB();
ClearBorders();
// Bind each eye texture, for composition in the shader
mBuffers->BindEyeTexture(0, 0);
mBuffers->BindEyeTexture(1, 1);
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glActiveTexture(GL_TEXTURE1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
const IntRect& box = screen->mOutputLetterbox;
glViewport(box.left, box.top, box.width, box.height);
shader.Bind();
if (framebuffer->IsHWGammaActive())
{
shader.Uniforms->InvGamma = 1.0f;
shader.Uniforms->Contrast = 1.0f;
shader.Uniforms->Brightness = 0.0f;
shader.Uniforms->Saturation = 1.0f;
}
else
{
shader.Uniforms->InvGamma = 1.0f / clamp<float>(vid_gamma, 0.1f, 4.f);
shader.Uniforms->Contrast = clamp<float>(vid_contrast, 0.1f, 3.f);
shader.Uniforms->Brightness = clamp<float>(vid_brightness, -0.8f, 0.8f);
shader.Uniforms->Saturation = clamp<float>(vid_saturation, -15.0f, 15.0f);
shader.Uniforms->GrayFormula = static_cast<int>(gl_satformula);
}
shader.Uniforms->HdrMode = 0;
shader.Uniforms->ColorScale = (gl_dither_bpc == -1) ? 255.0f : (float)((1 << gl_dither_bpc) - 1);
shader.Uniforms->Scale = {
screen->mScreenViewport.width / (float)mBuffers->GetWidth(),
screen->mScreenViewport.height / (float)mBuffers->GetHeight()
};
shader.Uniforms->Offset = { 0.0f, 0.0f };
shader.Uniforms.SetData();
static_cast<GLDataBuffer*>(shader.Uniforms.GetBuffer())->BindBase();
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::PresentColumnInterleaved()
{
FGLPostProcessState savedState;
savedState.SaveTextureBindings(2);
prepareInterleavedPresent(*mPresent3dColumnShader);
// Compute absolute offset from top of screen to top of current display window
// because we need screen-relative, not window-relative, scan line parity
// Todo:
//auto clientoffset = screen->GetClientOffset();
//auto windowHOffset = clientoffset.X % 2;
int windowHOffset = 0;
mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
mPresent3dColumnShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dColumnShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::PresentRowInterleaved()
{
FGLPostProcessState savedState;
savedState.SaveTextureBindings(2);
prepareInterleavedPresent(*mPresent3dRowShader);
// Todo:
//auto clientoffset = screen->GetClientOffset();
//auto windowVOffset = clientoffset.Y % 2;
int windowVOffset = 0;
mPresent3dRowShader->Uniforms->WindowPositionParity =
(windowVOffset
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2;
mPresent3dRowShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dRowShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::PresentCheckerInterleaved()
{
FGLPostProcessState savedState;
savedState.SaveTextureBindings(2);
prepareInterleavedPresent(*mPresent3dCheckerShader);
// Compute absolute offset from top of screen to top of current display window
// because we need screen-relative, not window-relative, scan line parity
//auto clientoffset = screen->GetClientOffset();
//auto windowHOffset = clientoffset.X % 2;
//auto windowVOffset = clientoffset.Y % 2;
int windowHOffset = 0;
int windowVOffset = 0;
mPresent3dCheckerShader->Uniforms->WindowPositionParity =
(windowVOffset
+ windowHOffset
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
) % 2; // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
mPresent3dCheckerShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(mPresent3dCheckerShader->Uniforms.GetBuffer())->BindBase();
RenderScreenQuad();
}
//==========================================================================
//
// Sometimes the stereo render context is not ready immediately at start up
//
//==========================================================================
bool FGLRenderer::QuadStereoCheckInitialRenderContextState()
{
// Keep trying until we see at least one good OpenGL context to render to
bool bQuadStereoSupported = false;
bool bDecentContextWasFound = false;
int contextCheckCount = 0;
if ((!bDecentContextWasFound) && (contextCheckCount < 200))
{
contextCheckCount += 1;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // This question is about the main screen display context
GLboolean supportsStereo, supportsBuffered;
glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered);
if (supportsBuffered) // Finally, a useful OpenGL context
{
// This block will be executed exactly ONCE during a game run
bDecentContextWasFound = true; // now we can stop checking every frame...
// Now check whether this context supports hardware stereo
glGetBooleanv(GL_STEREO, &supportsStereo);
bQuadStereoSupported = supportsStereo && supportsBuffered;
if (! bQuadStereoSupported)
UpdateVRModes(false);
}
}
return bQuadStereoSupported;
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::PresentQuadStereo()
{
if (QuadStereoCheckInitialRenderContextState())
{
mBuffers->BindOutputFB();
glDrawBuffer(GL_BACK_LEFT);
ClearBorders();
mBuffers->BindEyeTexture(0, 0);
DrawPresentTexture(screen->mOutputLetterbox, true);
glDrawBuffer(GL_BACK_RIGHT);
ClearBorders();
mBuffers->BindEyeTexture(1, 0);
DrawPresentTexture(screen->mOutputLetterbox, true);
glDrawBuffer(GL_BACK);
}
else
{
mBuffers->BindOutputFB();
ClearBorders();
mBuffers->BindEyeTexture(0, 0);
DrawPresentTexture(screen->mOutputLetterbox, true);
}
}
void FGLRenderer::PresentStereo()
{
auto vrmode = VRMode::GetVRMode(true);
const int eyeCount = vrmode->mEyeCount;
// Don't invalidate the bound framebuffer (..., false)
if (eyeCount > 1)
mBuffers->BlitToEyeTexture(mBuffers->CurrentEye(), false);
switch (vr_mode)
{
default:
return;
case VR_GREENMAGENTA:
PresentAnaglyph(false, true, false);
break;
case VR_REDCYAN:
PresentAnaglyph(true, false, false);
break;
case VR_AMBERBLUE:
PresentAnaglyph(true, true, false);
break;
case VR_SIDEBYSIDEFULL:
case VR_SIDEBYSIDESQUISHED:
PresentSideBySide();
break;
case VR_TOPBOTTOM:
PresentTopBottom();
break;
case VR_ROWINTERLEAVED:
PresentRowInterleaved();
break;
case VR_COLUMNINTERLEAVED:
PresentColumnInterleaved();
break;
case VR_CHECKERINTERLEAVED:
PresentCheckerInterleaved();
break;
case VR_QUADSTEREO:
PresentQuadStereo();
break;
}
}
}

View file

@ -41,28 +41,24 @@
#include "templates.h"
#include "palette.h"
#include "build.h"
#include "hw_viewpointbuffer.h"
#include "glbackend/glbackend.h"
#include "gl_load/gl_interface.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/renderer/gl_renderer.h"
#include "gl_renderstate.h"
#include "gl_renderbuffers.h"
#include "flatvertices.h"
#include "hw_lightbuffer.h"
/*
#include "gl/textures/gl_samplers.h"
#include "hwrenderer/utility/hw_clock.h"
#include "hwrenderer/utility/hw_vrmodes.h"
#include "hwrenderer/models/hw_models.h"
#include "hwrenderer/scene/hw_skydome.h"
#include "hwrenderer/data/hw_viewpointbuffer.h"
#include "gl/shaders/gl_shaderprogram.h"
*/
#include "hw_vrmodes.h"
#include "hwrenderer/postprocessing/hw_postprocess.h"
#include "gl_postprocessstate.h"
#include "hw_skydome.h"
#include "gl_shaderprogram.h"
#include "hw_cvars.h"
#include "gl_debug.h"
#include "r_videoscale.h"
//#include "gl_buffers.h"
//#include "hwrenderer/data/flatvertices.h"
EXTERN_CVAR (Bool, vid_vsync)
EXTERN_CVAR(Bool, r_drawvoxels)
@ -97,11 +93,9 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, bool fullscreen) :
Super::SetVSync(vid_vsync);
FHardwareTexture::InitGlobalState();
#ifdef IMPLEMENT_IT
// Make sure all global variables tracking OpenGL context state are reset..
gl_RenderState.Reset();
#endif
GLRenderer = nullptr;
}
@ -111,10 +105,8 @@ OpenGLFrameBuffer::~OpenGLFrameBuffer()
PPResource::ResetAll();
if (mVertexData != nullptr) delete mVertexData;
#ifdef IMPLEMENT_IT
if (mSkyData != nullptr) delete mSkyData;
if (mViewpoints != nullptr) delete mViewpoints;
#endif
if (mLights != nullptr) delete mLights;
mShadowMap.Reset();
@ -177,10 +169,8 @@ void OpenGLFrameBuffer::InitializeState()
SetViewportRects(nullptr);
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
#ifdef IMPLEMENT_IT
mSkyData = new FSkyVertexBuffer;
mViewpoints = new HWViewpointBuffer;
#endif
mLights = new FLightBuffer();
GLRenderer = new FGLRenderer(this);
GLRenderer->Initialize(GetWidth(), GetHeight());
@ -212,12 +202,50 @@ void OpenGLFrameBuffer::Update()
screen->mVertexData->Reset();
}
void OpenGLFrameBuffer::CopyScreenToBuffer(int width, int height, uint8_t* scr)
{
IntRect bounds;
bounds.left = 0;
bounds.top = 0;
bounds.width = width;
bounds.height = height;
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();
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, scr);
}
//===========================================================================
//
//
// Camera texture rendering
//
//===========================================================================
void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function<void(IntRect &)> renderFunc)
{
#if 0
GLRenderer->StartOffscreen();
GLRenderer->BindToFrameBuffer(tex);
IntRect bounds;
bounds.left = bounds.top = 0;
bounds.width = FHardwareTexture::GetTexDimension(tex->GetWidth());
bounds.height = FHardwareTexture::GetTexDimension(tex->GetHeight());
renderFunc(bounds);
GLRenderer->EndOffscreen();
tex->SetUpdated(true);
static_cast<OpenGLFrameBuffer*>(screen)->camtexcount++;
#endif
}
//===========================================================================
//
//
//
//===========================================================================
const char* OpenGLFrameBuffer::DeviceName() const
{
@ -283,38 +311,28 @@ void OpenGLFrameBuffer::SetTextureFilterMode()
if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode();
}
#ifdef IMPLEMENT_IT
void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
{
auto tex = mat->tex;
if (tex->isSWCanvas()) return;
if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return;
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
int flags = mat->isExpanded() ? CTF_Expand : (!tex->isScaled()) ? CTF_CheckHires : 0;
int numLayers = mat->GetLayers();
auto base = static_cast<FHardwareTexture*>(mat->GetLayer(0, translation));
int flags = mat->GetScaleFlags();
int numLayers = mat->NumLayers();
MaterialLayerInfo* layer;
auto base = static_cast<FHardwareTexture*>(mat->GetLayer(0, translation, &layer));
if (base->BindOrCreate(tex, 0, CLAMP_NONE, translation, flags))
if (base->BindOrCreate(layer->layerTexture, 0, CLAMP_NONE, translation, layer->scaleFlags))
{
for (int i = 1; i < numLayers; i++)
{
FTexture *layer;
auto systex = static_cast<FHardwareTexture*>(mat->GetLayer(i, 0, &layer));
systex->BindOrCreate(layer, i, CLAMP_NONE, 0, mat->isExpanded() ? CTF_Expand : 0);
systex->BindOrCreate(layer->layerTexture, i, CLAMP_NONE, 0, layer->scaleFlags);
}
}
// unbind everything.
FHardwareTexture::UnbindAll();
}
FModelRenderer *OpenGLFrameBuffer::CreateModelRenderer(int mli)
{
return new FHWModelRenderer(nullptr, gl_RenderState, mli);
}
#endif
IVertexBuffer *OpenGLFrameBuffer::CreateVertexBuffer()
{
return new GLVertexBuffer;
@ -335,13 +353,95 @@ void OpenGLFrameBuffer::BlurScene(float amount)
GLRenderer->BlurScene(amount);
}
#if 0
void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds)
{
Super::SetViewportRects(bounds);
if (!bounds)
{
auto vrmode = VRMode::GetVRMode(true);
vrmode->AdjustViewport(this);
}
}
void OpenGLFrameBuffer::UpdatePalette()
{
if (GLRenderer)
GLRenderer->ClearTonemapPalette();
}
#endif
FRenderState* OpenGLFrameBuffer::RenderState()
{
return &gl_RenderState;
}
void OpenGLFrameBuffer::AmbientOccludeScene(float m5)
{
gl_RenderState.EnableDrawBuffers(1);
GLRenderer->AmbientOccludeScene(m5);
glViewport(screen->mSceneViewport.left, mSceneViewport.top, mSceneViewport.width, mSceneViewport.height);
GLRenderer->mBuffers->BindSceneFB(true);
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
gl_RenderState.Apply();
}
void OpenGLFrameBuffer::FirstEye()
{
GLRenderer->mBuffers->CurrentEye() = 0; // always begin at zero, in case eye count changed
}
void OpenGLFrameBuffer::NextEye(int eyecount)
{
GLRenderer->mBuffers->NextEye(eyecount);
}
void OpenGLFrameBuffer::SetSceneRenderTarget(bool useSSAO)
{
GLRenderer->mBuffers->BindSceneFB(useSSAO);
}
void OpenGLFrameBuffer::UpdateShadowMap()
{
if (mShadowMap.PerformUpdate())
{
FGLDebug::PushGroup("ShadowMap");
FGLPostProcessState savedState;
static_cast<GLDataBuffer*>(screen->mShadowMap.mLightList)->BindBase();
static_cast<GLDataBuffer*>(screen->mShadowMap.mNodesBuffer)->BindBase();
static_cast<GLDataBuffer*>(screen->mShadowMap.mLinesBuffer)->BindBase();
GLRenderer->mBuffers->BindShadowMapFB();
GLRenderer->mShadowMapShader->Bind();
GLRenderer->mShadowMapShader->Uniforms->ShadowmapQuality = gl_shadowmap_quality;
GLRenderer->mShadowMapShader->Uniforms->NodesCount = screen->mShadowMap.NodesCount();
GLRenderer->mShadowMapShader->Uniforms.SetData();
static_cast<GLDataBuffer*>(GLRenderer->mShadowMapShader->Uniforms.GetBuffer())->BindBase();
glViewport(0, 0, gl_shadowmap_quality, 1024);
GLRenderer->RenderScreenQuad();
const auto& viewport = screen->mScreenViewport;
glViewport(viewport.left, viewport.top, viewport.width, viewport.height);
GLRenderer->mBuffers->BindShadowMapTexture(16);
FGLDebug::PopGroup();
screen->mShadowMap.FinishUpdate();
}
}
void OpenGLFrameBuffer::WaitForCommands(bool finish)
{
glFinish();
}
void OpenGLFrameBuffer::SetSaveBuffers(bool yes)
{
if (!GLRenderer) return;
if (yes) GLRenderer->mBuffers = GLRenderer->mSaveBuffers;
else GLRenderer->mBuffers = GLRenderer->mScreenBuffers;
}
//===========================================================================
//
@ -403,6 +503,8 @@ TArray<uint8_t> OpenGLFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &colo
// Screenshot should not use gamma correction if it was already applied to rendered image
gamma = 1;
if (vid_hdr_active && vid_fullscreen)
gamma *= 2.2f;
return ScreenshotBuffer;
}
@ -428,6 +530,49 @@ void OpenGLFrameBuffer::PostProcessScene(bool swscene, int fixedcm, const std::f
GLRenderer->PostProcessScene(fixedcm, afterBloomDrawEndScene2D);
}
//==========================================================================
//
// OpenGLFrameBuffer :: WipeStartScreen
//
// Called before the current screen has started rendering. This needs to
// save what was drawn the previous frame so that it can be animated into
// what gets drawn this frame.
//
//==========================================================================
FTexture *OpenGLFrameBuffer::WipeStartScreen()
{
const auto &viewport = screen->mScreenViewport;
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
tex->GetSystemTexture()->CreateTexture(nullptr, viewport.width, viewport.height, 0, false, "WipeStartScreen");
glFinish();
static_cast<FHardwareTexture*>(tex->GetSystemTexture())->Bind(0, false);
GLRenderer->mBuffers->BindCurrentFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
return tex;
}
//==========================================================================
//
// OpenGLFrameBuffer :: WipeEndScreen
//
// The screen we want to animate to has just been drawn.
//
//==========================================================================
FTexture *OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->Flush();
const auto &viewport = screen->mScreenViewport;
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
tex->GetSystemTexture()->CreateTexture(NULL, viewport.width, viewport.height, 0, false, "WipeEndScreen");
glFinish();
static_cast<FHardwareTexture*>(tex->GetSystemTexture())->Bind(0, false);
GLRenderer->mBuffers->BindCurrentFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
return tex;
}
}

View file

@ -28,10 +28,6 @@ public:
IHardwareTexture *CreateHardwareTexture(int numchannels) override;
void SetTextureFilterMode() override;
#ifdef IMPLEMENT_IT
void PrecacheMaterial(FMaterial *mat, int translation) override;
FModelRenderer *CreateModelRenderer(int mli) override;
#endif
void BeginFrame() override;
//void SetViewportRects(IntRect *bounds) override;
void BlurScene(float amount) override;
@ -49,6 +45,24 @@ public:
void SetVSync(bool vsync) override;
void SetViewportRects(IntRect* bounds) override;
void UpdatePalette() override;
void AmbientOccludeScene(float m5) override;
void FirstEye() override;
void NextEye(int eyecount) override;
void SetSceneRenderTarget(bool useSSAO) override;
void UpdateShadowMap() override;
void WaitForCommands(bool finish) override;
void SetSaveBuffers(bool yes) override;
void CopyScreenToBuffer(int width, int height, uint8_t* buffer) override;
bool FlipSavePic() const override { return true; }
void RenderTextureView(FCanvasTexture* tex, std::function<void(IntRect&)> renderFunc) override;
void PrecacheMaterial(FMaterial* mat, int translation) override;
FRenderState* RenderState() override;
FTexture* WipeStartScreen() override;
FTexture* WipeEndScreen() override;
//void Draw2D() override;
void PostProcessScene(bool swscene, int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D) override;