diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index d51b0ca32..9698aa3b1 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -178,6 +178,8 @@ class CRTCBusHandler { establish_palette_hits(); build_mode_table(); crt_.set_visible_area(Outputs::Display::Rect(0.1072f, 0.1f, 0.842105263157895f, 0.842105263157895f)); + crt_.set_brightness(3.0f / 2.0f); // As only the values 0, 1 and 2 will be used in each channel, + // whereas Red2Green2Blue2 defines a range of 0-3. } /*! diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 487dc1333..1a1478a85 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -98,6 +98,11 @@ void CRT::set_input_data_type(Outputs::Display::InputDataType input_data_type) { scan_target_->set_modals(scan_target_modals_); } +void CRT::set_brightness(float brightness) { + scan_target_modals_.brightness = brightness; + scan_target_->set_modals(scan_target_modals_); +} + void CRT::set_new_display_type(int cycles_per_line, Outputs::Display::Type displayType) { switch(displayType) { case Outputs::Display::Type::PAL50: diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index 89b76bd76..6854726b1 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -273,6 +273,9 @@ class CRT { /*! Sets the input data type. */ void set_input_data_type(Outputs::Display::InputDataType); + + /*! Sets the output brightness. */ + void set_brightness(float); }; } diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index 930daa9f3..59f37469c 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -285,8 +285,8 @@ void ScanTarget::setup_pipeline() { // lose any detail when combining the input. processing_width_ = modals_.cycles_per_line / modals_.clocks_per_pixel_greatest_common_divisor; - // Establish an output shader. TODO: add proper decoding and gamma correction here. - output_shader_ = conversion_shader(modals_.input_data_type, modals_.display_type, modals_.composite_colour_space); + // Establish an output shader. TODO: don't hard-code gamma. + output_shader_ = conversion_shader(modals_.input_data_type, modals_.display_type, modals_.composite_colour_space, 2.2f / modals_.intended_gamma, modals_.brightness); glBindVertexArray(line_vertex_array_); glBindBuffer(GL_ARRAY_BUFFER, line_buffer_name_); enable_vertex_attributes(ShaderType::Conversion, *output_shader_); diff --git a/Outputs/OpenGL/ScanTarget.hpp b/Outputs/OpenGL/ScanTarget.hpp index 6dedc7c6a..10dc4dbf9 100644 --- a/Outputs/OpenGL/ScanTarget.hpp +++ b/Outputs/OpenGL/ScanTarget.hpp @@ -181,7 +181,7 @@ class ScanTarget: public Outputs::Display::ScanTarget { Produces a shader that reads from a composition buffer and converts to host output RGB, decoding composite or S-Video as necessary. */ - static std::unique_ptr conversion_shader(InputDataType input_data_type, DisplayType display_type, ColourSpace colour_space); + static std::unique_ptr conversion_shader(InputDataType input_data_type, DisplayType display_type, ColourSpace colour_space, float gamma_ratio, float brightness); }; } diff --git a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp index cebc7eeb3..d96adfd4d 100644 --- a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp +++ b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp @@ -180,7 +180,7 @@ std::unique_ptr ScanTarget::composition_shader(InputDataType input_data_ )); } -std::unique_ptr ScanTarget::conversion_shader(InputDataType input_data_type, DisplayType display_type, ColourSpace colour_space) { +std::unique_ptr ScanTarget::conversion_shader(InputDataType input_data_type, DisplayType display_type, ColourSpace colour_space, float gamma_ratio, float brightness) { // Compose a vertex shader. If the display type is RGB, generate just the proper // geometry position, plus a solitary textureCoordinate. // @@ -451,7 +451,16 @@ std::unique_ptr ScanTarget::conversion_shader(InputDataType input_data_t break; } - // TODO gamma and range corrections. + // Apply a brightness adjustment if requested. + if(fabs(brightness - 1.0f) > 0.05f) { + fragment_shader += "fragColour3 = fragColour3 * " + std::to_string(brightness) + ";"; + } + + // Apply a gamma correction if required. + if(fabs(gamma_ratio - 1.0f) > 0.05f) { + fragment_shader += "fragColour3 = pow(fragColour3, vec3(" + std::to_string(gamma_ratio) + "));"; + } + fragment_shader += "fragColour = vec4(fragColour3, 0.64);" "}";