我的android——OpenGL(3)——学习笔记

本文为本人在学习过程中整理的学习笔记,由于本人也是正在学习中,所以如果文章中有什么错误,欢迎各位指教。



1、框架

这里的框架是指为实现在android应用程序中使用OpenGL ES应用而需遵循的固定的方法、格式。一般的,这个框架分为这样几个部分:一是应用程序主体,二是视图类,三是渲染器接口实现,其余为自定义的类。
下面我们一次介绍这几个类的功能。
首先,视图类,这个类继承自GLSurfaceView类,它帮助我们利用OpenGL绘制视图,实现消息响应。我们在实现这个类的构造函数的时候需要设置渲染器,要利用setRenderer()这个方法。
然后是渲染器接口实现,主要是实现其中三个方法,onSurfaceCreated(), onSurfaceChanged() 和 onDrawFrame(),这个是必须做的工作。第一个在surface创建以后调用,第二个是在surface发生改变以后调用,例如从竖屏切换到横 屏的时候,最后一个方法是当任何时候调用一个画图方法的时候。
最后是应用程序主体,主要实现UI。这里应该注意的是我们要重新加载我们定义的视图。
下面是一个小小的例子,我们将在这个例子中绘制一个三角形。
我们的渲染器如下:
package test.triangle;
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 MyRenderer implements GLSurfaceView.Renderer{
private float _red=1.0f;
private float _green=1.0f;
private float _blue=1.0f;
private ShortBuffer indexBuffer;
private FloatBuffer vertexBuffer; //设置顶点缓冲区
private int nOfVertices=3; //顶点个数
private short[] indicesArray = {0, 1, 2}; //索引矩阵
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// preparation
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
initTriangle();
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
}
public void onDrawFrame(GL10 gl) {
// 设置背景颜色,白色
gl.glClearColor(_red, _green, _blue, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//设置三角形颜色,深红色
gl.glColor4f(0.5f, 0f, 0f, 0.5f);
//设置顶点矩阵,供glDrawElements使用
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//绘出三角形
gl.glDrawElements(GL10.GL_TRIANGLES, nOfVertices, GL10.GL_UNSIGNED_SHORT, indexBuffer);
}
private void initTriangle() {
// float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(nOfVertices * 3 * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
// short has 2 bytes
ByteBuffer ibb = ByteBuffer.allocateDirect(nOfVertices * 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);
}
}
这里我们需要注意的是我们不能像OpenGL中一样直接调用函数绘制三角形,而是需要定义坐标矩阵、索引矩阵,还要开辟直接缓存,然后使用glDrawElements这个方法来绘制,这也是OpenGL与OpenGL ES的一个主要区别,OpenGL ES舍弃了一些低效的方法,更适合于嵌入式设备。
下面是我们的视图了
package test.triangle;
import android.content.Context;
import android.opengl.GLSurfaceView;
public class MySurface extends GLSurfaceView{
private MyRenderer mRender;
public MySurface(Context context) {
super(context);
mRender = new MyRenderer();
setRenderer(mRender);
}
}
很简单,就是设置了我们的渲染器,当然你也可以添加一些触发事件。
最后是主体类:
package test.triangle;
import android.app.Activity;
import android.os.Bundle;
public class triangle extends Activity {
/** Called when the activity is first created. */
private MySurface mSurface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSurface=new MySurface(this);
setContentView(mSurface);
}
}
也很简单,只是将我们的视图加载上去。
2、让我们的三角形平移、旋转、缩放。
其实简单的实现是很简单的,主要用到三个方法glTranslate、glRotate、glScale。而三个方法的具体参数及使用方法,在我的gl10方法的解析中有。
下面言归正传,让我们的三角形平移、旋转、缩放。
简单的方法是在onDrawFrame中添加这三个方法,具体代码如下:
//旋转
gl.glRotatef(10, 0f, 1f, 0f);
//平移
gl.glTranslatef(0.1f,0f,0f);
//缩放
if(isSingle){
gl.glScalef(1.0f, 0.95f, 1.0f);
i++;
if(i==50)isSingle=false;
}
else{
gl.glScalef(1.0f, 1.05f, 1.0f);
i--;
if(i==0)isSingle=true;
}
其中isSingle是该类中新添加的Boolean属性,i是用以计数的整型。由于这三个方法的效果会再每次刷屏中时时存在(具体原理需要参见我的gl10方法解析)其中尤其是缩放这个效果会把我们的三角形搞没,所以要放到条件语句中,让三角形变小之后,还能变大,这样不会一下子便没掉。
其实这个平移、旋转、缩放只是我们学习的一个过渡阶段,而不是重点,重点在于后面的3D绘图,所以很多东西也许很重要,但是我们也略过,直奔主题。
当然也留下了一些问题值得思考:
确定这三个方法的作用域以及这三个方法的精确控制。
3、为我们的三角形填充更精致的颜色
之前我们已经使用glColor4f方法为三角形填充为深红色,现在我们用更为有效的方法glColorPointer(该方法的详细说明请到我的gl10方法解析中寻找),当两种同时使用时后者会覆盖掉前者。
由于glColorPointer是客户端功能,并且默认为禁用所以我们要先启用GL_COLOR_ARRAY。同顶点矩阵、索引矩阵的使用方法一样,我们也要为这个颜色矩阵开辟空间。矩阵的每行表示一个点,四列分别表示R、G、B、A四个颜色元素。下面是我们渲染器的实现代码(在1中代码的基础上实现的):
package test.triangle;
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 MyRenderer implements GLSurfaceView.Renderer{
private float _red=1.0f;
private float _green=1.0f;
private float _blue=1.0f;
private ShortBuffer indexBuffer;
private FloatBuffer vertexBuffer; //设置顶点缓冲区
private FloatBuffer colorBuffer; //颜色缓冲区
private int nOfVertices=3; //顶点个数
private short[] indicesArray = {0, 1, 2}; //索引矩阵
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// preparation
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); //启用顶点矩阵功能
gl.glEnableClientState(GL10.GL_COLOR_ARRAY); //启用颜色矩阵功能
initTriangle();
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
}
public void onDrawFrame(GL10 gl) {
// 设置背景颜色,白色
gl.glClearColor(_red, _green, _blue, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//设置三角形颜色,深红色
//gl.glColor4f(0.5f, 0f, 0f, 0.5f);被glColorPointer覆盖了
//设置顶点矩阵,供glDrawElements使用
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//设定颜色
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
//绘出三角形
gl.glDrawElements(GL10.GL_TRIANGLES, nOfVertices, GL10.GL_UNSIGNED_SHORT, indexBuffer);
}
private void initTriangle() {
// float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(nOfVertices * 3 * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
ByteBuffer cbb=ByteBuffer.allocateDirect(nOfVertices*4*4);//每个点有4个颜色元素RGBA,每个元素8位
cbb.order(ByteOrder.nativeOrder());
colorBuffer=cbb.asFloatBuffer();
// short has 2 bytes
ByteBuffer ibb = ByteBuffer.allocateDirect(nOfVertices * 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)
};//三点坐标
float[] colors={
1.0f,0f,0f,1.0f, //第一个点颜色RGBA
0f,1.0f,0f,1.0f, //第二点颜色
0f,0f,1.0f,1.0f //第三点颜色
};
vertexBuffer.put(coords);
colorBuffer.put(colors);
indexBuffer.put(indicesArray);

vertexBuffer.position(0);
colorBuffer.position(0);
indexBuffer.position(0);
}
}

效果图:



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值