1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-01-22 08:26:48 +00:00

Ensure OpenGL appropriately letterboxes or pillarboxes.

This commit is contained in:
Thomas Harte
2025-10-07 21:37:10 -04:00
parent 4ea82581ec
commit da96df7df7
2 changed files with 21 additions and 8 deletions

View File

@@ -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) {

View File

@@ -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;