android opengl 简书,Android OpenGL 使用

基本框架

编写一个类来继承GLSurfaceView.Renderer,并实现其中的三个方法onSurfaceCreated、onSurfaceChanged、onDrawFrame。

/**

* 基本框架

* Created by mazaiting on 2017/8/9.

*/

public class GLRenderer implements GLSurfaceView.Renderer {

/**

* 在窗口被创建时被调用,需要做一些必要的初始化工作:

*/

@Override public void onSurfaceCreated(GL10 gl, EGLConfig config) {

// 启动阴影平滑

gl.glShadeModel(GL10.GL_SMOOTH);

// 黑色背景,设置清楚屏幕时所用的颜色取值:RGBA.0f-1.0f

gl.glClearColor(0, 0, 0, 1.0f);

// 设置深度缓存--决定哪个物体先画

gl.glClearDepthf(1.0f);

// 启动深度测试

gl.glEnable(GL10.GL_DEPTH_TEST);

// 所作深度测试的类型

gl.glDepthFunc(GL10.GL_LEQUAL);

// 告诉系统对透视进行修正

gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

}

/**

* 当窗口大小发生改变时被调用,不管窗口的大小是否已经改变,在程序开始时至少运行一次。

*/

@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 onDrawFrame(GL10 gl) {

// 清楚屏幕和深度缓存

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

// 重置当前的模型观察矩阵

gl.glLoadIdentity();

// 具体绘图开始...

}

/**

* OpenGL 是一个非常底层的画图接口,它所使用的缓冲区存储结构是和我们的 java 程序中不相同的。

* Java 是大端字节序(BigEdian),而 OpenGL 所需要的数据是小端字节序(LittleEdian)。

* 所以,我们在将 Java 的缓冲区转化为 OpenGL 可用的缓冲区时需要作一些工作。建立buff的方法如下

**/

public Buffer bufferUtil(int []arr){

// 先初始化buffer,数组的长度*4,因为一个int占4个字节

ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);

// 数组排列用nativeOrder

qbb.order(ByteOrder.nativeOrder());

// 将ByteBuffer转换为IntBuffer

IntBuffer mBuffer = qbb.asIntBuffer();

// 将数组设置进去

mBuffer.put(arr);

//mBuffer.position(0);

// 重置

mBuffer.flip();

return mBuffer;

}

}

其中都是一些具体的配置,在主Activity中,我们首先创建出一个GLRenderer对象 ,并创建GLSurfaceView对象,将GLRenderer对象设置在GLSurfaceView对象中。、

public class MainActivity extends AppCompatActivity {

@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// 基础框架

GLSurfaceView.Renderer renderer = new GLRenderer();

GLSurfaceView glView = new GLSurfaceView(this);

glView.setRenderer(renderer);

// 设置布局

setContentView(glView);

}

}

至此,我们将OpenGL开发时所要做的配置已完成,接下来我们在写新的Renderer时,只需要继承在GLRenderer,重写onDrawFrame(GL10 gl)方法即可。

绘制多边形

实现此类后,要想看到效果,务必将主AcitivityGLSurfaceView.Renderer renderer = new GLRenderer();的此行代码更改为GLSurfaceView.Renderer renderer = new PolygonRenderer();

/**

* 绘制多边形

* Created by mazaiting on 2017/8/9.

*/

public class PolygonRenderer extends GLRenderer{

int one = 0x00010000;

//三角形三个顶点

private int[] triggerBuffer = new int[] {

0, one, 0,//上顶点

- one, -one, 0, //左下点

one, -one, 0,}; //右下点

//正方形的4个顶点

private int[] quaterBuffer = new int[]{

one,one,0,

-one,one,0,

one,-one,0,

-one,-one,0};

@Override public void onDrawFrame(GL10 gl) {

super.onDrawFrame(gl);

// 此函数,就是将画笔沿X轴左移1.5f个单位,Y轴保持不变,Z轴向屏幕里面移动6.0f个单位。

//gl.glTranslatef(-1.5f, 0.0f, -6.0f);

// 左移 1.5 单位,并移入屏幕 6.0

gl.glTranslatef(-1.5f, 0.0f, -6.0f);// z 轴值小于-1.0f

// 允许设置顶点

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

// 设置三角形

gl.glVertexPointer(3, GL10.GL_FIXED, 0, bufferUtil(triggerBuffer));

// 绘制三角形

gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);

// 重置当前模型观察矩阵

gl.glLoadIdentity();

// 右移 1.5 单位,并移入屏幕 6.0

gl.glTranslatef(1.5f, 0.0f, -6.0f);// z 轴值小于-1.0f

// 设置四边形

gl.glVertexPointer(3,GL10.GL_FIXED,0,bufferUtil(quaterBuffer));

// 绘制四边形

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);

//取消顶点设置

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

// 重置当前的模型观察矩阵

gl.glLoadIdentity();

}

}

效果图:

2a2c06007210

绘制多边形.png

绘制颜色

实现此类后,要想看到效果,务必将主AcitivityGLSurfaceView.Renderer renderer = new GLRenderer();的此行代码更改为GLSurfaceView.Renderer renderer = new ColorRenderer();

