Android/OpenGLES sample1


(1)四角形を表示するだけ。
塗りつぶし色はuniform変数で指定している。

(2)三角形
頂点カラー

(3)　テクスチャ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/fcf47cbe-3538-7b2e-ea5c-127a05ef6e12.png)

サンプル(EGLのSurfaceを利用）
https://1drv.ms/u/s!ApO4wsxFJBbVuUr4rbo3RkWkdF_b?e=vmgUss

これはGLSurfaceViewのversion
https://1drv.ms/u/s!ApO4wsxFJBbVuUs1oL5qN6Zflebi?e=pjxOUU


◆[attribute 変数の index の指定](http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090827)
attribute 変数 position には, アプリケーションプログラム側から頂点情報 (位置) を与えなければならないので, この変数の index を獲得します. これには, 以下の二つの方法があります.

1)index の決定をシェーダのリンカ glLinkProgram() に任せて, リンク後に glGetAttribLocation() でそれを調べる方法
2)リンク前に glBindAttribLocation() を使って index を明示的に指定する方法

<font color="Red">
Androidのjava層のopenglesは(2)しか使えない？
native/c++で昔触ったときは制約なかったと思う。</font>

```

package com.ore.blackv2;
//package com.example.android.opengl;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import android.opengl.GLES20;
import android.util.Log;

import static android.opengl.GLES20.GL_FALSE;
import static android.opengl.GLES20.GL_LINK_STATUS;
import static android.opengl.GLES20.glDeleteProgram;
import static android.opengl.GLES20.glGetProgramInfoLog;
import static android.opengl.GLES20.glGetProgramiv;

public class Square {

    private final String vertexShaderCode =
            // This matrix member variable provides a hook to manipulate
            // the coordinates of the objects that use this vertex shader
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    private final FloatBuffer vertexBuffer;
    private final ShortBuffer drawListBuffer;
    private final int mProgram;
    private int mPositionHandle;
    private int mColorHandle;
    private int mMVPMatrixHandle;

    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    static float squareCoords[] = {
            -0.5f,  0.5f, 0.0f,   // top left
            -0.5f, -0.5f, 0.0f,   // bottom left
            0.5f, -0.5f, 0.0f,   // bottom right
            0.5f,  0.5f, 0.0f }; // top right

    private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices

    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    float color[] = { 1.0f, 0.709803922f, 0.898039216f, 1.0f };

    /**
     * Sets up the drawing object data for use in an OpenGL ES context.
     */
    public Square() {
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (# of coordinate values * 4 bytes per float)
                squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);

        // initialize byte buffer for the draw list
        ByteBuffer dlb = ByteBuffer.allocateDirect(
                // (# of coordinate values * 2 bytes per short)
                drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);

        // prepare shaders and OpenGL program
       // int vertexShader = MyGLRenderer.loadShader(  GLES20.GL_VERTEX_SHADER, vertexShaderCode);
       // int fragmentShader = MyGLRenderer.loadShader( GLES20.GL_FRAGMENT_SHADER,  fragmentShaderCode);

        int vertexShader = GLESUtils.createShader(  GLES20.GL_VERTEX_SHADER, vertexShaderCode);
         int fragmentShader = GLESUtils.createShader( GLES20.GL_FRAGMENT_SHADER,  fragmentShaderCode);


        mProgram = GLES20.glCreateProgram();             // create empty OpenGL Program
        GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
        GLES20.glLinkProgram(mProgram);                  // create OpenGL program executables
        int[] status = new int[1];
        glGetProgramiv(mProgram, GL_LINK_STATUS, status, 0);
        if (status[0] == GL_FALSE) {
            //Log.e(TAG, glGetProgramInfoLog(mProgram));
            glDeleteProgram(mProgram);
        }
    }

    /**
     * Encapsulates the OpenGL ES instructions for drawing this shape.
     *
     * @param mvpMatrix - The Model View Project matrix in which to draw
     * this shape.
     */
    public void draw(float[] mvpMatrix) {
        // Add program to OpenGL environment
        GLES20.glUseProgram(mProgram);

        // get handle to vertex shader's vPosition member
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(mPositionHandle);

        // Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer(
                mPositionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);

        // get handle to fragment shader's vColor member
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

        // Set color for drawing the triangle
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);

        // get handle to shape's transformation matrix
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        //MyGLRenderer.checkGlError("glGetUniformLocation");

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
        //MyGLRenderer.checkGlError("glUniformMatrix4fv");

        // Draw the square
        GLES20.glDrawElements(
                GLES20.GL_TRIANGLES, drawOrder.length,
                GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

}

```


