Android OpenGL ES(三)----编程框架(二)

简介: Android OpenGL ES(三)----编程框架(二)

5.把着色器一起链接进OpenGL的程序


既然我们已经加载并编译了一个顶点着色器和一个片段着色器,下一步就是把它们绑定在一起放入一个单个的程序里。


5.1理解OpenGL的程序:


简单来说,一个OpenGL程序就是把一个顶点着色器和一个片段着色器链接在一起变成单个对象。顶点着色器和片段着色器总是一起工作的。没有片段着色器,OpenGL就不知道怎么绘制那些组成的每个点,直线和三角形片段;如果没有顶点着色器,OpenGL就不知道在哪里绘制这些片段。


虽然顶点着色器和片段着色器总是要一起工作的,但并不意味着它们必须是一对一匹配的,我们可以同时在多个程序中使用同一个着色器。


让我们打开ShaderHelper,并在类的末尾加入如下代码:

public static int linkProgram(int vertexShaderId, int fragmentShaderId) {


下面我们将构建这个方法。


新建程序并附着上着色器,我们要做的第一件事就是调用glCreateProgram()新建程序对象,并把那个对象的ID存进programObjectId。如下:

final int programObjectId = GLES20.glCreateProgram();
         if (programObjectId == 0) {
             if (LoggerConfig.ON) {
                 Log.w(TAG, "Could not create new Program");
             }
             return 0;
         }


和上面的代码类似就不过多的解释了,下一步就是附上着色器:

GLES20.glAttachShader(programObjectId, vertexShaderId);
         GLES20.glAttachShader(programObjectId, fragmentShaderId);

使用glAttachShader()方法把顶点着色器和片段着色器附加到程序对象上。


5.2链接程序


现在准备把这些着色器联合起来了,为此,将调用

glLickProgram(programObjectId):
GLES20.glLinkProgram(programObjectId);


为了检查这个链接是成功还是失败,我们遵循编译着色器时所使用的步骤:

final int[] linkStatus = new int[1];
         GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0);


最后验证链接状态并返回程序对象ID,代码如下:

if (linkStatus[0]==0) {
             GLES20.glDeleteProgram(programObjectId);
             if(LoggerConfig.ON){
                 Log.w(TAG,"linking of program failed");
             }
             return 0;
         }
         return programObjectId;


给渲染类LYJRenderer加入代码,先定义成员变量:

private int program;


然后在onSurfaceCreated()结尾处加入如下代码把着色器链接起来:

program = ShaderHelper.linkProgram(vertexShader, fragmentShader);


6.最后的拼接


6.1验证OpenGL程序的对象


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



让我们在ShaderHelper加入如下代码:

public static boolean validateProgram(int programObjectId){
         GLES20.glValidateProgram(programObjectId);
         final int[] validateStatus=new int[1];
         GLES20.glGetProgramiv(programObjectId,GLES20.GL_VALIDATE_STATUS,validateStatus,0);
         Log.v(TAG,GLES20.glGetProgramInfoLog(programObjectId));
         return validateStatus[0]!=0;
     }


这段代码与上面验证类似就不过多的阐述了,然后在onSurfaceView()结尾处加入如下代码:

ShaderHelper.validateProgram(program);


然后调用glUseProgram(program);


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


获取属性的位置


在使用属性之前我们要获取它们的位置。我们可以让OpenGL自动给这些属性分配位置编号,或者在着色器被链接到一起之前,可以通过调用glBindAttrribLocation()由我们自己给它们分配位置编号。我们要让OpenGL自动分配这些位置,因为它使代码容易管理。


在LYJRenderer顶部加入如下定义:

private static final String A_POSITION="a_Position";
private int aPositionLocation;
private static final int POSITION_COMPONENT_COUNT = 2;


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

this.aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);


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


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


下一部就是要告诉OpenGL到哪里找到属性a_Position对应的数据。

this.vertexData.position(0);
         GLES20.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT, false, STRIDE, this.vertexData);


在我们告诉OpenGL从这个缓冲区中读取数据之前,需要确保它会从开头处开始读取数据,而不是中间或者结尾处。每个缓冲区都有一个内部指针,可以通过调用position(int)移动它,并且当OpenGL从缓冲区读取时,它会从这个位置开始读取。


