java - Android OpenGL ES 以纵横比全屏显示图像

标签 java android opengl-es opengl-es-2.0

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

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

但是我不知道该怎么做。有人有什么想法吗?

最佳答案

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

  1. 如果图像的纵横比大于 View 的纵横比,则需要在顶部和底部添加黑条。
  2. 如果图像的纵横比小于 View 的纵横比,则需要在右侧和左侧添加黑条。

在不应用任何变换的情况下,OpenGL 使用的坐标系在 x 和 y 方向上的范围都是 [-1.0, 1.0]。因此,如果您在两个方向上绘制一个覆盖 [-1.0, 1.0] 的四边形,它将填满整个 View 。由于我们不想在两个方向之一上填充整个范围,因此我们需要缩小情况 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;
}

还有一个简单地对纹理进行采样的 fragment 着色器:

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

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

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

关于java - Android OpenGL ES 以纵横比全屏显示图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24308894/

相关文章:

android - SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 和 FLAG_TRANSLUCENT_STATUS 已弃用

android - 如何使图像的一部分透明?

opengl-es - 使用 OpenGL ES 的 glTexCoordPointer 问题

java - java中的多线程下载器

java - 如何在 Spring 属性中扩展通配符?

Java AppDomain 之类的抽象?

java - 实现在 Servlet 中在 XML 和 JSON 之间切换的 REST api

android - 如何防止 Activity 重新加载后退 Action

android - Flutter 和 Dart 插件未安装

ios - 在OpenGL场景背景中绘制纹理四边形