【OpenGL】OpenGL编程常用类

  • BufferUtils
  • TextureUtils
  • Shader
  • GLSurfaceView
  • Renderer
  • Model
  • GLBitmap
  • GLUnfoldBitmap



BufferUtils

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;


public class BufferUtils {

    public static FloatBuffer newFloatBuffer (int numFloats) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4);
        buffer.order(ByteOrder.nativeOrder());
        return buffer.asFloatBuffer();
    }

    public static DoubleBuffer newDoubleBuffer (int numDoubles) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(numDoubles * 8);
        buffer.order(ByteOrder.nativeOrder());
        return buffer.asDoubleBuffer();
    }

    public static ByteBuffer newByteBuffer (int numBytes) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes);
        buffer.order(ByteOrder.nativeOrder());
        return buffer;
    }

    public static ShortBuffer newShortBuffer (int numShorts) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2);
        buffer.order(ByteOrder.nativeOrder());
        return buffer.asShortBuffer();
    }

    public static CharBuffer newCharBuffer (int numChars) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(numChars * 2);
        buffer.order(ByteOrder.nativeOrder());
        return buffer.asCharBuffer();
    }

    public static IntBuffer newIntBuffer(int numInts) {
        ByteBuffer buffer = ByteBuffer.allocate(numInts * 4);
        buffer.order(ByteOrder.nativeOrder());
        return buffer.asIntBuffer();
    }

    public static LongBuffer newLongBuffer(int numLongs) {
        ByteBuffer buffer = ByteBuffer.allocate(numLongs * 8);
        buffer.order(ByteOrder.nativeOrder());
        return buffer.asLongBuffer();
    }
}

TextureUtils

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

public class TextureUtils {

    public static int loadTexture(Context context, int drawableID) {

        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableID);

        int textureName = loadTexture(bitmap);

        bitmap.recycle();

        return textureName;
    }

    public static int loadTexture(Bitmap bitmap) {

        int textureName[] = new int[1];
        GLES20.glGenTextures(1, textureName, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureName[0]);

        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);

        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

        return textureName[0];
    }
}



Shader

import android.content.Context;
import android.content.res.AssetManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;

public class ShaderUtils {

    public static String readShaderFileFromRawResource(final Context context, final int resourceId)
    {
        final InputStream inputStream = context.getResources().openRawResource(resourceId);
        final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        String nextLine;
        final StringBuilder body = new StringBuilder();

        try
        {
            while ((nextLine = bufferedReader.readLine()) != null)
            {
                body.append(nextLine);
                body.append("\n");
            }
        }
        catch(IOException e)
        {
            return null;
        }

        return body.toString();
    }

    public static String readShaderFileFromFilePath(final Context context, final String filePath)
    {
        try
        {
            AssetManager assetManager = context.getAssets();
            InputStream ims = assetManager.open(filePath);

            String re = convertStreamToString(ims);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return "";
    }

    public static String convertStreamToString(InputStream is)
    {
        Scanner s = new Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }
}

import android.graphics.Color;
import android.graphics.PointF;
import android.opengl.GLES20;
import android.renderscript.Float2;
import android.renderscript.Float3;
import android.renderscript.Float4;
import android.renderscript.Matrix3f;
import android.renderscript.Matrix4f;

import java.nio.Buffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;


public class ShaderProgram {
    private String vertexShaderSource;
    private String fragmentShaderSource;

    private int vertexShaderHandle;
    private int fragmentShaderHandle;
    private int programHandle;
    private String log = "";
    private boolean isCompiled;

    private HashMap<String, Integer> uniforms = new HashMap<>();
    private HashMap<String, Integer> attributes = new HashMap<>();


    public ShaderProgram(String vertexShader, String fragmentShader) {
        if(vertexShader == null) throw new IllegalArgumentException("vertex shader must not be null");
        if(fragmentShader == null) throw new IllegalArgumentException("fragment shader must not be null");

        vertexShaderSource = vertexShader;
        fragmentShaderSource = fragmentShader;

        compileShaders(vertexShader, fragmentShader);

        if(isCompiled()) {
            fetchAttributes();
            fetchUniforms();
        }
    }

    // is this valid shader program?
    public boolean isValid() {
        return isCompiled;
    }

    // start to use shader program
    public void begin() {
        GLES20.glUseProgram(programHandle);
    }

    // end of using shader program
    public void end() {
        GLES20.glUseProgram(0);
    }

    // destory the shader program
    public void destroy() {
        GLES20.glUseProgram(0);
        GLES20.glDeleteShader(vertexShaderHandle);
        GLES20.glDeleteShader(fragmentShaderHandle);
        GLES20.glDeleteProgram(programHandle);
    }

    private void compileShaders(String vertexShader, String fragmentShader) {
        vertexShaderHandle = loadShader(GLES20.GL_VERTEX_SHADER, vertexShader);
        fragmentShaderHandle = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);

        if(vertexShaderHandle == -1 || fragmentShaderHandle == -1) {
            isCompiled = false;
            return;
        }

