我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android中的OpenGL怎么配置使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android中的OpenGL怎么配置使用

这篇文章主要介绍“Android中的OpenGL怎么配置使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android中的OpenGL怎么配置使用”文章能帮助大家解决问题。

介绍

Android 可通过开放图形库 OpenGL ES 来支持高性能 2D 和 3D 图形,OpenGL 是一种跨平台的图形 API,用于为 3D 图形处理硬件指定标准的软件接口。OpenGL ES 是 OpenGL 规范的一种形式,适用于嵌入式设备,Android 支持多版 OpenGL ES API,各版本情况如下:

  • OpenGL ES 1.0 和 1.1 - 此 API 规范受 Android 1.0 及更高版本的支持。

  • OpenGL ES 2.0 - 此 API 规范受 Android 2.2(API 级别 8)及更高版本的支持。

  • OpenGL ES 3.0 - 此 API 规范受 Android 4.3(API 级别 18)及更高版本的支持。

  • OpenGL ES 3.1 - 此 API 规范受 Android 5.0(API 级别 21)及更高版本的支持。

在 AndroidManifest.xml 中声明 OpenGL ES 的版本

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

GLSurfaceView

GLSurfaceViewSurfaceViewOpenGL实现,从 Android 1.5 开始加入,在 SurfaceView的基础上添加了 EGL 的管理以及自带的渲染线程 GLThread,其主要功能如下:

  • 管理一个Surface,这个Surface是一块特殊的内存,可以组合到 Android 的 View 系统中,也就是可以和View一起使用。

  • 管理一个 EGL,这个EGL可以让 OpenGL 渲染到这个Surface上,EGL是 Android 与 OpenGL之间的桥梁。

  • 支持用户自定义渲染器Renderer对象。

  • 使用专用线程上进行渲染。

  • 支持按需渲染(on-demand)和连续渲染(continuous )。

  • Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.

EGL 窗口、OpenGL 表面、GL 表面含义都相同。

GLSurfaceView常用设置如下:

EGL配置

EGLConfigChooser的默认实现是SimpleEGLConfigChooser,默认情况下GLSurfaceView将选择深度缓冲深度至少为 16 位的PixelFormat.RGB_888格式的 surface,默认的EGLConfigChooser实现是SimpleEGLConfigChooser,具体如下:

private class SimpleEGLConfigChooser extends ComponentSizeChooser {    public SimpleEGLConfigChooser(boolean withDepthBuffer) {        super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0);    }}

可以通过如下方式修改EGLConfig的默认行为:

// 设置默认EGLConfig的深度缓冲,true则为16位的深度缓冲setEGLConfigChooser(boolean needDepth)// 指定自定义的EGLConfigChoosersetEGLConfigChooser(android.opengl.GLSurfaceView.EGLConfigChooser configChooser)// 指定各个分量的值public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,            int alphaSize, int depthSize, int stencilSize)

渲染

通过setRenderer设置渲染器并启动渲染线程GLThread,渲染模式有两种如下:

  • RENDERMODE_CONTINUOUSLY:适合重复渲染的场景,默认的渲染模式。

  • RENDERMODE_WHEN_DIRTY:只有Surface被创建后渲染一次,只调用了requestRender才会继续渲染。

渲染模式可以通过setRenderMode来进行设置,具体如下:

// 设置渲染器public void setRenderer(Renderer renderer)// 设置渲染模式,仅在setRenderer之后调用生效public void setRenderMode(int renderMode)

setDebugFlags和setGLWrapper

setDebugFlags用于设置 Debug 标记,方便调试跟踪代码,可选值为DEBUG_CHECK_GL_ERRORDEBUG_LOG_GL_CALLSsetGLWrapper可以通过自定义GLWrapper来委托 GL 接口来添加一些自定义行为,具体如下:

// DEBUG_CHECK_GL_ERROR:每次GL调用都会检查,如果出现glError则会抛出异常// DEBUG_LOG_GL_CALLS:以TAG为GLSurfaceView将日志记录在verbose级别的日志中setDebugFlags(int debugFlags)// 用于调试跟踪代码,可自定义GLWrapper包装GL接口并返回GL接口,可在setGLWrapper(android.opengl.GLSurfaceView.GLWrapper glWrapper)

渲染器Renderer

这部分在前面提到过,这里单独说一下,要想在 GL 表面上执行渲染操作,需要实现Renderer对象完成实际渲染操作,通过如下方式给GLSurfaceView设置渲染器对象Renderer以及制定渲染模式,如下:

// 给GLSurfaceView设置渲染器对象Rendererpublic void setRenderer(Renderer renderer)// 设置渲染模式,仅在setRenderer之后调用生效public void setRenderMode(int renderMode)

设置渲染器Renderer的时候,同时会创建独立线程GLThread并开启该线程,这个线程就是独立于 UI 线程的渲染线程。

这里就涉及到两个线程 UI 线程和渲染线程,自然涉及到线程之间的通信,可以使用 volatilesynchronized等实现线程之间的通信。

