Android OpenGL ES正方體紋理貼圖(每個面一張)
正方體的紋理貼圖步驟如下:
1.陣列
1.1:頂點陣列
1.2:三角形
1.3:貼圖陣列
2.onSurfaceChanged:與3D的一樣
3.onSurfaceCreated:需要新增東西
3.1允許2D貼圖gl.glEnable(GL10.GL_TEXTURE_2D);
3.2生成幾個紋理,每個面都貼圖的話就要生成六個紋理,gl.glGenTextures(6, textureBuffer); //一次性生成幾個 紋理,放到陣列中,但是這時紋理和圖片還沒結合在一起
3.3將紋理繫結到目標上gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[i]);
3.4載入檢視生成紋理GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp[i], 0);
3.5設定目標紋理屬性gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
注:3.3-3.5:生成幾個紋理就繫結幾個
4.onDrawFrame
4.1啟動紋理功能,與開啟顏色渲染一樣gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
4.2設定貼圖座標資料 gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, BufferUtil.iBuffer(texCoords));
4.3繪製立方體並繫結紋理(繫結一個面的紋理對應的畫出那個面)
這是為正方體的每個面貼一張不同的圖片的程式,注意事項都在註釋中寫明,關於座標設定請看上篇
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
//清楚螢幕和深度快取
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
//重置當前的觀察模型矩陣
gl.glLoadIdentity();
//現將螢幕向裡移動,用來畫正方體
gl.glTranslatef(0.0f, 0.0f, -6.0f);
if(bAutoRotate)
{
rotateX+=0.5;
rotateY+=0.6;
//rotateZ+=0.3;
}
//設定3個方向的旋轉
gl.glRotatef(rotateX, 1.0f, 0.0f, 0.0f);
gl.glRotatef(rotateY, 0.0f, 1.0f, 0.0f);
gl.glRotatef(rotateZ, 0.0f, 0.0f, 1.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//紋理的使用與開啟顏色渲染一樣,需要開啟紋理功能
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//設定正方體 各頂點 資料和貼圖座標陣列,第一個引數都是代表幾個元素設定一個頂點,頂點是三個xyz,貼圖是兩個xy(因為是二維貼圖
gl.glVertexPointer(3, GL10.GL_FIXED, 0, BufferUtil.iBuffer(quarter)); //注意:這個地方的第二個引數是關於座標資料型別的,根據頂點資料和紋理資料座標的資料型別而改變,如果是FL_FLOAT的話資料型別就是float的,以前我寫的OpenGL版本都是float的
gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, BufferUtil.iBuffer(texCoords));
// 繪製立方體並繫結紋理
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[0]);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indices1);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[1]);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indices2);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[2]);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indices3);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[3]);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indices4);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[4]);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indices5);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[5]);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indices6);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
//當視窗改變時,呼叫,至少在建立視窗時呼叫一次,這邊設定下場景大小
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
//設定OpenGL場景大小
float ratio = (float) width / height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);//設定為投影矩陣模式
gl.glLoadIdentity();//重置
gl.glFrustumf(-ratio, ratio, -1, 1, 2, 10);//設定視角
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
//當視窗被建立時我們可以做些初始化工作
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
//設定清除螢幕時所用的顏色,引數依次為紅、綠、藍、Alpha值
gl.glClearColor(0, 0, 0, 0);
gl.glEnable(GL10.GL_CULL_FACE);
//啟用陰影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);//啟用深度測試
//以下是關於深度快取的設定,非常重要
gl.glClearDepthf(1.0f);//設定深度快取
gl.glDepthFunc(GL10.GL_LEQUAL);//所做深度測試的型別
//告訴系統對透視進行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
//允許2D貼圖
gl.glEnable(GL10.GL_TEXTURE_2D);
//gl.glGenTextures(6, tex_id, 0);
IntBuffer textureBuffer = IntBuffer.allocate(6);
gl.glGenTextures(6, textureBuffer); //一次性生成幾個紋理,放到陣列中,但是這時紋理和圖片還沒結合在一起
tex_id = textureBuffer.array();
for(int i = 0; i < 6; i++)
{
//將紋理繫結到目標GL10.GL_TEXTURE_2D上
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[i]);
//為目標紋理GL10.GL_TEXTURE_2D放上圖片
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp[i], 0);
//設定目標紋理屬性
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
}
}
}