diff --git a/Outputs/OpenGL/Primitives/TextureTarget.cpp b/Outputs/OpenGL/Primitives/TextureTarget.cpp index 747c9c2ef..5a252e898 100644 --- a/Outputs/OpenGL/Primitives/TextureTarget.cpp +++ b/Outputs/OpenGL/Primitives/TextureTarget.cpp @@ -41,7 +41,10 @@ TextureTarget::TextureTarget(GLsizei width, GLsizei height, GLenum texture_unit, // Also add a stencil buffer if requested. if(has_stencil_buffer) { + glGenRenderbuffers(1, &renderbuffer_); + glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_); glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX1, expanded_width_, expanded_height_); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer_); } // Check for successful construction. @@ -52,6 +55,7 @@ TextureTarget::TextureTarget(GLsizei width, GLsizei height, GLenum texture_unit, TextureTarget::~TextureTarget() { glDeleteFramebuffers(1, &framebuffer_); glDeleteTextures(1, &texture_); + if(renderbuffer_) glDeleteRenderbuffers(1, &renderbuffer_); if(drawing_vertex_array_) glDeleteVertexArrays(1, &drawing_vertex_array_); if(drawing_array_buffer_) glDeleteBuffers(1, &drawing_array_buffer_); } diff --git a/Outputs/OpenGL/Primitives/TextureTarget.hpp b/Outputs/OpenGL/Primitives/TextureTarget.hpp index 73801ee83..647275f23 100644 --- a/Outputs/OpenGL/Primitives/TextureTarget.hpp +++ b/Outputs/OpenGL/Primitives/TextureTarget.hpp @@ -78,7 +78,7 @@ class TextureTarget { }; private: - GLuint framebuffer_ = 0, texture_ = 0; + GLuint framebuffer_ = 0, texture_ = 0, renderbuffer_ = 0; GLsizei width_ = 0, height_ = 0; GLsizei expanded_width_ = 0, expanded_height_ = 0; GLenum texture_unit_ = 0; diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index 152f9fe4f..4990c3e64 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -488,10 +488,11 @@ void ScanTarget::draw(bool synchronous, int output_width, int output_height) { } // Ensure the accumulation buffer is properly sized. - if(!accumulation_texture_ || (!synchronous && (accumulation_texture_->get_width() != output_width || accumulation_texture_->get_height() != output_height))) { + const int proportional_width = (output_height * 4) / 3; + if(!accumulation_texture_ || (!synchronous && (accumulation_texture_->get_width() != proportional_width || accumulation_texture_->get_height() != output_height))) { std::unique_ptr new_framebuffer( new TextureTarget( - GLsizei(output_width), + GLsizei(proportional_width), GLsizei(output_height), AccumulationTextureUnit, GL_LINEAR, @@ -511,6 +512,12 @@ void ScanTarget::draw(bool synchronous, int output_width, int output_height) { // Bind the accumulation texture. accumulation_texture_->bind_framebuffer(); + glClear(GL_STENCIL_BUFFER_BIT); + + // Enable stenciling and ensure spans increment the stencil buffer. + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, 0, GLuint(-1)); + glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // Output all lines except the one currently being worked on. glBindVertexArray(line_vertex_array_); @@ -518,6 +525,10 @@ void ScanTarget::draw(bool synchronous, int output_width, int output_height) { glEnable(GL_BLEND); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, GLsizei(line_buffer_.size() - 2)); + // Clear untouched parts of the display. (TODO: at vertical sync, probably) + full_display_rectangle_.draw(0.0, 0.0, 0.0); + glDisable(GL_STENCIL_TEST); + // Copy the accumulatiion texture to the target (TODO: don't assume framebuffer 0). glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, (GLsizei)output_width, (GLsizei)output_height);