1. 程式人生 > >Android OpenGL ES 簡明開發教程_材質渲染

Android OpenGL ES 簡明開發教程_材質渲染

該系列文章均轉載自

由於原文好像無法開啟,正好自己有記錄,所以正好分享出來,其中也對一些API作了解釋。

前面討論瞭如何給 3D 圖形染色,更一般的情況是使用點陣圖來給 Mesh 上色(渲染材質)。主要步驟如下:

建立 Bitmap 物件

使用材質渲染,首先需要構建用來渲染的Bitmap物件,Bitmap物件可以從資原始檔中讀取或者是從網路載入,或者是用程式碼構造,為簡單起見,本例從資源中獲取:

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.jay);

要注意的是,有些裝置對使用的 Bitmap 的大小有要求,要求 Bitmap 的寬度和長度為 2 的幾次冪(1,2,4,8,16,32,64.。。。),如果使用不合要求的 Bitmap 來渲染,可能只會顯示白色。

建立材質(Generating a texture)

下一步使用 OpenGL 庫建立一個材質(Texture),首先是獲取一個 Texture Id。

// 建立一個int型別的陣列,長度表示需要幾個Texture
int[] textures = new int[1];

// 使用OpenGL庫建立材質
gl.glGenTextures(1,textures,0);

textures 中存放了建立的 Texture ID,使用同樣的 Texture Id ,也可以來刪除一個 Texture:

// 刪除材質
gl.glDeleteTextures(1,textures,0);

有了 Texture Id 之後,就可以通知 OpenGL 庫使用這個 Texture:

/**
 * 通知OpenGL庫使用這個Texture
 * 引數:
 * target——指明紋理要繫結的目標,必須是GL_TEXTURE_2D。
   texture——指明紋理的名稱。
 */
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[0]);

設定 Texture 引數 glTexParameter

下一步需要給 Texture 填充設定引數,用來渲染的 Texture 可能比要渲染的區域大或者小,這是需要設定 Texture 需要放大或是縮小時 OpenGL 的模式:

// Scale up if the texture if smaller.放大
gl.glTexParameterf
(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); // scale linearly when image smalled than texture 縮小 gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);

常用的兩種模式為 GL10.GL_LINEAR 和 GL10.GL_NEAREST。

需要比較清晰的影象使用 GL10.GL_NEAREST:
這裡寫圖片描述

而使用 GL10.GL_LINEAR 則會得到一個較模糊的影象:
這裡寫圖片描述

UV Mapping

下一步要告知 OpenGL 庫如何將 Bitmap 的畫素對映到 Mesh 上。這可以分為兩步來完成:

1.定義 UV 座標

UV Mapping 指將 Bitmap 的畫素對映到 Mesh 上的頂點。UV 座標定義為左上角(0,0),右下角(1,1)(因為使用的 2D Texture),下圖座標顯示了 UV 座標,右邊為我們需要染色的平面的頂點順序:

為了能正確的匹配,需要把 UV 座標中的(0,1)對映到頂點 0,(1,1)對映到頂點 2 等等。

float textureCoordinates[] = {0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f };

這裡寫圖片描述

如果使用如下座標定義:

float textureCoordinates[] = {0.0f, 0.5f,
        0.5f, 0.5f,
        0.0f, 0.0f,
        0.5f, 0.0f };

這裡寫圖片描述
Texture 匹配到 Plane 的左上角部分。

float textureCoordinates[] = {0.0f, 2.0f,
        2.0f, 2.0f,
        0.0f, 0.0f,
        2.0f, 0.0f };

將使用一些不存在的 Texture 去渲染平面(UV 座標為 0,0-1,1 而 (0,0)-(2,2)定義超過 UV 定義的大小),這時需要告訴 OpenGL 庫如何去渲染這些不存在的 Texture 部分。

有兩種設定

  • GL_REPEAT 重複 Texture。
  • GL_CLAMP_TO_EDGE 只靠邊線複製一次。
  • 下面有四種不同組合:

這裡寫圖片描述

本例使用如下配置:

gl.glTexParameterf(GL10.GL_TEXTURE_2D,
 GL10.GL_TEXTURE_WRAP_S,
 GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
 GL10.GL_TEXTURE_WRAP_T,
 GL10.GL_REPEAT);

然後是將 Bitmap 資源和 Texture 繫結起來:

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

2.使用 Texture

為了能夠使用上面定義的 Texture,需要建立一 Buffer 來儲存 UV 座標:

FloatBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(textureCoordinates);
textureBuffer.position(0); 

渲染

// Telling OpenGL to enable textures.
gl.glEnable(GL10.GL_TEXTURE_2D);
// Tell OpenGL where our texture is located.
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// Tell OpenGL to enable the use of UV coordinates.
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Telling OpenGL where our UV coordinates are.
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
// ... here goes the rendering of the mesh ...
// Disable the use of UV coordinates.
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Disable the use of textures.
gl.glDisable(GL10.GL_TEXTURE_2D);   

