diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index cfe48fc67..19f24884e 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -238,14 +238,15 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out // glTextureBarrierNV(); #endif - // copy framebuffer to the intended place + // Copy framebuffer to the intended place; apply a threshold so that any persistent errors in + // the lower part of the colour channels are invisible. glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER, static_cast(target_framebuffer_)); glViewport(0, 0, (GLsizei)output_width, (GLsizei)output_height); glActiveTexture(pixel_accumulation_texture_unit); framebuffer_->bind_texture(); - framebuffer_->draw(static_cast(output_width) / static_cast(output_height)); + framebuffer_->draw(static_cast(output_width) / static_cast(output_height), 4.0f / 255.0f); fence_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); draw_mutex_.unlock(); diff --git a/Outputs/CRT/Internals/TextureTarget.cpp b/Outputs/CRT/Internals/TextureTarget.cpp index b9652d8eb..c2d6f8f57 100644 --- a/Outputs/CRT/Internals/TextureTarget.cpp +++ b/Outputs/CRT/Internals/TextureTarget.cpp @@ -56,7 +56,7 @@ void TextureTarget::bind_texture() { glBindTexture(GL_TEXTURE_2D, texture_); } -void TextureTarget::draw(float aspect_ratio) { +void TextureTarget::draw(float aspect_ratio, float colour_threshold) { if(!pixel_shader_) { const char *vertex_shader = "#version 150\n" @@ -75,12 +75,15 @@ void TextureTarget::draw(float aspect_ratio) { "#version 150\n" "in vec2 texCoordVarying;" + "uniform sampler2D texID;" + "uniform float threshold;" + "out vec4 fragColour;" "void main(void)" "{" - "fragColour = texture(texID, texCoordVarying);" + "fragColour = clamp(texture(texID, texCoordVarying), threshold, 1.0);" "}"; pixel_shader_.reset(new Shader(vertex_shader, fragment_shader)); pixel_shader_->bind(); @@ -103,6 +106,8 @@ void TextureTarget::draw(float aspect_ratio) { GLint texIDUniform = pixel_shader_->get_uniform_location("texID"); glUniform1i(texIDUniform, static_cast(texture_unit_ - GL_TEXTURE0)); + + threshold_uniform_ = pixel_shader_->get_uniform_location("threshold"); } if(set_aspect_ratio_ != aspect_ratio) { @@ -134,6 +139,8 @@ void TextureTarget::draw(float aspect_ratio) { } pixel_shader_->bind(); + glUniform1f(threshold_uniform_, colour_threshold); + glBindVertexArray(drawing_vertex_array_); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/Outputs/CRT/Internals/TextureTarget.hpp b/Outputs/CRT/Internals/TextureTarget.hpp index 6c7b04b99..9a69efa47 100644 --- a/Outputs/CRT/Internals/TextureTarget.hpp +++ b/Outputs/CRT/Internals/TextureTarget.hpp @@ -58,9 +58,17 @@ class TextureTarget { } /*! + Draws this texture to the currently-bound framebuffer, which has the aspect ratio + @c aspect_ratio. This texture will fill the height of the frame buffer, and pick + an appropriate width based o the aspect ratio. + @c colour_threshold sets a threshold test that each colour must satisfy to be + output. A threshold of 0.0f means that all colours will pass through. A threshold + of 0.5f means that only colour components above 0.5f will pass through, with + 0.5f being substituted elsewhere. This provides a way to ensure that the sort of + persistent low-value errors that can result from an IIR are hidden. */ - void draw(float aspect_ratio); + void draw(float aspect_ratio, float colour_threshold = 0.0f); enum { ErrorFramebufferIncomplete @@ -75,6 +83,8 @@ class TextureTarget { std::unique_ptr pixel_shader_; GLuint drawing_vertex_array_ = 0, drawing_array_buffer_ = 0; float set_aspect_ratio_ = 0.0f; + + GLint threshold_uniform_; }; }