OpenGL ES教程(一)创建第一个程序

一.基本概念

OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。

OpenGL ES在Android上的应用领域广泛,主要用于游戏开发,音视频开发(如滤镜),在�VR,AR领域也有应用(如VR照相机)

Android本身支持了OpenGL,官方文档在此,官方文档用的例子是基于OpenGL ES2.0的,2.0与1.0的区别在于1.0采用固定管线来编程,而2.0则采用着色器来编程,增强了开发者的灵活性,由于现在大部分设备都支持2.0以上的OpenGL ES的驱动,所以这里我们就以2.0为例,至于2.0以上的版本,原理是一致的,api也相差不大。

二.初始化OpenGL

1.首先我们新建一个新的Android项目,命名为“FirstOpenGLApplication”

Android中的GLSurfaceView封装了OpenGL在设备上的显示逻辑,负责处理OpenGL初始化过程中比较基本的操作,如配置显示设备以及在后台线程中渲染,渲染是在显示设备中一个称为"surface"的特定区域完成的, 有时也称为视口(viewport)

2.然后我们检查设备是否支持OpenGL ES2.0

public class FirstOpenGLActivity extends AppCompatActivity {

    private GLSurfaceView glSurfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        glSurfaceView = new GLSurfaceView(this);
        final ActivityManager activityManager =
                (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
        final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;
    }
 }

如果你的设备是模拟器的话,需要用以下代码检查

public class FirstOpenGLActivity extends AppCompatActivity {

    private GLSurfaceView glSurfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        glSurfaceView = new GLSurfaceView(this);
        final ActivityManager activityManager =
                (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
        // Even though the latest emulator supports OpenGL ES 2.0,
        // it has a bug where it doesn't set the reqGlEsVersion so
        // the above check doesn't work. The below will detect if the
        // app is running on an emulator, and assume that it supports
        // OpenGL ES 2.0.
        final boolean supportsEs2 =
                configurationInfo.reqGlEsVersion >= 0x20000
                        || (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")));
    }
}

这段代码测试当前设备是不是模拟器,如果是,就假定它支持2.0,要确保程序能运行,模拟器一定要配置OpenGL ES2.0

3.为OpenGL配置渲染器

if (supportsEs2) {
            // Request an OpenGL ES 2.0 compatible context.
            glSurfaceView.setEGLContextClientVersion(2);

            // Assign our renderer.
            glSurfaceView.setRenderer(new FirstOpenGLProjectRenderer());
            rendererSet = true;
        } else {
            /*
             * This is where you could create an OpenGL ES 1.x compatible
             * renderer if you wanted to support both ES 1 and ES 2. Since
             * we're not doing anything, the app will crash if the device
             * doesn't support OpenGL ES 2.0. If we publish on the market, we
             * should also add the following to AndroidManifest.xml:
             *
             * 
             *
             * This hides our app from those devices which don't support OpenGL
             * ES 2.0.
             */
            Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
                    Toast.LENGTH_LONG).show();
            return;
        }
        setContentView(glSurfaceView);

接着新建一个类继承Renderer

public class FirstOpenGLProjectRenderer implements Renderer {
    @Override
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
        // Set the background clear color to red. The first component is
        // red, the second is green, the third is blue, and the last
        // component is alpha, which we don't use in this lesson.
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
    }

    /**
     * onSurfaceChanged is called whenever the surface has changed. This is
     * called at least once when the surface is initialized. Keep in mind that
     * Android normally restarts an Activity on rotation, and in that case, the
     * renderer will be destroyed and a new one created.
     *
     * @param width
     *            The new width, in pixels.
     * @param height
     *            The new height, in pixels.
     */
    @Override
    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
        // Set the OpenGL viewport to fill the entire surface.
        glViewport(0, 0, width, height);
    }

    /**
     * OnDrawFrame is called whenever a new frame needs to be drawn. Normally,
     * this is done at the refresh rate of the screen.
     */
    @Override
    public void onDrawFrame(GL10 glUnused) {
        // Clear the rendering surface.
        glClear(GL_COLOR_BUFFER_BIT);
    }
}

我们来看一下渲染器(Render)的方法

onSurfaceCreated(GL10 glUnused, EGLConfig)

当Suface被创建的时候,GLSurfaceView会调用这个方法,这一般发生在应用程序第一次运行的时候,但是如果你的Activity或者应用进程被回收(可以用开发者选项--不保留活动来模拟),再次回到应用的时候,也会被调用.

onSurfaceChanged(GL10 glUnused, int width, int height)

在Surface被创建后,每次Surface尺寸变化时,这个方法都会被GLSurfaceView调用到。在横屏,竖屏切换的时候,Surface尺寸会发生变化

onDrawFrame(GL10 glUnused)

当绘制一帧时,这个方法会被GLSurfaceView调用。在这个方法中,我们一定要绘制一些东西,即使只是清空屏幕,因为在这个方法返回后,渲染缓冲区会被交换并显示在屏幕上,如果什么都没画,可能会有闪烁的效果。

所以在这里,我们设置清空屏幕的颜色为红色,设置视口(viewport)的大小为GLSurfaceView的大小,并且在每一帧到来时,用glClearColor()设置的红色清屏

三.查看效果

经过了这三个步骤,我们运行一下程序,可以看到屏幕GLSurfaceView的部分被红色沾满,这样我们就完成了OpenGL绘制的第一步啦~


OpenGL ES教程(一)创建第一个程序_第1张图片
第一个opengl程序.png

PS: 如果你使用的是模拟器,且程序不工作,并且模拟器的配置选项“Use Host GPU”已经被勾选了,那请试试在glSurfaceView.setRenderer()调用之前加入glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0)的调用

你可能感兴趣的:(OpenGL ES教程(一)创建第一个程序)