        programHandle = linkProgram(createProgram());
        if(programHandle == -1) {
            isCompiled = false;
            return;
        }

        isCompiled = true;
    }

    private int createProgram() {
        int program = GLES20.glCreateProgram();
        return program != 0 ? program : -1;
    }

    private int linkProgram(int program) {
        if(program == -1)
            return -1;

        GLES20.glAttachShader(program, vertexShaderHandle);
        GLES20.glAttachShader(program, fragmentShaderHandle);
        GLES20.glLinkProgram(program);

        int[] linked = new int[1];
        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linked, 0);
        if(linked[0] == GLES20.GL_FALSE) {
            String infoLog = GLES20.glGetProgramInfoLog(program);
            log += infoLog;
            GLES20.glDeleteProgram(program);
            return  -1;
        }
        return program;
    }

    private int loadShader(int shaderType, String shaderCode) {
        int shader = GLES20.glCreateShader(shaderType);
        if(shader == 0)
            return -1;

        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        int[] compiled = new int[1];
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);

        if(compiled[0] == GLES20.GL_FALSE) {
            String infoLog = GLES20.glGetShaderInfoLog(shader);
            log += infoLog;
            GLES20.glDeleteShader(shader);
            return -1;
        }
        return shader;
    }

    public String getLog() {
        if(isCompiled) {
            log = GLES20.glGetProgramInfoLog(programHandle);
            return log;
        } else {
            return log;
        }
    }

    public boolean isCompiled() {
        return isCompiled;
    }

    private int fetchAttributeLocation(String name) {

        int location = attributes.get(name);
        if(location == -1) {
            location = GLES20.glGetAttribLocation(programHandle, name);
            if(location != -1) {
                attributes.put(name, location);
            }
        }
        return location;
    }

    private int fetchUniformLocation(String name) {
        int location = uniforms.get(name);
        if(location == -1) {
            location = GLES20.glGetUniformLocation(programHandle, name);
            if(location != -1) {
                uniforms.put(name, location);
            }
        }
        return location;
    }


    private void fetchAttributes() {

        attributes.clear();

        IntBuffer params = IntBuffer.allocate(1);
        IntBuffer type = IntBuffer.allocate(1);
        GLES20.glGetProgramiv(programHandle, GLES20.GL_ACTIVE_ATTRIBUTES, params);
        int numAttributes = params.get(0);

        for(int i=0; i<numAttributes; i++) {
            params.compact();
            params.put(0, 1);
            type.clear();
            String name = GLES20.glGetActiveAttrib(programHandle, i, params, type);
            int location = GLES20.glGetAttribLocation(programHandle, name);
            attributes.put(name, location);
        }
    }

    private void fetchUniforms() {

        uniforms.clear();

        IntBuffer params = IntBuffer.allocate(1);
        IntBuffer type = IntBuffer.allocate(1);
        GLES20.glGetProgramiv(programHandle, GLES20.GL_ACTIVE_UNIFORMS, params);
        int numUniform = params.get(0);

        for(int i=0; i<numUniform; i++) {
            params.compact();
            params.put(0, 1);
            type.clear();
            String name = GLES20.glGetActiveUniform(programHandle, i, params, type);
            int location = GLES20.glGetUniformLocation(programHandle, name);
            uniforms.put(name, location);
        }
    }

    /**
     * @param name name the name of the uniform
     * @return the location of the uniform or -1.
     */
    public int getUniformLocation(String name) {
        return uniforms.get(name) == null ? -1 : uniforms.get(name);
    }

    /**
     * @param name the name of the attribute
     * @return the location of the attribute or -1.
     */
    public int getAttributeLocation(String name) {
        return attributes.get(name) == null ? -1 : attributes.get(name);
    }

    /** @param name the name of the uniform
     * @return whether the uniform is available in the shader */
    public boolean hasUniform(String name) {
        return uniforms.containsKey(name);
    }

    /** @param name the name of the attribute
     * @return whether the attribute is available in the shader */
    public boolean hasAttribute(String name) {
        return attributes.containsKey(name);
    }


    /***********************************************************************************************
     * Set Uniforms and Attributes
     ***********************************************************************************************/

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value the value */
    public void setUniformi(String name, int value) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform1i(location, value);
    }

    public void setUniformi(int location, int value) {
        if(location == -1) return;
        GLES20.glUniform1i(location, value);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value1 the first value
     * @param value2 the second value */
    public void setUniformi (String name, int value1, int value2) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform2i(location, value1, value2);
    }

    public void setUniformi (int location, int value1, int value2) {
        if(location == -1) return;
        GLES20.glUniform2i(location, value1, value2);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value1 the first value
     * @param value2 the second value
     * @param value3 the third value */
    public void setUniformi (String name, int value1, int value2, int value3) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform3i(location, value1, value2, value3);

    }

    public void setUniformi (int location, int value1, int value2, int value3) {
        if(location != -1)
            GLES20.glUniform3i(location, value1, value2, value3);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value1 the first value
     * @param value2 the second value
     * @param value3 the third value
     * @param value4 the fourth value */
    public void setUniformi (String name, int value1, int value2, int value3, int value4) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform4i(location, value1, value2, value3, value4);
    }

    public void setUniformi (int location, int value1, int value2, int value3, int value4) {
        if(location == -1) return;
        GLES20.glUniform4i(location, value1, value2, value3, value4);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value the value */
    public void setUniformf (String name, float value) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform1f(location, value);
    }

    public void setUniformf (int location, float value) {
        if(location == -1) return;
        GLES20.glUniform1f(location, value);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value1 the first value
     * @param value2 the second value */
    public void setUniformf (String name, float value1, float value2) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform2f(location, value1, value2);
    }

    public void setUniformf (int location, float value1, float value2) {
        if(location == -1) return;
        GLES20.glUniform2f(location, value1, value2);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value1 the first value
     * @param value2 the second value
     * @param value3 the third value */
    public void setUniformf (String name, float value1, float value2, float value3) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform3f(location, value1, value2, value3);
    }

    public void setUniformf (int location, float value1, float value2, float value3) {
        if(location == -1) return;
        GLES20.glUniform3f(location, value1, value2, value3);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param value1 the first value
     * @param value2 the second value
     * @param value3 the third value
     * @param value4 the fourth value */
    public void setUniformf (String name, float value1, float value2, float value3, float value4) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform4f(location, value1, value2, value3, value4);
    }

    public void setUniformf (int location, float value1, float value2, float value3, float value4) {
        if(location == -1) return;
        GLES20.glUniform4f(location, value1, value2, value3, value4);
    }

    public void setUniform1fv (String name, float[] values, int offset, int length) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform1fv(location, length, values, offset);
    }

    public void setUniform1fv (int location, float[] values, int offset, int length) {
        if(location == -1) return;
        GLES20.glUniform1fv(location, length, values, offset);
    }

    public void setUniform2fv (String name, float[] values, int offset, int length) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform2fv(location, length / 2, values, offset);
    }

    public void setUniform2fv (int location, float[] values, int offset, int length) {
        if(location == -1) return;
        GLES20.glUniform2fv(location, length / 2, values, offset);
    }

    public void setUniform3fv (String name, float[] values, int offset, int length) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform3fv(location, length / 3, values, offset);
    }

    public void setUniform3fv (int location, float[] values, int offset, int length) {
        if(location == -1) return;
        GLES20.glUniform3fv(location, length / 3, values, offset);
    }

    public void setUniform4fv (String name, float[] values, int offset, int length) {
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniform4fv(location, length / 4, values, offset);
    }

    public void setUniform4fv (int location, float[] values, int offset, int length) {
        if(location == -1) return;
        GLES20.glUniform4fv(location, length / 4, values, offset);
    }

    /** Sets the uniform matrix with the given name.
     *
     * @param name the name of the uniform
     * @param matrix the matrix */
    public void setUniformMatrix (String name, Matrix4f matrix) {
        setUniformMatrix(name, matrix, false);
    }

    /** Sets the uniform matrix with the given name.
     *
     * @param name the name of the uniform
     * @param matrix the matrix
     * @param transpose whether the matrix should be transposed */
    public void setUniformMatrix (String name, Matrix4f matrix, boolean transpose) {
        setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
    }

    public void setUniformMatrix (int location, Matrix4f matrix) {
        setUniformMatrix(location, matrix, false);
    }

    public void setUniformMatrix (int location, Matrix4f matrix, boolean transpose) {
        if(location == -1) return;
        GLES20.glUniformMatrix4fv(location, 1, transpose, matrix.getArray(), 0);
    }


    /** Sets the uniform matrix with the given name.
     *
     * @param name the name of the uniform
     * @param matrix the matrix */
    public void setUniformMatrix (String name, Matrix3f matrix) {
        setUniformMatrix(name, matrix, false);
    }

    /** Sets the uniform matrix with the given name.
     *
     * @param name the name of the uniform
     * @param matrix the matrix
     * @param transpose whether the uniform matrix should be transposed */
    public void setUniformMatrix (String name, Matrix3f matrix, boolean transpose) {
        setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
    }

    public void setUniformMatrix (int location, Matrix3f matrix) {
        setUniformMatrix(location, matrix, false);
    }

    public void setUniformMatrix (int location, Matrix3f matrix, boolean transpose) {
        if(location == -1) return;
        GLES20.glUniformMatrix3fv(location, 1, transpose, matrix.getArray(), 0);
    }

    /** Sets an array of uniform matrices with the given name.
     *
     * @param name the name of the uniform
     * @param buffer buffer containing the matrix data
     * @param transpose whether the uniform matrix should be transposed */
    public void setUniformMatrix3fv (String name, FloatBuffer buffer, int count, boolean transpose) {
        buffer.position(0);
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniformMatrix3fv(location, count, transpose, buffer);
    }

    /** Sets an array of uniform matrices with the given name.
     *
     * @param name the name of the uniform
     * @param buffer buffer containing the matrix data
     * @param transpose whether the uniform matrix should be transposed */
    public void setUniformMatrix4fv (String name, FloatBuffer buffer, int count, boolean transpose) {
        buffer.position(0);
        int location = fetchUniformLocation(name);
        if(location == -1) return;
        GLES20.glUniformMatrix4fv(location, count, transpose, buffer);
    }

    public void setUniformMatrix4fv (int location, float[] values, int offset, int length) {
        if(location == -1) return;
        GLES20.glUniformMatrix4fv(location, length / 16, false, values, offset);
    }

    public void setUniformMatrix4fv (String name, float[] values, int offset, int length) {
        setUniformMatrix4fv(fetchUniformLocation(name), values, offset, length);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param vector x and y as the first and second values respectively */
    public void setUniformf (String name, Float2 vector) {
        setUniformf(name, vector.x, vector.y);
    }

    public void setUniformf (int location, Float2 vector) {
        setUniformf(location, vector.x, vector.y);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param vector x, y and z as the first, second and third values respectively */
    public void setUniformf (String name, Float3 vector) {
        setUniformf(name, vector.x, vector.y, vector.z);
    }

    public void setUniformf (int location, Float3 vector) {
        setUniformf(location, vector.x, vector.y, vector.z);
    }

    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param vector x, y, z and w as the first, second, third and forth values respectively */
    public void setUniformf (String name, Float4 vector) {
        setUniformf(name, vector.x, vector.y, vector.z, vector.w);
    }

    public void setUniformf (int location, Float4 vector) {
        setUniformf(location, vector.x, vector.y, vector.z, vector.w);
    }


    /** Sets the uniform with the given name.
     *
     * @param name the name of the uniform
     * @param color r, g, b and a as the first through fourth values respectively */
    public void setUniformColor (String name, int color) {
        setUniformf(name, Color.red(color) / 255.0f, Color.green(color) / 255.0f, Color.blue(color) / 255.0f, Color.alpha(color) / 255.0f);
    }

    public void setUniformf (int location, int color) {
        setUniformf(location, Color.red(color) / 255.0f, Color.green(color) / 255.0f, Color.blue(color) / 255.0f, Color.alpha(color) / 255.0f);
    }

    /** Sets the vertex attribute with the given name.
     *
     * @param name the attribute name
     * @param size the number of components, must be >= 1 and <= 4
     * @param type the type, must be one of GL20.GL_BYTE, GL20.GL_UNSIGNED_BYTE, GL20.GL_SHORT,
     *           GL20.GL_UNSIGNED_SHORT,GL20.GL_FIXED, or GL20.GL_FLOAT. GL_FIXED will not work on the desktop
     * @param normalize whether fixed point data should be normalized. Will not work on the desktop
     * @param stride the stride in bytes between successive attributes
     * @param buffer the buffer containing the vertex attributes. */
    public void setVertexAttribute (String name, int size, int type, boolean normalize, int stride, Buffer buffer) {
        int location = fetchAttributeLocation(name);
        if (location == -1) return;
        GLES20.glVertexAttribPointer(location, size, type, normalize, stride, buffer);
    }

    public void setVertexAttribute (int location, int size, int type, boolean normalize, int stride, Buffer buffer) {
        if(location == -1) return;
        GLES20.glVertexAttribPointer(location, size, type, normalize, stride, buffer);
    }

    /** Sets the vertex attribute with the given name.
     *
     * @param name the attribute name
     * @param size the number of components, must be >= 1 and <= 4
     * @param type the type, must be one of GL20.GL_BYTE, GL20.GL_UNSIGNED_BYTE, GL20.GL_SHORT,
     *           GL20.GL_UNSIGNED_SHORT,GL20.GL_FIXED, or GL20.GL_FLOAT. GL_FIXED will not work on the desktop
     * @param normalize whether fixed point data should be normalized. Will not work on the desktop
     * @param stride the stride in bytes between successive attributes
     * @param offset byte offset into the vertex buffer object bound to GL20.GL_ARRAY_BUFFER. */
    public void setVertexAttribute (String name, int size, int type, boolean normalize, int stride, int offset) {
        int location = fetchAttributeLocation(name);
        if (location == -1)
            return;
        GLES20.glVertexAttribPointer(location, size, type, normalize, stride, offset);
    }

    public void setVertexAttribute (int location, int size, int type, boolean normalize, int stride, int offset) {
        if(location == -1) return;
        GLES20.glVertexAttribPointer(location, size, type, normalize, stride, offset);
    }

    /** Disables the vertex attribute with the given name
     *
     * @param name the vertex attribute name */
    public void disableVertexAttribute (String name) {
        int location = fetchAttributeLocation(name);
        if (location == -1) return;
        GLES20.glDisableVertexAttribArray(location);
    }

    public void disableVertexAttribute (int location) {
        if(location == -1) return;
        GLES20.glDisableVertexAttribArray(location);
    }

    /** Enables the vertex attribute with the given name
     *
     * @param name the vertex attribute name */
    public void enableVertexAttribute (String name) {
        int location = fetchAttributeLocation(name);
        if (location == -1) return;
        GLES20.glEnableVertexAttribArray(location);
    }

    public void enableVertexAttribute (int location) {
        if(location == -1) return;
        GLES20.glEnableVertexAttribArray(location);
    }

    /** Sets the given attribute
     *
     * @param name the name of the attribute
     * @param value1 the first value
     * @param value2 the second value
     * @param value3 the third value
     * @param value4 the fourth value */
    public void setAttributef (String name, float value1, float value2, float value3, float value4) {
        int location = fetchAttributeLocation(name);
        if(location == -1) return;
        GLES20.glVertexAttrib4f(location, value1, value2, value3, value4);
    }

    public void setAttributef (String name, float value1, float value2, float value3) {
        int location = fetchAttributeLocation(name);
        if(location == -1) return;
        GLES20.glVertexAttrib3f(location, value1, value2, value3);
    }

    public void setAttributef (String name, float value1, float value2) {
        int location = fetchAttributeLocation(name);
        if(location == -1) return;
        GLES20.glVertexAttrib2f(location, value1, value2);
    }
}


GLSurfaceView

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;


public class OGLView extends GLSurfaceView {

    public OGLView(Context context) {
        super(context);
        init();
    }

    public OGLView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        // use opengl es 2.0
        setEGLContextClientVersion(2);

        // store opengl context
        setPreserveEGLContextOnPause(true);

        // set renderer
        setRenderer(new OGLRenderer(getContext()));
    }

}
public class Square extends Model {

