0
votes

Im trying to render a texture keeping its ratio in openGL es 2.0 .

I suppose I need to calculate the ratio and change the frustum dimensions, is that the right way? Right now Im rendering with frustum -1,1 for width and height so the texture gets stretched when it doesnt have the screen size.

How do I render the texture lets say width = 400 height = 800 at that ratio?

This is my code :

@Override
    public void onDrawFrame(GL10 glUnused) {

    GLES20.glClearColor(0.9f, 0.9f, 0.9f, .5f);
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
    GLES20.glEnable( GLES20.GL_BLEND );
    GLES20.glBlendFunc( GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA );


    Matrix.setIdentityM(mMMatrix, 0);
    Matrix.rotateM(mMMatrix, 0, 270.0f, 0, 0, 1);
    Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);

    GLES20.glUseProgram(programTextured);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);


    sqTex.getVertexBuffer().position(sqTex.VERT_OFFSET);
    GLES20.glVertexAttribPointer(
            GLES20.glGetAttribLocation(programTextured, "aPosition"), 3,
            GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer());
    GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(programTextured, "aPosition"));

    sqTex.getVertexBuffer().position(sqTex.TEXT_OFFSET);
    GLES20.glVertexAttribPointer(
            GLES20.glGetAttribLocation(programTextured, "aTextureCoord"), 2,
            GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer());
    GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(programTextured, "aTextureCoord"));


    GLES20.glUniformMatrix4fv(
            GLES20.glGetUniformLocation(programTextured, "uMVPMatrix"), 1, false,
            mMVPMatrix, 0);
    GLES20.glVertexAttrib4f(
            GLES20.glGetAttribLocation(programTextured, "acolor"), 
            .6f,0.3f,0.9f,.5f);
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, sqTex.getIndexBuffer());

    GLES20.glDisableVertexAttribArray(GLES20.glGetAttribLocation(programTextured, "aTextureCoord"));
}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);
    float ratio = (float) width / height;
    //flaot ratio2 = (float)height / 
    //Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3f, 17);



Matrix.frustumM(mProjMatrix, 0, -1, 1, -1, 1, 3, 17);

}

int mTextureID;
@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {

    program = createProgram(mVertexShader, mFragmentShader);
    programTextured = createProgram(mVertexShaderTextured, mFragmentShaderTextured);

    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    int[] textures = new int[1];
    GLES20.glGenTextures(1, textures, 0);

    mTextureID = textures[0];
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
            GLES20.GL_NEAREST);
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_MAG_FILTER,
            GLES20.GL_LINEAR);

    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
            GLES20.GL_REPEAT);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
            GLES20.GL_REPEAT);

    InputStream is = mContext.getResources()
        .openRawResource(R.drawable.image0003);
    Bitmap bitmap;
    try {
        bitmap = BitmapFactory.decodeStream(is);
    } finally {
        try {
            is.close();
        } catch(IOException e) {
            // Ignore.
        }
    }

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
    bitmap.recycle();
}
1

1 Answers

0
votes

I would leave the frustum and rather use scale:

You need 2 factors, first a screenRatio = screenWidth/screenHeight, then imageRatio = imageWidth/imageHeight.

Now if imageRatio < screenRatio you will need to scale it down in width:

if (imageWidth>imageHeight) scaleM(mMMatrix, 1/(imageWidth/imageHeight), 1, 1)
else scaleM(mMMatrix, 1/(imageHeight/imageWidth), 1, 1)

Or if imageRatio > screenRatio you will need to scale it down in height:

if (imageHeight>imageWidth) scaleM(mMMatrix, 1, 1/(imageHeight/imageWidth), 1)
else scaleM(mMMatrix, 1, 1/(imageWidth/imageHeight), 1)