Android GL如何绘制不同的纹理

时间:2017-07-12 10:09:51

标签: java android opengl-es textures

我遇到了Android,GL和Textures的麻烦,我有一个小例子,我想加载两个不同的纹理并在屏幕上绘制它,我的问题是总是绘制最后一个纹理加载。

我在Android中使用GL并且已经复制了一些教程中的代码。

以下是代码:

GLRenderer:

public class GLRenderer implements Renderer {

    // Our matrices
    private final float[] mtrxProjection = new float[16];
    private final float[] mtrxView = new float[16];
    private final float[] mtrxProjectionAndView = new float[16];

    // Our screenresolution
    float   mScreenWidth = 1280;
    float   mScreenHeight = 768;

    // Misc
    Context mContext;
    long mLastTime;
    int mProgram;

    CardView card1;
    CardView card2;

    public GLRenderer(Context c)
    {
        mContext = c;
        mLastTime = System.currentTimeMillis() + 100;
    }

    public void onPause()
    {
        /* Do stuff to pause the renderer */
    }

    public void onResume()
    {
        /* Do stuff to resume the renderer */
        mLastTime = System.currentTimeMillis();
    }

    @Override
    public void onDrawFrame(GL10 unused) {

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

        // Get the current time
        long now = System.currentTimeMillis();

        // We should make sure we are valid and sane
        if (mLastTime > now) return;

        // Get the amount of time the last frame took.
        long elapsed = now - mLastTime;

        // Update our example

        // Render our example
        card1.Draw(mtrxProjectionAndView);
        card2.Draw(mtrxProjectionAndView);

        // Save the current time to see how long it took :).
        mLastTime = now;

    }


    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

        // We need to know the current width and height.
        mScreenWidth = width;
        mScreenHeight = height;

        // Redo the Viewport, making it fullscreen.
        GLES20.glViewport(0, 0, (int)mScreenWidth, (int)mScreenHeight);

        // Clear our matrices
        for(int i=0;i<16;i++)
        {
            mtrxProjection[i] = 0.0f;
            mtrxView[i] = 0.0f;
            mtrxProjectionAndView[i] = 0.0f;
        }

        // Setup our screen width and height for normal sprite translation.
        Matrix.orthoM(mtrxProjection, 0, 0f, mScreenWidth, 0.0f, mScreenHeight, 0, 50);

        // Set the camera position (View matrix)
        Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        // Calculate the projection and view transformation
        Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);

    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        card1 = new CardView(mContext, 1);
        card2 = new CardView(mContext, 2);
    }
}


public class CardView {

    // Misc
    private Context mContext;

    // Geometric variables
    // number of coordinates per vertex in this array
    private static final int COORDS_PER_VERTEX = 3;
    private static float vertices[] = {
            10.0f, 300f, 0.0f,
            10.0f, 100f, 0.0f,
            450f, 100f, 0.0f,
            450f, 300f, 0.0f,
    };
    private static float vertices2[] = {
            450.0f, 600f, 0.0f,
            450.0f, 300f, 0.0f,
            900f, 300f, 0.0f,
            900f, 600f, 0.0f,
    };