    static final float squareCoords[] = {
             1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top left
             1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,// bottom left
            -1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,// bottom right
            -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,// top right
    };

    static final short indices[] = {
            0, 1, 2,
            2, 3, 0
    };

    public Square(ShaderProgram shader) {
        super("square", shader, squareCoords, indices);
    }

}
Renderer

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.renderscript.Float3;
import android.renderscript.Matrix4f;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import kr.pe.burt.android.projectiontransformation.glkit.ShaderProgram;
import kr.pe.burt.android.projectiontransformation.glkit.ShaderUtils;



public class OGLRenderer implements GLSurfaceView.Renderer {

    private static final float ONE_SEC = 1000.0f; // 1 second

    private Context context;
    private Square square;
    private long lastTimeMillis = 0L;

    public OGLRenderer(Context context) {
        this.context = context;
    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

        ShaderProgram shader = new ShaderProgram(
                ShaderUtils.readShaderFileFromRawResource(context, R.raw.simple_vertex_shader),
                ShaderUtils.readShaderFileFromRawResource(context, R.raw.simple_fragment_shader)
        );

        square = new Square(shader);
        square.setPosition(new Float3(0.0f, 0.0f, 0.0f));
        lastTimeMillis = System.currentTimeMillis();
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int w, int h) {
        GLES20.glViewport(0, 0, w, h);

        if(square != null) {
            Matrix4f perspective = new Matrix4f();
            perspective.loadPerspective(85.0f, (float)w / (float)h, 1.0f, -150.0f);
            square.setProjection(perspective);
        }
    }

