OpenGL可以绘制2D和3D的图形,如今,VR很火,所以有关3D图形绘制可能会尤为重要,体现:前几天比较火的游戏pokemon go,当然它不是用OpenGL做的,但是很明显,3D是以后开发的趋势,所以我们应该了解并且学习,在绘制3D图形之前,你必须得了解和会使用OpenGL,OK,我们一起学习下吧。
OpenGL ES 支持的基本图形为 点 Point, 线 Line, 和三角形 Triangle ,其它所有复制图形都是通过这几种基本几何图形组合而成。
在Android中,有个专门支持显示3D和2D图形的View:GLSurfaceView,GLSurfaceView的用法和SurfaceView的用法相似,因为它也是继承自SurfaceView的,用于显示图像,第一步就是创建GLSurfaceView,但是在创建之前最好判断一下手机或者模拟器是否支持OpenGL,实际上大多数手机是支持OpenGL的,所以这一步我们主要是判断是否支持OpenGL ES 2.0。
private Button firstDemo;
private boolean supportsEs2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkSupported();
firstDemo = (Button) findViewById(R.id.btn_first);
firstDemo.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (supportsEs2) {
Intent intent = new Intent();
switch (view.getId()) {
case R.id.btn_first:
intent.setClass(MainActivity.this, FirstActivity.class);
break;
}
startActivity(intent);
} else {
Toast.makeText(this, "当前设备不支持OpenGL ES 2.0!", Toast.LENGTH_SHORT).show();
}
}
/** * 检测手机或者模拟器是否支持OpenGL2.0 */
private void checkSupported() {
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;
boolean isEmulator = Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
&& (Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86"));
supportsEs2 = supportsEs2 || isEmulator;
}
然后创建GLSurfaceView
private GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView = new GLSurfaceView(this);
//设置渲染器
glSurfaceView.setRenderer(new GLRenderer());
setContentView(glSurfaceView);
}
@Override
protected void onResume() {
super.onResume();
if (glSurfaceView != null) {
glSurfaceView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
//防止activity不可见时还在绘制图形导致程序崩溃
if (glSurfaceView != null) {
glSurfaceView.onPause();
}
}
可以将GLSurfaceView理解成画布,然后就是在画布上画图形了,用什么画呢?注意下面这行代码
glSurfaceView.setRenderer(new GLRenderer());
Renderer是一个接口,它主要包含3个抽象函数:
GLRenderer是我们自定义的,他是实现了Renderer接口的,并且实现上面三个方法,以后绘制图形就在这个类里面,来看下怎么定义这个类:
/** * Created by Fussen on 16/8/22. */
public class GLRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
}
@Override
public void onSurfaceChanged(GL10 gl10, int i, int i1) {
}
@Override
public void onDrawFrame(GL10 gl10) {
}
}
写到这,大致框架就已经搭建好了,下面就是我们开始绘制图形的时候了,但是在绘制之前要注意,在我们的activity onPause和onResume的时候OpenGL还在绘制图形导致程序崩溃,所以我们还要做的就是在activity的生命周期里对GLSurfaceView做一些处理。
@Override
protected void onResume() {
super.onResume();
if (glSurfaceView != null) {
glSurfaceView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
//防止activity不可见时还在绘制图形导致程序崩溃
if (glSurfaceView != null) {
glSurfaceView.onPause();
}
}
接下来就开始对GLRenderer类进行操作了
先上代码,然后在解释
/** * Created by Fussen on 16/8/22. */
public class GLRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
//设置清屏的颜色(背景色),参数分别对应RGBA(红色)
gl10.glClearColor(1f, 0f, 0f, 0f);
}
/** * 在绘制图形时调用 * * @param gl10 * @param width * @param height */
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
//设置视角窗口大小 glViewport
gl10.glViewport(0,0,width,height);
}
/** * 在视图大小发生改变时调用 * * @param gl10 */
@Override
public void onDrawFrame(GL10 gl10) {
//使用glClearColor函数所设置的颜色进行清屏。
gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);
}
gl10.glClearColor()是设置清屏的颜色,参数分别是RGBA,它的取值范围是在0-1之间,gl10.glClearColor(1f, 0f, 0f, 0f)设置的就是红色,在OpenGL中很多参数的范围都是0-1之间。
然后是设置窗口的大小glViewport,就是决定绘制的矩形区域的大小,在GLSurfaceView窗口大小发生变化时我们动态改变视角窗口。这时候就开始真正的绘制图形了,我们暂时先给他一个红色的背景,把画板背景颜色设置为红色,glClear(GL10.GL_COLOR_BUFFER_BIT)的意思是,使用glClearColor函数所设置的颜色进行清屏。
写到这里我们就算完成了一个小Demo,用OpenGL绘制了一个红色背景,当然我们要做的不止这些,今天就学习到这吧,以后我们绘制图形的代码就都会写在GLRenderer这个类里面。