Search code examples
androidopengl-esglslscalingaspect-ratio

I have a plane in OpenGLES in android on which I am rendering the camera frames as textures,I want to upscale the texture maintaining the aspect ratio


I have a GLSurfaceView with a renderer and multiple Shader Programs. In one one of the shader programs, a square geometry being rendered and a texture is used to color the geometry. The texture used here is actually the live feed from camerax with the minimum dimensions. Now I want to upscale that camera frame to the dimensions of my view port while maintaining the aspect ratio of the texture image.

Vertex data :

{
                -1.0f, 1.0f, 0f,
                -1.0f, -1.0f, 0f,
                1.0f, -1.0f, 0f,
                1.0f, 1.0f, 0f
}

Draw Order :

{
            0, 1, 2,
            0, 2, 3
}

UV coords :

{
            0.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f,
            1.0f, 1.0f
}

Consider the view port dimensions and the texture image dimensions as arbitrary.

I want to upscale the image inside the shader as if I try to upscale the image using the bitmaps and canvas of android, it takes too long for with respect to live camera feed.

Also, if once such upscaling logic is defined, I have other shader programs using a complex mesh inferred from the camera input image. So, such logic must also translate and scale for these other shader programs(These other shaders with their mesh already have a transformation matrix working on them).

*Note : I am not using a perspective camera, not even an ortho camera.

I tried to obtain scaling values with :

        float imgAspectRatio = (float) cameraFrameTexture.getWidth() / (float) cameraFrameTexture.getHeight();
        float viewAspectRatio = (float) GLRenderer.rendererWidth / (float) GLRenderer.rendererHeight;

        if (imgAspectRatio > viewAspectRatio) {
            yScale = viewAspectRatio / imgAspectRatio;
        } else {
            xScale = imgAspectRatio / viewAspectRatio;
        }

and

                    "uniform mat4 uMVPMatrix;" +
                    "uniform vec2 uScaleFactor;" +
                    "attribute vec2 uTexCoords;" +
                    "attribute vec3 vPosition;" +

                    "varying vec2 bTexCoords;" +
                    "void main() {" +
                    "   vec4 pos = uMVPMatrix * vec4(vPosition.xyz,1.0);" +
                    "   gl_Position = vec4(uScaleFactor * pos.xy,pos.z,1.0);" +


                    "   bTexCoords = uTexCoords ;" +
                    "}";

This code will scale down my geometry but does the work. While I do not want to scale down the geometry of my plane but keep it as it is.


Solution

  • I was able to solve this issue using the answer from here.

    I used the scaling logic as follows:

            float[] vPMatrix = new float[16];
            Matrix.setIdentityM(vPMatrix, 0);
            float textureAspectRatio = (float) texture.getWidth() / (float) texture.getHeight();
            float viewAspectRatio = 
                    (float) newWidth / (float) newHeight;
            float scaleX = textureAspectRatio / viewAspectRatio ;
    
            xScale = yScale = 1f;
    
            if (scaleX >= 1f)
                xScale = scaleX;
            else
                yScale = 1f / scaleX;
            
            Matrix.scaleM(vPMatrix, 0, xScale, yScale, 1.0f);
    

    Use the vPMatrix in your vertex shader to multiply it with your position vectors.