    @Override
    public void onDrawFrame(GL10 gl10) {
        GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        long currentTimeMillis = System.currentTimeMillis();
        updateWithDelta(currentTimeMillis - lastTimeMillis);
        lastTimeMillis = currentTimeMillis;
    }

    public void updateWithDelta(long dt) {

        final float secsPerMove = 2.0f * ONE_SEC;
        float movement = (float)(Math.sin(System.currentTimeMillis() * 2 * Math.PI / secsPerMove));

        // move camera
        Matrix4f camera = new Matrix4f();
        camera.translate(0.0f, -1.0f * movement, -15.0f);
        camera.rotate(360.0f * movement, 0.0f, 0.0f, 1.0f);
        camera.scale(movement, movement, movement);
        square.setCamera(camera);
        square.draw(dt);
    }

}
Model

import android.opengl.GLES20;
import android.renderscript.Float3;
import android.renderscript.Matrix4f;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Arrays;

import kr.pe.burt.android.projectiontransformation.glkit.BufferUtils;
import kr.pe.burt.android.projectiontransformation.glkit.ShaderProgram;


/**
 * Created by burt on 2016. 6. 22..
 */
public class Model {
    private static final int COORDS_PER_VERTEX = 3;
    private static final int COLORS_PER_VERTEX = 4;
    private static final int SIZE_OF_FLOAT = 4;
    private static final int SIZE_OF_SHORT = 2;

