http://www.imobilebbs.com/wordpress/?p=1889
Android OpenGL ES 相关的包主要定义在:
其中GLSurfaceView 为android.opengl 包中核心类:
使用过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一个可能的实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
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;
}
|
可以看到需要派生SurfaceView ,并手工创建,销毁Display,Context ,工作繁琐。
使用GLSurfaceView 内部提供了上面类似的实现,对于大部分应用只需调用一个方法来设置OpenGLView用到的GLSurfaceView.Renderer.
1
|
public
void
setRenderer(GLSurfaceView.Renderer renderer)
|
GLSurfaceView.Renderer定义了一个统一图形绘制的接口,它定义了如下三个接口函数:
1
2
3
4
5
6
|
// 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)
|
如果有需要,也可以通过函数来修改GLSurfaceView一些缺省设置:
GLSurfaceView 缺省创建为RGB_565 颜色格式的Surface ,如果需要支持透明度,可以调用getHolder().setFormat(PixelFormat.TRANSLUCENT).
GLSurfaceView 的渲染模式有两种,一种是连续不断的更新屏幕,另一种为on-demand ,只有在调用requestRender() 在更新屏幕。 缺省为RENDERMODE_CONTINUOUSLY 持续刷新屏幕。