Adreno OpenGL ES 2.0 介绍(3)

  • 1. 应用程序示例
    • 1.2 在Android上创建ES 2.0 上下文/环境
    • 1.3 Adreno GPU检测
    • 1.4 检查支持的ES拓展

1. 应用程序示例

本节讨论在开发OpenGL ES应用程序时可能面临的一些关键任务。特别是:

  • 如何在Android下建立一个OpenGL ES上下文
  • 如何检测Adreno GPU并确定其版本
  • 如何检测可用的OpenGL ES扩展
  • 如何实现基本的Phong-Blinn照明
  • 如何检索渲染上下文的OpenGL ES常量的值

本节通过引用Adreno SDK中包含的一个示例应用程序的源代码来说明以上这些要点,该示例应用程序称为Lighting。本节还用代码片段说明了其他附加要点。

1.2 在Android上创建ES 2.0 上下文/环境

当开发Android平台时,OpenGL ES上下文必须使用EGL API。对于Adreno SDK中提供的示例应用程序,均是通过公共框架代码完成的,这些框架代码在不同的示例应用程序之间都是共通的(共享)。本节将讨论该框架的Android的处理与实现。本文还提供了一些用于理解EGL的基本信息的代码的。有关EGL的更多详细信息,请参见:

  • EGL参考页面
  • EGL详述

初始化过程由CFrmAppContainer::InitializeEgl方法处理,在SDK\Development\Samples\Framework\Android\FrmApplication_Platform.cpp文件中实现。如果该方法返回TRUE,则初始化已经成功执行,并且OpenGL ES渲染上下文已经绑定到调用线程。

该方法首先初始化EGLDisplay实例来表示默认显示。EGLDisplay是允许绘制图形显示的抽象。每个EGLDisplay实例通常对应一个物理屏幕。所有其他EGL对象都是EGLDisplay实例的子对象。因此,OpenGL ES上下文由类型为EGLContext的EGL对象表示,所以有必要在继续之前初始化EGLDisplay。

EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, NULL, /* major */NULL); /* minor */
eglInitialize的最后两个参数是可选的。如果提供了指向EGLint变量的指针,
它们就会被驱动程序提供的EGL实现的主版本号和次版本号所填充。

在创建OpenGL ES上下文之前,先格外注意以下几个问题:

  1. 默认的帧缓冲区应该提供什么功能?
  2. 每个组件的颜色缓冲区应该使用多少位?
  3. 它是否应该包含深度缓冲区?如果是,每个像素应该使用多少位?
  4. 它应该包含一个模板缓冲区吗?如果是,每个像素应该使用多少位?
  5. 需要哪个OpenGL ES版本?
  6. 呈现过程的输出应该指向哪里?如果是指向当前窗口,或者是屏幕外的渲染目标?

底层硬件通常支持渲染许多不同的帧缓冲区配置。为了查询其中哪个与应用程序的需求相匹配,EGL实现必须提供一个表示受支持配置的EGLConfig实例列表。

下面的代码片段定义了一个“属性列表(attribute list)”,它是一个键/值数组,以一个EGL_NONE条目结束。属性列表指定帧缓冲区配置的要求。这里只指定了少数属性。列表中还可以包含许多其他属性。由于它们被忽略了,EGL假定它们采用EGL规范中定义的默认值。

属性列表作为参数之一传递给EGL API函数eglChooseConfig。该函数返回满足要求的EGLConfig实例列表。它们按照与请求的属性的最佳匹配进行排序。如果列表大小被限制为单个条目,则保证检索到最佳匹配配置。

EGLConfig config;
EGLint configAttribs[] =
{EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_RED_SIZE, 5,EGL_GREEN_SIZE, 6,EGL_BLUE_SIZE, 5,EGL_DEPTH_SIZE, 16,EGL_STENCIL_SIZE, 8,#ifdef _OGLES3// this bit opens access to ES3 functions on// QCOM hardware pre-Android support for ES3EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, #elseEGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,#endifEGL_NONE /* terminator */
};
eglChooseConfig(display, configAttribs, &config,1, /* config_size */&numConfigs);

同时,要确保本机窗口缓冲区的尺寸和像素格式与所呈现的图像数据相匹配。因为它使用的是本机代码,所以可以通过调用ANativeWindow_setBuffersGeometry来实现这一点。本机视觉ID从所选配置中检索,并以ANativeWindow_setBuffersGeometry保证能够理解的方式定义像素格式。

eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry( m_pAndroidApp->window, ANativeWindow_getWidth (m_pAndroidApp->window),ANativeWindow_getHeight(m_pAndroidApp->window), format);