    private final short indices[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
    private static float uvs[] = {
            0.0f, 0.0f,
            0.0f, 1.0f,
            1.0f, 1.0f,
            1.0f, 0.0f
    };
    private FloatBuffer vertexBuffer;
    private ShortBuffer drawListBuffer;
    private FloatBuffer uvBuffer;


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

    public CardView(Context c, int index)
    {
        // Save context reference
        mContext = c;
        // Create the triangles
        SetupCard(index);
        // Create the image information
        SetupImage(index);

        // Set the clear color to black
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);

        // Create the shaders, solid color
        int vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_SolidColor);
        int fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_SolidColor);

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

        // Create the shaders, images
        vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_Image);
        fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_Image);

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


        // Set our shader programm
        GLES20.glUseProgram(riGraphicTools.sp_Image);
    }



    public void SetupImage(int index)
    {
        // The texture buffer
        ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4);
        bb.order(ByteOrder.nativeOrder());
        uvBuffer = bb.asFloatBuffer();
        uvBuffer.put(uvs);
        uvBuffer.position(0);

        // Generate Textures, if more needed, alter these numbers.
        int[] texturenames = new int[1];
        GLES20.glGenTextures(1, texturenames, 0);

        // Retrieve our image from resources.
        //int id = mContext.getResources().getIdentifier("drawable/test_backbground1", null, mContext.getPackageName());
        if(index == 1) {
            int id = riGraphicTools.loadTexture(mContext, R.drawable.test_backbground1, index);
        }else{
            int id = riGraphicTools.loadTexture(mContext, R.drawable.test_backbground2, index);
        }

    }


    public void SetupCard(int index)
    {

        if( index == 1) {
            // The vertex buffer.
            ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
            bb.order(ByteOrder.nativeOrder());
            vertexBuffer = bb.asFloatBuffer();
            vertexBuffer.put(vertices);
            vertexBuffer.position(0);
        }else{
            // The vertex buffer.
            ByteBuffer bb = ByteBuffer.allocateDirect(vertices2.length * 4);
            bb.order(ByteOrder.nativeOrder());
            vertexBuffer = bb.asFloatBuffer();
            vertexBuffer.put(vertices2);
            vertexBuffer.position(0);
        }

        // initialize byte buffer for the draw list
        ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(indices);
        drawListBuffer.position(0);


    }

    /**
     * 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){

        // clear Screen and Depth Buffer, we have set the clear color as black.
        //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

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

        // Enable generic vertex attribute array
        GLES20.glEnableVertexAttribArray(mPositionHandle);

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

        // Get handle to texture coordinates location
        int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "a_texCoord" );

        // Enable generic vertex attribute array
        GLES20.glEnableVertexAttribArray ( mTexCoordLoc );

        // Prepare the texturecoordinates
        GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
                false,
                0, uvBuffer);

        // Get handle to shape's transformation matrix
        int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image, "uMVPMatrix");

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mvpMatrix, 0);

        // Get handle to textures locations
        int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image, "s_texture" );

        // Set the sampler texture unit to 0, where we have saved the texture.
        GLES20.glUniform1i ( mSamplerLoc, 0);

        // Draw the triangle
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
                GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

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

    }
}


public class riGraphicTools {

    private static final String TAG = "GraphicTools";

    // Program variables
    public static int sp_SolidColor;
    public static int sp_Image;


    /* SHADER Solid
     *
     * This shader is for rendering a colored primitive.
     *
     */
    public static final String vs_SolidColor =
            "uniform    mat4        uMVPMatrix;" +
                    "attribute  vec4        vPosition;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "}";

    public static final String fs_SolidColor =
            "precision mediump float;" +
                    "void main() {" +
                    "  gl_FragColor = vec4(0.5,0,0,1);" +
                    "}";

    /* SHADER Image
     *
     * This shader is for rendering 2D images straight from a texture
     * No additional effects.
     *
     */
    public static final String vs_Image =
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "attribute vec2 a_texCoord;" +
                    "varying vec2 v_texCoord;" +
                    "void main() {" +
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "  v_texCoord = a_texCoord;" +
                    "}";

    public static final String fs_Image =
            "precision mediump float;" +
                    "varying vec2 v_texCoord;" +
                    "uniform sampler2D s_texture;" +
                    "void main() {" +
                    "  gl_FragColor = texture2D( s_texture, v_texCoord );" +
                    "}";




    /**
     * Utility method for compiling a OpenGL shader.
     *
     * <p><strong>Note:</strong> When developing shaders, use the checkGlError()
     * method to debug shader coding errors.</p>
     *
     * @param type - Vertex or fragment shader type.
     * @param shaderCode - String containing the shader code.
     * @return - Returns an id for the shader.
     */
    public static int loadShader(int type, String shaderCode){

        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
        int shader = GLES20.glCreateShader(type);

        // add the source code to the shader and compile it
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        // return the shader
        return shader;
    }



    /**
     * Utility method for debugging OpenGL calls. Provide the name of the call
     * just after making it:
     *
     * <pre>
     * mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
     * FandeckRenderer.checkGlError("glGetUniformLocation");</pre>
     *
     * If the operation is not successful, the check throws an error.
     *
     * @param glOperation - Name of the OpenGL call to check.
     */
    public static void checkGlError(String glOperation) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, glOperation + ": glError " + error);
            throw new RuntimeException(glOperation + ": glError " + error);
        }
    }

    public static int loadTexture(final Context context, final int resourceId, int[] textureHandler, int index)
    {

        //GLES20.glGenTextures(1, textureHandler, index);

        if (textureHandler[index] != 0)
        {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false;   // No pre-scaling

            // Read in the resource
            final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);

            // Bind to the texture in OpenGL
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandler[index]);

            // 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();
        }

        if (textureHandler[index] == 0)
        {
            throw new RuntimeException("Error loading texture.");
        }

        return textureHandler[0];
    }
}

1 个答案:

答案 0 :(得分:0)

好的,问题是textureHandle,我把它移到了上层来保存数据,而在方法Draw中我添加了:

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[textureIndex]);

它有效。

最后的代码是下一个代码:

公共类GLRenderer实现Renderer {

// Our matrices
private final float[] mtrxProjection = new float[16];
private final float[] mtrxView = new float[16];
private final float[] mtrxProjectionAndView = new float[16];

// Our screenresolution
float   mScreenWidth = 1280;
float   mScreenHeight = 768;

// Misc
Context mContext;
long mLastTime;
int mProgram;

CardView card1;
CardView card2;

public GLRenderer(Context c)
{
    mContext = c;
    mLastTime = System.currentTimeMillis() + 100;
}

public void onPause()
{
    /* Do stuff to pause the renderer */
}

public void onResume()
{
    /* Do stuff to resume the renderer */
    mLastTime = System.currentTimeMillis();
}

@Override
public void onDrawFrame(GL10 unused) {

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

    // Get the current time
    long now = System.currentTimeMillis();

    // We should make sure we are valid and sane
    if (mLastTime > now) return;

    // Get the amount of time the last frame took.
    long elapsed = now - mLastTime;

    // Update our example

    // Render our example
    card1.Draw(mtrxProjectionAndView, 0);

    card2.Draw(mtrxProjectionAndView , 1);

    // Save the current time to see how long it took :).
    mLastTime = now;

}


@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {

    // We need to know the current width and height.
    mScreenWidth = width;
    mScreenHeight = height;

    // Redo the Viewport, making it fullscreen.
    GLES20.glViewport(0, 0, (int)mScreenWidth, (int)mScreenHeight);

    // Clear our matrices
    for(int i=0;i<16;i++)
    {
        mtrxProjection[i] = 0.0f;
        mtrxView[i] = 0.0f;
        mtrxProjectionAndView[i] = 0.0f;
    }

    // Setup our screen width and height for normal sprite translation.
    Matrix.orthoM(mtrxProjection, 0, 0f, mScreenWidth, 0.0f, mScreenHeight, 0, 50);

    // Set the camera position (View matrix)
    Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);

}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    card1 = new CardView(mContext, 0);
    card2 = new CardView(mContext, 1);
}

}

公共类CardView {

// Misc
private Context mContext;

// Geometric variables
// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 3;
private static float vertices[] = {
        10.0f, 300f, 0.0f,
        10.0f, 100f, 0.0f,
        450f, 100f, 0.0f,
        450f, 300f, 0.0f,
};
private static float vertices2[] = {
        450.0f, 600f, 0.0f,
        450.0f, 300f, 0.0f,
        900f, 300f, 0.0f,
        900f, 600f, 0.0f,
};

private final short indices[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
private static float uvs[] = {
        0.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
        1.0f, 0.0f
};
private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
private FloatBuffer uvBuffer;


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

final int[] textureHandle;

public CardView(Context c, int index)
{

    textureHandle = new int[2];
    // Save context reference
    mContext = c;
    // Create the triangles
    SetupCard(index);
    // Create the image information
    SetupImage(index);

    // Set the clear color to black
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);

    // Create the shaders, solid color
    int vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_SolidColor);
    int fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_SolidColor);

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

    // Create the shaders, images
    vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_Image);
    fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_Image);

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


    // Set our shader programm
    GLES20.glUseProgram(riGraphicTools.sp_Image);
}



