您的位置:首页 > 移动开发 > Android开发

Android OpenGL ES 开发教程(6):GLSurfaceView

2012-11-29 10:28 393 查看
Android OpenGL ES 相关的包主要定义在

javax.microedition.khronos.opengles GL 绘图指令
javax.microedition.khronos.egl EGL 管理Display, surface等
android.opengl Android GL辅助类,连接OpenGL 与Android View,Activity
javax.nio Buffer类

其中GLSurfaceView 为android.opengl 包中核心类:

起到连接OpenGL ES与Android 的View层次结构之间的桥梁作用。
使得Open GL ES库适应于Anndroid系统的Activity生命周期。
使得选择合适的Frame buffer像素格式变得容易。
创建和管理单独绘图线程以达到平滑动画效果。
提供了方便使用的调试工具来跟踪OpenGL ES函数调用以帮助检查错误。

使用过Java ME ,JSR 239 开发过OpenGL ES可以看到 Android 包javax.microedition.khronos.egl ,javax.microedition.khronos.opengles 和JSR239 基本一致,因此理论上不使用android.opengl 包中的类也可以开发Android上OpenGL ES应用,但此时就需要自己使用EGL来管理Display,Context, Surfaces 的创建,释放,捆绑,可以参见Android
OpenGL ES 开发教程(5):关于EGL 。

使用EGL 实现GLSurfaceView一个可能的实现如下:

Java代码



class GLSurfaceView extends SurfaceView
implements SurfaceHolder.Callback, Runnable {
public GLSurfaceView(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}

public void setRenderer(Renderer renderer) {
mRenderer = renderer;
}

public void surfaceCreated(SurfaceHolder holder) {
}

public void surfaceDestroyed(SurfaceHolder holder) {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
}
thread = null;
}

public void surfaceChanged(SurfaceHolder holder,
int format, int w, int h) {
synchronized(this){
mWidth = w;
mHeight = h;
thread = new Thread(this);
thread.start();
}
}

public interface Renderer {
void EGLCreate(SurfaceHolder holder);
void EGLDestroy();
int Initialize(int width, int height);
void DrawScene(int width, int height);
}

public void run() {
synchronized(this) {
mRenderer.EGLCreate(mHolder);
mRenderer.Initialize(mWidth, mHeight);

running=true;
while (running) {
mRenderer.DrawScene(mWidth, mHeight);
}

mRenderer.EGLDestroy();
}
}

private SurfaceHolder mHolder;
private Thread thread;
private boolean running;
private Renderer mRenderer;
private int mWidth;
private int mHeight;

}

class GLRenderer implements GLSurfaceView.Renderer {
public GLRenderer() {
}

public int Initialize(int width, int height){
gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

return 1;
}

public void DrawScene(int width, int height){
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

egl.eglSwapBuffers(eglDisplay, eglSurface);
}

public void EGLCreate(SurfaceHolder holder){
int[] num_config = new int[1];
EGLConfig[] configs = new EGLConfig[1];
int[] configSpec = {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,

EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
EGL10.EGL_NONE
};

this.egl = (EGL10) EGLContext.getEGL();

eglDisplay = this.egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
this.egl.eglInitialize(eglDisplay, null);

this.egl.eglChooseConfig(eglDisplay, configSpec,
configs, 1, num_config);

eglConfig = configs[0];
eglContext = this.egl.eglCreateContext(eglDisplay, eglConfig,
EGL10.EGL_NO_CONTEXT, null);

eglSurface = this.egl.eglCreateWindowSurface(eglDisplay,
eglConfig, holder, null);

this.egl.eglMakeCurrent(eglDisplay, eglSurface,
eglSurface, eglContext);

gl = (GL10)eglContext.getGL();
}

public void EGLDestroy(){
if (eglSurface != null) {
egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(eglDisplay, eglSurface);
eglSurface = null;
}
if (eglContext != null) {
egl.eglDestroyContext(eglDisplay, eglContext);
eglContext = null;
}
if (eglDisplay != null) {
egl.eglTerminate(eglDisplay);
eglDisplay = null;
}
}

private EGL10 egl;
private GL10 gl;
private EGLDisplay eglDisplay;
private EGLConfig eglConfig;
private EGLContext eglContext;
private EGLSurface eglSurface;
}

Java代码 



public void  setRenderer(GLSurfaceView.Renderer renderer)  

public void  setRenderer(GLSurfaceView.Renderer renderer)


GLSurfaceView.Renderer定义了一个统一图形绘制的接口,它定义了如下三个接口函数:

Java代码



// Called when the surface is created or recreated.

public void onSurfaceCreated(GL10 gl, EGLConfig config)
// Called to draw the current frame.
public void onDrawFrame(GL10 gl)
// Called when the surface changed size.
public void onSurfaceChanged(GL10 gl, int width, int height)

// Called when the surface is created or recreated.
public void onSurfaceCreated(GL10 gl, EGLConfig config)
// Called to draw the current frame.
public void onDrawFrame(GL10 gl)
// Called when the surface changed size.
public void onSurfaceChanged(GL10 gl, int width, int height)
onSurfaceCreated : 在这个方法中主要用来设置一些绘制时不常变化的参数,比如:背景色,是否打开 z-buffer等。
onDrawFrame: 定义实际的绘图操作。
onSurfaceChanged: 如果设备支持屏幕横向和纵向切换,这个方法将发生在横向<->纵向互换时。此时可以重新设置绘制的纵横比率。
如果有需要,也可以通过函数来修改GLSurfaceView一些缺省设置:

setDebugFlags(int) 设置Debug标志。
setEGLConfigChooser (boolean) 选择一个Config接近16bitRGB颜色模式,可以打开或关闭深度(Depth)Buffer ,缺省为RGB_565 并打开至少有16bit 的 depth Buffer.

setEGLConfigChooser(EGLConfigChooser) 选择自定义EGLConfigChooser。
setEGLConfigChooser(int, int, int, int, int, int) 指定red ,green, blue, alpha, depth ,stencil 支持的位数,缺省为RGB_565 ,16 bit depth buffer.

GLSurfaceView 缺省创建为RGB_565 颜色格式的Surface ,如果需要支持透明度,可以调用getHolder().setFormat(PixelFormat.TRANSLUCENT).

GLSurfaceView 的渲染模式有两种,一种是连续不断的更新屏幕,另一种为on-demand ,只有在调用requestRender() 在更新屏幕。 缺省为RENDERMODE_CONTINUOUSLY 持续刷新屏幕。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: