Opengl ES(四) 绘制三角形

Opengl ES基础系列文章是音视频学习的图形图像部分,旨在通过这部分学习,能够把Opengl ES和视频结合在一起,最终形成一个完整的知识体系。   

源码链接在文章底部,大家自行下载配合源码阅读本文。

从本节开始,通过实际的项目配合进行讲解,但是我不会贴代码(整段代码),我会从设计的角度先说流程,然后再结合实际项目,而不是一上来就写代码,所以,本系列文章注重先构思,把我们要做的事情先构思好,然后再代码实现,培养大家思考问题的方法,而不是把一堆代码展现给大家,因此,在看文章的同时一定要自己手动用代码完成,不知道再查看我们提供的项目事例工程,这样理解才会深刻,效率才会高。

前面已经学习了Opengl ES的基础知识以及怎么样搭建一个基本的Opengl ES运行环境,现在我们来实现最基本的图形显示:绘制三角形,这里重点不是显示三角形,主要通过绘制三角形,帮助我们掌握如下知识点:
1)顶点着色器的写法;
2)片元着色器写法;
3)怎么给顶点着色器中的变量赋值;
4)怎么把顶点位置信息传给Opengl ES;
5)怎么把颜色的值通过片元着色器传给Opengl ES;
6)怎么样把三角形绘制并显示出来;

以下我们就一步一步来实现绘制三角形,看看以上的几个知识点是怎么样体现出来的,下面是在Opengl ES中绘制三角形的流程图:


上图描述绘制三角形的完整流程示意,每个关键步骤下面会详细介绍,包括用到的Opengl ES的函数也会给出详细的调用说明,大家可以根据这个图和结合下面的类设计图试着用代码实现这个绘制流程。

前面说过,这系列文章主要是设计、Opengl ES知识点和代码相结合,因此,在实际编码之前,我都会先进行简要的设计,力求做到前面写的东西后面一直可以复用,以最小的代价帮助大家完成设计到编码然后到成品的转换,所以,再次强调,在编码前要先想、先思考,尽量做一些抽象,下面是绘制三角形中用到的类结构图。


上图主要说明了绘制三角形涉及到的类,我们采用面向对象思想来完成,后面可以代码复用,这些类对应的项目代码有实现,并且有详细的注释,大家结合项目来理解。

1. 环境搭建

新建一个Android的工程(实现最基本的就可以),然后,按照之前介绍的建立最基本的Opengl ES绘制环境,具体请参考第三节Opengl ES 环境搭建的介绍。

2. 编写顶点着色器

我们顶点着色器代码如下:

      attribute vec2 aVertexPos;
      void main(void)
      {
          gl_Position = aVertexPos;
      }

上面的着色器就定义一个成员变量:aVertexPos。

aVertexPos:存储顶点坐标信息;

3. 编写片元着色器

       uniform vec4 uColor;
       void main(void)
       {
          gl_FragColor = uColor;
       }

片元着色器也很简单,就一个变量:uColor,用来给顶点着色的颜色。

这里再重复一下,顶点着色器确定绘制区域,片元着色器给顶点确定的区域涂上颜色。

4. 编译着色器

创建着色器对象:int vertexShader = glCreateShader(GL_VERTEX_SHADER);

设置着色器源码:glShaderSource(id, source);

编译着色器源码:glCompileShader(id);

检查编译是否成功:glGetShaderiv();

这里大家可以参考前面章节对着色器的介绍。

5. 链接Program

生成program对象:int program = glCreateProgram();

关联色器到program:glAttachShader(program, vertexShader);

链接program:glLinkProgram(program);

检查链接是否成功:glProgramiv();

6. 给顶点坐标赋值

顶点坐标变量值设置主要是attribute和uniform,前面已经详细介绍过它们的含义,接下来分别讲下怎么样对attribute和uniform修饰的变量赋值。

attribute 赋值

1)定位变量在program中的索引位置(Opengl ES根据情况生成);

2)激活变量(只有激活了才对Opengl ES可见,因为attribute也是一种紧缺资源);

