OpenGL ES (3): planar graphics - surface texture mapping

Keywords: Mobile Android

1. introduction

In the previous article, a plane figure has been drawn. This time, we will make texture mapping on the surface of the figure drawn last time.

Picture preparation: (width and height must be N power of 2)

The final image is in Bitmap form. Now consider how to map this image to the drawing plane?

So we also need an array float [], which is used to set the texture coordinate data. The texture coordinate data is based on the upper left corner (0, 0) and the lower right corner (1, 1) of the picture

As we know in the previous article, the face array is drawn as {0,1,2,3,4,5}, so we need to map a texture coordinate data for each vertex of the component face, as follows:

float[]{

0f, 0f, 0f, 1f, 1f, 1f, / / three points on the first face

0f,0f , 1f,1f , 1f,0f

}

In this way, all the images are mapped to the drawing plane.

 

2. code

public class OtherShader implements GLSurfaceView.Renderer{
    FloatBuffer vertextBuffer;
//Texture coordinate data
    FloatBuffer textureBuffer;
    ByteBuffer faceBuffer;
    private float roate;
//Texture used
    int texture;
    Context context;

    public OtherShader(Context context) {
        this.context = context;
        vertextBuffer = floatArray2Buffer(vertex);
        faceBuffer = ByteBuffer.wrap(face);
        textureBuffer = floatArray2Buffer(text);
    }

    float[] vertex = new float[]{
            -0.5f , 0.5f , 0f ,
            -0.5f , -0.5f , 0f ,
            0.5f , -0.5f , 0f ,
            -0.5f , 0.5f , 0f ,
            0.5f , -0.5f , 0f ,
            0.5f , 0.5f , 0f
    };

    byte[] face = new byte[]{
            0,1,2,
            3,4,5
    };

//Texture coordinate data
    float[] text = {
            0f,0f , 0f,1f , 1f,1f,
            0f,0f , 1f,1f , 1f,0f
    };

    //The conversion of vertex color array to IntBuffer is required by OpenGl ES, and vertex color can not be set
    private IntBuffer intArray2Buffer(int[] rect1color) {
        IntBuffer intBuffer;
        //Do not use this method to get IntBuffer. Because of the limitation of Android platform, Buffer must be native Buffer, so it should be created through allocateDirect()
        //And the Buffer must be sorted, so the order() method is used for sorting
        //intBuffer = IntBuffer.wrap(rect1color);
        //Because an int=4 bytes
        ByteBuffer bb = ByteBuffer.allocateDirect(rect1color.length * 4);
        bb.order(ByteOrder.nativeOrder());
        intBuffer = bb.asIntBuffer();
        intBuffer.put(rect1color);
        intBuffer.position(0); //Data moved to first point
        return intBuffer;
    }

    //Converting the vertex position array to FloatBuffer is required by OpenGl ES
    private FloatBuffer floatArray2Buffer(float[] rect1) {
        FloatBuffer floatBuffer;
        //Do not use this method to get the FloatBuffer. Because of the limitation of Android platform, the Buffer must be native Buffer, so it should be created through allocateDirect()
        //And the Buffer must be sorted, so the order() method is used for sorting
        //floatBuffer = FloatBuffer.wrap(rect1);
        //Because an int=4 bytes
        ByteBuffer bb = ByteBuffer.allocateDirect(rect1.length * 4);
        bb.order(ByteOrder.nativeOrder());
        floatBuffer = bb.asFloatBuffer();
        floatBuffer.put(rect1);
        floatBuffer.position(0); //Data moved to first point
        return floatBuffer;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //Turn off anti jitter
        gl.glDisable(GL10.GL_DITHER);
        //Fix system perspective
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT , GL10.GL_FASTEST);
        //Set shadow smoothing mode
        gl.glShadeModel(GL10.GL_SMOOTH);
        //Enable depth test to record Z-axis depth
        gl.glEnable(GL10.GL_DEPTH_TEST);
        //Set the type of depth test
        gl.glDepthFunc(GL10.GL_LEQUAL);

        //*******Enable 2D texture*************
        gl.glEnable(GL10.GL_TEXTURE_2D);
        //Loading texture
        loadTexture(gl);
    }

    private void loadTexture(GL10 gl) {
        Bitmap bitmap = null;
        bitmap = BitmapFactory.decodeResource(context.getResources() , R.drawable.bj);
        int[] textures = new int[1];
        gl.glGenTextures(1 , textures , 0);
        texture = textures[0];
        gl.glBindTexture(GL10.GL_TEXTURE_2D , texture);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_MIN_FILTER , GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_MAG_FILTER , GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_WRAP_S , GL10.GL_REPEAT);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D , GL10.GL_TEXTURE_WRAP_T , GL10.GL_REPEAT);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D , 0 , bitmap , 0);
        if (bitmap != null){
            bitmap.recycle();
        }
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //Set the size and location of the 3D window
        gl.glViewport(0 , 0 , width , height );
        //Set matrix mode to projection matrix
        gl.glMatrixMode(GL10.GL_PROJECTION);
        //Initialize unit matrix
        gl.glLoadIdentity();
        //Calculate the aspect ratio of perspective window
        float ratio = (float)width/height;
        //Set the space size of perspective window to - 1,1, - 1,1, - 1,1 by default
        //gl.glFrustumf(-ratio , ratio , -1 , 1  ,1 , 10);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        //Clear screen cache and depth cache
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        //Enable vertex coordinate data
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        //Set the current rectangle stack as the model stack
        gl.glMatrixMode(GL10.GL_MODELVIEW);

        //Enable array of texture map coordinates
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        //Reset the current model view matrix
        gl.glLoadIdentity();
       //If you need to fill the plane with color, you also need to disable vertex color data
        gl.glColor4f(0.2f , 1.0f , 0.2f , 0.0f);
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        //Rotate around y axis
        //gl.glRotatef(roate , 0f , 1f , 0f);
        //Set vertex position data
        gl.glVertexPointer(3 , GL10.GL_FLOAT , 0 , vertextBuffer);
        //Set map array
        gl.glTexCoordPointer(2 , GL10.GL_FLOAT , 0 , textureBuffer);
        //Draw plane from vertex / / Map

        gl.glBindTexture(GL10.GL_TEXTURE_2D , texture);
        gl.glDrawElements(GL10.GL_TRIANGLES, faceBuffer.remaining() , GL10.GL_UNSIGNED_BYTE , faceBuffer);


        //Stop drawing
        gl.glFinish();
        //Disable coordinate data
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        //Disable texture array
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        roate+=1;
        if (roate == 360){
            roate = 0;
        }
    }


}

 

 

 

Posted by adwfun on Sat, 14 Dec 2019 09:37:28 -0800