【Android】OpenGL ES---绘制3D图形、应用纹理贴图
16lz
2021-01-26
绘制3D图形
glDrawElements(int mode,int count,int type Buffer indices):
- 根据indices指定的索引点来绘制三角形
- 第一个参数mode指定绘制的图形类型,可设置为GL10.GL_TRIANGLES或GL10.GL_TRIANGLE_STRIPE;
- 第二个参数指定一共包含多少个顶点。
- indices参数最重要,它包装了一个长度为3N的数组,比如让该参数包装(0,2,3,
1, 4,5 )数组,这意味着告诉OpenGL ES 要绘制两个三角形,第一个三角形的三个顶点为0、2、3顶点,第二个三角形的三个顶点为1、4、5顶点。
MyRenderer.java
public class MyRenderer implements GLSurfaceView.Renderer { float[] taperVertices = new float[]{ 0.0f,0.5f,0.0f,//0 -0.5f,-0.5f,-0.2f,//1 0.5f,-0.5f,-0.2f,//2 0.0f,-0.6f,0.2f//3 }; int [] taperColors = new int[]{ 65535,0,0,0, 0,65535,0,0, 0,0,65535,0, 65535,65535,0 }; byte[] taperFaces = new byte[]{ 0,1,2, 0,1,3, 1,2,3, 0,2,3 }; FloatBuffer taperVerticesBuffer; IntBuffer taperColorsBuffer; ByteBuffer taperFacesBuffer; private float angle = 1.0f; public MyRenderer(){ taperVerticesBuffer = Utils.getFloatBuffer(taperVertices); taperColorsBuffer = Utils.getIntBuffer(taperColors); taperFacesBuffer = Utils.getByteBuffer(taperFaces); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.1f,0.1f,0.1f,0.0f); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); float ratio = (float) width/height; gl.glFrustumf(-ratio,ratio,-1,1,1,10); } @Override public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //所有的旋转和缩放都是在ModelView下进行的 gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f,0.0f,-1.5f); gl.glRotatef(angle,0f,0.2f,0f); gl.glVertexPointer(3,GL10.GL_FLOAT,0,taperVerticesBuffer); gl.glColorPointer(4,GL10.GL_FIXED,0,taperColorsBuffer); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,taperFacesBuffer.remaining(), GL10.GL_UNSIGNED_BYTE,taperFacesBuffer); gl.glFinish(); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); angle++; }}
Utils.java
public class Utils { public static FloatBuffer getFloatBuffer(float[] floats){ FloatBuffer floatBuffer; ByteBuffer byteBuffer = ByteBuffer.allocateDirect(floats.length*4); byteBuffer.order(ByteOrder.nativeOrder()); floatBuffer = byteBuffer.asFloatBuffer(); floatBuffer.put(floats); floatBuffer.position(0); return floatBuffer; } public static IntBuffer getIntBuffer(int[] arrays){ IntBuffer intBuffer; ByteBuffer byteBuffer = ByteBuffer.allocateDirect(arrays.length*4); byteBuffer.order(ByteOrder.nativeOrder()); intBuffer = byteBuffer.asIntBuffer(); intBuffer.put(arrays); intBuffer.position(0); return intBuffer; } public static ByteBuffer getByteBuffer(byte[] arrays){ ByteBuffer byteBuffer; byteBuffer = ByteBuffer.allocateDirect(arrays.length*4); byteBuffer.order(ByteOrder.nativeOrder()); byteBuffer.put(arrays); byteBuffer.position(0); return byteBuffer; }}
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GLSurfaceView surfaceView = new GLSurfaceView(this); surfaceView.setRenderer(new MyRenderer()); setContentView(surfaceView); }}
绘制立方体
MyRenderer.java
public class MyRenderer implements GLSurfaceView.Renderer { float[] cubeVertices = new float[]{ //前面四个顶点 0.5f,0.5f,0.5f,//0 -0.5f,0.5f,0.5f,//1 -0.5f,-0.5f,0.5f,//2 0.5f,-0.5f,0.5f,//3 //后面四个顶点 0.5f,0.5f,-0.5f,//4 -0.5f,0.5f,-0.5f,//5 -0.5f,-0.5f,-0.5f,//6 0.5f,-0.5f,-0.5f//7 }; int [] cubeColors = new int[]{ 65535,0,0,0, 0,65535,0,0, 0,0,65535,0, 65535,65535,0, 65535,0,0,0, 0,65535,0,0, 0,0,65535,0, 65535,65535,0 }; //正方体 byte[] cubeFaces = new byte[]{ //前后面 0,1,2, 0,2,3, 4,5,6, 4,6,7, //左右面 1,2,5, 2,5,6, 0,3,4, 3,4,7, //上下面 0,1,4, 1,4,5, 2,3,6, 3,6,7 }; FloatBuffer cubeVerticesBuffer; IntBuffer cubeColorsBuffer; ByteBuffer cubeFacesBuffer; private float angle = 1.0f; public MyRenderer(){ cubeVerticesBuffer = Utils.getFloatBuffer(cubeVertices); cubeColorsBuffer = Utils.getIntBuffer(cubeColors); cubeFacesBuffer = Utils.getByteBuffer(cubeFaces); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.1f,0.1f,0.1f,0.0f); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); float ratio = (float) width/height; gl.glFrustumf(-ratio,ratio,-1,1,1,10); } @Override public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //所有的旋转和缩放都是在ModelView下进行的 gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f,0.0f,-2.5f); gl.glRotatef(angle,0f,0.2f,0f); gl.glRotatef(angle,0.2f,0f,0f); gl.glVertexPointer(3,GL10.GL_FLOAT,0, cubeVerticesBuffer); gl.glColorPointer(4,GL10.GL_FIXED,0, cubeColorsBuffer); //gl.glColor4f(1,0,0,0); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, cubeFacesBuffer.remaining(), GL10.GL_UNSIGNED_BYTE, cubeFacesBuffer); gl.glFinish(); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); angle++; }}
应用纹理贴图
在onSurfaceCreated(GL10 gl, EGLConfig config)中启动纹理贴图
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GLSurfaceView surfaceView = new GLSurfaceView(this); //surfaceView.setRenderer(new Texture2DRenderer(MainActivity.this));//正方形贴图 surfaceView.setRenderer(new PureColorCubeRenderer());//立方体不同面纯色 //surfaceView.setRenderer(new CubeGraduateRenderer());//正方体,纯色过度 //surfaceView.setRenderer(new Texture3DRenderer(this));//立方体贴图 //surfaceView.setRenderer(new Special3DFigureRenderer(this)); setContentView(surfaceView); }}
Texture3DRenderer.java
public class Texture3DRenderer implements GLSurfaceView.Renderer { float[] cubeVertices = new float[]{ //前面四个顶点// 0.5f,0.5f,0.5f,//0// -0.5f,0.5f,0.5f,//1// -0.5f,-0.5f,0.5f,//2// 0.5f,-0.5f,0.5f,//3// //后面四个顶点// 0.5f,0.5f,-0.5f,//4// -0.5f,0.5f,-0.5f,//5// -0.5f,-0.5f,-0.5f,//6// 0.5f,-0.5f,-0.5f,//7 0.5f,0.5f,0.5f,//0 -0.5f,0.5f,0.5f,//1 -0.5f,-0.5f,0.5f,//2 0.5f,0.5f,0.5f,//0 -0.5f,-0.5f,0.5f,//2 0.5f,-0.5f,0.5f,//3 0.5f,0.5f,-0.5f,//4 -0.5f,0.5f,-0.5f,//5 -0.5f,-0.5f,-0.5f,//6 0.5f,0.5f,-0.5f,//4 -0.5f,-0.5f,-0.5f,//6 0.5f,-0.5f,-0.5f,//7 -0.5f,0.5f,0.5f,//1 -0.5f,-0.5f,0.5f,//2 -0.5f,0.5f,-0.5f,//5 -0.5f,-0.5f,0.5f,//2 -0.5f,0.5f,-0.5f,//5 -0.5f,-0.5f,-0.5f,//6 0.5f,0.5f,0.5f,//0 0.5f,-0.5f,0.5f,//3 0.5f,0.5f,-0.5f,//4 0.5f,-0.5f,0.5f,//3 0.5f,0.5f,-0.5f,//4 0.5f,-0.5f,-0.5f,//7 0.5f,0.5f,0.5f,//0 -0.5f,0.5f,0.5f,//1 0.5f,0.5f,-0.5f,//4 -0.5f,0.5f,0.5f,//1 0.5f,0.5f,-0.5f,//4 -0.5f,0.5f,-0.5f,//5 -0.5f,-0.5f,0.5f,//2 0.5f,-0.5f,0.5f,//3 -0.5f,-0.5f,-0.5f,//6 0.5f,-0.5f,0.5f,//3 -0.5f,-0.5f,-0.5f,//6 0.5f,-0.5f,-0.5f,//7 }; //正方体 byte[] cubeFaces = new byte[]{ //前后面 0,1,2, 3,4,5, 6,7,8, 9,10,11, //左右面 12,13,14, 15,16,17, 18,19,20, 21,22,23, //上下面 24,25,26, 27,28,29, 30,31,32, 33,34,35 }; float[] texturesVertices = new float[]{ //前 1.0f,0.0f, 0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f,1.0f, //后 0.0f,0.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 0.0f,1.0f, //左 1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f, //右 0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f, 1.0f,1.0f, //上 1.0f,1.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,0.0f, //下 0.0f,0.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f,1.0f }; FloatBuffer cubeVerticesBuffer; ByteBuffer cubeFacesBuffer; FloatBuffer texturesVerticesBuffer; private Context context; private int texture; private float anglex = 1.0f; private float angley = 1.0f; public Texture3DRenderer(Context context){ this.context = context; cubeVerticesBuffer = Utils.getFloatBuffer(cubeVertices); cubeFacesBuffer = Utils.getByteBuffer(cubeFaces); texturesVerticesBuffer = Utils.getFloatBuffer(texturesVertices); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.1f,0.1f,0.1f,0.0f); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glEnable(GL10.GL_TEXTURE_2D); loadTexture(gl); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); float ratio = (float) width/height; gl.glFrustumf(-ratio,ratio,-1,1,1,10); } @Override public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //所有的旋转和缩放都是在ModelView下进行的 gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f,0.0f,-2.5f); gl.glRotatef(angley,0f,0.2f,0f); gl.glRotatef(anglex,0.2f,0f,0f); gl.glVertexPointer(3,GL10.GL_FLOAT,0, cubeVerticesBuffer); gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,texturesVerticesBuffer); gl.glBindTexture(GL10.GL_TEXTURE_2D,texture); gl.glDrawElements(GL10.GL_TRIANGLES, cubeFacesBuffer.remaining(), GL10.GL_UNSIGNED_BYTE, cubeFacesBuffer); gl.glFinish(); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); anglex++; angley+=2; } private void loadTexture(GL10 gl) { Bitmap bitmap = null; bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.a1111); int[] textures = new int[4]; gl.glGenTextures(1,textures,0); texture = textures[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D,texture); gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); 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); GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bitmap,0); }}
总结
在实现这个贴图的过程中当中,要注意纹理映射的顶点数组(textureVertices)中的值是要与顶点数组(cubeVertices)中的值一一对应的
更多相关文章
- Android(安卓)Paint绘制边框注意事项
- ListView从底部开始绘制和新item自动移动到底部
- android View 树的理解
- android布局优化 笔记
- Android(安卓)TV native层中Canvas库的实现思路
- 探究Android(安卓)View 绘制流程,Canvas 的由来。
- Android(安卓)绘制线程动画
- 这是我见过有关Android(安卓)RecyclerView最好的一篇文章:深入解
- Android图形显示系统——上层显示2:硬件加速实现