3)把数据设置给属性(这里需要告诉Opengl ES怎么读取设置的数据,后面会讲);

对attribute变量在program中的定位采用glGetAttribLocation完成,其原型如下:

GLint glGetAttribLocation(GLuint program,const GLchar *name);

program:glCreateProgram()生成的program标识;

name:属性变量的名称;

返回值:返回program中属性变量name的索引;

比如获取顶点着色器中定义的变量“aVertexPos”,调用如下:

GLint pos = glGetAttribLocation(program,"aVertexPos");

上述功能其实还可以用glBindAttribLocation直接在指定的属性索引上绑定属性变量,其原型如下:

void glBindAttribLocation(GLuint program,GLuint index, const GLchar *name);

program:glCreateProgram()生成的program标识;

index:指定给属性变量的索引;

name:属性变量的名称;

返回值:无;

注意,指定的index属性索引要在Opengl ES支持的范围内。

然后调用glEnableVertexAttribArray激活属性,使得其对GPU绘制可见,如果关闭属性,则调用glDisableVertexAttribArray使其变得不可见,其原型如下:

void glEnableVertexAttribArray(GLuint index);

void glDisableVertexAttribArray(GLuint index);

index:指定给属性变量的索引;

最后,我们使用glVertexAttribPointer给属性赋值,这个方法一定要注意最后一个参数,可以指向普通的内存数据和VBO的偏移,关于VBO后面会讲,大家知道有这么个东西就行,glVertexAttribPointer原型如下:

void glVertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * pointer);

index:指定给属性变量的索引;

size:顶点属性的组件数,必须为1,2,3或4,这里的组件数意思就是:比如定义三个顶点坐标,每个顶点使用x,y表示,那么这里的组件数就是2,就是每组有两个值。

type:size指定的组件数中每个组件的类型,比如顶点坐标类型是GL_FLOAT,浮点类型,占四个字节。

normalized:是否把设置的值进行归一化处理,这个值一般设置为GL_FALSE。

stride:指连续顶点组件数偏移的字节数,比如顶点属性后面可能有颜色(R、G、B,每个占一个字节),那么这个值应该是11个字节,x、y加上rgb计算得到。

pointer:属性数据地址指针,如果VBO则表示在VBO中的偏移。

uniform 赋值

对uniform修饰的变量,对其赋值流程如下:

1)同样获取uniform变量在program中的索引值;

2)使用glUniformxxx类型的函数给其设置值;
         
上述的glUniformxxx后面的xxx只诸如1fv、2fv等等,用来设置GL_FLOAT类型的变量值,其中的location通过函数glGetUniformLocation从program获取,其原型如下:

GLint glGetUniformLocation(GLuint program,const GLchar *name);

program:glCreateProgram()生成的program标识;

name:变量的名称;

返回值:返回program中变量name的索引;

7. 给片元着色器指定颜色

定位uColor在program中的位置,其有uniform修饰,代码如下:

int uPos = glGetUniformLocation(program, "uColor");

然后给uColor变量赋值:

glUniform4fv(uPos, 0,0,0,1);

8. 执行绘制

glDrawArrays(GL_TRIANGLES, 0, count);

9. 把绘制好的三角形显示出来

glSwapBuffers();

Opengl ES是通过双缓冲来管理绘制的,绘制完成后,需要把后台的缓冲和前台的交换,这样才能完成显示。

到这里,一个最简单的Opengl ES的绘制流程我们就完成了,通过上面的学习,我们知道了使用Opengl ES绘制一个三角形需要经过的步骤,有了这个基础,下一节学习在Opengl ES怎样显示一副图片。

项目源码:https://github.com/china20/EGLShowShape

本系列文章均为原创,主要总结作者多年在软件行业的一些经验,和大家共同学习、进步,转载请注明出处,谢谢!

来源:CSDN,作者:会说话的小鱼,转载此文目的在于传递更多信息,版权归原作者所有。
原文:https://blog.csdn.net/china0851/article/details/85156165
版权声明:本文为博主原创文章,转载请附上博文链接!

最新文章