下面是参数的解析:


aPositionLocation:这个是属性位置。


POSITION_COMPONENT_COUNT:这个属性有多少分量


GLES20.GL_FLOAT:这是数据的类型


false:只有使用整型数组时候,这个数据才有意义。


STRIDE:多于一个属性时候,就要告诉取下个数据要跳过多少分量。


vertexData:这个参数告诉OpenGL去哪里读取数据。


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

GLES20.glEnableVertexAttribArray(aPositionLocation);

同理颜色分量的代码如下:

private static final int COLOR_COMPONENT_COUNT=3;
private static final String A_COLOR = "a_Color";
     private int aColorLocation;
private static final int STRIDE=(POSITION_COMPONENT_COUNT+COLOR_COMPONENT_COUNT)*BYTES_PER_FLOAT;
this.vertexData.position(POSITION_COMPONENT_COUNT);
        GLES20.glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GLES20.GL_FLOAT, false, STRIDE, this.vertexData);
        GLES20.glEnableVertexAttribArray(aColorLocation);


7.在屏幕上绘制


在onDrawFrame() 方法的结尾添加如下代码:

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);
         GLES20.glDrawArrays(GLES20.GL_LINES, 6, 2);
         GLES20.glDrawArrays(GLES20.GL_POINTS, 8, 1);
         GLES20.glDrawArrays(GLES20.GL_POINTS, 9, 1);


第一个语句告诉OpenGL绘制三角扇形,什么是三角扇形后面讲解,第二个语句告诉OpenGL绘制直线,第三,四条语句告诉OpenGL绘制点。


这七个步骤就是开发OpenGL程序的基本流程。如图

7.png

相关文章
|
4月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
5月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台框架解析
在移动应用开发的广阔舞台上,安卓和iOS一直是两大主角。随着技术的进步,开发者们渴望能有一种方式,让他们的应用能同时在这两大平台上运行,而不必为每一个平台单独编写代码。这就是跨平台框架诞生的背景。本文将探讨几种流行的跨平台框架,包括它们的优势、局限性,以及如何根据项目需求选择合适的框架。我们将从技术的深度和广度两个维度,对这些框架进行比较分析,旨在为开发者提供一个清晰的指南,帮助他们在安卓和iOS的开发旅程中,做出明智的选择。
|
1月前
|
算法 JavaScript Android开发
|
2月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
111 1
|
3月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
393 3
|
3月前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
88 8
|
4月前
|
设计模式 Java Android开发
探索安卓应用开发:从新手到专家的旅程探索iOS开发中的SwiftUI框架
【8月更文挑战第29天】本文旨在通过一个易于理解的旅程比喻,带领读者深入探讨安卓应用开发的各个方面。我们将从基础概念入手,逐步过渡到高级技术,最后讨论如何维护和推广你的应用。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的代码示例。让我们一起开始这段激动人心的旅程吧!
|
4月前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
如何使用Amlogic T972安卓9.0系统上的misc框架来简化驱动程序开发,通过misc框架自动分配设备号并创建设备文件,从而减少代码量并避免设备号冲突。
53 0
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
|
4月前
|
存储 前端开发 Java
Android MVVM框架详解与应用
在Android开发中,随着应用复杂度的增加,如何有效地组织和管理代码成为了一个重要的问题。MVVM(Model-View-ViewModel)架构模式因其清晰的结构和高效的开发效率,逐渐成为Android开发者们青睐的架构模式之一。本文将详细介绍Android MVVM框架的基本概念、优势、实现流程以及一个实际案例。
129 0
|
5月前
|
移动开发 开发工具 Android开发
探索安卓与iOS开发的差异:平台特性与编程实践
【7月更文挑战第8天】在移动开发的广阔天地中,安卓和iOS这两大操作系统各自占据着半壁江山。它们在用户界面设计、系统架构及开发工具上展现出截然不同的特色。本文将深入探讨这两个平台在技术实现和开发生态上的关键差异,并分享一些实用的开发技巧,旨在为跨平台开发者提供有价值的见解和建议。