Results 1 to 3 of 3

Thread: textures upside down on android app

  1. #1
    Junior Member Newbie
    Join Date
    Aug 2014
    Posts
    13

    textures upside down on android app

    Yo,

    I'm getting started with opengl es on android, and I'm stumbling on this problem that the textures are displayed upside down.

    I do understand that the origin is at the bottom right. I think the vertex and texture coordinates I supply are correct:


    Code :
        static float triangleCoords[] = {   // in counterclockwise order:
                -0.5f, -0.311004243f, 0.0f, // bottom left
                0.5f, -0.311004243f, 0.0f,  // bottom right
                -.5f,  0.622008459f, 0.0f // top left
        };
     
        static float texCoords[] = {   // in counterclockwise order:
                0f, 0.0f, // bottom left
                1, 0.0f,  // bottom right
                0f,  1f // top left
        };

    I'm getting the same result (ie: upside down image) on the emulator for Nexus 5X and on my actual Galaxy S5.

    I'm putting the full code below for the two relevant classes. It's really the bare minimum for displaying a textured triangle. Anyone wanna take a look?

    Thanks!
    Code :
    package textest;
     
    import javax.microedition.khronos.egl.EGLConfig;
     
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.opengl.GLES20;
    import android.opengl.GLSurfaceView;
    import android.opengl.GLUtils;
     
    import javax.microedition.khronos.opengles.GL10;
     
    /**
     * Created by David on 14/09/2016.
     */
    public class TexTestRenderer implements GLSurfaceView.Renderer {
     
        private TexTestTriangle texTestTriangle;
        public Context context;
     
        int textId;
        public void onSurfaceCreated(GL10 unused, EGLConfig config) {
            GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
     
            texTestTriangle = new TexTestTriangle();
     
            textId = loadTexture();
        }
     
        public void onDrawFrame(GL10 unused) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
            GLES20.glBindTexture(GL10.GL_TEXTURE_2D, textId);
     
            texTestTriangle.draw();
        }
     
        public void onSurfaceChanged(GL10 unused, int width, int height) {
            GLES20.glViewport(0, 0, width, height);
        }
     
        public static int loadShader(int type, String shaderCode){
     
            int shader = GLES20.glCreateShader(type);
     
            GLES20.glShaderSource(shader, shaderCode);
            GLES20.glCompileShader(shader);
     
            return shader;
        }
     
        public int loadTexture() {
            final int[] textureHandle = new int[1];
     
            GLES20.glGenTextures(1, textureHandle, 0);
     
            if (textureHandle[0] != 0) {
                final BitmapFactory.Options options = new BitmapFactory.Options();
                options.inScaled = false;   // No pre-scaling
     
                // Read in the resource
                int resourceId = R.drawable.myimage;
                final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
     
                // Bind to the texture in OpenGL
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
     
                // Set filtering
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
     
                // Load the bitmap into the bound texture.
                GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
     
                // Recycle the bitmap, since its data has been loaded into OpenGL.
                bitmap.recycle();
     
                return textureHandle[0];
     
            } else {
                throw new RuntimeException("Error loading texture.");
            }
        }
    }

    Code :
    package textest;
     
    import android.opengl.GLES20;
     
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
     
    /**
     * Created by David on 14/09/2016.
     */
    public class TexTestTriangle {
     
        private final String vertexShaderCode =
                "attribute vec4 vPosition;" +
                " attribute vec2 texCoordIn; " +
                " varying vec2 texCoordFrag; " +
                        "void main() {" +
                        "  gl_Position = vPosition;" +
                        "  texCoordFrag = texCoordIn;" +
                        "}";
     
        private final String fragmentShaderCode =
                "precision mediump float;" +
                        "uniform sampler2D texture;" +
                        "varying vec2 texCoordFrag;" +
                        "void main() {" +
                        "  gl_FragColor = texture2D(texture, texCoordFrag);" +
                        "}";
     
        private FloatBuffer vertexBuffer;
        private FloatBuffer texCoordBuffer;
     
        // number of coordinates per vertex in this array
        static final int COORDS_PER_VERTEX = 3;
        static float triangleCoords[] = {   // in counterclockwise order:
                -0.5f, -0.311004243f, 0.0f, // bottom left
                0.5f, -0.311004243f, 0.0f,  // bottom right
                -.5f,  0.622008459f, 0.0f // top left
        };
     
        static float texCoords[] = {   // in counterclockwise order:
                0f, 0.0f, // bottom left
                1, 0.0f,  // bottom right
                0f,  1f // top left
        };
     
        private final int mProgram;
     
        public TexTestTriangle() {
            ByteBuffer bb = ByteBuffer.allocateDirect(triangleCoords.length * 4);
            bb.order(ByteOrder.nativeOrder());
     
            vertexBuffer = bb.asFloatBuffer();
            vertexBuffer.put(triangleCoords);
            vertexBuffer.position(0);
     
            ByteBuffer bbtex = ByteBuffer.allocateDirect(texCoords.length * 4);
            bbtex.order(ByteOrder.nativeOrder());
     
            texCoordBuffer = bbtex.asFloatBuffer();
            texCoordBuffer.put(texCoords);
            texCoordBuffer.position(0);
     
            int vertexShader = TexTestRenderer.loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
            int fragmentShader = TexTestRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
     
            mProgram = GLES20.glCreateProgram();
     
            GLES20.glAttachShader(mProgram, vertexShader);
            GLES20.glAttachShader(mProgram, fragmentShader);
            GLES20.glLinkProgram(mProgram);
        }
     
     
     
        private int mPositionHandle;
        private int texPositionHandle;
     
        private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
        private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
     
        public void draw() {
            // Add program to OpenGL ES environment
            GLES20.glUseProgram(mProgram);
     
            // get handle to vertex shader's vPosition member
            mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
            texPositionHandle = GLES20.glGetAttribLocation(mProgram, "texCoordIn");
     
            // Enable a handle to the triangle vertices
            GLES20.glEnableVertexAttribArray(mPositionHandle);
            GLES20.glEnableVertexAttribArray(texPositionHandle);
     
            // Prepare the triangle coordinate data
            GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                    GLES20.GL_FLOAT, false,
                    vertexStride, vertexBuffer);
     
            GLES20.glVertexAttribPointer(texPositionHandle, 2,
                    GLES20.GL_FLOAT, false,
                    8, texCoordBuffer);
     
            // Draw the triangle
            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
     
            // Disable vertex array
            GLES20.glDisableVertexAttribArray(mPositionHandle);
            GLES20.glDisableVertexAttribArray(texPositionHandle);
        }
    }

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,111
    Quote Originally Posted by davoring View Post
    I do understand that the origin is at the bottom right.
    The origin is (0,0).

    Window coordinates of (0,0) correspond to the bottom-left corner of the window. Normalised device coordinates of (0,0) correspond to the centre of the viewport. Normalised device coordinates of (-1,-1) correspond to the bottom-left corner of the viewport.

    Texture coordinates of (0,0) correspond to the first texel in the array passed to glTexImage2D. You'd need to refer to the documentation for GLUtils.texImage2D to see exactly what it does, but it probably creates a texture where (0,0) is the top-left corner of the image. If you render the image with texture coordinates having the same orientation as window coordinates (i.e. increasing T maps to increasing Y), this will result in the image being drawn upside-down.

  3. #3
    Junior Member Newbie
    Join Date
    Aug 2014
    Posts
    13
    Quote Originally Posted by GClements View Post
    Window coordinates of (0,0) correspond to the bottom-left corner of the window.
    Yep sorry that's what I meant, I dunno why i said right.

    I'll investigate on GLUtils.texImage2D then, thanks for the tip.

Similar Threads

  1. Replies: 1
    Last Post: 02-05-2015, 01:39 PM
  2. Replies: 6
    Last Post: 07-17-2013, 03:12 PM
  3. Textures showing inverted (upside down) !
    By imported_fakhir in forum OpenGL: Basic Coding
    Replies: 5
    Last Post: 03-10-2013, 04:37 PM
  4. upside down cubemap
    By gunslinger in forum OpenGL: Advanced Coding
    Replies: 2
    Last Post: 03-04-2004, 11:53 PM
  5. Upside down cube map?
    By dalangalma in forum OpenGL: Basic Coding
    Replies: 2
    Last Post: 02-12-2004, 04:25 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean