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

作者: CharlesYale | 来源:发表于2017-11-07 22:38 被阅读53次

    一.基本概念

    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:
                 *
                 * <uses-feature android:glEsVersion="0x00020000"
                 * android:required="true" />
                 *
                 * 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程序.png

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

    相关文章

      网友评论

        本文标题:OpenGL ES教程(一)创建第一个程序

        本文链接:https://www.haomeiwen.com/subject/nkghmxtx.html