繪圖有很多需要注意的地方,直接提出demo,里面注釋部分需要注意:
public class MainActivity extends AppCompatActivity {
private GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
glSurfaceView=new GLSurfaceView(this);
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.ayx);
Bitmap bitmap2 = BitmapFactory.decodeResource(this.getResources(), R.drawable.ayx2);
Bitmap mBitmap[] = {bitmap,bitmap2};
GLSurfaceView.Renderer renderer=new GLRender3(mBitmap);
glSurfaceView.setRenderer(renderer);
setContentView(glSurfaceView);
}
}
package com.example.zp.myapplication;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.graphics.Bitmap;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
public class GLRender3 implements Renderer
{
float xrot, yrot, zrot;
int textureSize = 2;
int texture[] = new int [textureSize];
int one = 0x10000;
private Bitmap mBitmap[];
//正方體的6個面,4個點確定一個面
IntBuffer vertices = BufferUtil.intToBuffer(new int[]{
-one,-one,one,
one,-one,one,
one,one,one,
-one,one,one,
-one,-one,-one,
-one,one,-one,
one,one,-one,
one,-one,-one,
-one,one,-one,
-one,one,one,
one,one,one,
one,one,-one,
-one,-one,-one,
one,-one,-one,
one,-one,one,
-one,-one,one,
one,-one,-one,
one,one,-one,
one,one,one,
one,-one,one,
-one,-one,-one,
-one,-one,one,
-one,one,one,
-one,one,-one,
});
IntBuffer vertices2 = BufferUtil.intToBuffer(new int[]{
-one, -one, one,
one, -one, one,
one, one, one,
-one, one, one,
});
//圖像的2維坐標與正方體每個面對應的坐標對應關系矩陣,
//存放紋理坐標的數組,指明將繪制的第i個點(i<count)分別對應着貼圖的哪一個角,
// (經過實驗證明紋理貼圖與原來圖像是上下顛倒的)四個角分別用(0,1)(左上角)、(1,1)(右上角)、(1,0)(右下角)、(0,0)(左下角)表示
IntBuffer texCoords = BufferUtil.intToBuffer(new int[]{
// one,0,0,0,0,one,one,one,
0,one,one,one,one,0,0,0,
0,0,0,one,one,one,one,0,
one,one,one,0,0,0,0,one,
0,one,one,one,one,0,0,0,
0,0,0,one,one,one,one,0,
one,0,0,0,0,one,one,one,
});
IntBuffer texCoords2= BufferUtil.intToBuffer(new int[]{
//通過實驗證明生成的紋理貼圖是上下顛倒的,因此vertices里一個平面對應的點應該是上下反過來,才能在矩陣上顯示為正圖像
//按點
// 0,0,
// one,0,
// one,one,
// 0,one
//如:矩陣: 3 2 應該對應的是: 第 0個點:按點位置左下角 0 -> (0,0) 反過來去上 -> (0,1)
// 0 1 ----> 第 3個點:按點位置左上角 3 -> (0,1) 反過來去下 -> (0,0)
//反過來后的對應關系
0,one,
one,one,
one,0,
0,0
});
ByteBuffer indices = ByteBuffer.wrap(new byte[]{
0,1,3,2,
4,5,7,6,
8,9,11,10,
12,13,15,14,
16,17,19,18,
20,21,23,22,
});
public GLRender3(Bitmap mBitmap[])
{
this.mBitmap = mBitmap;
}
@Override
public void onDrawFrame(GL10 gl)
{
// 清除屏幕和深度緩存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 重置當前的模型觀察矩陣
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -4.0f);
//設置3個方向的旋轉
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
gl.glRotatef(yrot, -1.0f, 0.0f, 0.0f);
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//啟用紋理映射
//紋理和四邊形對應的頂點
// gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices);
// gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords);
// //----------------繪制一個矩陣,並投影紋理---------------------------------//
// // 綁定紋理
// gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
// gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices2);
// gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords2);
// ByteBuffer indicesi = ByteBuffer.wrap(new byte[]{
//// 1,2,0,3
// 0,1,3,2
//// 2,3,1,0
//// 3,0,2,1
//
//
////實驗證明,第一個是逆時針畫,第二個順時針這樣循環,否則不對應的就不會畫
// });
// //4指保存的點和繪圖順序就是取連續的3個點繪制三角形。
// gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indicesi);
// //----------------繪制一個立方體,並投影紋理---------------------------------//
//下面是一下畫24個點,直接投影一種紋理和 投影2中紋理
// // 投影一個紋理
// gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices);
// gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords);
// gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
// //用drawElments同時畫24點會導致立方體內部有三角形,只是不透明看不到。
// gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_UNSIGNED_BYTE, indices);
//投影2種紋理
gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices);
gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords);
for(int i = 0 ; i < 6 ; i++)
{
//當i為偶數時候投影第一個紋理,奇數時候投影第二個
if(i%2==0)
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
else
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
int first = i*4;
ByteBuffer indicesi = ByteBuffer.wrap(new byte[]{
(byte) first,(byte)( first+1),(byte)( first+3),(byte)( first+2)
});
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indicesi);
}
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
xrot+=0.5f;
yrot+=0.2f;
zrot+=0.3f;
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
float ratio = (float) width / height;
//設置OpenGL場景的大小
gl.glViewport(0, 0, width, height);
//設置投影矩陣
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩陣
gl.glLoadIdentity();
// 設置視口的大小
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
// 選擇模型觀察矩陣
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置模型觀察矩陣
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// 黑色背景
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_NICEST);
//允許2D貼圖,紋理
gl.glEnable(GL10.GL_TEXTURE_2D);
getTextures(gl);
}
private void getTextures(GL10 gl)
{
IntBuffer intBuffer = IntBuffer.allocate(2);//申請2個紋理存儲空間
// 創建紋理
gl.glGenTextures(2 , intBuffer); //創建2個紋理,綁定intuffer
texture[0] = intBuffer.get(); // 獲取第一個紋理的存儲指針,即紋理存儲位置,位置+1
texture[1] = intBuffer.get(); //獲取下一個紋理存儲的位置
// 設置要使用的紋理
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
//生成紋理
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[0] , 0);//利用圖mBitmap[0]生成紋理,存儲在texture[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);
//生成第二個紋理
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[1] , 0);//利用圖mBitmap[0]生成紋理,存儲在texture[1]
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);
}
}
立方體生成多個紋理圖的效果圖:

