《OpenGL ES应用开发实践指南:Android卷》—— 3.2 编译着色器

简介:

本节书摘来自华章出版社《OpenGL ES应用开发实践指南:Android卷》一 书中的第3章,第3.2节,作者:(美)Kevin Brothaler ,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.2 编译着色器

现在我们已经把着色器源代码从文件中读出来了,下一步就是编译每个着色器了。我们要创建一个新的辅助类,它可以创建新的OpenGL着色器对象、编译着色器代码并且返回代表那段着色器代码的着色器对象。一旦写出样板代码,在未来的项目中就可以重用了。
作为开始,创建一个名为ShaderHelper的新类,并在类中添加如下代码:
screenshot
screenshot

这些代码会作为着色器辅助类的基础。与以前一样,不要忘了把导入加进代码中;如果你在使用静态导入时碰到什么问题,请参考1.5节;在本书的剩余部分,我们会一直遵循这个样式。
在下一节中,我们会逐步构建compileShader()方法。

3.2.1 创建一个新的着色器对象

我们应该做的第一件事就是创建一个新的着色器对象,并且检查这个创建是否成功。在compileShader()中加入如下代码:
screenshot

这里,用glCreateShader()调用创建了一个新的着色器对象,并把这个对象的ID存入变量shaderObjectId。这个type可以是代表顶点着色器的GL_VERTEX_SHADER,或者是代表片段着色器的GL_FRAGMENT_SHADER。剩下的代码也用同样的方式。
记住我们是如何创建对象并检查它是否有效的;这个模式将在OpenGL里广泛使用:
1.首先使用一个如glCreateShader()一样的调用创建一个对象,这个调用会返回一个整型值(integer)。
2.这个整型值就是OpenGL对象的引用。无论后面什么时候想要引用这个对象,就要把这个整型值传回OpenGL。
3.返回值0表示这个对象创建失败,它类似于Java代码中返回null值。
如果对象创建失败,就给调用代码返回0。为什么返回0而不是抛出一个异常呢?这是因为OpenGL内部实际不会抛出任何异常;相反,我们会得到返回值0,并且OpenGL通过glGetError()告诉我们这个错误,这个方法可以让我们询问OpenGL是不是某个API调用导致了错误。我们会一直遵从这个惯例。
附录B介绍了更多关于glGetError()的知识以及其他调试OpenGL代码的方法。

3.2.2 上传和编译着色器源代码

让我们加入如下代码把着色器源代码上传到着色器对象里:
screenshot

一旦有了有效的着色器对象,就可以调用glShaderSource(shaderObjectId, shaderCode)上传源代码了。这个调用告诉OpenGL读入字符串shaderCode定义的源代码,并把它与shaderObjectId所引用的着色器对象关联起来。然后,可以调用glCompileShader(shaderObjectId)编译这个着色器:
screenshot

这个调用告诉OpenGL编译先前上传到shaderObjectId的源代码。

3.2.3 取出编译状态

让我们加入如下代码检查OpenGL是否能成功地编译这个着色器:
screenshot

为了检查编译是失败还是成功,首先要创建一个新的长度为1的int数组,称为compileStatus;然后调用glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0)。这就告诉OpenGL读取与shaderObjectId关联的编译状态,并把它写入compileStatus的第0个元素。
这是Android平台上的OpenGL的另外一个通用模式。为了取出一个值,我们通常会使用一个长度为1的数组,并把这个数组传进一个OpenGL调用。在同一个调用中,我们告诉OpenGL把结果存进数组的第一个元素中。

3.2.4 取出着色器信息日志

当我们获得编译状态的时候,OpenGL只给出一个简单的是或否的回答。难道没兴趣知道发生了什么错误以及哪里出问题了吗?事实证明,我们可以通过调用glGetShaderInfoLog(shaderObjectId)获得一个可读的消息。如果OpenGL有什么关于着色器的有用内容,它就会把消息存到着色器的信息日志里。
让我们加入如下代码获取着色器信息日志:
screenshot

我们把日志输出到Android的日志输出中,并把一切都封装在那个检查LoggerConfg.ON值的if语句里。通过把这个常量赋值为“false”,我们可以很容易地关闭这些日志。

3.2.5 验证编译状态并返回着色器对象ID

既然我们已经记录了着色器信息日志,就可以查看一下编译是否成功了:
screenshot

我们所需要做的就是检查在3.2.3节那步的返回值,它是不是0。如果它是0,编译就失败了,这种情况下,我们就不再需要着色器对象了,因此告诉OpenGL把它删除并返回0给调用代码;如果编译成功,着色器对象就是有效的,我们就可以在代码中使用它了。
这就是为了编译一个着色器所需要的全部内容,让我们返回那个新的着色器对象ID:
screenshot

3.2.6 在Renderer类中编译着色器