```


public class Triangle {
     public final String vertexShaderCode =
                        "attribute vec4 vPosition;" +
                        "attribute vec4 vColor;" +
                        "varying mediump vec4 varColor;"+
                        "void main() {" +
                        "  varColor = vColor;"+
                        "  gl_Position = vPosition;" +
                        "}";
        public final String fragmentShaderCode =
                "precision mediump float;" +
                        "varying mediump vec4 varColor;"+
                        "void main() {" +
                        "  gl_FragColor = varColor;" +
                        "}";

    private int loadShader(int type, String shaderCode){
        int err = 0;
        int shader = GLES20.glCreateShader(type);
        err = EGL14.eglGetError();
        if (err != EGL14.EGL_SUCCESS)  return 0;

        GLES20.glShaderSource(shader, shaderCode);
        if (EGL14.eglGetError() != EGL14.EGL_SUCCESS)  return 0;

        GLES20.glCompileShader(shader);
        return shader;
    }

    private  int shaderProgram;

    public Triangle() {
    }
    public int Init(){
        int err = 0;
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        shaderProgram = GLES20.glCreateProgram();

        err = GLES20.glGetError();
        if (err != GLES20.GL_NO_ERROR)  return err;

        GLES20.glAttachShader(shaderProgram, vertexShader);
        GLES20.glAttachShader(shaderProgram, fragmentShader);
        GLES20.glLinkProgram(shaderProgram);
        err = GLES20.glGetError();
        if (err != GLES20.GL_NO_ERROR)  return err;

        int[] status = new int[1];
        glGetProgramiv(shaderProgram, GL_LINK_STATUS, status, 0);
        if (status[0] == GL_FALSE) {
            String msz = glGetProgramInfoLog(shaderProgram);
            Log.e("sample", glGetProgramInfoLog(shaderProgram));
            glDeleteProgram(shaderProgram);
        }


        return GLES20.GL_NO_ERROR;
    }

    public void draw(){
        int err = 0;
        //if( shaderProgram == 0 ) return;
        GLES20.glUseProgram(shaderProgram);
        err = GLES20.glGetError();
        if (err != GLES20.GL_NO_ERROR)  return ;

        int positionAttrib = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
        GLES20.glEnableVertexAttribArray(positionAttrib);

        if( true ) {
            // xyz, rgba,

            float vertices[] = {
                    0.0f, 0.4f, 0.0f, 1.0f,
                    -0.3f, -0.3f, 0.0f, 1.0f,
                    0.5f, -0.3f, 0.0f, 1.0f,
            };

            ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer vertexBuffer = bb.asFloatBuffer();
            vertexBuffer.put(vertices);
            vertexBuffer.position(0);
            int stride = 0;
            GLES20.glVertexAttribPointer(positionAttrib, 4, GLES20.GL_FLOAT, false, stride, vertexBuffer);
        }


        boolean enableColor = true;
        int colorAttrib = 0;
        if( enableColor ) {
            float colors[] = {
                    1.0f, 0.0f, 0.0f, 1.0f,
                    0.0f, 1.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f,
            };
            colorAttrib = GLES20.glGetAttribLocation(shaderProgram, "vColor");
            GLES20.glEnableVertexAttribArray(colorAttrib);

            ByteBuffer bb2 = ByteBuffer.allocateDirect(colors.length * 4);
            bb2.order(ByteOrder.nativeOrder());
            FloatBuffer colorBuffer = bb2.asFloatBuffer();
            colorBuffer.put(colors);
            colorBuffer.position(0);
            int stride = 0;
            GLES20.glVertexAttribPointer(colorAttrib, 4, GLES20.GL_FLOAT, false, stride, colorBuffer);
        }

        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);


        GLES20.glDisableVertexAttribArray(positionAttrib);
        if( enableColor ) {
            GLES20.glDisableVertexAttribArray(colorAttrib);
        }
    }


```


