通过VBO和VAO准备好数据后,接下来要指示GPU如何通过这些数据绘制图形。类似CPU可以通过执行程序来完成特定的任务,GPU也可以执行特定的程序来完成绘制任务,GPU执行的程序称为Shader,也叫着色器。
GPU绘制图形分为不同的处理阶段,在顶点处理和片元
OpenGL的着色器使用GLSL语言编写
着色器程序示例
三角形示例https://blog.csdn.net/leesino/article/details/139093716 使用到了顶点着色器(Vertex Shader)和片元着色器(Fragment Shader),下面分别对两者进行介绍。
首先介绍的是顶点着色器,示例中的三角形的Vertex Shader的源码如下所示:
#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 outColor;
void main()
{gl_Position = vec4(aPos, 1.0);outColor = aColor;
}
Vertex Shader的源码解析:
- #version 300 es 指定使用 OpenGL ES 3.0版本。
- aPos 声明接收顶点数据的变量,其中layout (location = 0)表示数据从0号属性取出,in表示这是一个输入变量。vec3表示这是一个3个浮点数的向量。
- aColor用于接收颜色数据,内容从1号顶点属性获得。
- 在main方法中,把aPos转成4维向量后传给gl_Position,这是个内置变量,一般用于传递顶点数据,是一个4维的浮点数向量,因此这里要把顶点从3维向量转为4维向量。
- outColor用于将颜色属性传递到下一个阶段,out表示输出变量。
顶点着色器程序的执行次数与顶点数量有关,因此绘制一个三角形要执行3次顶点着色器程序。
接下来介绍片元着色器程序,片元着色器程序用于确定每个片元的最终颜色,三角形示例的代码如下。
#version 300 es
precision mediump float;
out vec4 FragColor;in vec3 outColor;
void main()
{FragColor = vec4(outColor, 1.0);
}
- precision mediump float 设置浮点数精度为中精度。
- FragColor,该变量声明为out,用于输出片元的最终颜色。
- outColor,接收顶点着色器传递过来的颜色,名称必须与顶点着色器声明的一样。
在光栅化阶段会计算得到一个三角形的片元数量,每个片元执行一次片元着色器程序才能得到它的颜色。
使用方法
着色器程序准备好了以后,接下来是如何使用着色器绘制图形,大体上分为以下3步:
1、编译,使用着色器程序绘制图形,首先要对着色器进行编译,编译步骤如下。
GLuint shader = glCreateShader(shader_type);//attach source to shader objectglShaderSource(shader, 1, &source, NULL);glCompileShader(shader);// Check for compilation errorsGLint compiled = 0;glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
着色器编译流程解析如下:
- glCreateShader,创建着色器对象,创建成功后得到着色器的句柄。参数用于指明着色器的类型,GL_VERTEX_SHADER表示创建的是顶点着色器对象,GL_FRAGMENT_SHADER表示创建的是片元着色器对象。
- glShaderSource,将着色器程序加载到着色器对象中
- glCompileShader,对着色器进行编译
- glGetShaderiv,第二个参数传GL_COMPILE_STATUS表示要获取编译结果。
如果顶点着色器和片元着色器编译都没有问题,下一步可以对它们进行链接。
2、链接
链接过程主要把不同阶段的着色器变成一个程序,主要步骤如下
GLuint program = glCreateProgram();
glAttachShader(program, shaders[i]);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &linked);
链接步骤解析如下。
- glCreateProgram,创建着色器程序对象,成功后返回程序对象的句柄。
- glAttachShader,将着色器添加到程序对象
- glLinkProgram,链接程序
- glGetProgramiv,通过该方法可以获取链接结果。
链接没有问题,最后可以使用着色器程序绘制图形。
3、使用
使用着色器绘制图形比较简单,以下是使用着色器程序绘制图形的过程。
void onDraw(){glUseProgram(mProgram);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 3);glUseProgram(0);
}
绘制流程解析如下:
- glUseProgram指定要使用的着色器程序
- glBindVertextArray指定VAO,相当于明确了顶点数据
- glDrawArrays开始绘制
- 最后glUseProgram传入0表示未指定任何着色器程序。
到此为止,三角形示例的主要代码流程基本介绍完成,通过OpenGL系列(二)EGL,OpenGL系列(三)VBO、VAO和本文的学习,基本上能理解三角形的绘制流程。