2012/3/19

2012/3/19

第二节

         这节讲Renderer。首先,定义一个自己的Renderer类,比如,MyRenderer。这个类要实现Renderer接口。代码如下:

         public class MyRenderer implements Renderer

{

    public void onDrawFrame(GL10 gl) {}

    public void onSurfaceChanged(GL10gl, intwidth, intheight) {}

    public void onSurfaceCreated(GL10gl, EGLConfig config) {} 

}

    这里讲一下implements。Java中有两个关于继承的很相似的东西,extends和implements关键字。extends和就是C++里面的继承,但是Java里面没有多重继承,所以设计了implements。这里有个帖子讲得特别好,http://apps.hi.baidu.com/share/detail/16567303。大概什么意思呢?就是说,把方法看为对象,拥有几个方法的实体为一个新的对象。这时使用implements,来实现各个方法。我说得很抽象,不懂的话最好还是看下上面这个帖子。

         然后来说下Renderer。我认为可以看为一个容器,其中布满了各种要渲染的对象,比如几个立方体,以及他们的颜色等。在实现Renderer的时候,可以直接利用eclipse的补全功能写出需要实现的接口。分别讲一下。

         onSurfaceCreated(GL10gl, EGLConfig arg1)中,需要做很多初始化工作,一般来说,有这么几件事。

1.      设置清屏时背景的颜色。

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

2.      开启深度测试。

gl.glEnable(GL10.GL_DEPTH_TEST);

3.      启用背面裁剪。

gl.glEnable(GL10.GL_CULL_FACE);

4.      设置初始深度值。

gl.glClearDepthf(1.0f);

5.      设置深度判定规则。

gl.glDepthFunc(GL10.GL_LEQUAL);

6.      选择颜色过渡模式。

gl.glShadeModel(GL10.GL_SMOOTH);

        

         接下来说onSurfaceChanged(GL10gl, int w, int h)。要做这么几件事:

1.      设置视口。什么是视口?可以理解为窗口,就是没有windows中窗口的边缘罢了。换句话说,就是设置你的程序在屏幕上所占的空间。一般设为全屏。

gl.glViewport(0, 0, w, h);

2.      设置透视模式。这里涉及到几个函数:gl.glMatrixMode(GL10.GL_PROJECTION),gluPerspective()和glOrtho()。详细的介绍可以回顾我之前在csdn上发的帖子:http://blog.youkuaiyun.com/ouchz/article/details/7213338。这里大概讲下。glMatrixMode是用来指定哪一个矩阵是当前矩阵,而它的参数代表要操作的目标。GL_PROJECTION是对投影矩阵操作,后面一般跟gluPerspective,设置锥形视图。GL_MODELVIEW是对模型视景矩阵操作,后面一般跟glulookat,设置视点等。顺便讲下glOrtho(),,这叫做正交视图,和锥形视图对比起来理解就很好懂了。一般,我们写三维场景,都是用锥形视图而非正交视图。代码如下:

         publicvoid onSurfaceChanged(GL10 gl, int w, int h) {

                   gl.glViewport(0,0, w, h);

                   gl.glMatrixMode(GL10.GL_PROJECTION);

                   gl.glLoadIdentity();

                   GLU.gluPerspective(gl,45.0f,((float)w)/h, 0.1f, 15f);               

         }

 

         最后是onDrawFrame。要绘制的各种模型就在这里面设置。抛开光照、纹理等不讲,先从最简单的入手。

1.      清除屏幕和深度缓存

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

2.      设置视景矩阵。

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

                   gl.glMatrixMode(GL10.GL_MODELVIEW);

                   gl.glLoadIdentity();

                   GLU.gluLookAt(gl,eyex,eyey,eyez,0,0, 0, 0, 1, 0);

3.      定义一个float数组,装入坐标信息。

4.    glVertexPointer关联顶点数组。该函数的第四个参数类型是Buffer,需要对float类型进行转换。Java里面有个FloatBuffer,其中有个wrap方法,可以把float类型转换为FloatBuffer。但是,我自己在使用时,发现float数组比较大的时候,程序会异常。所以,推荐使用下面这个功能函数:

         publicFloatBuffer makeFloatBuffer(float[] arr) {

ByteBuffer bb =ByteBuffer.allocateDirect(arr.length * 4);                                         bb.order(ByteOrder.nativeOrder());

                   FloatBufferfb = bb.asFloatBuffer();

                   fb.put(arr);

                   fb.position(0);

                   returnfb;

         }

另外,详细讲解下glVertexPointer的几个参数:

voidglVertexPointer(GLint size,GLenum type,GLsizei stride,const GLvoid *pointer)

size,指绑定数组后,每个图形的顶点会用到数组中多少个数据做为顶点的数据。Type,规定调用数组的数据时应该用什么类型。一般与定义的数组的类型是一至的。Stride,规定每个顶点应该从数组中移动的字节。一般情况下写0系统会自动识别。识别方式为size*sizeof(数组定义时报类型)。Pointer,要绑定数组的地址。

5.      启用顶点数组。

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

6.      绘制操作。比如,旋转、平移、上色、绘制。代码如下:

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

gl.glRotatef(yrot, 0, 1, 0);

gl.glTranslatef(3f, 0, 0);

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

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

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

讲下这个函数:glDrawArrays。参数一指明以TRIANGLE_STRIP的方式画面,参数二是开始绘制的顶点号,参数三是一共要绘制的顶点数。

另外,glRotatef的第一个参数是角度,以度为单位。方便测试的话,可以写45度。

7.      还有一个很重要的,构造函数。在里面做各种数据的初始化。可以把数组的wrap工作放到里面。

public MyRenderer(){};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值