现在是时候充分利用我们刚刚写过的代码了。切换到AirHockeyRender.java,并在onSurfaceCreated()的结尾处加入如下代码:
screenshot

让我们回顾一下本节所完成的工作。首先,我们创建了一个新类ShaderHelper,并加入了一个用来创建、编译新着色器对象的方法;我们也创建了LoggerConfig,一个用来在单一代码行打开或者关闭日志的类。
如果你再看一下ShaderHelper,就会发现我们实际上定义了三个方法。
compileShader():这个compileShader(type, shaderCode)方法使用了着色器源代码和类型;type可以是代表顶点着色器的GL_VERTEX_SHADER,或者是代表片段着色器的GL_FRAGMENT_SHADER。如果OpenGL能成功编译这个着色器,这个方法就会给调用代码返回着色器对象的ID,否则,它就会返回0。
compileVertexShader():这个compileVertexShader(shaderCode)方法是调用compileShader()的辅助方法,使用GL_VERTEX_SHADER作为着色器类型。
compileFragmentShader():这个compileVertexShder(shaderCode)方法也是调用compileShader()的辅助方法,它使用GL_FRAGMENT_SHADER作为着色器类型。
如你所见,这段代码的实质内容都在compileshader()中;其他两个方法就是使用GL_VERTEX_SHADER或GL_FRAGMENT_SHADER调用它。

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
存储 XML 开发工具
探索安卓应用开发:从基础到进阶
在这篇文章中,我们将一起踏上安卓应用开发的旅程。不论你是编程新手还是希望提升技能的开发者,这里都有你需要的东西。我们会从最基础的概念开始,逐步深入到更复杂的主题。文章将涵盖开发环境设置、用户界面设计、数据处理以及性能优化等方面。通过理论与实践的结合,你将能够构建出既美观又高效的安卓应用。让我们一起开启这段技术之旅吧!
|
Android开发 Swift iOS开发
深入探索iOS与Android操作系统的架构差异及其对应用开发的影响
在当今数字化时代,移动设备已经成为我们日常生活和工作不可或缺的一部分。其中,iOS和Android作为全球最流行的两大移动操作系统,各自拥有独特的系统架构和设计理念。本文将深入探讨iOS与Android的系统架构差异,并分析这些差异如何影响应用开发者的开发策略和用户体验设计。通过对两者的比较,我们可以更好地理解它们各自的优势和局限性,从而为开发者提供有价值的见解,帮助他们在这两个平台上开发出更高效、更符合用户需求的应用。
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
406 0
|
搜索推荐 Android开发 开发者
安卓应用开发中的自定义控件实践
在安卓应用开发的广阔天地中,自定义控件如同璀璨的星辰,点亮了用户界面设计的夜空。它们不仅丰富了交互体验,更赋予了应用独特的个性。本文将带你领略自定义控件的魅力,从基础概念到实际应用,一步步揭示其背后的原理与技术细节。我们将通过一个简单的例子——打造一个具有独特动画效果的按钮,来展现自定义控件的强大功能和灵活性。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇通往更高阶UI设计的大门。
198 2
|
缓存 监控 前端开发
探索Android应用开发之旅:从新手到专家
【10月更文挑战第42天】本文将带你踏上Android应用开发的旅程,无论你是初学者还是有经验的开发者。我们将一起探索如何从零开始创建你的第一个Android应用,并逐步深入到更高级的主题,如自定义视图、网络编程和性能优化。通过实际示例和清晰的解释,你将学会如何构建高效、吸引人的Android应用。让我们一起开启这段激动人心的旅程吧!
182 2
|
开发框架 前端开发 Android开发
探索安卓和iOS应用开发中的跨平台解决方案
【10月更文挑战第42天】在移动应用开发的广阔天地中,安卓和iOS系统如同两座巍峨的山峰,分别占据着半壁江山。开发者们在这两座山峰之间穿梭,努力寻找一种既能节省资源又能提高效率的跨平台开发方案。本文将带你走进跨平台开发的世界,探讨各种解决方案的优势与局限,并分享一些实用的代码示例,助你在应用开发的道路上更加游刃有余。
|
传感器 XML IDE
探索安卓应用开发:从基础到进阶
【10月更文挑战第23天】在数字化时代的浪潮中,移动应用已成为人们日常生活的延伸。本文以安卓平台为例,深入浅出地介绍了如何从零开始构建一个安卓应用,涵盖了开发环境搭建、基本组件使用、界面设计原则以及进阶技巧等关键步骤。通过实例演示和代码片段,引导读者逐步掌握安卓应用开发的核心技能,旨在激发更多开发者对安卓平台的探索热情,并为初学者提供一条清晰的学习路径。
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
192 4
|
Android开发 Swift iOS开发
探索iOS与安卓应用开发的差异性
探索iOS与安卓应用开发的差异性
245 2

热门文章

最新文章