Jay Snayder
Jay Snayder

Reputation: 4338

Android ImageView Matrix to Texture Matrix

It has been quite a while since understanding Matrix calculations and mapping them to expected results. It's sort of intimidating. Curious if there is anyone out there who have done mapping from an ImageView Matrix android.graphics.Matrix to an openGL Matrix 'android.opengl.Matrix' in order to update the texture based upon the image behind it.

There will always be a photograph directly behind the texture, and the texture in front should stay at the same scale and translation as the ImageView (actually using the ImageTouchView library). The ImageView scaling and zooming works as expected and desired.

Order of the layout for the project

So, while the Image is being re-sized, I want to update the OpenGL ES 2.0 shader code in the project such that it changes size with it. I thought that I would be able to do this by using callbacks and directly manipulating the shader code, but it doesn't seem to be working. Not sure if this is a shader problem or a direct Matrix passing problem. The trigger is reached from the ImageTouchView when a matrix change is detected.

@Override
public void onMatrixChanged(Matrix matrix)
{
    photoViewRenderer_.updateTextureMatrix(matrix);
    photoSurfaceView_.requestRender();
}

When I receive that matrix data and attempt to display the new matrix in the texture then, I get a black screen overtop of the ImageTouchView. So, this could very well just be an OpenGL problem in the code. However, this is what it looks like so as we can see exactly what is being described.

What happens to the texture when implementing a matrix over it in Shader code.

The shader code looks something like this. And I'll start with these and add additional code as requested based upon feedback.

private final String vertexShader_ =
            "uniform float zoom;\n" +
            "attribute vec4 a_position;\n" +
            "attribute vec4 a_texCoord;\n" +
            "attribute vec3 a_translation;\n" +
            "varying vec2 v_texCoord;\n" +
            "void main() {\n" +
            "  gl_Position = a_position * vec4(a_translation, 1.0);\n" +
            "  v_texCoord = a_texCoord.xy * zoom;\n" +
            "}\n";

Before adding in the line for vec4(a_translation, 1.0); it seemed be working as expected in that the image was being displayed directly on top of the ImageTouchView of equal size just fine. So it is probably the shader. But...I cannot rule out that the data going in from an Image Matrix is screwing up the texture either and representing it way off screen. I don't know what to use as a default matrix for a_translation in to check against that.

Edit:

The black screen is actually not an issue now. The default a_position set to private float[] positionTranslationData_ = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; brought the image back. But the texture is not getting manipulated with the inputs from the onMatrixChanged(Matrix matrix) function called in by the ImageTouchView.

Upvotes: 1

Views: 797

Answers (1)

Trax
Trax

Reputation: 1910

If you want to translate the image (By moving the pixels renderer) you have two options.

  1. Translate the gl_Position:

    private final String vertexShader_ =
        "uniform float zoom;\n" +
        "attribute vec4 a_position;\n" +
        "attribute vec4 a_texCoord;\n" +
        "attribute vec3 a_translation;\n" +
        "varying vec2 v_texCoord;\n" +
        "void main() {\n" +
        "  gl_Position = a_position + vec4(a_translation, 1.0);\n" + // Note the + here
        "  v_texCoord = a_texCoord.xy * zoom;\n" +
        "}\n";
    
  2. Apply an affine transform, using a 4x4 matrix, to gl_Position (be aware that the 4th component of a_position must be 1.0):

     private final String vertexShader_ =
        "uniform float zoom;\n" +
        "attribute vec4 a_position;\n" +
        "attribute vec4 a_texCoord;\n" +
        "attribute mat4 a_translation;\n" +
        "varying vec2 v_texCoord;\n" +
        "void main() {\n" +
        "  gl_Position = a_position*a_translation;\n" + 
        "  v_texCoord = a_texCoord.xy * zoom;\n" +
        "}\n";
    

if you want to move the texture (not the quad or whatever you are rendering) you can apply the same logic to the v_texCoord. This will apply a translation and/or rotation to the output texture coordinates.

Probably one reason for you problem is that right now, your code that a multiply component wise, which will multiply a_position.x by a_translation.x component, the same for 'y' and so on, which I think is not what you are trying to archive.

Upvotes: 1

Related Questions