《OpenGL ES应用开发实践指南:Android卷》—— 3.4 做最后的拼接

简介:

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

3.4 做最后的拼接

我们在前两章中用了很大篇幅为这个应用打下了很好的基础:我们学习了如何使用属性数组定义一个物体的结构,也学习了如何创建着色器、加载并编译它们,以及把它们链接起来形成一个OpenGL的程序。
现在是时候在这个基础上开始构建并把它们拼接起来了。在下面的几个步骤里,我们就要把这些部分拼在一起,并准备好把第一个版本的空气曲棍球桌子画到屏幕上。

3.4.1 验证OpenGL程序的对象

在开始使用OpenGL的程序之前,我们首先应该验证一下它,看看这个程序对于当前的OpenGL状态是不是有效的。根据OpenGL ES 2.0的文档,它也给OpenGL提供了一种方法让我们知道为什么当前的程序可能是低效率的、无法运行,等等。
让我们在ShaderHelper中加入如下代码:
screenshot

我们调用glValidateProgram()来验证这个程序,然后用GL_VALIDATA_STATUS作为参数调用glGetProramiv()方法检查其结果。如果OpenGL有什么有用的信息要透露,这些信息会显示在程序日志里,因此我们也用glGetProgramInfoLog () 把日志打印出来。
在开始使用这个程序之前,我们应该验证它,并且我们应该只有在开发或调试应用的时候才去验证它。让我们在onSurfaceCreated()的结尾处加入如下代码:
screenshot

只有日志需要打开时,它才会调用我们早前定义的验证代码。下一步我们应该做的就是使用曾花费了很大力气创建的OpenGL程序。在onSurfaceCreated()结尾处加入如下代码:
screenshot

调用glUseProgram()告诉OpenGL在绘制任何东西到屏幕上的时候要使用这里定义的程序。

3.4.2 获得一个uniform的位置

下一步是获得我们早前在着色器中定义的uniform的位置。当OpenGL把着色器链接成一个程序的时候,它实际上用一个位置编号把片段着色器中定义的每个uniform都关联起来了。这些位置编号用来给着色器发送数据,并且我们需要u_Color的位置,以便我们可以在要绘画的时候设置颜色。
让我们快速看一下片段着色器:
screenshot
screenshot

在这个着色器里,我们已经定义了一个称为u_Color的uniform,并在main()中把这个uniform的值赋给了gl_FragColor。我们要使用这个uniform设置将要绘制的东西的颜色;我们要绘制一张桌子、一个中间分隔线和两个木槌,并且我们要使用不同的颜色绘制它们。
让我们在AirHockeyRenderer的顶部加入如下定义:
screenshot

我们已经为这个uniform的名字创建了一个常量和一个用来容纳它在OpenGL程序对象中的位置的变量。uniform的位置并不是事先指定的,因此,一旦程序链接成功了,我们就要查询这个位置。一个uniform的位置在一个程序对象中是唯一的:即使在两个不同的程序中使用了相同的uniform名字,也不意味着它们使用相同的位置。
在onSurfaceCreated()结尾处加入如下代码:
screenshot

我们调用glGetUniformLocation()获取uniform的位置,并把这个位置存入uColorLocation;当我们稍后要更新这个uniform值的时候,我们会使用它。

3.4.3 获取属性的位置

像uniform一样,在使用属性之前我们也要获得它们的位置。我们可以让OpenGL自动给这些属性分配位置编号,或者在着色器被链接到一起之前,可以通过调用glBindAttribLocation()由我们自己给它们分配位置编号。我们要让OpenGL自动分配这些属性位置,因为它使代码更容易管理。
让我们在AirHockeyRender顶部加入如下定义:
screenshot

一旦着色器被链接在一起了,我们就只需要加入一些代码去获取属性位置。在onSurfaceCreated()结尾处加入如下代码:
screenshot

调用glGetAttribLocation()获取属性的位置。有了这个位置,就能告诉OpenGL到哪里去找到这个属性对应的数据了。

3.4.4 关联属性与顶点数据的数组

下一步是要告诉OpenGL到哪里找到属性a_Position对应的数据。
在onSurfaceCreated()的结尾处加入如下代码:
screenshot

回到本章的开始处,我们创建了一个浮点数数组,这些浮点数表示组成空气曲棍球桌子的顶点的位置;我们在本地内存中创建了一个缓冲区,称为vertexData,并把这些位置复制到这个缓冲区内。
在我们告诉OpenGL从这个缓冲区中读取数据之前,需要确保它会从开头处开始读取数据,而不是中间或者结尾处。每个缓冲区都有一个内部的指针,可以通过调用position(int)移动它,并且当OpenGL从缓冲区中读取时,它会从这个位置开始读取。为了保证它一定从最开头处开始读取,我们调用position(0)把位置设在数据的开头处。
然后我们调用glVertexAttribPointer()告诉OpenGL,它可以在缓冲区vertexData中找到a_Position对应的数据。这是一个非常重要的函数,因此,让我们仔细看一下每个参数传递了什么(见表3-1)。
screenshot

传递不正确的参数给glVertexAttribPointer()会导致奇怪的结果,甚至导致程序崩溃。这种崩溃还很难跟踪,因此,我不是言过其实,获得正确的参数是非常重要的。
调用了glVertexAttribPointer()之后,OpenGL就知道在哪里读取属性a_Position的数据了。

3.4.5 使能顶点数组

尽管我们已经把数据属性链接起来了,在开始绘制之前,我们还需要调用glEnableVertexAttribArray()使能这个属性。在glVertexAttribPointer()调用之后加入如下代码:
screenshot

通过这最后一个调用,OpenGL现在就知道去哪里寻找它所需要的数据了。
在这一节里,我们取得了u_Color(uniform)及a_Position(属性)的位置;每个变量都有一个位置,并且OpenGL将使用这些位置,而不是直接使用这些变量的名字;之后,我们调用glVertexAttribPointer()告诉OpenGL,它可以从vertexData找到属性a_Position的数据。

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