我将会写一个系列的关于安卓opengl ES的教程。对于不同的设备,opengl的原理是相通的,所以你能够很容易的移植到其他平台。
我不可能记清我具体从哪里获取的这些详细信息,所以有时候我可能不能给出足够正确的引用文献。如果你认为我引用了你的文章却没有加入到引用文献中,你可以给我发邮件通知我更正。
在这个样例代码中,为每个章节,我有两个不同的链接,一个是链接到安卓官方开发文档,另一个是opengl ES文档。接下来,像这样:
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
让我们开始吧!
在这篇教程中,我将展示如何建立一个opengl ES的view,这也适合作为教程开始的切入点。
初始化一个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应用运行流畅,这就是你需要开始了解的地方。
你唯一需要调用的方法就是:
public void setRenderer(GLSurfaceView.Renderer renderer)
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
如果你的设备支持横竖屏切换,那么在切换时会被调用此方法。这个方法用来设置新的比例。
组装代码
首先我们创建一个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.
}
这就差不多是视图初始化和运行所需要做的所有工作了。如果你编译并且运行了,你将会看到一个漂亮的。。黑屏。
引用
这篇教程引用如下文献: