使用 OpenGL ES 2.0 的长宽比适合和长宽比填充内容模式

Xys*_*Xys 3 shader opengl-es glsl

我需要添加两种新的内容模式来使用 OpenGL ES 2.0 显示纹理:“Aspect Fit”和“Aspect Fill”。

这是解释不同内容模式的图像:

我已经有了“缩放以填充”内容模式,我猜这是默认行为。

这是我的基本纹理顶点着色器代码:

precision highp float;

attribute vec2 aTexCoordinate;
varying vec2 vTexCoordinate;
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;

void main() {
    vTexCoordinate = aTexCoordinate;
    gl_Position = uMVPMatrix * vPosition;
}
Run Code Online (Sandbox Code Playgroud)

这是我的纹理片段着色器:

precision mediump float;

uniform vec4 vColor;
uniform sampler2D uTexture;
varying vec2 vTexCoordinate;

void main() {
    // premultiplied alpha
    vec4 texColor = texture2D(uTexture, vTexCoordinate);
    // Scale the texture RGB by the vertex color
    texColor.rgb *= vColor.rgb;
    // Scale the texture RGBA by the vertex alpha to reinstate premultiplication
    gl_FragColor = texColor * vColor.a;
    //gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
Run Code Online (Sandbox Code Playgroud)

对于“长宽比填充”模式,我想我可以使用纹理坐标来裁剪图像。但对于“Aspect Fit”模式,我不清楚如何在着色器中做到这一点,甚至更好地使用屏幕截图中的红色背景颜色。

Rab*_*d76 8

您必须缩放纹理坐标。我建议添加一个制服来缩放纹理:

uniform vec2 textureScale;

void main()
{
    vTexCoordinate = textureScale * (aTexCoordinate - 0.5) + 0.5;
    // [...]
}
Run Code Online (Sandbox Code Playgroud)

计算纹理的纵横比:

aspect = textrueHeight / textureWidth
Run Code Online (Sandbox Code Playgroud)

必须textureScale根据模式进行设置:

  • “缩放以填充”:vec2(1.0, 1.0).
  • 景观“方面适合”:vec2(1.0, aspect)
  • 景观“纵横比填充”:vec2(1.0/aspect, 1.0).
  • 肖像“方面适合”:vec2(1.0/aspect, 1.0)
  • 肖像“纵横比填充”:vec2(1.0, aspect).

您必须将纹理包裹参数 ( GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T) 模式设置为GL_CLAMP_TO_EDGE。看glTexParameter

或者,您可以discard在片段着色器中添加多余的片段:

void main() {
    if (vTexCoordinate.x < 0.0 || vTexCoordinate.x > 1.0 ||
        vTexCoordinate.y < 0.0 || vTexCoordinate.y > 1.0) {
    
        discard;
    }

    // [...]
}   
Run Code Online (Sandbox Code Playgroud)