From aaa3581ee698c6d6859cff551327f099e471c817 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 7 Sep 2016 21:52:43 +0200 Subject: [PATCH] Hook up eye textures in renderer --- src/gl/renderer/gl_postprocess.cpp | 33 ++++++++++++++++++++++++++++ src/gl/renderer/gl_renderbuffers.cpp | 12 +++++----- src/gl/renderer/gl_renderbuffers.h | 2 +- src/gl/renderer/gl_renderer.h | 2 +- src/gl/scene/gl_scene.cpp | 2 ++ src/gl/stereo3d/gl_stereo3d.cpp | 23 +++++++++++++++++++ src/gl/stereo3d/gl_stereo3d.h | 5 +++++ 7 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index d7eac80071..243a73a38d 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,38 @@ 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); + m2DDrawer->Flush(); // Draw the 2D + FGLDebug::PopGroup(); + } + + FGLPostProcessState savedState; + FGLDebug::PushGroup("PresentEyes"); + stereo3dMode.Present(); + FGLDebug::PopGroup(); + } +} + //----------------------------------------------------------------------------- // // Gamma correct while copying to frame buffer diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index a7a07a43c1..7ad299e2e8 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -122,12 +122,12 @@ void FGLRenderBuffers::ClearBloom() void FGLRenderBuffers::ClearEyeBuffers() { - for (auto handle : mEyeTextures) - DeleteTexture(handle); - for (auto handle : mEyeFBs) DeleteFrameBuffer(handle); + for (auto handle : mEyeTextures) + DeleteTexture(handle); + mEyeTextures.Clear(); mEyeFBs.Clear(); } @@ -311,7 +311,7 @@ void FGLRenderBuffers::CreateEyeBuffers(int eye) glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding); - while (mEyeFBs.Size() < eye) + while (mEyeFBs.Size() <= eye) { GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight); mEyeTextures.Push(texture); @@ -546,10 +546,10 @@ void FGLRenderBuffers::BindEyeTexture(int eye, int texunit) glBindTexture(GL_TEXTURE_2D, mEyeTextures[eye]); } -void FGLRenderBuffers::BindEyeFB(int eye) +void FGLRenderBuffers::BindEyeFB(int eye, bool readBuffer) { CreateEyeBuffers(eye); - glBindFramebuffer(GL_FRAMEBUFFER, mEyeFBs[eye]); + glBindFramebuffer(readBuffer ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER, mEyeFBs[eye]); } //========================================================================== diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index e5600fde40..08731e39f7 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -34,7 +34,7 @@ public: void BlitToEyeTexture(int eye); void BindEyeTexture(int eye, int texunit); - void BindEyeFB(int eye); + void BindEyeFB(int eye, bool readBuffer = false); enum { NumBloomLevels = 4 }; FGLBloomTextureLevel BloomLevels[NumBloomLevels]; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index f652b4765c..d768728c45 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -173,7 +173,7 @@ public: void ClearTonemapPalette(); void LensDistortScene(); void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma); - void Flush() { CopyToBackbuffer(nullptr, true); } + 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_scene.cpp b/src/gl/scene/gl_scene.cpp index 48d4fb7ff2..5fca06dad8 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()) + mBuffers->BlitToEyeTexture(eye_ix); eye->TearDown(); } stereo3dMode.TearDown(); diff --git a/src/gl/stereo3d/gl_stereo3d.cpp b/src/gl/stereo3d/gl_stereo3d.cpp index d686a4a43e..e1c4f63068 100644 --- a/src/gl/stereo3d/gl_stereo3d.cpp +++ b/src/gl/stereo3d/gl_stereo3d.cpp @@ -36,6 +36,7 @@ #include "gl/system/gl_system.h" #include "gl/stereo3d/gl_stereo3d.h" #include "gl/renderer/gl_renderer.h" +#include "gl/renderer/gl_renderbuffers.h" #include "vectors.h" // RAD2DEG #include "doomtype.h" // M_PI @@ -79,6 +80,28 @@ Stereo3DMode::~Stereo3DMode() { } +void Stereo3DMode::Present() const +{ + // Example copying eye textures to the back buffer: + + // The letterbox for the output destination. + // If stereo modes needs different dimensions then that needs to be added to FGLRenderer::SetOutputViewport. + const auto &box = GLRenderer->mOutputLetterbox; + + GLRenderer->mBuffers->BindOutputFB(); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + for (int eye_ix = 0; eye_ix < eye_count(); ++eye_ix) + { + GLRenderer->mBuffers->BindEyeFB(eye_ix, true); + int width = GLRenderer->mBuffers->GetWidth(); + int height = GLRenderer->mBuffers->GetHeight(); + glBlitFramebuffer(0, 0, width, height, box.left + eye_ix * box.width / eye_count(), box.top, box.left + (eye_ix + 1) * box.width / eye_count(), box.height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + } + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + // Avoid static initialization order fiasco by declaring first Mode type (Mono) here in the // same source file as Stereo3DMode::getCurrentMode() // https://isocpp.org/wiki/faq/ctors#static-init-order diff --git a/src/gl/stereo3d/gl_stereo3d.h b/src/gl/stereo3d/gl_stereo3d.h index c56cc078fc..3cac6b79d5 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; + protected: TArray eye_ptrs; @@ -102,6 +105,8 @@ class MonoView : public Stereo3DMode public: static const MonoView& getInstance(); + bool IsMono() const override { return true; } + protected: MonoView() { eye_ptrs.Push(¢ralEye); } EyePose centralEye;