一、OpenGL ES 与GLSurfaceView的入门使用

什么是OpenGL?

OpenGL的全称是Open Graphics Library,简单说就是图形库。

什么是OpenGL ES?

OpenGL ES的全称是OpenGL for Embedded Systems,它是 OpenGL 三维图形 API 的子集,是针对手机等嵌入式设备而设计。
在OpenGL ES的世界里,没有四边形、多边形,无论多复杂的图形都是由点、线和三角形组成的

一、初始化OpenGL

我们需要一个特殊的类GLSurfaceView来初始化OpenGL,GLSurfaceView会处理OpenGL初始化过程中比较基本的操作,例如配置显示设备(display)以及在后台线程中渲染,渲染是指在显示设备中一个叫做surface的区域完成的,这个区域有时候也称为(viewpoint)。

在幕后,GLSurfaceView实际上为它自己创建了一个窗口(window),并在视图层次(view hierarchy)上穿了一个“洞”,让底层的OpenGL surface能够显示出来,对应大多数情况这就够了,但是GLSurfaceView与常规的View不同,它没有动画和变形特效,因为GLSurfaceView是窗口(window)的一部分。

从Android4.0开始,Android提供了一个纹理视图(TextrueView),它也可以渲染OpenGL而不用创建单独的窗口或者打洞,意味着可以向常规视图一样可以被操作并且支持动画和变形处理,当时TextureView内部没有处理OpenGL的初始化,需要自定义OpenGL的初始化并在TextureView上运行,或者将GLSurfaceView的源码拷贝出来在TextureView上做适配。

二、创建GLSurfaceView的实例

package com.example.openglstudy.demo1

import android.app.ActivityManager
import android.content.Context
import android.opengl.GLSurfaceView
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.openglstudy.R

class FirstOpenGLProjectActivity : AppCompatActivity() {

    private val glSurfaceView: GLSurfaceView by lazy {
        GLSurfaceView(this) //创建GLSurfaceView
    }
    private var rendererSet = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first_open_glproject)

        //1.检查系统是否支持OpenGL ES 2.0
        val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

        val supportsEs2 =
            activityManager.deviceConfigurationInfo.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")));

        if (supportsEs2) {
            //2.配置渲染的表面rendering surface
            glSurfaceView.setEGLContextClientVersion(2) //Request an OpenGL ES 2.0 compatible context
            //3.设置自定义的render渲染器
            glSurfaceView.setRenderer(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
        }
        //最后展示glSurfaceView
        setContentView(glSurfaceView)
    }

    override fun onPause() {
        super.onPause()
        if (rendererSet) {
            glSurfaceView.onPause()
        }
    }

    override fun onResume() {
        super.onResume()
        if (rendererSet) {
            glSurfaceView.onResume()
        }
    }
}

三、创建Render类

 GLSurfaceView会在一个单独的线程中调用渲染器的方法,默认情况下,GLSurfaceView会以显示设备的刷新频率不断地渲染,
 当然,它也可以配置为按请求渲染,只需要用GLSurfaceView.RENDERMODE_WHEN_DIRTY作为参数调用GLSurfaceView.setRenderMode()即可。

自定义类继承至GLSurfaceView.Renderer

package com.example.openglstudy.demo1

import android.opengl.GLES20.*
import android.opengl.GLSurfaceView
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class FirstOpenGLProjectRenderer : GLSurfaceView.Renderer{

    /**
     * 当Surface被创建的时候,GLSurfaceView会调用这个方法,这发生在应用程序第一次运行的时候,并且当设备被唤醒
     * 或者用户从其他activity切换回来时,这个方法也可能会被调用,意味着这个方法会调用多次
     */
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        //调用该方法来设置清屏用的颜色,红色分量设置为1,那么当屏幕被清空时就会显示红色,色彩的取值范围是[0,1]
       glClearColor(1.0f,0.0f,0.0f,0.0f)
    }

    /**
     * 在Surface被创建以后,每次Surface尺寸发生变化时,都会被GLSurfaceView调用.
     * 在横竖屏切换的时候,Surface尺寸会发生变化
     */
    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        //设置视口尺寸来告诉OpenGL可以用来渲染的surface的大小
        glViewport(0,0,width,height)
    }

    /**
     * 当绘制一帧时,这个方法会被GLSurfaceView调用,在这个方法中,我们一定要绘制一些东西,即使只是清空屏幕;
     * 因为,在这个方法返回后,渲染缓冲区会被交换并显示在屏幕上,如果什么都没有画,可能会看到闪烁效果
     */
    override fun onDrawFrame(gl: GL10?) {
        //调用下面方法清空屏幕,这会清除屏幕上的所有颜色,并调用之前glClearColor定义的颜色来填充整个屏幕
        glClear(GL_COLOR_BUFFER_BIT)
    }

}

上面3个接口的方法参数中都有一个GL10,它是OpenGL ES 1.0的API遗留下来的,如果要编写OpenGL ES 1.0的渲染器,就要用到
这个参数,但是对于OpenGL ES 2.0, GLES20类提供了静态方法来存取。

ok,到目前为止就可以运行起来看看效果了,效果就如下图所示全屏的红色,这是因为我们设置的清屏颜色是红色。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值