I need to add two new content modes to display my textures with OpenGL ES 2.0 : "Aspect Fit" and "Aspect Fill'.
Here's an image explaining the different content modes :

I already have the "Scale to fill" content mode, which is the default behavior I guess.
Here's my basic vertex shader code for textures :
precision highp float;
attribute vec2 aTexCoordinate;
varying vec2 vTexCoordinate;
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
void main() {
vTexCoordinate = aTexCoordinate;
gl_Position = uMVPMatrix * vPosition;
}
And here's my fragment shader for textures :
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);
}
For the "Aspect Fill" mode, I thought I could play with the texture coordinates to crop the image. But for the "Aspect Fit" mode, I don't have a clear idea on how I could do it in the shaders, and even better with a red background color like in the screenshot.
You have to scale the texture coordinates. I recommend to add a uniform for scaling the texture:
uniform vec2 textureScale;
void main()
{
vTexCoordinate = textureScale * (aTexCoordinate - 0.5) + 0.5;
// [...]
}
Compute the aspect ratio of the texture:
aspect = textrueHeight / textureWidth
The the textureScale has to be set dependent on the mode:
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).You have to set the texture wrap parameters (GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T) mode to GL_CLAMP_TO_EDGE. See glTexParameter.
Alternatively you can discard superfluous fragments in the fragment shader:
void main() {
if (vTexCoordinate.x < 0.0 || vTexCoordinate.x > 1.0 ||
vTexCoordinate.y < 0.0 || vTexCoordinate.y > 1.0) {
discard;
}
// [...]
}
Thanks to @Rabbid76 and his answer here , I managed to do it after adding this part to his answer :
float textureAspect = (float)textureSize.width / (float)textureSize.height;
float frameAspect = (float)frameSize.width / (float)frameSize.height;
float scaleX = 1, scaleY = 1;
float textureFrameRatio = textureAspect / frameAspect;
BOOL portraitTexture = textureAspect < 1;
BOOL portraitFrame = frameAspect < 1;
if(contentMode == AspectFill) {
if(portraitFrame)
scaleX = 1.f / textureFrameRatio;
else
scaleY = textureFrameRatio;
}
else if(contentMode == AspectFit) {
if(portraitFrame)
scaleY = textureFrameRatio;
else
scaleX = 1.f / textureFrameRatio;
}
Then I do vec2(scaleX, scaleY)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With