本例程式碼是在一個平面上(SimplePlane)下使用 Texture 來渲染,首先是修改 Mesh 基類,使它能夠支援定義 UV 座標:

// Our UV texture buffer.
private FloatBuffer mTextureBuffer;
/**
 * Set the texture coordinates.
 *
 * @param textureCoords
 */
protected void setTextureCoordinates(float[] textureCoords) {
 // float is 4 bytes, therefore we multiply the number if
 // vertices with 4.
 ByteBuffer byteBuf = ByteBuffer.allocateDirect(
 textureCoords.length * 4);
 byteBuf.order(ByteOrder.nativeOrder());
 mTextureBuffer = byteBuf.asFloatBuffer();
 mTextureBuffer.put(textureCoords);
 mTextureBuffer.position(0);
} 

並新增設定 Bitmap 和建立 Texture 的方法:

// Our texture id.
private int mTextureId = -1;
// The bitmap we want to load as a texture.
private Bitmap mBitmap;
/**
 * Set the bitmap to load into a texture.
 *
 * @param bitmap
 */
public void loadBitmap(Bitmap bitmap) {
 this.mBitmap = bitmap;
 mShouldLoadTexture = true;
}
/**
 * Loads the texture.
 *
 * @param gl
 */
private void loadGLTexture(GL10 gl) {
 // Generate one texture pointer...
 int[] textures = new int[1];
 gl.glGenTextures(1, textures, 0);
 mTextureId = textures[0];
 // ...and bind it to our array
 gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
 // Create Nearest Filtered Texture
 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
 GL10.GL_LINEAR);
 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
 GL10.GL_LINEAR);
 // Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
 GL10.GL_CLAMP_TO_EDGE);
 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
 GL10.GL_REPEAT);
 // Use the Android GLUtils to specify a two-dimensional texture image
 // from our bitmap
 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
} 

最後修改 draw 方法來渲染材質:

// Indicates if we need to load the texture.
private boolean mShouldLoadTexture = false;
/**
 * Render the mesh.
 *
 * @param gl
 *            the OpenGL context to render to.
 */
public void draw(GL10 gl) {
 ...
 // Smooth color
 if (mColorBuffer != null) {
 // Enable the color array buffer to be used during rendering.
 gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
 gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
 }
 if (mShouldLoadTexture) {
 loadGLTexture(gl);
 mShouldLoadTexture = false;
 }
 if (mTextureId != -1 && mTextureBuffer != null) {
 gl.glEnable(GL10.GL_TEXTURE_2D);
 // Enable the texture state
 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
 // Point to our buffers
 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
 gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
 }
 gl.glTranslatef(x, y, z);
 ...
 // Point out the where the color buffer is.
 gl.glDrawElements(GL10.GL_TRIANGLES, mNumOfIndices,
 GL10.GL_UNSIGNED_SHORT, mIndicesBuffer);
 ...
 if (mTextureId != -1 && mTextureBuffer != null) {
 gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
 }
 ...
} 

本例使用的 SimplePlane 定義如下:

/**
 * SimplePlane is a setup class for Mesh that creates a plane mesh.
 *
 * @author Per-Erik Bergman ([email protected])
 *
 */
public class SimplePlane extends Mesh {
 /**
 * Create a plane with a default with and height of 1 unit.
 */
 public SimplePlane() {
 this(1, 1);
 }
 /**
 * Create a plane.
 *
 * @param width
 *            the width of the plane.
 * @param height
 *            the height of the plane.
 */
 public SimplePlane(float width, float height) {
 // Mapping coordinates for the vertices
 float textureCoordinates[] = { 0.0f, 2.0f, //
 2.0f, 2.0f, //
 0.0f, 0.0f, //
 2.0f, 0.0f, //
 };
 short[] indices = new short[] { 0, 1, 2, 1, 3, 2 };
 float[] vertices = new float[] { -0.5f, -0.5f, 0.0f,
 0.5f, -0.5f, 0.0f,
 -0.5f,  0.5f, 0.0f,
 0.5f, 0.5f, 0.0f };
 setIndices(indices);
 setVertices(vertices);
 setTextureCoordinates(textureCoordinates);
 }
} 

最後效果如下:
這裡寫圖片描述

相關推薦

Android OpenGL ES 簡明開發教程_材質渲染

該系列文章均轉載自 由於原文好像無法開啟,正好自己有記錄,所以正好分享出來,其中也對一些API作了解釋。 前面討論瞭如何給 3D 圖形染色,更一般的情況是使用點陣圖來給 Mesh 上色(渲染材質)。主要步驟如下: 建立 Bitmap 物件 使用材

Android OpenGL ES 簡明開發教程_真正的3D圖形

摘要:該系列文章均轉載自/content/540025.html由於原文好像無法開啟,正好自己有記錄,所以正好分享出來。Mesh(網格,三角面)是構成空間形體的基本元素,前面的正方形也是由兩個Mesh構成的。本篇將介紹使用Mesh構成四面體,椎體等基本空間形體。Design設計在使用Ope

