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