/**

* 绘制颜色

* Created by mazaiting on 2017/8/9.

*/

public class ColorRenderer extends GLRenderer {

int one = 0x10000;

//三角形三个顶点 (r,g,b,a)

private int[] triggerBuffer = new int[] {

0, one, 0,//上顶点

- one, -one, 0, //左下点

one, -one, 0,}; //右下点

//正方形的4个顶点

private int[] quaterBuffer = new int[]{

one,one,0,

-one,one,0,

one,-one,0,

-one,-one,0};

//三角形的顶点颜色值(r,g,b,a)

private int[] colorBuffer = new int[]{

one,0,0,one,

0,one,0,one,

0,0,one,one,

};

@Override public void onDrawFrame(GL10 gl) {

super.onDrawFrame(gl);

// 左移 1.5 单位,并移入屏幕 6.0

gl.glTranslatef(-1.5f,0.0f,-6.0f);

//设置定点数组

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//设置颜色数组 -- 开启颜色渲染功能.

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// 设置三角形顶点的颜色

gl.glColorPointer(4,GL10.GL_FIXED,0,bufferUtil(colorBuffer));

// 设置三角形顶点

gl.glVertexPointer(3,GL10.GL_FIXED,0,bufferUtil(triggerBuffer));

gl.glDrawArrays(GL10.GL_TRIANGLES,0,3);

//关闭颜色数组 -- 关闭颜色渲染功能.

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

gl.glLoadIdentity();

// 右移 1.5 单位,并移入屏幕 6.0

gl.glTranslatef(1.5f,0.0f,-6.0f);

// 设置当前色为蓝色

gl.glColor4f(0.0f,0.5f,1.0f,1.0f);

//设置和绘制正方形

gl.glVertexPointer(3,GL10.GL_FIXED,0,bufferUtil(quaterBuffer));

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);

//取消顶点数组

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

}

}

效果图:

2a2c06007210

绘制颜色.png

绘制旋转

实现此类后,要想看到效果,务必将主AcitivityGLSurfaceView.Renderer renderer = new GLRenderer();的此行代码更改为GLSurfaceView.Renderer renderer = new RotateRenderer();

/**

* 绘制旋转图形

* Created by mazaiting on 2017/8/9.

*/

public class RotateRenderer extends GLRenderer {

int one = 0x00010000;

//三角形三个顶点

private int[] triggerBuffer = new int[] {

0, one, 0,//上顶点

- one, -one, 0, //左下点

one, -one, 0,}; //右下点

@Override public void onDrawFrame(GL10 gl) {

super.onDrawFrame(gl);

gl.glTranslatef(-1.5f,0.0f,-6.0f);

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glRotatef(180f,0,0,0);//旋转180

gl.glVertexPointer(3,GL10.GL_FIXED,0,bufferUtil(triggerBuffer));

gl.glDrawArrays(GL10.GL_TRIANGLES,0,3);

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glLoadIdentity();

}

}

效果图:

2a2c06007210

绘制旋转.png

绘制三棱锥

实现此类后,要想看到效果,务必将主AcitivityGLSurfaceView.Renderer renderer = new GLRenderer();的此行代码更改为GLSurfaceView.Renderer renderer = new PyramidRenderer();

/**

* 四棱锥

* Created by mazaiting on 2017/8/9.

*/

public class PyramidRenderer extends GLRenderer {

int one = 0x10000;

// 四棱锥顶点数组:

private int[] triggerBuffer = new int[] {

0, one, 0,

-one, -one, one,

one, -one, one,

0,one, 0,

one,-one, one,

one, -one, -one,

0, one, 0,

one, -one, -one,

-one, -one, -one,

0, one, 0,

-one, -one, -one,

-one, -one, one

};

/**

* Every vertex has got its own color, described by 4 values

* R(ed)

* G(green)

* B(blue)

* A(lpha)

*/

int colors[] = {

0, 0, 0, one, one, 0, 0, one, one, one, 0, one, 0, one, 0, one, 0, 0, one, one, one, 0, one,

one, one, one, one, one, 0, one, one, one,

};

/**

* The last thing is that we need to describe some Triangles.

* A triangle got 3 vertices.

* The confusing thing is, that it is important in which order

* the vertices of each triangle are described.

* So describing a triangle through the vertices: "0, 4, 5"

* will not result in the same triangle as: "0, 5, 4"

* You probably ask: Why the hell isn't that the same ???

* The reason for that is the call of: "gl.glFrontFace(gl.GL_CW);"

* which means, that we have to describe the "visible" side of the

* triangles by naming its vertices in a ClockWise order!

* From the other side, the triangle will be 100% lookthru!

* You can create a kind of magic mirror with that

**/

byte indices[] = {

0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 4, 7, 6, 4, 6, 5, 3,

0, 1, 3, 1, 2

};

@Override public void onSurfaceChanged(GL10 gl, int width, int height) {

super.onSurfaceChanged(gl, width, height);

// 设置透视范围

GLU.gluPerspective(gl, 45.0f, ((float) width) / height, 0.1f, 10f);

}

float xRot = 0.0f;

float yRot = 0.0f;

@Override public void onDrawFrame(GL10 gl) {

super.onDrawFrame(gl);

gl.glMatrixMode(GL10.GL_MODELVIEW);// 切换至模型观察矩阵

gl.glLoadIdentity();// 重置当前的模型观察矩阵

GLU.gluLookAt(gl, 0f, 0f, 3f, 0f, 0f, 0f, 0f, 1f, 0f);//设置视点和模型中心位置

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glVertexPointer(3, GL10.GL_FIXED, 0, bufferUtil(triggerBuffer));

gl.glRotatef(xRot,1f,0f,0f);// 绕着(0,0,0)与(1,0,0)即x轴旋转

gl.glRotatef(yRot,0f,1f,0f);

gl.glColor4f(1.0f,0.0f,0.0f,1.0f);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);

gl.glColor4f(0.0f,1.0f,0.0f,1.0f);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 3, 3);