Android OpenGL ES 簡明開發教程一 概述

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android OpenGL ES 簡明開發教程二 構造OpenGL ES View

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android OpenGL ES 簡明開發教程三 3D繪圖基本概念

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android OpenGL ES 簡明開發教程一:概述

ApiDemos 的Graphics示例中含有OpenGL ES 例子,OpenGL ES 主要用來開發3D圖形應用的。OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三維圖形 API 的子集,針對手機、PDA和遊戲主機等嵌入式裝置而設計。 下面

Android OpenGL ES 簡明開發教程二:構造OpenGL ES View

在Andorid平臺上構造一個OpenGL View非常簡單,主要有兩方面的工作: GLSurfaceView Android平臺提供的OpenGL ES API主要定義在包android.opengl ,javax.microedition.khronos.egl ,j

Android OpenGL ES 開發教程 22 繪製一個球體

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android OpenGL ES 開發教程 5 關於EGL

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android OpenGL ES 開發教程 26 設定光照效果Set Lighting

                上一篇簡單介紹了OpenGL中使用的光照模型,本篇結合OpenGL ES API說明如何使用光照效果:設定光源定義法線設定物體材料光學屬性光源OpenGL ES中可以最多同時使用八個光源,分別使用0到7表示。OpenGL ES光源可以分為平行光源(Parallel light

Android OpenGL ES 開發教程(1):導言

Android ApiDemos到目前為止,介紹完了出View以外的所有例子,在介紹Graphics示例時跳過了和OpenGL ES 相關的例子,OpenGL ES 3D圖形開發需要專門的開發教程,因此從今天開始一邊繼續Android ApiDemos Views例子的解析

Android OpenGL ES 開發教程(8):基本幾何圖形定義

通常二維圖形庫可以繪製點,線,多邊形,圓弧,路徑等等。OpenGL ES 支援繪製的基本幾何圖形分為三類:點,線段,三角形。也就是說OpenGL ES 只能繪製這三種基本幾何圖形。任何複雜的2D或是3D圖形都是通過這三種幾何圖形構造而成的。 比如下圖複雜的3D圖形,都有

Android OpenGL ES濾鏡開發之美顏效果

前言 其實之前我就是已經把美顏效果啥的都做完了,但是就一直懶得記錄,今天來記錄一下,之前記錄的就是大眼睛還有貼紙的效果。以前的時候不愛寫部落格,總覺得很麻煩,現在發現寫部落格是用來總結複習很好的一個途徑,很多時候寫效果或者做些什麼,就基本就是做完就完事兒了,也不去總結一下或者拿來複習一下

Android OpenGL ES 開發(二)— 繪製三角形

        在前一篇部落格我們知道了Android中OpenGL ES是什麼,然後知道了怎麼搭建一個OpenGL ES的執行環境,現在我們就來開始繪製我們自己想要的圖形了(繪製圖片會在後面講解,因為繪製圖形是繪製圖片的基礎),我們最先開始繪製一個三角形

OpenGL ES應用開發實踐指南(android 卷)筆記 第一章

public class FirstOpenGLActivity extends Activity { private GLSurfaceView glSurfaceView; //用於記住GLSurfaceView是否處於有效狀態 private boolean

Android OpenGL ES 開發:繪製圖形

# OpenGL 繪製圖形步驟 上一篇介紹了 OpenGL 的相關概念,今天來實際操作,使用 OpenGL 繪製出圖形,對其過程有一個初步的瞭解。 OpenGL 繪製圖形主要概括成以下幾個步驟: 1. 建立程式 2. 初始化著色器 3. 將著色器加入程式 4. 連結並使用程式 6. 繪製圖形 上述每個

Android OpenGL ES 入門系列(一) --- 了解OpenGL ES的前世今生

target 初始化 vertex 單獨 http hang tex 變化 3d圖 轉載請註明出處 本文出自Hansion的博客 OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三維圖形 API 的子集,

Android OpenGL ES基礎

前言 此篇僅僅介紹一些概念,其他的內容,會在後面更新,後面內容會以仿抖音小視訊專案形式進行介紹。 什麼是OpenGL ES OpenGL :Open Graphics Library 圖形領域的工業標準,是一套跨程式語言、跨平臺的、專業的圖形程式設計(軟體)介面。它主

Android OpenGL ES- Cube Map

                Cube Map,中文可以翻譯成立方環境對映,下面是摘自維基百科的說明:立方反射對映是用立方對映使得物體看起來如同在反射周圍環境的一項技術。通常,這通常使使用者外渲染中使用的 skybox 完成。儘管由於反射物周圍的物體無法在結果中看到,所以這並不是一個真正的反射,但是通常仍然

Android OpenGL ES(一)----必備知識

1.手機的座標空間 我們都知道要想在手機上隨心所欲的繪製圖形,就必須瞭解手機的座標體系。下圖就是將座標對映到手機螢幕的座標。  圖1手機螢幕基本座標系 2.OpenGL基本圖形 在OpenGL裡,只能繪製點,直線以及三角形。 三角形是最基本的圖形,因為它的結構如此