diff --git a/src/gl/renderer/gl_2ddrawer.cpp b/src/gl/renderer/gl_2ddrawer.cpp index ac7d35397..e0f67c713 100644 --- a/src/gl/renderer/gl_2ddrawer.cpp +++ b/src/gl/renderer/gl_2ddrawer.cpp @@ -378,7 +378,7 @@ void F2DDrawer::AddPixel(int x1, int y1, int palcolor, uint32 color) // //========================================================================== -void F2DDrawer::Flush() +void F2DDrawer::Draw() { F2DDrawer::EDrawType lasttype = DrawTypeTexture; @@ -490,10 +490,12 @@ void F2DDrawer::Flush() } i += dg->mLen; } - mVertices.Clear(); - mData.Clear(); gl_RenderState.SetVertexBuffer(GLRenderer->mVBO); glset.lightmode = savedlightmode; } - +void F2DDrawer::Clear() +{ + mVertices.Clear(); + mData.Clear(); +} diff --git a/src/gl/renderer/gl_2ddrawer.h b/src/gl/renderer/gl_2ddrawer.h index 32d2ad1f5..8c27f13d8 100644 --- a/src/gl/renderer/gl_2ddrawer.h +++ b/src/gl/renderer/gl_2ddrawer.h @@ -66,7 +66,8 @@ public: void AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color); void AddPixel(int x1, int y1, int palcolor, uint32 color); - void Flush(); + void Draw(); + void Clear(); }; diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index d7eac8007..00083480c 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -75,6 +75,7 @@ #include "gl/shaders/gl_lensshader.h" #include "gl/shaders/gl_presentshader.h" #include "gl/renderer/gl_2ddrawer.h" +#include "gl/stereo3d/gl_stereo3d.h" //========================================================================== // @@ -375,6 +376,41 @@ void FGLRenderer::LensDistortScene() FGLDebug::PopGroup(); } +//----------------------------------------------------------------------------- +// +// Copies the rendered screen to its final destination +// +//----------------------------------------------------------------------------- + +void FGLRenderer::Flush() +{ + const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode(); + + if (stereo3dMode.IsMono() || !FGLRenderBuffers::IsEnabled()) + { + CopyToBackbuffer(nullptr, true); + } + else + { + // Render 2D to eye textures + for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix) + { + FGLDebug::PushGroup("Eye2D"); + mBuffers->BindEyeFB(eye_ix); + glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); + glScissor(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); + m2DDrawer->Draw(); + FGLDebug::PopGroup(); + } + m2DDrawer->Clear(); + + FGLPostProcessState savedState; + FGLDebug::PushGroup("PresentEyes"); + stereo3dMode.Present(); + FGLDebug::PopGroup(); + } +} + //----------------------------------------------------------------------------- // // Gamma correct while copying to frame buffer @@ -383,7 +419,9 @@ void FGLRenderer::LensDistortScene() void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) { - m2DDrawer->Flush(); // draw all pending 2D stuff before copying the buffer + m2DDrawer->Draw(); // draw all pending 2D stuff before copying the buffer + m2DDrawer->Clear(); + FGLDebug::PushGroup("CopyToBackbuffer"); if (FGLRenderBuffers::IsEnabled()) { @@ -401,28 +439,8 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) box = mOutputLetterbox; } - // Present what was rendered: - glViewport(box.left, box.top, box.width, box.height); - - mPresentShader->Bind(); - mPresentShader->InputTexture.Set(0); - if (!applyGamma || framebuffer->IsHWGammaActive()) - { - mPresentShader->InvGamma.Set(1.0f); - mPresentShader->Contrast.Set(1.0f); - mPresentShader->Brightness.Set(0.0f); - } - else - { - mPresentShader->InvGamma.Set(1.0f / clamp(Gamma, 0.1f, 4.f)); - mPresentShader->Contrast.Set(clamp(vid_contrast, 0.1f, 3.f)); - mPresentShader->Brightness.Set(clamp(vid_brightness, -0.8f, 0.8f)); - } - mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight()); mBuffers->BindCurrentTexture(0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - RenderScreenQuad(); + DrawPresentTexture(box, applyGamma); } else if (!bounds) { @@ -432,6 +450,32 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) FGLDebug::PopGroup(); } +void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma) +{ + glViewport(box.left, box.top, box.width, box.height); + + glActiveTexture(GL_TEXTURE0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + mPresentShader->Bind(); + mPresentShader->InputTexture.Set(0); + if (!applyGamma || framebuffer->IsHWGammaActive()) + { + mPresentShader->InvGamma.Set(1.0f); + mPresentShader->Contrast.Set(1.0f); + mPresentShader->Brightness.Set(0.0f); + } + else + { + mPresentShader->InvGamma.Set(1.0f / clamp(Gamma, 0.1f, 4.f)); + mPresentShader->Contrast.Set(clamp(vid_contrast, 0.1f, 3.f)); + mPresentShader->Brightness.Set(clamp(vid_brightness, -0.8f, 0.8f)); + } + mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight()); + RenderScreenQuad(); +} + //----------------------------------------------------------------------------- // // Fills the black bars around the screen letterbox diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index f66ea1354..7ad299e2e 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -85,6 +85,7 @@ FGLRenderBuffers::~FGLRenderBuffers() { ClearScene(); ClearPipeline(); + ClearEyeBuffers(); ClearBloom(); } @@ -119,6 +120,18 @@ void FGLRenderBuffers::ClearBloom() } } +void FGLRenderBuffers::ClearEyeBuffers() +{ + for (auto handle : mEyeFBs) + DeleteFrameBuffer(handle); + + for (auto handle : mEyeTextures) + DeleteTexture(handle); + + mEyeTextures.Clear(); + mEyeFBs.Clear(); +} + void FGLRenderBuffers::DeleteTexture(GLuint &handle) { if (handle != 0) @@ -202,6 +215,7 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei { ClearScene(); ClearPipeline(); + ClearEyeBuffers(); ClearBloom(); mWidth = 0; mHeight = 0; @@ -239,6 +253,7 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples) void FGLRenderBuffers::CreatePipeline(int width, int height) { ClearPipeline(); + ClearEyeBuffers(); for (int i = 0; i < NumPipelineTextures; i++) { @@ -279,6 +294,35 @@ void FGLRenderBuffers::CreateBloom(int width, int height) } } +//========================================================================== +// +// Creates eye buffers if needed +// +//========================================================================== + +void FGLRenderBuffers::CreateEyeBuffers(int eye) +{ + if (mEyeFBs.Size() > eye) + return; + + GLint activeTex, textureBinding, frameBufferBinding; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex); + glActiveTexture(GL_TEXTURE0); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding); + + while (mEyeFBs.Size() <= eye) + { + GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight); + mEyeTextures.Push(texture); + mEyeFBs.Push(CreateFrameBuffer("EyeFB", texture)); + } + + glBindTexture(GL_TEXTURE_2D, textureBinding); + glActiveTexture(activeTex); + glBindFramebuffer(GL_FRAMEBUFFER, frameBufferBinding); +} + //========================================================================== // // Creates a 2D texture defaulting to linear filtering and clamp to edge @@ -471,6 +515,43 @@ void FGLRenderBuffers::BlitSceneToTexture() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } +//========================================================================== +// +// Eye textures and their frame buffers +// +//========================================================================== + +void FGLRenderBuffers::BlitToEyeTexture(int eye) +{ + CreateEyeBuffers(eye); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, mPipelineFB[mCurrentPipelineTexture]); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mEyeFBs[eye]); + glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + if ((gl.flags & RFL_INVALIDATE_BUFFER) != 0) + { + GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_STENCIL_ATTACHMENT }; + glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, attachments); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + +void FGLRenderBuffers::BindEyeTexture(int eye, int texunit) +{ + CreateEyeBuffers(eye); + glActiveTexture(GL_TEXTURE0 + texunit); + glBindTexture(GL_TEXTURE_2D, mEyeTextures[eye]); +} + +void FGLRenderBuffers::BindEyeFB(int eye, bool readBuffer) +{ + CreateEyeBuffers(eye); + glBindFramebuffer(readBuffer ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER, mEyeFBs[eye]); +} + //========================================================================== // // Makes the scene frame buffer active (multisample, depth, stecil, etc.) diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index 08303a912..08731e39f 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -32,6 +32,10 @@ public: void BindOutputFB(); + void BlitToEyeTexture(int eye); + void BindEyeTexture(int eye, int texunit); + void BindEyeFB(int eye, bool readBuffer = false); + enum { NumBloomLevels = 4 }; FGLBloomTextureLevel BloomLevels[NumBloomLevels]; @@ -43,10 +47,12 @@ public: private: void ClearScene(); void ClearPipeline(); + void ClearEyeBuffers(); void ClearBloom(); void CreateScene(int width, int height, int samples); void CreatePipeline(int width, int height); void CreateBloom(int width, int height); + void CreateEyeBuffers(int eye); GLuint Create2DTexture(const FString &name, GLuint format, int width, int height); GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height); GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height); @@ -83,6 +89,10 @@ private: // Back buffer frame buffer GLuint mOutputFB = 0; + // Eye buffers + TArray mEyeTextures; + TArray mEyeFBs; + static bool FailedCreate; static bool BuffersActive; }; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index f652b4765..162fb6dcf 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -173,7 +173,8 @@ public: void ClearTonemapPalette(); void LensDistortScene(); void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma); - void Flush() { CopyToBackbuffer(nullptr, true); } + void DrawPresentTexture(const GL_IRECT &box, bool applyGamma); + void Flush(); void SetProjection(float fov, float ratio, float fovratio); void SetProjection(VSMatrix matrix); // raw matrix input from stereo 3d modes diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 9e9a73e5d..48ad30786 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -419,15 +419,17 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE); gl_SetColor(lightlevel, rel, Colormap, alpha); gl_SetFog(lightlevel, rel, &Colormap, false); - gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); if (!gltexture) { + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.EnableTexture(false); DrawSubsectors(pass, false, true); gl_RenderState.EnableTexture(true); } else { + if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); + else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_SetPlaneTextureRotation(&plane, gltexture); DrawSubsectors(pass, !gl.legacyMode, true); @@ -477,6 +479,21 @@ inline void GLFlat::PutFlat(bool fog) // translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list. list = (renderflags&SSRF_RENDER3DPLANES) ? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER; } + else if (gltexture->GetTransparent()) + { + if (stack) + { + list = GLDL_TRANSLUCENTBORDER; + } + else if ((renderflags&SSRF_RENDER3DPLANES) && !plane.plane.isSlope()) + { + list = GLDL_TRANSLUCENT; + } + else + { + list = GLDL_PLAINFLATS; + } + } else { bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 48d4fb7ff..26e226554 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -863,6 +863,8 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo DrawBlend(lviewsector); } mDrawingScene2D = false; + if (!stereo3dMode.IsMono() && FGLRenderBuffers::IsEnabled()) + mBuffers->BlitToEyeTexture(eye_ix); eye->TearDown(); } stereo3dMode.TearDown(); diff --git a/src/gl/stereo3d/gl_anaglyph.cpp b/src/gl/stereo3d/gl_anaglyph.cpp index c84c35091..3c051d390 100644 --- a/src/gl/stereo3d/gl_anaglyph.cpp +++ b/src/gl/stereo3d/gl_anaglyph.cpp @@ -34,6 +34,8 @@ */ #include "gl_anaglyph.h" +#include "gl/renderer/gl_renderer.h" +#include "gl/renderer/gl_renderbuffers.h" namespace s3d { @@ -44,6 +46,25 @@ MaskAnaglyph::MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters) eye_ptrs.Push(&rightEye); } +void MaskAnaglyph::Present() const +{ + GLRenderer->mBuffers->BindOutputFB(); + GLRenderer->ClearBorders(); + + gl_RenderState.SetColorMask(leftEye.GetColorMask().r, leftEye.GetColorMask().g, leftEye.GetColorMask().b, true); + gl_RenderState.ApplyColorMask(); + GLRenderer->mBuffers->BindEyeTexture(0, 0); + GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + + gl_RenderState.SetColorMask(rightEye.GetColorMask().r, rightEye.GetColorMask().g, rightEye.GetColorMask().b, true); + gl_RenderState.ApplyColorMask(); + GLRenderer->mBuffers->BindEyeTexture(1, 0); + GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + + gl_RenderState.ResetColorMask(); + gl_RenderState.ApplyColorMask(); +} + /* static */ const GreenMagenta& GreenMagenta::getInstance(float ipd) diff --git a/src/gl/stereo3d/gl_anaglyph.h b/src/gl/stereo3d/gl_anaglyph.h index a82ce0f3b..e3383fe26 100644 --- a/src/gl/stereo3d/gl_anaglyph.h +++ b/src/gl/stereo3d/gl_anaglyph.h @@ -61,14 +61,8 @@ class AnaglyphLeftPose : public LeftEyePose { public: AnaglyphLeftPose(const ColorMask& colorMask, float ipd) : LeftEyePose(ipd), colorMask(colorMask) {} - virtual void SetUp() const { - gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true); - gl_RenderState.ApplyColorMask(); - } - virtual void TearDown() const { - gl_RenderState.ResetColorMask(); - gl_RenderState.ApplyColorMask(); - } + ColorMask GetColorMask() const { return colorMask; } + private: ColorMask colorMask; }; @@ -77,14 +71,8 @@ class AnaglyphRightPose : public RightEyePose { public: AnaglyphRightPose(const ColorMask& colorMask, float ipd) : RightEyePose(ipd), colorMask(colorMask) {} - virtual void SetUp() const { - gl_RenderState.SetColorMask(colorMask.r, colorMask.g, colorMask.b, true); - gl_RenderState.ApplyColorMask(); - } - virtual void TearDown() const { - gl_RenderState.ResetColorMask(); - gl_RenderState.ApplyColorMask(); - } + ColorMask GetColorMask() const { return colorMask; } + private: ColorMask colorMask; }; @@ -93,6 +81,7 @@ class MaskAnaglyph : public Stereo3DMode { public: MaskAnaglyph(const ColorMask& leftColorMask, double ipdMeters); + void Present() const override; private: AnaglyphLeftPose leftEye; AnaglyphRightPose rightEye; diff --git a/src/gl/stereo3d/gl_quadstereo.cpp b/src/gl/stereo3d/gl_quadstereo.cpp index 63bbbedc1..cd689d3b5 100644 --- a/src/gl/stereo3d/gl_quadstereo.cpp +++ b/src/gl/stereo3d/gl_quadstereo.cpp @@ -34,6 +34,8 @@ */ #include "gl_quadstereo.h" +#include "gl/renderer/gl_renderer.h" +#include "gl/renderer/gl_renderbuffers.h" namespace s3d { @@ -46,7 +48,7 @@ QuadStereo::QuadStereo(double ipdMeters) GLboolean supportsStereo, supportsBuffered; glGetBooleanv(GL_STEREO, &supportsStereo); glGetBooleanv(GL_DOUBLEBUFFER, &supportsBuffered); - bool bQuadStereoSupported = supportsStereo && supportsBuffered; + bQuadStereoSupported = supportsStereo && supportsBuffered; leftEye.bQuadStereoSupported = bQuadStereoSupported; rightEye.bQuadStereoSupported = bQuadStereoSupported; @@ -57,6 +59,33 @@ QuadStereo::QuadStereo(double ipdMeters) } } +void QuadStereo::Present() const +{ + if (bQuadStereoSupported) + { + GLRenderer->mBuffers->BindOutputFB(); + + glDrawBuffer(GL_BACK_LEFT); + GLRenderer->ClearBorders(); + GLRenderer->mBuffers->BindEyeTexture(0, 0); + GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + + glDrawBuffer(GL_BACK_RIGHT); + GLRenderer->ClearBorders(); + GLRenderer->mBuffers->BindEyeTexture(1, 0); + GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + + glDrawBuffer(GL_BACK); + } + else + { + GLRenderer->mBuffers->BindOutputFB(); + GLRenderer->ClearBorders(); + GLRenderer->mBuffers->BindEyeTexture(1, 0); + GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + } +} + /* static */ const QuadStereo& QuadStereo::getInstance(float ipd) { diff --git a/src/gl/stereo3d/gl_quadstereo.h b/src/gl/stereo3d/gl_quadstereo.h index f27fb78f8..d9aa4f435 100644 --- a/src/gl/stereo3d/gl_quadstereo.h +++ b/src/gl/stereo3d/gl_quadstereo.h @@ -47,14 +47,6 @@ class QuadStereoLeftPose : public LeftEyePose { public: QuadStereoLeftPose(float ipd) : LeftEyePose(ipd), bQuadStereoSupported(false) {} - virtual void SetUp() const { - if (bQuadStereoSupported) - glDrawBuffer(GL_BACK_LEFT); - } - virtual void TearDown() const { - if (bQuadStereoSupported) - glDrawBuffer(GL_BACK); - } bool bQuadStereoSupported; }; @@ -62,14 +54,6 @@ class QuadStereoRightPose : public RightEyePose { public: QuadStereoRightPose(float ipd) : RightEyePose(ipd), bQuadStereoSupported(false){} - virtual void SetUp() const { - if (bQuadStereoSupported) - glDrawBuffer(GL_BACK_RIGHT); - } - virtual void TearDown() const { - if (bQuadStereoSupported) - glDrawBuffer(GL_BACK); - } bool bQuadStereoSupported; }; @@ -84,10 +68,12 @@ class QuadStereo : public Stereo3DMode { public: QuadStereo(double ipdMeters); + void Present() const override; static const QuadStereo& getInstance(float ipd); private: QuadStereoLeftPose leftEye; QuadStereoRightPose rightEye; + bool bQuadStereoSupported; }; diff --git a/src/gl/stereo3d/gl_stereo3d.h b/src/gl/stereo3d/gl_stereo3d.h index c56cc078f..2cb9417d2 100644 --- a/src/gl/stereo3d/gl_stereo3d.h +++ b/src/gl/stereo3d/gl_stereo3d.h @@ -85,6 +85,9 @@ public: virtual void SetUp() const {}; virtual void TearDown() const {}; + virtual bool IsMono() const { return false; } + virtual void Present() const = 0; + protected: TArray eye_ptrs; @@ -102,6 +105,9 @@ class MonoView : public Stereo3DMode public: static const MonoView& getInstance(); + bool IsMono() const override { return true; } + void Present() const override { } + protected: MonoView() { eye_ptrs.Push(¢ralEye); } EyePose centralEye; diff --git a/src/gl/stereo3d/gl_stereo_leftright.cpp b/src/gl/stereo3d/gl_stereo_leftright.cpp index 354185792..8605c9b53 100644 --- a/src/gl/stereo3d/gl_stereo_leftright.cpp +++ b/src/gl/stereo3d/gl_stereo_leftright.cpp @@ -37,7 +37,10 @@ #include "vectors.h" // RAD2DEG #include "doomtype.h" // M_PI #include "gl/system/gl_cvars.h" +#include "gl/system/gl_system.h" +#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderer.h" +#include "gl/renderer/gl_renderbuffers.h" #include EXTERN_CVAR(Float, vr_screendist) @@ -89,6 +92,13 @@ const LeftEyeView& LeftEyeView::getInstance(float ipd) return instance; } +void LeftEyeView::Present() const +{ + GLRenderer->mBuffers->BindOutputFB(); + GLRenderer->ClearBorders(); + GLRenderer->mBuffers->BindEyeTexture(0, 0); + GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); +} /* static */ const RightEyeView& RightEyeView::getInstance(float ipd) @@ -98,5 +108,13 @@ const RightEyeView& RightEyeView::getInstance(float ipd) return instance; } +void RightEyeView::Present() const +{ + GLRenderer->mBuffers->BindOutputFB(); + GLRenderer->ClearBorders(); + GLRenderer->mBuffers->BindEyeTexture(0, 0); + GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); +} + } /* namespace s3d */ diff --git a/src/gl/stereo3d/gl_stereo_leftright.h b/src/gl/stereo3d/gl_stereo_leftright.h index de13a32cb..250846651 100644 --- a/src/gl/stereo3d/gl_stereo_leftright.h +++ b/src/gl/stereo3d/gl_stereo_leftright.h @@ -83,6 +83,7 @@ public: LeftEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); } float getIpd() const { return eye.getIpd(); } void setIpd(float ipd) { eye.setIpd(ipd); } + void Present() const override; protected: LeftEyePose eye; }; @@ -96,6 +97,7 @@ public: RightEyeView(float ipd) : eye(ipd) { eye_ptrs.Push(&eye); } float getIpd() const { return eye.getIpd(); } void setIpd(float ipd) { eye.setIpd(ipd); } + void Present() const override; protected: RightEyePose eye; }; diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp index 05d63f65d..577bc12db 100644 --- a/src/gl/system/gl_wipe.cpp +++ b/src/gl/system/gl_wipe.cpp @@ -189,7 +189,8 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type) void OpenGLFrameBuffer::WipeEndScreen() { - GLRenderer->m2DDrawer->Flush(); + GLRenderer->m2DDrawer->Draw(); + GLRenderer->m2DDrawer->Clear(); const auto &viewport = GLRenderer->mScreenViewport; wipeendscreen = new FHardwareTexture(viewport.width, viewport.height, true); diff --git a/src/textures/bitmap.h b/src/textures/bitmap.h index 27d3c0b4b..a27d1ff98 100644 --- a/src/textures/bitmap.h +++ b/src/textures/bitmap.h @@ -380,7 +380,7 @@ struct bCopyAlpha }; struct bOverlay -{ +{ static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = (s*a + d*(255-a))/255; } static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = MAX(s,d); } static __forceinline bool ProcessAlpha0() { return false; } diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 6ae45c785..5d9aeb433 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -629,8 +629,9 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota { ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info); } - - if (ret > retv) retv = ret; + // treat -1 (i.e. unknown) as absolute. We have no idea if this may have overwritten previous info so a real check needs to be done. + if (ret == -1) retv = ret; + else if (retv != -1 && ret > retv) retv = ret; } // Restore previous clipping rectangle. bmp->SetClipRect(saved_cr);