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, 不能變
