opengles 2.0如何绘制纹理

时间:2023-02-09 11:24:05
以下代码实现了绘制正方形,但是绘制纹理就崩溃了。
原因是加了下面2句:
"attribute vec2 aTextureCoord;\n" + 光加这个不会崩溃,
mTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); 这句崩溃了

public class MyRenderer implements Renderer {


private Bitmap mBitmap = null;
private float[] mVMatrix = new float[16];
    private float[] mProjMatrix = new float[16];
    private float[] mMVPMatrix = new float[16];

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

bulidProgram();

Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);

float ratio = (float) width / height;
        Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
GLES20.glUseProgram(mProgram);

mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config .ARGB_8888);
mBitmap.eraseColor(Color.BLUE);
}

@Override
public void onDrawFrame(GL10 gl) {
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
// GLES20.glUseProgram(mProgram);
        
        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);// 应用投影和视口变换

        drawImage();
        drawSquare();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static final int COORDS_PER_IMAGE_VERTEX = 2;
private FloatBuffer mImageCubeVertices;
    private FloatBuffer mTTextureVertices;
final float cubePosition[] =  { 
-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
1.0f, 1.0f,
};
    final float cubeColor[] = {     
     0.0f, 0.0f, 1.0f, 1.0f};

    final float cubeTextureCoordinate[] = {  
     0.0f, 0.0f,   
     0.0f, 1.0f,   
     1.0f, 0.0f,   
     0.0f, 1.0f,   
     1.0f, 1.0f,   
     1.0f, 0.0f};


private void drawImage() {
GLES20.glEnable(GLES20.GL_TEXTURE_2D);// 启用2D纹理贴图
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, textures[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);

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

        if (null == mBitmap || mBitmap.isRecycled()) {
         return;
        }
        else {
         GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBitmap, 0);
        }
        GLES20.glDeleteTextures(1, textures, 0);

mImageCubeVertices = ByteBuffer.allocateDirect(cubePosition.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
mImageCubeVertices.put(cubePosition).position(0);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_IMAGE_VERTEX, GLES20.GL_FLOAT, false, cubePosition.length * COORDS_PER_IMAGE_VERTEX, mImageCubeVertices);
// Set color for drawing the triangle
        GLES20.glUniform4fv(mColorHandle, 1, cubeColor, 0);
        
        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(mPositionHandle);

        mTTextureVertices = ByteBuffer.allocateDirect(cubeTextureCoordinate.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTTextureVertices.put(cubeTextureCoordinate).position(0);
        GLES20.glVertexAttribPointer(mTextureHandle, 2, GLES20.GL_FLOAT, false, COORDS_PER_IMAGE_VERTEX * BYTES_PER_FLOAT, mTTextureVertices);
        GLES20.glEnableVertexAttribArray(mTextureHandle);
        

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

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static final int COORDS_PER_SQUARE_VERTEX = 2;
private FloatBuffer mSquareVertexBuffer;
private ShortBuffer mSquareIndexBuffer;
private void drawSquare() {
createRectangle();
        float squareColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };

        // Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_SQUARE_VERTEX, GLES20.GL_FLOAT, false, COORDS_PER_SQUARE_VERTEX * BYTES_PER_FLOAT, mSquareVertexBuffer);// 每个顶点只有(x,y)2个点
        // Set color for drawing the triangle
        GLES20.glUniform4fv(mColorHandle, 1, squareColor, 0);
        
        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(mPositionHandle);

//        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, squareCoords.length * COORDS_PER_SQUARE_VERTEX);// Draw the triangle
     // Draw the square
        GLES20.glDrawElements(
                GLES20.GL_TRIANGLES, squareIndex.length,
                GLES20.GL_UNSIGNED_SHORT, mSquareIndexBuffer);
        GLES20.glDisableVertexAttribArray(mPositionHandle);// Disable vertex array
}

    private void createRectangle() {
        ByteBuffer vbb  = ByteBuffer.allocateDirect(squareCoords.length * BYTES_PER_FLOAT);
        vbb.order(ByteOrder.nativeOrder());
        mSquareVertexBuffer = vbb.asFloatBuffer();
        mSquareVertexBuffer.put(squareCoords);
        mSquareVertexBuffer.position(0);

        ByteBuffer ibb = ByteBuffer.allocateDirect(squareIndex.length * 2);
        ibb.order(ByteOrder.nativeOrder());
        mSquareIndexBuffer = ibb.asShortBuffer();
        mSquareIndexBuffer.put(squareIndex);
        mSquareIndexBuffer.position(0);
    }
short squareIndex[] = { 0, 1, 2, 0, 2, 3 };// 设置顶点的绘制顺序

static float squareCoords[] = {
-0.4f,  0.4f,// 左上
-0.4f, -0.4f,// 左下
0.4f, -0.4f,// 右下
0.4f,  0.4f };// 右上

private int mProgram = 0;
    private int mMVPMatrixHandle = -1;
private int mPositionHandle = -1;
private int mColorHandle = -1;
    private int mTextureHandle;
private boolean bulidProgram() {
mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
if (0 == mProgram) {
return false;
}

mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
        if (-1 == mPositionHandle) {
            throw new RuntimeException("Could not get attrib location for aPosition");
        }
                
        mTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
        if (-1 == mTextureHandle) {
            throw new RuntimeException("Could not get attrib location for aTextureCoord");
        }
        
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        if (-1 == mColorHandle) {
            throw new RuntimeException("Could not get attrib location for vColor");
        }

mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        if (-1 == mMVPMatrixHandle) {
            throw new RuntimeException("Could not get attrib location for uMVPMatrix");
        }

return true;
}
    
    private int createProgram(String vertexSource, String fragmentSource) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (0 == vertexShader) {
            return 0;
        }

        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (0 == pixelShader) {
            return 0;
        }

        int program = GLES20.glCreateProgram();
        if (0 != program) {
            GLES20.glAttachShader(program, vertexShader);
            GLES20.glAttachShader(program, pixelShader);
            GLES20.glLinkProgram(program);

            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if (GLES20.GL_TRUE != linkStatus[0]) {// 链接失败
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }

    private int loadShader(int shaderType, String source) {
        int shader = GLES20.glCreateShader(shaderType);
        if (0 != shader) {
            GLES20.glShaderSource(shader, source);
            GLES20.glCompileShader(shader);
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
            if (0 == compiled[0]) {
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }



    private final String VERTEX_SHADER =
        // This matrix member variable provides a hook to manipulate
        // the coordinates of the objects that use this vertex shader
        "uniform mat4 uMVPMatrix;\n" +
        "attribute vec4 aPosition;\n" +
        "attribute vec2 aTextureCoord;\n" +
        "void main() {\n" +
        // the matrix must be included as a modifier of gl_Position
        "  gl_Position = uMVPMatrix * aPosition;\n" +
        "}\n";

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