为了创建一个OpenGL ES渲染上下文,有必要提供绘制和读取表面。考虑到EGL被要求创建的是OpenGL ES上下文,这意味着:

  • 绘制表面对应于所有在默认帧缓冲区上操作的绘制调用将栅格化到的表面
  • Read surface对应于所有在默认帧缓冲区上操作的Read调用将从其中获取数据的表面

在这种情况下,正在创建一个窗口表面,因为应用程序必须渲染到一个Android窗口。在EGL中,窗口表面总是双缓冲的。
为了创建一个表面,提供EGLDisplay句柄,以及EGLConfig实例,它们告诉EGL要创建的对象的需求。可以通过传递属性列表来进一步自定义表面行为,但在这种情况下没有必要这样做。

EGLSurface surface = eglCreateWindowSurface( display, config,m_pAndroidApp->window, NULL); /* attrib_list */

现在所有必要的EGL对象都可用来创建OpenGL ES上下文。调用eglCreateContext函数,传递前面创建的EGLDisplay和EGLConfig。由于上下文不需要与任何其他呈现上下文共享其名称空间,因此将第三个参数设置为NULL。

在传递给eglCreateContext的属性列表中,EGL_CONTEXT_CLIENT_VERSION属性被设置为2。
对此的解释是,EGL为最高层次创建了一个环境以向后兼容请求版本的OpenGL ES版本,且驱动程序支持该版本。

eglCreateContext调用返回一个OpenGL ES上下文实例,但不绑定到当前线程;这是由下一行中的eglMakeCurrent调用完成的。如下面的代码片段所示,调用使用前面创建的EGLSurface实例作为绘制和读取表面。在eglMakeCurrent调用成功完成后,应用程序可以从调用eglMakeCurrent的线程开始发出OpenGL ES调用。

EGLint contextAttribs[] =
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE /* terminator */
};
EGLContext context = eglCreateContext( display, config, NULL, /* share_context */ contextAttribs);if (eglMakeCurrent(display, surface, /* draw */ surface, /* read */ context) == EGL_FALSE) { return FALSE; }

1.3 Adreno GPU检测

如果应用程序需要检查是否存在Adreno GPU,它可以:

  1. 在活动呈现上下文中调用glGetString(GL_RENDERER)来检索包含有关于活动渲染程序特定于平台的信息的字符串。
  2. 检查检索到的字符串是否包含子字符串Adreno。

Adreno GPU版本也可以在GL_RENDERER字符串中找到,在“Adreno”关键字后面。
来自PlatformDetect示例应用程序的以下代码展示了如何做到这一点。它解析GL_RENDERER字符串并使用文本输出函数来显示结果。这段代码可以在文件场景中找到。const GLubyte renderer = glGetString(GL_RENDERER);

