diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index e1f093701..26edb868e 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -167,20 +167,21 @@ void ScanTarget::setup_pipeline() { set_uniforms(ShaderType::QAMSeparation, *qam_separation_shader_); } - // Pick a single zoom level to apply to the output, given the intended aspect ratio compared to the 4/3 this - // scan target halways uses, and the required output dimensions. + // Select whichever of a letterbox or pillarbox avoids cropping. constexpr float output_ratio = 4.0f / 3.0f; const float aspect_ratio_stretch = modals.aspect_ratio / output_ratio; - const float zoom = modals.visible_area.appropriate_zoom(aspect_ratio_stretch); - // TODO: Adjust origin to recentre content, given the zoom. auto adjusted_rect = modals.visible_area; -// adjusted_rect.origin.x = (aspect_ratio_stretch * zoom - modals.visible_area.size.width) * 0.5f; -// adjusted_rect.origin.y -= (zoom - modals.visible_area.size.height) * 0.5f; + const float letterbox_scale = adjusted_rect.size.height / (adjusted_rect.size.width * aspect_ratio_stretch); + if(letterbox_scale > 1.0f) { + adjusted_rect.scale(letterbox_scale, 1.0f); + } else { + adjusted_rect.scale(1.0f, 1.0f / letterbox_scale); + } // Provide to shader. output_shader_->set_uniform("origin", adjusted_rect.origin.x, adjusted_rect.origin.y); - output_shader_->set_uniform("size", zoom, zoom / aspect_ratio_stretch); + output_shader_->set_uniform("size", 1.0f / adjusted_rect.size.width, 1.0f / adjusted_rect.size.height); // Establish an input shader. if(!existing_modals_ || existing_modals_->input_data_type != modals.input_data_type) { diff --git a/Outputs/ScanTarget.hpp b/Outputs/ScanTarget.hpp index c3146b09d..dbe82a646 100644 --- a/Outputs/ScanTarget.hpp +++ b/Outputs/ScanTarget.hpp @@ -40,7 +40,7 @@ struct Rect { return size.width == 0.0f || size.height == 0.0f; } - void expand(const float min_x, const float max_x, const float min_y, float max_y) { + void expand(const float min_x, const float max_x, const float min_y, const float max_y) { origin.x = std::min(origin.x, min_x); size.width = std::max(size.width, max_x - origin.x); @@ -48,6 +48,18 @@ struct Rect { size.height = std::max(size.height, max_y - origin.y); } + /// Scales a rectange around its centre. + void scale(const float scale_x, const float scale_y) { + const float centre[] = { + origin.x + size.width * 0.5f, + origin.y + size.height * 0.5f, + }; + size.width *= scale_x; + size.height *= scale_y; + origin.x = centre[0] - size.width * 0.5f; + origin.y = centre[1] - size.height * 0.5f; + } + float appropriate_zoom(const float aspect_ratio_stretch) const { const float width_zoom = 1.0f / (size.width * aspect_ratio_stretch); const float height_zoom = 1.0f / size.height;