Android的OpenGL ES的显示图像全屏宽高比 [英] Android OpenGL ES display image fullscreen with aspect ratio
问题描述
我要不失其宽高比显示在我的OpenGL应用程序的图像全屏。我知道,我可以绘制图像作为纹理到一个魔方或2D平面。但我不知道这是否是真的时,我只是单纯的想显示2D图像的最佳方式。
I want to display an image fullscreen in my OpenGL app without losing its aspect ratio. I know that I can draw an image as a texture onto a "cube" or 2d plane. But I'm not sure if this is really the best way when I just simply want to show a 2d image.
Espcially因为我想没有失去其高宽比全屏这一形象。我知道这是很容易与ImageView的。但我需要在我的OpenGL ES的应用程序。
Espcially because I want this image to be fullscreen without losing its aspect ratio. I know this is easy with an ImageView. But I need this in my OpenGL ES application.
不过,我不知道如何做到这一点。任何人任何想法?
But I have no clue how to do this. Anyone any idea?
推荐答案
由于图像的长宽比和视图的纵横比通常是不同的,有两种情况。随着宽高比定义为宽度/高度:
Since the aspect ratio of your image and the aspect ratio of your view will generally be different, there are two cases. With aspect ratio defined as width/height:
- 如果图像的纵横比小于视图的长宽比越大,则需要在顶部和底部出现黑条。
- 如果图像的纵横比小于视图的纵横比小,则需要在正确的黑条和左
没有任何转换施加时,OpenGL使用的坐标系,其具有范围为[-1.0,1.0]中x轴和y方向。所以,如果你画在两个方向四覆盖[-1.0,1.0],它会填满整个视图。因为我们不希望以填充整个范围在两个方向中的一个,我们需要在壳体2比例缩放需要相当于之间的比率的向下的y坐标在情况1中,与x坐标的量两种显示比例。
Without any transformations applied, OpenGL uses a coordinate system that has a range of [-1.0, 1.0] in both the x- and y-direction. So if you draw a quad covering [-1.0, 1.0] in both directions, it will fill the entire view. Since we do not want to fill the entire range in one of the two directions, we need to scale down the y-coordinates in case 1, and the x-coordinates in case 2. The amount of scaling needed corresponds to the ratio between the two aspect ratios.
通过以下值:
float imgAspectRatio = (float)imgWidth / (float)imgHeight;
float viewAspectRatio = (float)viewWidth / (float)viewHeight;
我们计算缩放因子x和y为:
We calculate the scaling factors for x and y as:
float xScale = 1.0f;
float yScale = 1.0f;
if (imgAspectRatio > viewAspectRatio) {
yScale = viewAspectRatio / imgAspectRatio;
} else {
xScale = imgAspectRatio / viewAspectRatio;
}
现在,所有剩下的就是应用这些比例系数,同时呈现。有这样做的多种方式。你可以用它们为您的输入坐标,并绘制一个四边形跨越范围[-xScale,xScale等在X方向和[-yScale,yScale] y方向。或者,你可以申请的比例在你的着色器,我认为这是稍微更优雅。在这种情况下,你仍然绘制在两个方向的程度[-1.0,1.0]四,并使用一个顶点着色器,可能是这样的:
Now all that's left is to apply these scale factors while rendering. There's multiple ways of doing that. You could use them for your input coordinates, and draw a quad that spans a range of [-xScale, xScale] in x-direction and [-yScale, yScale] in y-direction. Or you can apply the scaling in your shader, which I think is slightly more elegant. In this case, you still draw a quad with extent [-1.0, 1.0] in both directions, and use a vertex shader that could look like this:
#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;
}
和片段着色器,简单的样品质地:
And a fragment shader that simply samples the texture:
#version 100
precision mediump float;
uniform sampler2D Tex;
varying vec2 TexCoord;
void main() {
gl_FragColor = texture2D(Tex, TexCoord);
}
您传递我们上面的 ScaleFact
均匀值,设置了计算的 xScale等/ yScale
值该属性的位置和一切的方式,你通常会,然后渲染[-1.0,1.0]×[-1.0,1.0]四。
You pass in the xScale/yScale
values we calculated above for the value of the ScaleFact
uniform, set up the attribute location and everything else the way you normally would, and then render the [-1.0, 1.0] x [-1.0, 1.0] quad.
做着色器中的结垢的优点是,你仍然可以轻松获得的位置,并从单一的输入属性纹理坐标。如果传入的缩放位置,你可能会需要一个单独的属性来传递纹理坐标。这是一个完全正常的事情为好。
The advantage of doing the scaling in the shader is that you can still easily derive position and texture coordinates from a single input attribute. If you pass in the scaled positions, you would probably want a separate attribute to pass in the texture coordinates. Which is a perfectly fine thing to do as well.
这篇关于Android的OpenGL ES的显示图像全屏宽高比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!