OpenGL ES着色器解析

OpenGL ES简介

OpenGL ES(OpenGL for Embedded Systems)是基于OpenGL的3D图形应用程序编程接口,主要是为手机、平板等手持和嵌入式设备设计。其支持的平台包括Android、iOS、Linux和Windows等。

顶点着色器

从编程角度,顶点着色器是一段代码指令,用于描述针对于顶点的着色器程序源代码或可执行文件。在顶点着色器中包含以下几部分内容:

  • 顶点着色器输入。顶点着色器输入是由顶点数组提供的顶点数据,通过传入顶点着色器能够做矩阵变换、顶点颜色或照明等计算,从而输出进行后续供后续的图元装配、光栅化,再到片段着色器的运行。
  • 统一变量。顶点着色器中不变的数据,通常会传入计算好的旋转矩阵,从而实现模型-视图-投影坐标的转换
  • 采样器。在后续的纹理处理中会用到的特殊变量。纹理获取不会传递指针指向GLSL,而是通过纹理ID绑定的方式在内存中查找。代表顶点着色器使用纹理的特殊统一变量类型;

顶点着色器示例

一段简单的顶点着色器代码

其中第2行是指明使用的着色器版本;第3行和第4行分别指明了位置和颜色的属性位置索引为1和2;第5行描述了统一变量u_MVPMatrix,开发人员可以自定义的将计算好的模型-视图-投影矩阵传入;第6行声明了一个描述顶点纹理坐标的输出变量,存储了每个顶点纹理输出。其中gl_Position是内建变量,变换后的顶点坐标都需要写入这个变量;第9行则是通过矩阵变换后的坐标输出写入gl_Position;第10行则是读入顶点纹理坐标并写入到v_texCoord变量中,供后续片段着色器写入使用。

片段着色器

片段着色器中包含以下几部分内容:

  • 顶点着色器中生成的插值数据输入。顶点着色器的输出通过图元变换后传递给片段着色器作为输入变量。
  • 统一变量。这些变量在片段着色器上不会变化。
  • 采样器。片段着色器使用的特殊变量,用于访问着色器中的纹理图像。

片段着色器示例

一段简单的片段着色器代码

其中第2行指明了着色器语言版本;第3行设定精度限定符;第4行则是声明一个通过顶点着色器输出后,经过图元变换后作为片段着色器的输入变量;第5行指明输出颜色的位置属性索引为0;第6行声明一个统一变量,可供后续设定输入纹理;第9行中,s_Texturemap是一个类型为sampler2D的统一变量,内建函数texture会从纹理贴图中读取加载相应的纹理。开发过程中则包括使用glActiveTexure激活当前纹理单元,以便后续glBindTexture调用将纹理绑定到当前活动单元。

着色器装载和使用

要进行着色器渲染需要创建两个基本对象,分别是着色器对象和程序对象,以下将分成4部分介绍着色器渲染所需的所有前置步骤:

  • 创建和编译着色器
  • 创建和链接程序
  • 统一变量的获取和设置
  • 属性的获取和设置

1. 创建和编译着色器

创建和编译一个着色器代码

图中1使用glCreateShader(GLenum shader)用于创建一个着色器对象;2则是使用glShaderSource(GLuint shader,GLsizei count,const GLchar* const *string,const GLint *length)将着色器源代码提供给该着色器;3是在指定着色器后进行编译,使用glCompileShader(GLuint shader)。该环节后则完成了着色器的创建和编译,后续代码第4步则是提供查询编译是否错误和着色器对象的相关信息,使用glGetShaderiv(GLuint shader, GLenum pname,GLint *params);此外,如果想进一步检索信息日志,可以使用第5步中的glGetShaderInfoLog(GLuint shader, GLsizei maxLength,GLsizei *length, GLchar *infoLog)获取。最后如果着色器对象没有完成创建或其他错误,可使用第6步中的glDeleteShader(GLuint shader)删除着色器对象的句柄,释放内存。

2. 创建和链接程序

创建和链接程序代码

第1步中,程序对象创建通过glCreateProgram()方法创建,返回一个指向对象的句柄;第2步中使用glAttachShade(GLuint program, GLuint shader)将程序对象与着色器进行连接,值得注意的是每个程序对象需要连接一个顶点着色器和一个片段着色器;完成程序对象与着色器的连接后可以通过第3步glLinkProgram(GLuint program)完成程序对象的链接,即生成最终可执行程序;第4步则是完成链接后可使程序对象与着色器断开连接,使用glDetachShader(GLuint program, GLuint shader);第5和6步与上文的着色器信息查询相同,同样的在程序链接完成后可以通过glGetProgramiv(GLuint program, GLenum pname, GLint *params)检查链接状态,并通过glGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog)获取程序的相关信息日志;最后第7步如果程序对象创建错误或未成功链接,可使用glDeleteProgram(GLuint program)删除程序对象。

3. 统一变量的获取和设置

通常我们会在着色器中自定义统一变量,在后续代码编写过程中加载所需要的自定义数据,最常见的如u_MVPMatrix,通过提前计算好的坐标转换矩阵,在输入坐标时可将物体的世界坐标转换成视口坐标。具体方法名为glGetUniformLocation(GLuint program, const GLchar* name),其中name指明了统一变量的位置,和着色器源码中的名称相同。通过该方法返回的GLint位置返回值可以作为加载统一变量方法glUniform1f中的参数进行赋值,其中类比不同的统一变量,加载方法也有不同的函数,如glUniform1f(GLint location,GLfloat x)glUniform3f(GLint location, GLfloat x, GLfloat y,GLfloat z)等等。以下图代码为例,1为着色器中定义的统一变量,2为加载相关统一变量的方法。

统一变量的获取和设置示例代码

4. 属性的获取和设置

和统一变量相同,程序对象还需要设置顶点属性,可以通过glGetActiveAttrib查找某个属性特性,并通过glBindAttribLocation将通用顶点属性索引绑定到顶点着色器中的一个属性变量。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容