最近学习 opengl,看了一些简单的教程。发现一般都是到实现金字塔或者立方体就结束了。
纹理方面,对三维物体的多个面未做处理。参看了这些例子,做一个android 上的多纹理的立方体。
效果图:
1.
2.
以下是主要代码:
Activity负责初始化相关资源文件。重写了onTouchEvent()方法,实现鼠标翻转,方便观察。
主类:
public class Cube extends Activity { GLRender render = new GLRender(); private float mPreviousX; private float mPreviousY; private final float TOUCH_SCALE_FACTOR = 180.0f / 320; private final float TRACKBALL_SCALE_FACTOR = 36.0f; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GLImage.load(this.getResources()); GLSurfaceView glView = new GLSurfaceView(this); glView.setRenderer(render); setContentView(glView); } public boolean onKeyUp(int keyCode, KeyEvent event) { render.onKeyUp(keyCode, event); return false; } public boolean onTrackballEvent(MotionEvent e) { render.xrot += e.getX() * TRACKBALL_SCALE_FACTOR; render.yrot += e.getY() * TRACKBALL_SCALE_FACTOR; return true; } public boolean onTouchEvent(MotionEvent e) { float x = e.getX(); float y = e.getY(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: float dx = x - mPreviousX; float dy = y - mPreviousY; render.xrot += dx * TOUCH_SCALE_FACTOR; render.yrot += dy * TOUCH_SCALE_FACTOR; } mPreviousX = x; mPreviousY = y; return true; } } class GLImage { public static Bitmap mBitmap1; public static Bitmap mBitmap2; public static Bitmap mBitmap3; public static Bitmap mBitmap4; public static Bitmap mBitmap5; public static Bitmap mBitmap6; public static void load(Resources resources) { mBitmap1 = BitmapFactory.decodeResource(resources, R.drawable.icon1); mBitmap2 = BitmapFactory.decodeResource(resources, R.drawable.icon2); mBitmap3 = BitmapFactory.decodeResource(resources, R.drawable.icon3); mBitmap4 = BitmapFactory.decodeResource(resources, R.drawable.icon4); mBitmap5 = BitmapFactory.decodeResource(resources, R.drawable.icon5); mBitmap6 = BitmapFactory.decodeResource(resources, R.drawable.icon6); } }
Render实现有修改:
public class GLRender implements Renderer { boolean key = true; float xrot = 0.0f; float yrot = 0.0f; float xspeed, yspeed; float z = -5.0f; int one = 0x10000; //光线参数 FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f,0.5f,0.5f,1.0f}); FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f,1.0f,1.0f,1.0f}); FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,0.0f,2.0f,1.0f}); int [] texture; // 六个面,一个面4个点 int[] vertice = 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, }; int[] normal = new int[]{ 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,one,0, 0,one,0, 0,one,0, 0,one,0, 0,-one,0, 0,-one,0, 0,-one,0, 0,-one,0, one,0,0, one,0,0, one,0,0, one,0,0, -one,0,0, -one,0,0, -one,0,0, -one,0,0, }; // 纹理映射数据 int[] texCoord = new int[]{ one,0,0,0,0,one,one,one, 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 vertices=GLTool.getIntBu(vertice); IntBuffer normals=GLTool.getIntBu(normal); IntBuffer texCoords=GLTool.getIntBu(texCoord); ByteBuffer indices1 = ByteBuffer.wrap(new byte[]{ 0,1,3,2, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }); ByteBuffer indices2 = ByteBuffer.wrap(new byte[]{ 0,0,0,0, 4,5,7,6, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }); ByteBuffer indices3 = ByteBuffer.wrap(new byte[]{ 0,0,0,0, 0,0,0,0, 8,9,11,10, 0,0,0,0, 0,0,0,0, 0,0,0,0, }); ByteBuffer indices4 = ByteBuffer.wrap(new byte[]{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 12,13,15,14, 0,0,0,0, 0,0,0,0, }); ByteBuffer indices5 = ByteBuffer.wrap(new byte[]{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 16,17,19,18, 0,0,0,0, }); ByteBuffer indices6 = ByteBuffer.wrap(new byte[]{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 20,21,23,22, }); @Override public void onDrawFrame(GL10 gl) { // 清除屏幕和深度缓存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); // 重置当前的模型观察矩阵 gl.glLoadIdentity(); gl.glEnable(GL10.GL_LIGHTING); //////////////// gl.glTranslatef(0.0f, 0.0f, z); //设置旋转 gl.glRotatef(xrot, 0.0f, 1.0f, 0.0f); gl.glRotatef(yrot, 1.0f, 0.0f, 0.0f); gl.glNormalPointer(GL10.GL_FIXED, 0, normals); gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices); gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords); gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //绘制四边形 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_BYTE, indices1); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 8, GL10.GL_UNSIGNED_BYTE, indices2); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[2]); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 12, GL10.GL_UNSIGNED_BYTE, indices3); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[3]); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 16, GL10.GL_UNSIGNED_BYTE, indices4); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[4]); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 20, GL10.GL_UNSIGNED_BYTE, indices5); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[5]); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_UNSIGNED_BYTE, indices6); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); //修改旋转角度 xrot+=0.3f; yrot+=0.2f; //混合开关 if (key) { gl.glEnable(GL10.GL_BLEND); // 打开混合 gl.glDisable(GL10.GL_DEPTH_TEST); // 关闭深度测试 } else { gl.glDisable(GL10.GL_BLEND); // 关闭混合 gl.glEnable(GL10.GL_DEPTH_TEST); // 打开深度测试 } } @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.glDisable(GL10.GL_DITHER); // 告诉系统对透视进行修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); // 黑色背景 gl.glClearColor(0, 0, 0, 0); gl.glEnable(GL10.GL_CULL_FACE); // 启用阴影平滑 gl.glShadeModel(GL10.GL_SMOOTH); // 启用深度测试 gl.glEnable(GL10.GL_DEPTH_TEST); //设置光线,,1.0f为全光线,a=50% gl.glColor4f(1.0f,1.0f,1.0f,0.5f); // 基于源象素alpha通道值的半透明混合函数 gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE); //纹理相关 IntBuffer textureBuffer = IntBuffer.allocate(6); gl.glGenTextures(6, textureBuffer); texture = textureBuffer.array(); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap1, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap2, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[2]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap3, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[3]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap4, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[4]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap5, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[5]); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap6, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); //深度测试相关 gl.glClearDepthf(1.0f); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); gl.glEnable(GL10.GL_TEXTURE_2D); //设置环境光 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient); //设置漫射光 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse); //设置光源位置 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition); //开启一号光源 gl.glEnable(GL10.GL_LIGHT1); //开启混合 gl.glEnable(GL10.GL_BLEND); } public boolean onKeyUp(int keyCode, KeyEvent event) { key = !key; return false; } }
自定义的工具类:
public class GLTool { /* *返回字节化的intbuffer */ public static IntBuffer getIntBu(int[] source){ ByteBuffer bb = ByteBuffer.allocateDirect(source.length*4); bb.order(ByteOrder.nativeOrder()); IntBuffer vertices = bb.asIntBuffer(); vertices.put(source); vertices.position(0); return vertices; } }转自:http://blog.csdn.net/one2zero/article/details/5895548