OpenGL ES2 繪制圖檔

class DrawPicture

此類別有二個方法, 建構子設定vertex buffer及texture buffer, 編譯shader程式碼, 然後再載入圖片於到顯卡中. 另一個方法就是onDraw()

建構子載入圖片

public DrawPicture(Context context, int[] textures){
    this.context=context;
    this.textures=textures;
    shaderProgram=ShaderCreator.getInstance(context, R.raw.vertex_picture, R.raw.fragment_picture);
    initializeBuffers();

    //從資源檔中將圖片載入成Bitmap物件
    bitmap= BitmapFactory.decodeResource(context.getResources(), R.drawable.girl);
    width=bitmap.getWidth();
    height=bitmap.getHeight();
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(width * height * 4);
    byteBuffer.order(ByteOrder.nativeOrder());
    //使用copyPixelsToBuffer() 將圖片資料 copy到ByteBuffer中, OpenGL只看得懂ByteBuffer
    bitmap.copyPixelsToBuffer(byteBuffer);
    bitmap.recycle();
    byteBuffer.position(0);

    /*
    glTexParameteri(GL_TEXTURE_2D, pname , param );
    設定圖檔縮放行為
    第一個參數 : 和glTexImage2D()相同
    第二個參數 : 
        GL_TEXTURE_MAG_FILTER : 圖片放大時的處理
            處理方法用第三個參數決定,有兩個方式
            GL_NEAREST:採用位置靠近的顏色來處理,放大效果像馬賽克,一般看圖程式也是這麼做,效率好又誠實
            GL_LINEAR:用線性內插法處理,比較耗運算資源,放大後就有點模糊感,這個做法比較適合遊戲
        GL_TEXTURE_MIN_FILTER : 圖片縮小時的處理
            處理方法用第三個參數決定,同樣有 GL_NEAREST及GL_LINEAR
        GL_TEXTURE_WRAP_S及GL_TEXTURE_WRAP_T : 補齊方法的設定
            S和T就是材質座標的s軸和t軸(想成x軸y軸即可)
            第三個參數可以選 GL_CLAMP及GL_REPEAT
    */
    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_CLAMP_TO_EDGE );
    GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );

    /*
    glTexImage2D(GL_TEXTURE_2D, 0 ,component,圖寬,圖高,border,GL_RGBA,GL_UNSIGNED_BYTE,image );
    將圖檔讀進顯示卡的記憶體中
    第一個參數為內定
    第二個參數 代表圖像的詳細程度, 只能設為 0
    第三個參數 component: 在RGBA四個顏色中會使用到顏色數,真正決定用色數是由第七個參數決定
    第六個參數 border:邊界寬度
    第七個參數 : 要使用到的顏色數
    第九個參數 image: 圖檔陣列內容,陣列的資料型態由第八個參數決定
    */

    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
            width, height, 0,GLES20.GL_RGBA,
            GLES20.GL_UNSIGNED_BYTE, byteBuffer);
}

onDraw

public void onDraw(){
    GLES20.glUseProgram(shaderProgram);
    GLES20.glDisable(GLES20.GL_BLEND);

    //置入texturePosition
    int texturePositionHandle = GLES20.glGetAttribLocation(shaderProgram, "aTexPosition");
    GLES20.glEnableVertexAttribArray(texturePositionHandle);
    GLES20.glVertexAttribPointer(texturePositionHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);

    //置入gl_position
    int positionHandle = GLES20.glGetAttribLocation(shaderProgram, "aPosition");
    GLES20.glEnableVertexAttribArray(positionHandle);
    GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, verticesBuffer);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}

ShaderFactory

vertex

attribute vec4 aPosition;
attribute vec2 aTexPosition;
varying vec2 vTexPosition;
void main(){
    gl_Position = aPosition;
    vTexPosition = aTexPosition;
}

fragment

precision mediump float;
uniform sampler2D uTexture;
varying vec2 vTexPosition;
void main() {
    gl_FragColor = texture2D(uTexture, vTexPosition);
}

多張圖像

載入圖檔時

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[1]);
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_CLAMP_TO_EDGE );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
        width, height, 0, GLES20.GL_RGBA,
        GLES20.GL_UNSIGNED_BYTE, byteBuffer);

繪制圖檔

//切換到textures[1]
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[1]);
int textureHandle = GLES20.glGetUniformLocation(shaderProgram, "uTexture");
GLES20.glUniform1i(textureHandle, 0); //一樣是 0, 不能變

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *