初始化一个opengl ES视图
初始化一个opengl 视图一向很简单,在安卓平台也不例外。你只需要从两件事入手就可以。
GLSurfaceView
GLSurfaceView是Android 1.5之后提供的一个类,可以帮助我们开发opengl ES程序。
提供glue-code用于连接opengl ES到系统视图中。
提供glue-code使opengl ES工作在Activity的生命周期。
使得选择frame buffer的像素格式变得容易。
创建并且管理一个独立的渲染线程,从而使平滑动画变得可能。
提供一个易于使用的debug工具,来跟踪opengl调用和检查错误。
如果你想要你的opengl ES应用运行流畅,这就是你需要开始了解的地方。
你唯一需要调用的方法就是:
?1public void setRenderer(GLSurfaceView.Renderer renderer)
更多可以参考这里:GLSurfaceView
GLSurfaceView.Renderer
GLSurfaceView.Renderer是GLSurfaceView的内部静态接口。在你实现这个接口的时候,你应该把你用来渲染的调用都放进来。
// 在surface被创建或者重复创建的时候调用
public void onSurfaceCreated(GL10 gl, EGLConfig config)
// 用来绘制当前帧
public void onDrawFrame(GL10 gl)
// 在surface大小改变的时候调用
public void onSurfaceChanged(GL10 gl, int width, int height)
onSurfaceCreated
这个方法适合用来初始化一些在渲染周期里不经常变动的东西。诸如用什么颜色清空屏幕,开启z-buffer等。
onDrawFrame
这是实际渲染的方法。
onSurfaceChanged
如果你的设备支持横竖屏切换,那么在切换时会被调用此方法。这个方法用来设置新的比例。
更多可以参考这里:GLSurfaceView.Renderer
组装代码
首先我们创建一个Activity,保持简洁。
package se.jayway.opengl.tutorial;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class TutorialPartI extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GLSurfaceView view = new GLSurfaceView(this);
view.setRenderer(new OpenGLRenderer());
setContentView(view);
}
}
我们的Renderer类处理一些初始化的工作,让我们来看一下,我稍作解释。
package se.jayway.opengl.tutorial;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
public class OpenGLRenderer implements Renderer {
/*
* (non-Javadoc)
*
* @see
* android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.
* microedition.khronos.opengles.GL10, javax.microedition.khronos.
* egl.EGLConfig)
*/
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 设置背景色为黑色( rgba ).
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
// 开启平滑阴影,默认是不需要
gl.glShadeModel(GL10.GL_SMOOTH);
// 初始化depth缓冲
gl.glClearDepthf(1.0f);
// 开启depth测试
gl.glEnable(GL10.GL_DEPTH_TEST);
// 设置depth测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
// 最佳的透视计算
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
GL10.GL_NICEST);
}
/*
* (non-Javadoc)
*
* @see
* android.opengl.GLSurfaceView.Renderer#onDrawFrame(javax.
* microedition.khronos.opengles.GL10)
*/
public void onDrawFrame(GL10 gl) {
// 清空屏幕和depth缓冲
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | //
GL10.GL_DEPTH_BUFFER_BIT);
}
/*
* (non-Javadoc)
*
* @see
* android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(javax.
* microedition.khronos.opengles.GL10, int, int)
*/
public void onSurfaceChanged(GL10 gl, int width, int height) {
// 设置当前视口大小为新值
gl.glViewport(0, 0, width, height);
// 选择投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
// 重置投影矩阵
gl.glLoadIdentity();
// 计算窗口的方向比例
GLU.gluPerspective(gl, 45.0f,
(float) width / (float) height,
0.1f, 100.0f);
// 选择modelview矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置modelview矩阵
gl.glLoadIdentity();
}
}
全屏
只需要在这个openglDemo类中添加这几行代码,就可以全屏了。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE); // (NEW)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); // (NEW)
... // Previous code.
}
Frame Buffer 对象的概念可以参见前面文章Android OpenGL ES 开发教程(23):FrameBuffer。
简单的和2D图像类比,Frame Buffer 如果 对应到二维图形环境中,就是一个2D的内存数组空间,缺省情况为屏幕的显存,也可以创建Offscreen 内存空间,此时Frame Buffer 可以是一个二维数组,数组每个元素代表一个像素颜色。
对于三维图形来说,除了需要代表颜色的二维数组(Color Buffer),还需要深度二维数组(Depth Buffer) 或遮罩数组(Stencil Buffer),因此在OpenGL 中的Frame Buffer为上述Color Buffer,Depth Buffer,Stencil Buffer 的集合。如果手机具有GPU,其缺省的Frame Buffer也是3D屏幕显示区域。
通过Opengl ES扩展支持,应用程序也可以创建内存中的Frame Buffer对象(不用于屏幕显示)。通过这种应用程序创建的FrameBuffer对象,OpenGL应用可以将图像显示输出重新定向到这个非屏幕显示用FrameBuffer对象中,类似于二维图形绘制中常用的Offscreen 技术。
和缺省的屏幕显示FrameBuffer一样,由应用程序创建的FrameBuffer对象也是由Color Buffer, Depth Buffer和Stencil Buffer(可选)的集合组成。这些Buffer在FrameBuffer对象中可以称为FrameBuffer-attachable 图像,FrameBuffer定义了一些接入点(Attachment Point)可以用于连接(Attach)这些Buffer数组。
OpenGL ES定义了两种FrameBuffer-attachable 图像,Texture 和 renderbuffer ,简单的可以将Texture 理解为Color buffer 或是2D图像,render buffer 对应于depth buffer。