Android OpenGL ES 以宽高比全屏显示图像

2023-12-26

我想在我的 OpenGL 应用程序中全屏显示图像而不丢失其纵横比。我知道我可以将图像作为纹理绘制到“立方体”或二维平面上。但当我只想显示二维图像时,我不确定这是否真的是最好的方法。

特别是因为我希望该图像全屏显示而不丢失其纵横比。我知道使用 ImageView 很容易。但我的 OpenGL ES 应用程序需要这个。

但我不知道如何做到这一点。有人有什么想法吗?


由于图像的长宽比和视图的长宽比通常会不同,因此有两种情况。纵横比定义为宽度/高度:

  1. 如果图像的长宽比大于视图的长宽比,则需要在顶部和底部设置黑条。
  2. 如果图像的长宽比小于视图的长宽比,则需要在右侧和左侧设置黑条。

在不应用任何变换的情况下,OpenGL 使用 x 和 y 方向范围均为 [-1.0, 1.0] 的坐标系。因此,如果您在两个方向上绘制一个覆盖 [-1.0, 1.0] 的四边形,它将填充整个视图。由于我们不想在两个方向之一上填充整个范围,因此我们需要缩小情况 1 中的 y 坐标和情况 2 中的 x 坐标。所需的缩放量对应于两个长宽比。

具有以下值:

float imgAspectRatio = (float)imgWidth / (float)imgHeight;
float viewAspectRatio = (float)viewWidth / (float)viewHeight;

我们将 x 和 y 的缩放因子计算为:

float xScale = 1.0f;
float yScale = 1.0f;
if (imgAspectRatio > viewAspectRatio) {
    yScale = viewAspectRatio / imgAspectRatio;
} else {
    xScale = imgAspectRatio / viewAspectRatio;
}

现在剩下的就是在渲染时应用这些比例因子。有多种方法可以做到这一点。您可以将它们用作输入坐标,并绘制一个在 x 方向上跨越 [-xScale, xScale] 范围和在 y 方向上跨越 [-yScale, yScale] 范围的四边形。或者您可以在着色器中应用缩放,我认为这稍微更优雅。在这种情况下,您仍然在两个方向上绘制一个范围为 [-1.0, 1.0] 的四边形,并使用如下所示的顶点着色器:

#version 100
uniform vec2 ScaleFact;
attribute vec2 Position;
varying vec2 TexCoord;
void main() {
    gl_Position = vec4(ScaleFact * Position, 0.0, 1.0);
    TexCoord = 0.5 * Position + 0.5;
}

以及一个仅对纹理进行采样的片段着色器:

#version 100
precision mediump float;
uniform sampler2D Tex;
varying vec2 TexCoord;
void main() {
    gl_FragColor = texture2D(Tex, TexCoord);
}

你通过在xScale/yScale我们上面计算的值ScaleFact统一,按照通常的方式设置属性位置和其他所有内容,然后渲染 [-1.0, 1.0] x [-1.0, 1.0] 四边形。

在着色器中进行缩放的优点是您仍然可以轻松地从单个输入属性导出位置和纹理坐标。如果您传递缩放位置,您可能需要一个单独的属性来传递纹理坐标。这也是一件非常好的事情。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android OpenGL ES 以宽高比全屏显示图像 的相关文章

随机推荐