```

package com.ore.egltest4;


import java.nio.*;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.EGL14;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;

import static android.opengl.GLES20.GL_FALSE;
import static android.opengl.GLES20.GL_LINK_STATUS;
import static android.opengl.GLES20.glDeleteProgram;
import static android.opengl.GLES20.glGetProgramInfoLog;
import static android.opengl.GLES20.glGetProgramiv;
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_ELEMENT_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_STATIC_DRAW;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glViewport;


import static android.opengl.GLES20.GL_TRIANGLES;
import static android.opengl.GLES20.GL_UNSIGNED_INT;
import static android.opengl.GLES20.glAttachShader;
import static android.opengl.GLES20.glBufferData;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glCompileShader;
import static android.opengl.GLES20.glCreateProgram;
import static android.opengl.GLES20.glCreateShader;
import static android.opengl.GLES20.glDeleteShader;
import static android.opengl.GLES20.glDrawElements;
import static android.opengl.GLES20.glGenBuffers;
import static android.opengl.GLES20.glGetProgramInfoLog;
import static android.opengl.GLES20.glGetProgramiv;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glLinkProgram;
import static android.opengl.GLES20.glShaderSource;
import static android.opengl.GLES20.glViewport;
import static android.opengl.GLES20.glGetShaderiv;
import static android.opengl.GLES20.glBindAttribLocation;
import static android.opengl.GLES20.glGenTextures;
import static android.opengl.GLES20.glBindTexture;
import static android.opengl.GLES20.glTexImage2D;
import static android.opengl.GLES20.glTexParameterf;
import static android.opengl.GLES20.glGetIntegerv;
import static android.opengl.GLES20.glGenFramebuffers;
import static android.opengl.GLES20.glBindFramebuffer;
import static android.opengl.GLES20.glFramebufferTexture2D;
import static android.opengl.GLES20.glCheckFramebufferStatus;
import static android.opengl.GLES20.glGetError;
import static android.opengl.GLES20.glBindBuffer;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glActiveTexture;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glUniformMatrix4fv;
import static android.opengl.GLES20.glEnableVertexAttribArray;
import static android.opengl.GLES20.glUniform1i;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glDisableVertexAttribArray;
import static android.opengl.GLES20.glTexParameteri;
import static android.opengl.GLES20.glVertexAttribPointer;


import android.opengl.GLES11Ext;
import static android.opengl.EGL14.eglGetError;


import static android.opengl.GLES20.GL_TEXTURE_2D;
import static android.opengl.GLES20.GL_RGBA;
import static android.opengl.GLES20.GL_UNSIGNED_BYTE;
import static android.opengl.GLES20.GL_LINEAR;
import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
import static android.opengl.GLES20.GL_FRAMEBUFFER_BINDING;

import static android.opengl.GLES20.GL_TEXTURE_WRAP_S;
import static android.opengl.GLES20.GL_CLAMP_TO_EDGE;
import static android.opengl.GLES20.GL_TEXTURE_WRAP_T;
import static android.opengl.GLES20.GL_FRAMEBUFFER;
import static android.opengl.GLES20.GL_COLOR_ATTACHMENT0;
import static android.opengl.GLES20.GL_DEPTH_ATTACHMENT;
import static android.opengl.GLES20.GL_RENDERBUFFER;
import static android.opengl.GLES20.GL_FRAMEBUFFER_COMPLETE;
import static android.opengl.GLES20.GL_TEXTURE0;
import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
import static android.opengl.GLES20.GL_COMPILE_STATUS;
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_ELEMENT_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_FALSE;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
import static android.opengl.GLES20.GL_LINK_STATUS;
import static android.opengl.GLES20.GL_NO_ERROR;
import static android.opengl.GLES20.GL_STATIC_DRAW;
import static android.opengl.GLES20.GL_VERTEX_SHADER;

/*
*  public final String vertexShaderCode =
    "attribute vec4 vPosition;" +
    "attribute vec4 vColor;" +
    "attribute vec2 vUV;" +
    "varying mediump vec2 varUV;"+
    "varying mediump vec4 varColor;"+
    "void main() {" +
    "  varColor = vColor;"+
    "  gl_Position = vPosition;" +
    "  varUV = vUV.st;"+
    "}";

        public final String fragmentShaderCode =
                "precision mediump float;" +
                        "uniform sampler2D sampler2d;"+
                        "varying mediump vec2 varUV;"+
                        "varying mediump vec4 varColor;"+
                        "void main() {" +
                        "  gl_FragColor = varColor;" +
                        "  gl_FragColor = texture2D(sampler2d,varUV);"+
            "}";
* */
public class Triangle {
 public final String vertexShaderCode =
    "attribute vec4 vPosition;" +
    "attribute vec4 vColor;" +
    "attribute vec2 vUV;" +
    "varying mediump vec2 varUV;"+
    "varying mediump vec4 varColor;"+
    "void main() {" +
    "  varColor = vColor;"+
    "  varUV = vUV.st;"+
    "  gl_Position = vPosition;" +
    "}";

public final String fragmentShaderCode =
    "precision mediump float;" +
    "uniform sampler2D sampler2d;"+
    "varying mediump vec2 varUV;"+
    "varying mediump vec4 varColor;"+
    "void main() {" +
            "  gl_FragColor = texture2D(sampler2d,varUV);"+
    "}";

    private int loadShader(int type, String shaderCode){
        int err = 0;
        int shader = GLES20.glCreateShader(type);
        err = EGL14.eglGetError();
        if (err != EGL14.EGL_SUCCESS)  return 0;

        GLES20.glShaderSource(shader, shaderCode);
        if (EGL14.eglGetError() != EGL14.EGL_SUCCESS)  return 0;

        GLES20.glCompileShader(shader);
        return shader;
    }

    private static String LOGTAG = "ORE";

    public static void checkError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(LOGTAG, op + ": glError 0x" + Integer.toHexString(error));
        }
    }
    private  int shaderProgram;
    public Triangle() {
    }

    int[] m_nIchimatsuTexture = new int[1];
    int[] m_nHogeTexture = new int[1];

    public void loadGLTexture(Context context){
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.texaxis);
        //Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.r1);
        Bitmap bitmap01 = Bitmap.createScaledBitmap(bitmap, 512, 512, false);
        try {
            bitmap = bitmap01;

        } finally {
        }

        glGenTextures(1, m_nHogeTexture, 0);
        glBindTexture(GL_TEXTURE_2D, m_nHogeTexture[0]);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);

    }
    
    //やり方がわからない。
    /*
    void init_texture()
    {
        final int TEX_SIZE = 256;
        byte[] pTexData = new byte[TEX_SIZE*TEX_SIZE*4];
        for (int i = 0; i < TEX_SIZE; i++) {
            for (int j = 0; j < TEX_SIZE; j++) {
                // Fills the data with a fancy pattern
                //int col = (255 << 24) + ((255 - j * 2) << 16) + ((255 - i) << 8) + (255 - i * 2);
                int col1 = 255;
                int col2 = (255 - j * 2);
                int col3 = (255 - i);
                int col4 = (255 - i * 2);

                if(( ((i * j) / 8) % 2) != 0){
                    //   col = (int) (255 << 24) + (255 << 16) + (0 << 8) + (255);
                    col1 = 255;
                    col2 = 255;
                    col3 = 0;
                    col4 = 255;
                }
                //pTexData[j * TEX_SIZE + i] = col;
                int index = (i*TEX_SIZE + j)*4;
                pTexData[index + 3] = (byte)col1;
                pTexData[index + 2] = (byte)col2;
                pTexData[index + 1] = (byte)col3;
                pTexData[index + 0] = (byte)col4;
            }
        }

        //for (int i = 0; i < TEX_SIZE*TEX_SIZE*4; i++) pTexData[i] = (byte)0xff;

        GLES20.glGenTextures(1, m_nIchimatsuTexture,0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, m_nIchimatsuTexture[0]);

        GLES20.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        GLES20.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        checkError("glTexParameterf");
        {
            Bitmap bitmap = BitmapFactory.decodeByteArray(pTexData, 0, pTexData.length);
            Bitmap bitmap01 = Bitmap.createScaledBitmap(bitmap, TEX_SIZE, TEX_SIZE, false);

            try {
                bitmap = bitmap01;
            } catch (Exception e) {
                e.printStackTrace();
            }

            ByteBuffer bb = ByteBuffer.allocate(TEX_SIZE * TEX_SIZE);
            bb.wrap(pTexData);


            GLES20.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, bb);
            GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
            checkError("glTexImage2D");
        }

    }*/

    public int Init(){
        int err = 0;
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        shaderProgram = GLES20.glCreateProgram();

        err = GLES20.glGetError();
        if (err != GLES20.GL_NO_ERROR)  return err;

        GLES20.glAttachShader(shaderProgram, vertexShader);
        GLES20.glAttachShader(shaderProgram, fragmentShader);
        GLES20.glLinkProgram(shaderProgram);
        err = GLES20.glGetError();
        if (err != GLES20.GL_NO_ERROR)  return err;

        int[] status = new int[1];
        glGetProgramiv(shaderProgram, GL_LINK_STATUS, status, 0);
        if (status[0] == GL_FALSE) {
            String msz = glGetProgramInfoLog(shaderProgram);
            Log.e("sample", glGetProgramInfoLog(shaderProgram));
            glDeleteProgram(shaderProgram);
        }

      //  init_texture();

        return GLES20.GL_NO_ERROR;
    }

    public void draw(){
        int err = 0;
        //if( shaderProgram == 0 ) return;
        GLES20.glUseProgram(shaderProgram);
        err = GLES20.glGetError();
        if (err != GLES20.GL_NO_ERROR)  return ;


        glBindTexture(GL_TEXTURE_2D, m_nHogeTexture[0]);
        glActiveTexture((m_nHogeTexture[0]));



        glUniform1i(glGetUniformLocation(shaderProgram, "sampler2d"), 0);

        int positionAttrib = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
        GLES20.glEnableVertexAttribArray(positionAttrib);



        if( true ) {
            // xyz, rgba,

            float vertices[] = {
                    -0.6f, -0.4f, 0.0f, 1.0f,
                     0.6f, -0.4f, 0.0f, 1.0f,
                    -0.6f, 0.4f, 0.0f, 1.0f,
                     0.6f, 0.4f, 0.0f, 1.0f,
            };

            ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer vertexBuffer = bb.asFloatBuffer();
            vertexBuffer.put(vertices);
            vertexBuffer.position(0);
            int stride = 0;
            GLES20.glVertexAttribPointer(positionAttrib, 4, GLES20.GL_FLOAT, false, stride, vertexBuffer);
        }

        boolean enableColor = true;
        int colorAttrib = 0;
        if( enableColor ) {
            float colors[] = {
                    1.0f, 0.0f, 0.0f, 1.0f,
                    0.0f, 1.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f,
            };
            colorAttrib = GLES20.glGetAttribLocation(shaderProgram, "vColor");
            GLES20.glEnableVertexAttribArray(colorAttrib);

            ByteBuffer bb2 = ByteBuffer.allocateDirect(colors.length * 4);
            bb2.order(ByteOrder.nativeOrder());
            FloatBuffer colorBuffer = bb2.asFloatBuffer();
            colorBuffer.put(colors);
            colorBuffer.position(0);
            int stride = 0;
            glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, false, stride, colorBuffer);
        }

        boolean enableTexture = true;
        int uvAttrib = 0;
        if( enableTexture ) {
            float uvs[] = {
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    0.0f, 0.0f,
                    1.0f, 0.0f,
            };
            uvAttrib = GLES20.glGetAttribLocation(shaderProgram, "vUV");
            GLES20.glEnableVertexAttribArray(uvAttrib);
            checkError("glEnableVertexAttribArray");

            ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer uvBuffer = bb.asFloatBuffer();
            uvBuffer.put(uvs);
            uvBuffer.position(0);
            int stride = 0;
            glVertexAttribPointer(uvAttrib, 2, GL_FLOAT, false, stride, uvBuffer);
            checkError("glVertexAttribPointer");
        }

        //GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);


        checkError("glDrawArrays");

        GLES20.glDisableVertexAttribArray(positionAttrib);
        if( enableColor ) GLES20.glDisableVertexAttribArray(colorAttrib);
        if( enableTexture ) GLES20.glDisableVertexAttribArray(uvAttrib);
        checkError("glDisableVertexAttribArray");

    }
}

```