    private ShaderProgram shader;
    private String name;
    private float vertices[];
    private short indices[];


    private FloatBuffer vertexBuffer;
    private int vertexBufferId;
    private int vertexStride;

    private ShortBuffer indexBuffer;
    private int indexBufferId;

    // ModelView Transformation
    protected Float3 position = new Float3(0f, 0f, 0f);
    protected float rotationX  = 0.0f;
    protected float rotationY  = 0.0f;
    protected float rotationZ  = 0.0f;
    protected float scale      = 1.0f;
    protected Matrix4f camera  = new Matrix4f();
    protected Matrix4f projection = new Matrix4f();

    public Model(String name, ShaderProgram shader, float[] vertices, short[] indices) {
        this.name = name;
        this.shader = shader;
        this.vertices = Arrays.copyOfRange(vertices, 0, vertices.length);
        this.indices = Arrays.copyOfRange(indices, 0, indices.length);

        setupVertexBuffer();
        setupIndexBuffer();
    }

    public void setPosition(Float3 position) {
        this.position = position;
    }

    public void setRotationX(float rotationX) {
        this.rotationX = rotationX;
    }

    public void setRotationY(float rotationY) {
        this.rotationY = rotationY;
    }

    public void setRotationZ(float rotationZ) {
        this.rotationZ = rotationZ;
    }

