Android的OpenGL ES的显示图像全屏宽高比 [英] Android OpenGL ES display image fullscreen with aspect ratio

查看:823
本文介绍了Android的OpenGL ES的显示图像全屏宽高比的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要不失其宽高比显示在我的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:

  1. 如果图像的纵横比小于视图的长宽比越大,则需要在顶部和底部出现黑条。
  2. 如果图像的纵横比小于视图的纵横比小,则需要在正确的黑条和左

没有任何转换施加时,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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