const char* pos = strstr((char *) renderer, "Adreno");
if (pos) { ShowText("Adreno GPU detected\n"); pos += strlen("Adreno"); if (*pos == ' ') ++pos; if (!strncmp(pos, "(TM)", strlen("(TM)"))) { pos += strlen("(TM)"); // Ignore TM marker}if (*pos == ' ') ++pos; ShowText("Adreno version: %s\n", pos); } else {ShowText("Adreno GPU not detected\n");
}

1.4 检查支持的ES拓展

根据OpenGL ES的运行版本,有两种方法来检索驱动程序支持的扩展列表。

  • 在OpenGL ES 2.0(或更高版本)下,通过调用来检索扩展列表:
const GLubyte* extensions = glGetString(GL_EXTENSIONS);

在执行此调用之前,将线程绑定到呈现上下文。它返回一个以空结尾的字符串,其中包含active OpenGL ES实现支持的扩展列表。

扩展名由单个空格字符分隔。当前的扩展数也可以通过OpenGL ES常量值GL_NUM_EXTENSIONS获得,可以通过glGetIntegerv调用查询。

请注意扩展字符串可以很大。应用程序绝不能断言字符串是一个特定的最大大小,或将扩展名的数量限制为特定的数量。

Adreno SDK中的平台检测示例应用程序是为OpenGL ES 2.0编写的,它使用上述方法列出了所有支持的扩展。从文件场景中检索和解析GL_EXTENSIONS字符串的代码。方法CSample::ListExtensions如下所示。

const char* extensions = (const char *) glGetString(GL_EXTENSIONS);
for (int posStart = 0, posCurrent = 0; true; ++posCurrent) { char c = extensions[posCurrent]; if (c == ' ' || c == 0) { if (posCurrent > posStart) { ShowText("Extension: %.*s\n", posCurrent - posStart, extensions + posStart); } if (c == 0) { break; // reached the terminating EOS character}posStart = posCurrent + 1; // next extension will start // after the space character}
}
  • 使用OpenGL ES 3.0或更高版本时,会更加简单些,因为引入了一个名为glGetStringi的新函数。这个函数允许根据索引号请求每个扩展名,这意味着不再需要编写字符串解析代码。在这种情况下,上面的代码片段可以被下面的代码替换:
glGetIntegerv(GL_NUM_EXTENSIONS, &n_extensions);
for (int n_extension = 0; n_extension < n_extensions; ++n_extension) { const GLubyte* extension;extension = glGetStringi(GL_EXTENSIONS, n_extension);ShowText("Extension: %s\n", extension);
}

Adreno OpenGL ES 2.0 介绍(3)相关推荐

  1. Adreno OpenGL ES 3.1 介绍(3)

    Adreno OpenGL ES 3.1 介绍(3) 4.1.7单独的着色器对象 4.1.8着色器存储缓冲区对象 4.1.7单独的着色器对象 OpenGL ES中的关键对象类型之一是程序对象. 他们需 ...

  2. OpenGL ES 2.0 Shader相关介绍

    转自:http://xiaxveliang.blog.163.com/blog/static/29708034201272101349650/ 不得不说,百度搜技术文章,搜出来的垃圾文章非常多.用搜索 ...

  3. 借助 OpenGL* ES 2.0 实现动态分辨率渲染

    作者:omar-a-rodrigue 下载 借助 OpenGL* ES 2.0 实现动态分辨率渲染[PDF 677KB] 代码样本: dynamic-resolution.zip[ZIP 4MB] 像 ...

  4. 《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》一6.6 本章小结

    本节书摘来异步社区<OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例>一书中的第6章,第6.6节,作者: 吴亚峰 责编: 张涛,更多章节内容可以访问云栖社区"异步社 ...

  5. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  6. 《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——2.8节本章小结

    本节书摘来自异步社区<Android 3D游戏开发技术宝典--OpenGL ES 2.0>一书中的第2章,第2.8节本章小结,作者 吴亚峰,更多章节内容可以访问云栖社区"异步社区 ...

  7. 《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》——6.5节光照的每顶点计算与每片元计算...

    本节书摘来自异步社区<OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例>一书中的第6章,第6.5节光照的每顶点计算与每片元计算,作者 吴亚峰,更多章节内容可以访问云栖社区&q ...

  8. 《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》一第6章 让场景更逼真——光照效果...

    本节书摘来异步社区<OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例>一书中的第6章,第6.1节,作者: 吴亚峰 责编: 张涛,更多章节内容可以访问云栖社区"异步社 ...

  9. 《Android 3D游戏开发技术宝典——OpenGL ES 2.0》——2.4节文件I/O

    本节书摘来自异步社区<Android 3D游戏开发技术宝典--OpenGL ES 2.0>一书中的第2章,第2.4节文件I/O,作者 吴亚峰,更多章节内容可以访问云栖社区"异步社 ...

最新文章

  1. js 打开窗口window.open
  2. oracle dataguard延迟,Oracle DataGuard延迟应用归档归档日志
  3. Jq学习笔记(7)JQ动画
  4. 外卖ERP管理系统(二)
  5. 简单的家庭无线路由设置
  6. HDU 5531 Rebuild
  7. CRT 入口函数 CRTStartup
  8. .net core 实现基于 JSON 的多语言
  9. 前端学习(1956)vue之电商管理系统电商系统之添加代码到仓库中
  10. 请阐述调用Activity有哪几种方法,并写出相关的Java代码
  11. LeetCode 6 - ZigZag Conversion
  12. 【Python实例第21讲】确定类个数的silhouette分析法
  13. [GO]冒泡排序的原理和代码实现
  14. matlab作图函数的总结与分析.pdf,Matlab作图函数的总结与分析_黄琼湘
  15. mac idea svn配置
  16. 有哪些VPS云主机值得学生选择?
  17. windows 远程桌面客户端
  18. 从头开始学习->JVM(九):垃圾收集(上)
  19. Linksys路由器被曝多个漏洞
  20. 小米电视安装 Plex 打造家庭影院

热门文章

  1. 互联网金融P2P转型小额贷款全流程方案分享
  2. 支付宝开放平台 设置应用公钥
  3. 反相、同相比例运算电路与基尔霍夫电流定律的关联分析
  4. RTP PS H264详解
  5. 2021年中国稀土永磁材料产量、需求量及发展趋势分析[图]
  6. B2B订货系统源码就这样选
  7. python 爬虫去获得省市区县的数据
  8. Oka解压专家 Pro for Mac(压缩解压软件)
  9. 电影下载全攻略 [初、中、高级]——老猫
  10. 计算机电路基础卡诺图,2019“计算机电路基础”作业.doc