    public void setScale(float scale) {
        this.scale = scale;
    }

    private void setupVertexBuffer() {
        vertexBuffer = BufferUtils.newFloatBuffer(vertices.length);
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);

        IntBuffer buffer = IntBuffer.allocate(1);
        GLES20.glGenBuffers(1, buffer);
        vertexBufferId = buffer.get(0);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.length * SIZE_OF_FLOAT, vertexBuffer, GLES20.GL_STATIC_DRAW);
        vertexStride = (COORDS_PER_VERTEX + COLORS_PER_VERTEX) * SIZE_OF_FLOAT; // 4 bytes per vertex
    }

    private void setupIndexBuffer() {
        // initialize index short buffer for index
        indexBuffer = BufferUtils.newShortBuffer(indices.length);
        indexBuffer.put(indices);
        indexBuffer.position(0);

        IntBuffer buffer = IntBuffer.allocate(1);
        GLES20.glGenBuffers(1, buffer);
        indexBufferId = buffer.get(0);
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
        GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.length * SIZE_OF_SHORT, indexBuffer, GLES20.GL_STATIC_DRAW);
    }

    public Matrix4f modelMatrix() {
        Matrix4f mat = new Matrix4f(); // make a new identitiy 4x4 matrix
        mat.translate(position.x, position.y, position.z);
        mat.rotate(rotationX, 1.0f, 0.0f, 0.0f);
        mat.rotate(rotationY, 0.0f, 1.0f, 0.0f);
        mat.rotate(rotationZ, 0.0f, 0.0f, 1.0f);
        mat.scale(scale, scale, scale);
        return mat;
    }

    public void setCamera(Matrix4f mat) {
        camera.load(mat);
    }

    public void setProjection(Matrix4f mat) {
        projection.load(mat);
    }

    public void draw(long dt) {

        shader.begin();

        camera.multiply(modelMatrix());
        shader.setUniformMatrix("u_ProjectionMatrix", projection);
        shader.setUniformMatrix("u_ModelViewMatrix",  camera);
        shader.enableVertexAttribute("a_Position");
        shader.setVertexAttribute("a_Position", COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, 0);

        shader.enableVertexAttribute("a_Color");
        shader.setVertexAttribute("a_Color", COLORS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, COORDS_PER_VERTEX * SIZE_OF_FLOAT);

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
        GLES20.glDrawElements(
                GLES20.GL_TRIANGLES,        // mode
                indices.length,             // count
                GLES20.GL_UNSIGNED_SHORT,   // type
                0);                         // offset

        shader.disableVertexAttribute("a_Position");
        shader.disableVertexAttribute("a_Color");

        shader.end();
    }
}

GLBitmap:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;

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

import javax.microedition.khronos.opengles.GL10;

/**
 * 参考:
 * http://blog.csdn.net/nupt123456789/article/details/40375731
 * http://blog.piasy.com/2016/06/07/Open-gl-es-android-2-part-1/
 * Created by Administrator on 2016/9/23.
 */

public class GLBitmap {
    //程式(Program):一个OpenGL ES对象,包含了你希望用来绘制一个或更多图形所要用到的着色器。
    private final int mProgram;

    //顶点着色器(Vertex Shader):用来渲染形状顶点的OpenGL ES代码。
    private final String vertexShaderCode =
            // This matrix member variable (uMVPMatrix) provides a hook to manipulate the coordinates of the objects that use this vertex shader
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "attribute vec2 a_texCoord;" +//外部传入
                    "varying vec2 v_texCoord;" +//传到片段着色器中
                    "void main() {" +
                    // the matrix must be included as a modifier of gl_Position
                    // Note that the uMVPMatrix factor *must be first* in order for the matrix multiplication product to be correct.uMVPMatrix左乘才是对的
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "  v_texCoord = a_texCoord;" +
                    "}";
    // Use to access and set the view transformation 顶点着色器中的mMVPMatrix
    private int mMVPMatrixHandle;
    private int mPositionHandle;
    private int mTexCoordHandle;

    //片段着色器(Fragment Shader):使用颜色或纹理渲染形状表面的OpenGL ES代码。
    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "varying vec2 v_texCoord;" +
                    "uniform sampler2D s_texture;" +
                    "void main() {" +
                    "  gl_FragColor =texture2D( s_texture, v_texCoord );" +
                    "}";
    private int mTexSamplerHandle;