gl.glColor4f(0.0f,0.0f,1.0f,1.0f);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 6, 3);

gl.glColor4f(1.0f,0.0f,1.0f,1.0f);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 9, 3);

xRot += 1.0f;

yRot += 0.5f;

}

}

效果图:

2a2c06007210

三棱锥.png

绘制正方体

实现此类后,要想看到效果,务必将主AcitivityGLSurfaceView.Renderer renderer = new GLRenderer();的此行代码更改为GLSurfaceView.Renderer renderer = new CubeRenderer();

/**

* 绘制正方体

* Created by mazaiting on 2017/8/10.

*/

public class CubeRenderer extends GLRenderer{

float box[] = new float[] {

// FRONT

-0.5f, -0.5f, 0.5f,

0.5f, -0.5f, 0.5f,

-0.5f, 0.5f, 0.5f,

0.5f, 0.5f, 0.5f,

// BACK

-0.5f, -0.5f, -0.5f,

-0.5f, 0.5f, -0.5f,

0.5f, -0.5f, -0.5f,

0.5f, 0.5f, -0.5f,

// LEFT

-0.5f, -0.5f, 0.5f,

-0.5f, 0.5f, 0.5f,

-0.5f, -0.5f, -0.5f,

-0.5f, 0.5f, -0.5f,

// RIGHT

0.5f, -0.5f, -0.5f,

0.5f, 0.5f, -0.5f,

0.5f, -0.5f, 0.5f,

0.5f, 0.5f, 0.5f,

// TOP

-0.5f, 0.5f, 0.5f,

0.5f, 0.5f, 0.5f,

-0.5f, 0.5f, -0.5f,

0.5f, 0.5f, -0.5f,

// BOTTOM

-0.5f, -0.5f, 0.5f,

-0.5f, -0.5f, -0.5f,

0.5f, -0.5f, 0.5f,

0.5f, -0.5f, -0.5f,

};

FloatBuffer cubeBuff;

float xRot = 0.0f;

float yRot = 0.0f;

public CubeRenderer(){

cubeBuff = makeFloatBuffer(box);//转换为float数组

}

@Override public void onSurfaceChanged(GL10 gl, int width, int height) {

super.onSurfaceChanged(gl, width, height);

// 设置透视范围

GLU.gluPerspective(gl,45.0f,((float)width)/height,0.1f,10f);

}

@Override public void onDrawFrame(GL10 gl) {

super.onDrawFrame(gl);

gl.glMatrixMode(GL10.GL_MODELVIEW);// 切换至模型观察矩阵

gl.glLoadIdentity();// 重置当前的模型观察矩阵

GLU.gluLookAt(gl,0f,0f,3f,0f,0f,0f,0f,1f,0f);//设置视点和模型中心位置

gl.glVertexPointer(3,GL10.GL_FLOAT, 0,cubeBuff);//设置顶点数据

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glRotatef(xRot,1f,0f,0f);// 绕着(0,0,0)与(1,0,0)即x轴旋转

gl.glRotatef(yRot,0f,1f,0f);

gl.glColor4f(1.0f,0f,0f,1.0f);//设置颜色,红色

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);//绘制正方形FRONT面

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,4,4);

gl.glColor4f(0f,1.0f,0f,1.0f);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,8,4);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,12,4);

gl.glColor4f(0f,0f,1.0f,1.0f);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,16,4);

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,20,4);

xRot += 1.0f;

yRot += 0.5f;

}

/**

* 将float数组转换为存储在字节缓冲数组

* @param arr

* @return

*/

public FloatBuffer makeFloatBuffer(float[] arr){

// 分配缓冲空间,一个float占4个字节

ByteBuffer byteBuffer = ByteBuffer.allocateDirect(arr.length*4);

// 设置字节顺序,其中ByteOrder.nativeOrder()是获取本机字节顺序

byteBuffer.order(ByteOrder.nativeOrder());

// 转换为float型

FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();

// 添加数据

floatBuffer.put(arr);

// 设置数组的起始位置

floatBuffer.position(0);

return floatBuffer;

}

}

效果图:

2a2c06007210

立方体.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值