public void SetupImage(int index)
{

    GLES20.glGenTextures(2, textureHandle, 0);

    // The texture buffer
    ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4);
    bb.order(ByteOrder.nativeOrder());
    uvBuffer = bb.asFloatBuffer();
    uvBuffer.put(uvs);
    uvBuffer.position(0);

    // Generate Textures, if more needed, alter these numbers.
    int[] texturenames = new int[1];
    GLES20.glGenTextures(1, texturenames, 0);

    // Retrieve our image from resources.
    //int id = mContext.getResources().getIdentifier("drawable/test_backbground1", null, mContext.getPackageName());
    if(index == 1) {
        int id = riGraphicTools.loadTexture(mContext, R.drawable.test_backbground1, textureHandle, index);
    }else{
        int id = riGraphicTools.loadTexture(mContext, R.drawable.test_backbground2, textureHandle, index);
    }

}


public void SetupCard(int index)
{

    if( index == 1) {
        // The vertex buffer.
        ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);
    }else{
        // The vertex buffer.
        ByteBuffer bb = ByteBuffer.allocateDirect(vertices2.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(vertices2);
        vertexBuffer.position(0);
    }

    // initialize byte buffer for the draw list
    ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer = dlb.asShortBuffer();
    drawListBuffer.put(indices);
    drawListBuffer.position(0);


}

/**
 * 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, int textureIndex){

    // clear Screen and Depth Buffer, we have set the clear color as black.
    //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);


    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[textureIndex]);

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

    // Enable generic vertex attribute array
    GLES20.glEnableVertexAttribArray(mPositionHandle);

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

    // Get handle to texture coordinates location
    int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "a_texCoord" );

    // Enable generic vertex attribute array
    GLES20.glEnableVertexAttribArray ( mTexCoordLoc );

    // Prepare the texturecoordinates
    GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
            false,
            0, uvBuffer);

    // Get handle to shape's transformation matrix
    int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image, "uMVPMatrix");

    // Apply the projection and view transformation
    GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mvpMatrix, 0);

    // Get handle to textures locations
    int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image, "s_texture" );

    // Set the sampler texture unit to 0, where we have saved the texture.
    GLES20.glUniform1i ( mSamplerLoc, 0);

    // Draw the triangle
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
            GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

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

}

}

public class riGraphicTools {

// Program variables
public static int sp_SolidColor;
public static int sp_Image;


/* SHADER Solid
 * 
 * This shader is for rendering a colored primitive.
 * 
 */
public static final String vs_SolidColor =
    "uniform    mat4        uMVPMatrix;" +
    "attribute  vec4        vPosition;" +
    "void main() {" +
    "  gl_Position = uMVPMatrix * vPosition;" +
    "}";

public static final String fs_SolidColor =
    "precision mediump float;" +
    "void main() {" +
    "  gl_FragColor = vec4(0.5,0,0,1);" +
    "}"; 

/* SHADER Image
 * 
 * This shader is for rendering 2D images straight from a texture
 * No additional effects.
 * 
 */
public static final String vs_Image =
    "uniform mat4 uMVPMatrix;" +
    "attribute vec4 vPosition;" +
    "attribute vec2 a_texCoord;" +
    "varying vec2 v_texCoord;" +
    "void main() {" +
    "  gl_Position = uMVPMatrix * vPosition;" +
    "  v_texCoord = a_texCoord;" +
    "}";

public static final String fs_Image =
    "precision mediump float;" +
    "varying vec2 v_texCoord;" +
    "uniform sampler2D s_texture;" +
    "void main() {" +
    "  gl_FragColor = texture2D( s_texture, v_texCoord );" +
    "}"; 



public static int loadShader(int type, String shaderCode){

    // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
    int shader = GLES20.glCreateShader(type);

    // add the source code to the shader and compile it
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);

    // return the shader
    return shader;
}

public static int loadTexture(final Context context, final int resourceId, int[] textureHandle , int index)
{

    if (textureHandle[index] != 0)
    {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;   // No pre-scaling

        // Read in the resource
        final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);

        // Bind to the texture in OpenGL
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[index]);

        // 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();
    }

    if (textureHandle[index] == 0)
    {
        throw new RuntimeException("Error loading texture.");
    }

    return textureHandle[index];
}

}

我希望这会对某人有所帮助。