我希望在我的OpenGL应用程序中全屏显示图像,而不会失去其宽高比。我知道我可以将图像作为纹理绘制到“立方体”或2d平面上。但是,当我只是想展示一张2D图像时,我不确定这是否真的是最好的方式。
特别是因为我希望这个图像是全屏而不会失去其宽高比。我知道使用ImageView很容易。但我需要在我的OpenGL ES应用程序中使用它。
但我不知道如何做到这一点。任何人都有任何想法?
答案 0 :(得分:4)
由于图像的宽高比和视图的宽高比通常不同,因此有两种情况。纵横比定义为宽度/高度:
在未应用任何变换的情况下,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] quad。
在着色器中进行缩放的优点是,您仍然可以轻松地从单个输入属性派生位置和纹理坐标。如果传入缩放位置,则可能需要在纹理坐标中传递单独的属性。这也是一件非常好的事情。