    private FloatBuffer vertexBuffer; // buffer holding the vertexes
    private float vertexes[] = { // in counterclockwise order:
            1.0f, 1.0f, 0.0f, //  top right
            -1.0f, 1.0f, 0.0f, //  top left
            -1.0f, -1.0f, 0.0f, //  bottom left
            1.0f, -1.0f, 0.0f //  bottom right
    };
    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    private ShortBuffer drawListBuffer;
    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertexes

    //指定截取纹理的哪一部分绘制到图形上:
    private FloatBuffer textureBuffer; // buffer holding the texture coordinates
    private float texture[] = {
            // Mapping coordinates for the vertexes
            1.0f, 0.0f, // bottom right (V3)
            0.0f, 0.0f, // bottom left (V1)
            0.0f, 1.0f, // top left (V2)
            1.0f, 1.0f // top right (V4)

    };


    public GLBitmap() {
        // initialize vertexBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertexes.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        vertexBuffer = byteBuffer.asFloatBuffer();
        vertexBuffer.put(vertexes);
        vertexBuffer.position(0);

        //textureBuffer
        byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        textureBuffer = byteBuffer.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.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);


        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);

        // create empty OpenGL ES Program
        mProgram = GLES20.glCreateProgram();
        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, vertexShader);
        // add the fragment shader to program
        GLES20.glAttachShader(mProgram, fragmentShader);
        // creates OpenGL ES program executables
        GLES20.glLinkProgram(mProgram);

    }

    /** The texture pointer */
    private int[] textures = new int[1];
    public void loadGLTexture(GL10 unused, Context context) {
//        我们需要先通过 glGenTextures 创建纹理,再通过 glActiveTexture 激活指定编号的纹理,再通过 glBindTexture 将新建的纹理和编号绑定起来。我们可以对图片纹理设置一系列参数,例如裁剪策略、缩放策略,这部分更详细的介绍,建议看看《OpenGL ES 2 for Android A Quick - Start Guide (2013)》这本书,里面有很详细的讲解。最后,我们通过 texImage2D 把图片数据拷贝到纹理中。

        // loading texture
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.pic3);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        // ...and bind it to our array
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        // create GL_LINEAR filtered texture
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameteri(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);
        // Use Android GLUtils to specify a two-dimensional texture image from our bitmap
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }

    public void draw(float[] mvpMatrix) {
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram, "s_texture");

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        GLES20.glUseProgram(mProgram);

        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride,vertexBuffer);

        GLES20.glEnableVertexAttribArray(mTexCoordHandle);
        GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0,textureBuffer);

        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
        GLES20.glUniform1i(mTexSamplerHandle, 0);

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        GLES20.glDisableVertexAttribArray(mPositionHandle);
        GLES20.glDisableVertexAttribArray(mTexCoordHandle);

    }

}

GLUnfoldBitmap

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

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

import javax.microedition.khronos.opengles.GL10;

/**
 * 参考:
 * http://blog.csdn.net/nupt123456789/article/details/40375731
 * http://blog.piasy.com/2016/06/07/Open-gl-es-android-2-part-1/
 * Created by Administrator on 2016/9/23.
 */

public class GLUnfoldBitmap {
    //程式(Program):一个OpenGL ES对象,包含了你希望用来绘制一个或更多图形所要用到的着色器。
    private final int mProgram;

    //顶点着色器(Vertex Shader):用来渲染形状顶点的OpenGL ES代码。
    private final String vertexShaderCode =
            // This matrix member variable (uMVPMatrix) provides a hook to manipulate the coordinates of the objects that use this vertex shader
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "attribute vec2 a_texCoord;" +//外部传入
                    "varying vec2 v_texCoord;" +//传到片段着色器中
                    "varying vec4 Position;" +//传到片段着色器中
                    "varying vec4 rotFai;"+
                    "void main() {" +
                    // the matrix must be included as a modifier of gl_Position
                    // Note that the uMVPMatrix factor *must be first* in order for the matrix multiplication product to be correct.uMVPMatrix左乘才是对的
//                    "  gl_Position =  vPosition;" +
                    "  gl_Position = uMVPMatrix * vPosition ;" +
                    "  v_texCoord = a_texCoord;" +
                    "	Position = vPosition;" +

                    "}";
    // Use to access and set the view transformation 顶点着色器中的mMVPMatrix
    private int mMVPMatrixHandle;
    private int mPositionHandle;
    private int mTexCoordHandle;
    private int mRotFaiHandle;

    //片段着色器(Fragment Shader):使用颜色或纹理渲染形状表面的OpenGL ES代码。
    private final String fragmentShaderCode =
            "precision mediump float;" +
//                    "precision mediump int;" +
                    "varying vec2 v_texCoord;" +
                    "uniform sampler2D s_texture;" +
                    "varying vec4 Position;" +//从上方获取坐标
                    "varying vec4 rotFai;"+
                    "void main() {" +
                    "float PI= 3.14159265359;" +
//                    "int degree=210;" +
                    "float F0 = radians(210.0);" +
                    "float f = 0.5/2.0/sin(F0/4.0);" +//焦距
//                    "float f = 1.0;" +//焦距

//                    "float R = 2.0* f * sin(radians(90.0));" +
                    "float R = 1.0;" +

