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

相关文章
|
1月前
|
存储 消息中间件 人工智能
【03】AI辅助编程完整的安卓二次商业实战-本地构建运行并且调试-二次开发改注册登陆按钮颜色以及整体资源结构熟悉-优雅草伊凡
【03】AI辅助编程完整的安卓二次商业实战-本地构建运行并且调试-二次开发改注册登陆按钮颜色以及整体资源结构熟悉-优雅草伊凡
84 3
|
1月前
|
存储 消息中间件 人工智能
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
153 10
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
|
1月前
|
存储 消息中间件 人工智能
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
88 11
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
|
1月前
|
XML 存储 Java
【06】AI辅助编程完整的安卓二次商业实战-背景布局变更增加背景-二开发现页面跳转逻辑-替换剩余图标-优雅草卓伊凡
【06】AI辅助编程完整的安卓二次商业实战-背景布局变更增加背景-二开发现页面跳转逻辑-替换剩余图标-优雅草卓伊凡
68 3
【06】AI辅助编程完整的安卓二次商业实战-背景布局变更增加背景-二开发现页面跳转逻辑-替换剩余图标-优雅草卓伊凡
|
1月前
|
存储 消息中间件 人工智能
【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡
【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡
71 4
|
8月前
|
前端开发 Java 编译器
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
227 36
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台框架解析
在移动应用开发的广阔舞台上,安卓和iOS一直是两大主角。随着技术的进步,开发者们渴望能有一种方式,让他们的应用能同时在这两大平台上运行,而不必为每一个平台单独编写代码。这就是跨平台框架诞生的背景。本文将探讨几种流行的跨平台框架,包括它们的优势、局限性,以及如何根据项目需求选择合适的框架。我们将从技术的深度和广度两个维度,对这些框架进行比较分析,旨在为开发者提供一个清晰的指南,帮助他们在安卓和iOS的开发旅程中,做出明智的选择。
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
11月前
|
算法 JavaScript Android开发
|
11月前
|
API Android开发 iOS开发
深入探索Android与iOS的多线程编程差异
在移动应用开发领域,多线程编程是提高应用性能和响应性的关键。本文将对比分析Android和iOS两大平台在多线程处理上的不同实现机制,探讨它们各自的优势与局限性,并通过实例展示如何在这两个平台上进行有效的多线程编程。通过深入了解这些差异,开发者可以更好地选择适合自己项目需求的技术和策略,从而优化应用的性能和用户体验。

热门文章

最新文章