diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index f66ea1354..a7a07a43c 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 : mEyeTextures) + DeleteTexture(handle); + + for (auto handle : mEyeFBs) + DeleteFrameBuffer(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) +{ + CreateEyeBuffers(eye); + glBindFramebuffer(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..e5600fde4 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); + 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; };