如果是在 UI 线程中调用渲染线程中的操作,可以使用GLSurfaceViewqueueEvent 方法来将该操作执行到渲染线程中,一般需要自定义GLSurfaceView的时候会用到,同样如果在渲染线程可以通过runOnUiThread来将与 UI 相关的操作执行到 UI 线程。

下面看下渲染器Reander的基本实现:

public class GLES20Renderer implements Renderer {    private static final String TAG = GLES20Renderer.class.getSimpleName();    public void onSurfaceCreated(GL10 gl, EGLConfig config) {        Log.i(TAG, "onSurfaceCreated");        GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1);    }    public void onSurfaceChanged(GL10 gl, int width, int height) {        Log.i(TAG, "onSurfaceChanged");        GLES20.glViewport(0, 0, width, height);    }    public void onDrawFrame(GL10 gl) {        Log.i(TAG, "onDrawFrame");        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);    }}

坐标映射

先来了解下 OpenGL 的世界坐标系和与之对应的 Android 上的纹理坐标系,如下图所示:

Android中的OpenGL怎么配置使用

在 Android 中使用 OpenGL 就要进行相应坐标的转换,下面看下 OpenGL 坐标系在 Android 屏幕中的映射关系,如下图所示:

Android中的OpenGL怎么配置使用

如上图所示,左侧是默认的 OpenGL 坐标系,右侧是 OpenGL 坐标系在 Android 屏幕上的映射,可以明显看到图中的三角形是变形了的,为了保证图像比例就需要应用 OpenGL 投影模式和相机视图来转换坐标,这就涉及到投影矩阵和视图矩阵,这部分内容会在后续的文章中介绍。

绘制三角形

通过以上内容,Android OpenGL 算是初步入门了,按照习惯来个小案例,这里使用 OpenGL 绘制一个三角形,如下Triangle是三角形数据封装及着色器的的使用,后续渲染直接调用draw方法进行渲染绘制,如下:

// Triangleclass Triangle(context: Context) {    companion object {        // 坐标数组中每个顶点的坐标数        private const val COORDINATE_PER_VERTEX = 3    }    private var programHandle: Int = 0    private var positionHandle: Int = 0    private var colorHandler: Int = 0    private var vPMatrixHandle: Int = 0    private var vertexStride = COORDINATE_PER_VERTEX * 4    // 三角形的三条边    private var triangleCoordinate = floatArrayOf(     // 逆时针的顺序的三条边        0.0f, 0.5f, 0.0f,      // top        -0.5f, -0.5f, 0.0f,    // bottom left        0.5f, -0.5f, 0.0f      // bottom right    )    // 颜色数组    private val color = floatArrayOf(0.63671875f, 0.76953125f, 0.22265625f, 1.0f)    private var vertexBuffer: FloatBuffer =        // (number of coordinate values * 4 bytes per float)        ByteBuffer.allocateDirect(triangleCoordinate.size * 4).run {            // ByteBuffer使用本机字节序            this.order(ByteOrder.nativeOrder())            // ByteBuffer to FloatBuffer            this.asFloatBuffer().apply {                put(triangleCoordinate)                position(0)            }        }    init {        // read shader sourceCode        val vertexShaderCode = GLUtil.readShaderSourceCodeFromRaw(context, R.raw.vertex_shader_triangle_default)        val fragmentShaderCode =            GLUtil.readShaderSourceCodeFromRaw(context, R.raw.fragment_shader_triangle)        if (vertexShaderCode.isNullOrEmpty() || fragmentShaderCode.isNullOrEmpty()) {            throw RuntimeException("vertexShaderCode or fragmentShaderCode is null or empty")        }        // compile shader        val vertexShaderHandler = GLUtil.compileShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)        val fragmentShaderHandler =            GLUtil.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)        // create and link program        programHandle = GLUtil.createAndLinkProgram(vertexShaderHandler, fragmentShaderHandler)    }        fun draw(mvpMatrix: FloatArray) {        GLES20.glUseProgram(programHandle)        // 获取attribute变量的地址索引        // get handle to vertex shader's vPosition member        positionHandle = GLES20.glGetAttribLocation(programHandle, "vPosition").also {            // enable vertex attribute,默认是disable            GLES20.glEnableVertexAttribArray(it)            GLES20.glVertexAttribPointer(                it, // 着色器中第一个顶点属性的位置                COORDINATE_PER_VERTEX,                GLES20.GL_FLOAT,                false,                vertexStride, // 连续的顶点属性组之间的间隔                vertexBuffer            )        }        // get handle to fragment shader's vColor member        colorHandler = GLES20.glGetUniformLocation(programHandle, "vColor").also {            GLES20.glUniform4fv(it, 1, color, 0)        }        // draw triangle        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, triangleCoordinate.size / COORDINATE_PER_VERTEX)        GLES20.glDisableVertexAttribArray(positionHandle)    }}

渲染器实现如下:

// 渲染器实现class MRenderer(private var context: Context) : GLSurfaceView.Renderer {    private val tag = MRenderer::class.java.simpleName    private lateinit var triangle: Triangle    private val vPMatrix = FloatArray(16) // 模型视图投影矩阵    private val projectionMatrix = FloatArray(16)    private val viewMatrix = FloatArray(16)    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {        // 创建Surface时调用,在渲染开始时调用,用来创建渲染开始时需要的资源        Log.d(tag, "onSurfaceCreated")        triangle = Triangle(context)    }    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {        // Surface改变大小时调用,设置视口        Log.d(tag, "onSurfaceChanged")        GLES20.glViewport(0, 0, width, height)    }    override fun onDrawFrame(gl: GL10?) {        // 绘制当前frame,用于渲染处理具体的内容        Log.d(tag, "onDrawFrame")        triangle.draw(vPMatrix)    }}

上面都是基本的绘制操作,没啥好说的,其中着色器的使用流程会在后续文章中进行介绍,这里就不贴其他代码了,感兴趣的可以直接在文末查看源代码。

绘制效果

上面的绘制没有使用投影矩阵和相机视图来进行坐标转换,当横竖屏切换到时候会到导致变形,这个会在下篇文章中进行修正,看下上述代码绘制的效果图,如下图所示:

Android中的OpenGL怎么配置使用

关于“Android中的OpenGL怎么配置使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android中的OpenGL怎么配置使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android中的OpenGL怎么配置使用

这篇文章主要介绍“Android中的OpenGL怎么配置使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android中的OpenGL怎么配置使用”文章能帮助大家解决问题。介绍Android 可通
2023-07-05

Android中的OpenGL使用配置详解

这篇文章主要为大家介绍了Android中的OpenGL使用配置详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-28

Android中怎么配置 Imageloader

本篇文章为大家展示了Android中怎么配置 Imageloader,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 ImageLoader 优点(1) 支持下载进度监听(2) 可以在 View 滚
2023-05-30

怎么使用C++的OpenGL绘制三角形

这篇文章主要讲解了“怎么使用C++的OpenGL绘制三角形”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用C++的OpenGL绘制三角形”吧!一、绘制三角形1、初始化(1)初始化GLF
2023-07-02

Android服务Service怎么配置和使用

要配置和使用Android服务Service,可以按照以下步骤进行操作:在AndroidManifest.xml文件中注册Service:创建一个继承自Service
Android服务Service怎么配置和使用
2024-03-08

k8s中kubeconfig怎么配置使用

这篇文章主要讲解了“k8s中kubeconfig怎么配置使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“k8s中kubeconfig怎么配置使用”吧!1、概述kubeconfig文件保存了
2023-06-26

idea中怎么配置使用gitlab

Git是一个流行的版本控制系统,它允许用户在开发过程中进行版本控制,并协作开发代码。GitLab是一个基于Git的网站,它为用户提供了一个使用Git进行版本控制的平台。Idea是一个受欢迎的Java开发环境,它可以使用GitLab实现代码版
2023-10-22

Vue中怎么配置使用process.env

这篇文章主要讲解了“Vue中怎么配置使用process.env”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue中怎么配置使用process.env”吧!vue process.envpr
2023-07-05

Android中怎么利用RecycleView添加head配置

这篇文章给大家介绍Android中怎么利用RecycleView添加head配置,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。实例代码:package com.wwl.android; import android.
2023-05-30

linux中Teminator怎么配置和使用

在Linux中使用Terminator,你需要执行以下步骤来配置和使用它:安装Terminator:打开终端并输入以下命令来安装Terminator:sudo apt-get install terminator打开Terminator:
2023-10-24

Eclipse中怎么配置和使用Docker

在Eclipse中配置和使用Docker可以通过以下步骤来实现:安装Docker插件:首先,在Eclipse的Marketplace中搜索并安装Docker插件。可以选择Docker Tooling插件,该插件提供了Docker容器的管理和
Eclipse中怎么配置和使用Docker
2024-04-03

vue中怎么配置和使用mockjs

这篇文章主要讲解了“vue中怎么配置和使用mockjs”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue中怎么配置和使用mockjs”吧!mockjs配置和使用方式需求在前后端分离的开发中
2023-06-29

Linux中mplayer怎么配置和使用

在Linux中,你可以通过以下步骤配置和使用mplayer:安装mplayer:打开终端,运行以下命令安装mplayer:sudo apt updatesudo apt install mplayer配置mplayer:mplayer的
2023-10-23

HTTPS配置如何在Android项目中使用

本篇文章给大家分享的是有关HTTPS配置如何在Android项目中使用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Android 使用 HTTPS 配置的步骤。1、step配
2023-05-31

怎么配置使用redis

本篇内容主要讲解“怎么配置使用redis”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么配置使用redis”吧!Spring-data-redis为spring-data模块中对redis的支
2023-06-04

Java怎么使用ConfigurationProperties获取yml中的配置

这篇文章主要介绍“Java怎么使用ConfigurationProperties获取yml中的配置”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java怎么使用ConfigurationProper
2023-06-29

Android中怎么使用WallPaper设置壁纸

今天就跟大家聊聊有关Android中怎么使用WallPaper设置壁纸,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。具体如下:public class SetWallpaperAct
2023-05-30

SpringBoot中怎么使用yaml配置文件

本篇内容介绍了“SpringBoot中怎么使用yaml配置文件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.基本语法key: value
2023-07-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录