Android的OpenGL学习笔记(2)
上篇主要目的是介绍OpenGL的基本框架,这里就用基本的框架绘画出一个三角形,绘制三角形在OpenGL中比较重要,因为在OpenGL(Android)中的图形都是用三角形拼凑起来的!
画三角形有两种,主要是调用的方法不同而已:
第一种,调用glDrawElements()方法绘画:
看代码,主要看继承GLSurfaceView的代码部分,其他的和上篇基本一样:
VortexRenderer.java
- package com.droidnova.android.games.vortex;
- import java.nio.ByteBuffer;
- import java.nio.ByteOrder;
- import java.nio.FloatBuffer;
- import java.nio.ShortBuffer;
- import javax.microedition.khronos.egl.EGLConfig;
- import javax.microedition.khronos.opengles.GL10;
- import android.opengl.GLSurfaceView;
- public class VortexRenderer implements GLSurfaceView.Renderer {
- //private static final String LOG_TAG = VortexRenderer.class.getSimpleName();
- private float _red = 0f;
- private float _green = 0f;
- private float _blue = 0f;
- // a raw buffer to hold indices allowing a reuse of points.
- private ShortBuffer _indexBuffer;
- // a raw buffer to hold the vertices
- private FloatBuffer _vertexBuffer;
- private short[] _indicesArray = {0, 1, 2};//关于索引的理解:即三角形三个顶点的索引,这里暂时画了一个平面二维的三角形,
- //看不出它的作用,当画三维的时候,就会清楚了,这里大概提一下,索引组合可以构成一个面!相当于三个点可以构成一个面,这里用索引代替了三个点而已!
- private int _nrOfVertices = 3;
- private float _angle;
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- // preparation
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- initTriangle();
- }
- @Override
- public void onSurfaceChanged(GL10 gl, int w, int h) {
- gl.glViewport(0, 0, w, h);
- }
- @Override
- public void onDrawFrame(GL10 gl) {
- // define the color we want to be displayed as the "clipping wall"
- gl.glClearColor(_red, _green, _blue, 1.0f);
- gl.glLoadIdentity();//还原场景,还原矩阵。假如你旋转一个三角形之后,调用这个方法,
- //可以让该三角形还原到初始位置,这里的主要作用是为了防止三角形不停的旋转。
- // clear the color buffer to show the ClearColor we called above...
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
- // set rotation
- gl.glRotatef(_angle, 0f, 1f, 0f);//旋转时需要进行3D图像到2D的转换,需要进行浮点运算,
- //会有偏差,所以随着时间的延长,三角形的顶点有偏移现象,暂时就这么理解着!
- gl.glColor4f(0.5f, 0f, 0f, 0.5f);//对三角形进行着色!
- gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);//第三个参数表示在数组元素中,两个有意义的数据单元之间相隔的字节数。
- //当值为0时,表示该数组数据是紧密排列的,没有间隔
- gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
- }
- private void initTriangle() {
- // float has 4 bytes
- ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);
- vbb.order(ByteOrder.nativeOrder());
- _vertexBuffer = vbb.asFloatBuffer();//将字节Buffer转换为FloatBuffer,暂时这么理解的!
- // short has 2 bytes
- ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);//申请空间
- ibb.order(ByteOrder.nativeOrder());//必须设置为原生字节序!
- _indexBuffer = ibb.asShortBuffer();
- float[] coords = {
- -0.5f, -0.5f, 0f, // (x1, y1, z1)
- 0.5f, -0.5f, 0f, // (x2, y2, z2)
- 0f, 0.5f, 0f // (x3, y3, z3)
- };
- _vertexBuffer.put(coords);
- _indexBuffer.put(_indicesArray);
- _vertexBuffer.position(0);
- _indexBuffer.position(0);
- }
- public void setColor(float r, float g, float b) {
- _red = r;
- _green = g;
- _blue = b;
- }
- public void setAngle(float angle) {
- _angle = angle;
- }
- }
VortexView.java
- package com.droidnova.android.games.vortex;
- import android.content.Context;
- import android.opengl.GLSurfaceView;
- import android.view.MotionEvent;
- public class VortexView extends GLSurfaceView {
- // private static final String LOG_TAG = VortexView.class.getSimpleName();
- private VortexRenderer _renderer;
- public VortexView(Context context) {
- super(context);
- _renderer = new VortexRenderer();
- setRenderer(_renderer);
- }
- public boolean onTouchEvent(final MotionEvent event) {
- queueEvent(new Runnable() {
- public void run() {
- _renderer.setColor(event.getX() / getWidth(), event.getY()
- / getHeight(), 1.0f);
- _renderer.setAngle(event.getX());
- }
- });
- return true;
- }
- }
第二种,调用glDrawArrays()绘画三角形:
GLRender.java代码:
- package com.android.myOpenGL;
- import java.nio.ByteBuffer;
- import java.nio.ByteOrder;
- import java.nio.FloatBuffer;
- import javax.microedition.khronos.egl.EGLConfig;
- import javax.microedition.khronos.opengles.GL10;
- import android.opengl.GLSurfaceView.Renderer;
- public class GLRender implements Renderer {
- private float _red = 0.9f;
- private float _green = 0.2f;
- private float _blue = 0.2f;
- private float _angle;
- private FloatBuffer _vertexBuffer;
- private int _nrOfVertices = 3;
- @Override
- public void onDrawFrame(GL10 gl) {
- // TODO Auto-generated method stub
- gl.glClearColor(_red, _green, _blue, 1.0f);
- gl.glLoadIdentity();//如果注释掉这句,效果将如同地球绕太阳旋转一样,自身旋转,也绕太阳公转,注意三角形分正反面
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
- gl.glTranslatef(0.5f, 0f, 0f);
- gl.glRotatef(_angle, 0f, 1f, 0f);//绕Y轴旋转,Y轴正方向单位1处,X,Y,Z三个参数共同决定讯转轴的方向。
- _angle++;//为了测试旋转平移的先后顺序会对结果造成何种影响添加上的,这样也可以让三角形不停的旋转,一般我喜欢这么做!
- /*
- * 先旋转还是先平移,顺序不同,效果也会不同的,具体怎么样的效果,自己运行一下程序,并改变次序,就会得到结果!
- */
- gl.glColor4f(0.5f, 0f, 0f, 0.5f);
- gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
- gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
- //gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);//取消顶点设置,如果在这里添加这句,三角形会一闪而过。为了显示三角形,我们注释掉这句话。
- }
- @Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- // TODO Auto-generated method stub
- gl.glViewport(0, 0, width, height);
- }
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
- // TODO Auto-generated method stub
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- initTriangle();
- }
- private void initTriangle() {
- // float has 4 bytes
- ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);
- vbb.order(ByteOrder.nativeOrder());
- _vertexBuffer = vbb.asFloatBuffer();
- float[] coords = {
- -0.5f, -0.5f, 0f, // (x1, y1, z1)
- 0.5f, -0.5f, 0f, // (x2, y2, z2)
- 0f, 0.5f, 0f // (x3, y3, z3)
- };
- _vertexBuffer.put(coords);
- _vertexBuffer.position(0);
- }
- public void setColor(float r, float g, float b) {
- _red = r;
- _green = g;
- _blue = b;
- }
- public void setAngle(float angle) {
- _angle = angle;
- }
- }
最终效果图都是一样的,如图:
必要的解释都在代码注释中,如有问题,请留言提出,如有错误,也同样请留言指出,小弟感激不尽……