                    "float i = Position.x;" +
                    "float j = Position.y;" +

                    "float faiP =  PI * i / R ;" +
                    "float citaP = PI * j / R ;" +

                    "float rotFai=-90.0;"+
                    "faiP -= radians(rotFai);"+

                    "float x1p=R*sin(citaP)*cos(faiP);" +
                    "float y1p=R*sin(citaP)*sin(faiP);" +
                    "float z1p = R * cos(citaP);" +

                    "float rotSita=90.0;" +
                    "float rotSitaRad=radians(rotSita);" +
                    "float x1pp=x1p;" +
                    "float y1pp=y1p*cos(rotSitaRad)-z1p*sin(rotSitaRad);" +
                    "float z1pp=y1p*sin(rotSitaRad)+z1p*cos(rotSitaRad);" +

                    "float rotGamma=0.0;"+
                    "float rotGammaRad=radians(rotGamma);" +
                    "float x1=z1pp*sin(rotGammaRad)+x1pp*cos(rotGammaRad);" +
                    "float y1=y1pp;" +
                    "float z1=z1pp*cos(rotGammaRad)-x1pp*sin(rotGammaRad);" +

                    "float cita=acos(z1/R);"+
                    "float fai=atan(y1,x1);"+

                    "float a;"+
                    "a=2.0*f*sin(cita/2.0);"+

                    "float xp=a*cos(fai);"+
                    "float yp=a*sin(fai);"+

                    "float x,y;"+
                    "x = xp+0.5;"+
                    "y = -yp+0.5;"+

                    "vec2 test;" +
                    "test=vec2(x,y);" +
                    "  gl_FragColor =texture2D( s_texture, test );" +
//                    "  gl_FragColor =texture2D( s_texture, v_texCoord );" +
                    "}";

    private int mTexSamplerHandle;

    private FloatBuffer vertexBuffer; // buffer holding the vertexes
    private float vertexes[] = { // in counterclockwise order:
            1.0f, 1.0f, 0.0f, //  top right
            -1.0f, 1.0f, 0.0f, //  top left
            -1.0f, -1.0f, 0.0f, //  bottom left
            1.0f, -1.0f, 0.0f //  bottom right
    };
    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    private ShortBuffer drawListBuffer;
    private short drawOrder[] = {0, 1, 2, 0, 2, 3}; // order to draw vertexes

    //指定截取纹理的哪一部分绘制到图形上:
    private FloatBuffer textureBuffer; // buffer holding the texture coordinates
    private float texture[] = {
            // Mapping coordinates for the vertexes
            1.0f, 0.0f, // bottom right (V3)
            0.0f, 0.0f, // bottom left (V1)
            0.0f, 1.0f, // top left (V2)
            1.0f, 1.0f // top right (V4)

    };


    public GLUnfoldBitmap() {
        // initialize vertexBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertexes.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        vertexBuffer = byteBuffer.asFloatBuffer();
        vertexBuffer.put(vertexes);
        vertexBuffer.position(0);

        //textureBuffer
        byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        textureBuffer = byteBuffer.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.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);


        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

        // create empty OpenGL ES Program
        mProgram = GLES20.glCreateProgram();
        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, vertexShader);
        // add the fragment shader to program
        GLES20.glAttachShader(mProgram, fragmentShader);
        // creates OpenGL ES program executables
        GLES20.glLinkProgram(mProgram);
    }

    /**
     * The texture pointer
     */
    private int[] textures = new int[1];

    public void loadGLTexture(GL10 unused, Context context) {
//        我们需要先通过 glGenTextures 创建纹理,再通过 glActiveTexture 激活指定编号的纹理,再通过 glBindTexture 将新建的纹理和编号绑定起来。我们可以对图片纹理设置一系列参数,例如裁剪策略、缩放策略,这部分更详细的介绍,建议看看《OpenGL ES 2 for Android A Quick - Start Guide (2013)》这本书,里面有很详细的讲解。最后,我们通过 texImage2D 把图片数据拷贝到纹理中。


        // loading texture
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.pic1);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        // ...and bind it to our array
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        // create GL_LINEAR filtered texture
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(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);
        // Use Android GLUtils to specify a two-dimensional texture image from our bitmap
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }

    public void draw(float[] mvpMatrix) {
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram, "s_texture");

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        GLES20.glUseProgram(mProgram);

        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);

        GLES20.glEnableVertexAttribArray(mTexCoordHandle);
        GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);

        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
        GLES20.glUniform1i(mTexSamplerHandle, 0);

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        GLES20.glDisableVertexAttribArray(mPositionHandle);
        GLES20.glDisableVertexAttribArray(mTexCoordHandle);

    }

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值