从0开始的OpenGL学习(四)-着色器类

本文主要解决两个问题:

1、着色器和应用、着色器之间是如何进行数据传递的?
2、如何封装一个着色器类?

一、开胃小菜GLSL

先来点开胃菜,扯两句GLSL。之前我们就用过GLSL搞了个顶点着色器和片元着色器,也算是对它不陌生了。语法上,它和C语言十分类似,所以使用起来的时候感觉还是很友好的(笔者是学C语言出生的,吼吼)。不说太多关于语法、操作符、数据类型这些废话,学了一门语言之后,所有的语言都会往自己熟悉的方向去用,学一门新语言的时候最讨厌的就是先看语法,烦透了。我们直接从关键点着手!

1、着色器代码的格式:

#version 版本号
in 数据类型 变量名;
in 数据类型 变量名;
out 数据类型 变量名;
uniform 数据类型 变量名;
void main() {
        //处理过程
         输出变量 = 处理结果;
}

in表示从上一个阶段输入的数据,out表示这个阶段需要输出的数据,uniform表示全局的数据(应用里也能读取和写入这个变量,这就是着色器和应用之间互通数据的方法),主函数main中包含了处理过程,将处理结果赋值给输出变量。

2、向量

用的最多的数据类型就是向量,反正到现在为止我们用的是最多的,以后用的也是最多的。已经用过的类型有:vec3,vec4。表示有3个、4个float数据的向量。当然还有vec1,vec2。(vec2可以理解,这个vec1是什么鬼?别问我,我也是新手,别说用过,见都没见过。)这只是包含float类型的向量,还有包含布尔类型的向量bvec1234,包含整型数的向量ivec1234,包含无符号整型数的向量uvec1234,包含双精度浮点型数的向量dvec1234。除了包含的类型不同,操作方式都一样,用到的时候再说。

二、着色器之间的数据互通

说穿了很简单,上一个阶段的输出变量就会成为下一个阶段的输入变量,只要变量名相同就行了。注意,必须要相同变量名,否则接收不到。

顶点着色器和片元着色器数据互通代码

在顶点着色器中定义一个输出的颜色,片元着色器中接收,然后直接将这个颜色赋值给了片元颜色输出量,这样三角形的颜色就成了顶点着色器中定义的暗红色了。

显示效果

三、着色器和应用之间的数据互通

说穿了也很简单,定义成uniform方式的变量就是全局的变量,可以在应用中访问,不过需要一些特殊的访问方式。

使用uniform的着色器代码

(坑提醒:如果申明了一个uniform但是在GLSL中没有使用,编译器会自动将这个变量删除的,这会引起一系列诡谲的BUG,到时候慢慢填吧,哇哈哈)
要使用这个变量,需要两步:

  • 1、获取该变量在着色器程序中的位置(这里是着色器程序,不是片元着色器,是顶点着色器和片元着色器链接进入的那个着色器程序)。
  • 2、通过glUniform4fv函数对其进行赋值。
使用uniform数据的代码

这里的glUniform4f函数调用可以放到glUserProgram之前,在使用着色器程序之前就可以完成对颜色的赋值操作。
运行之后的效果显示了一个绿色三角形:

运行效果

四、封装一个着色器类

直接在源代码中写着色器实在是太麻烦了,不好管理不说,可读性也很差。作为一个上进的好程序员,怎么能不封装一下节省时间呢?
这个类需要什么功能?从文件中读取并且编译是必要的,也要可以设置着色器中变量的功能,使用着色器的功能也不能少,嗯,干脆就弄一个编译链接之后的着色器程序类。

头文件代码

不多解释了,按照我们的思路来编码,代码本身很简单。

其他的实现都很简单,主要是Shader这个构造函数,要完成两个主要步骤:

  • 其一、从文件中读取着色器代码
  • 其二、编译链接这些代码

先实现读取代码的功能:

读取着色器文件

简单地使用C++的STL库来读取文件,保存到流中,再从流中转换到字符串里保存,这样,我们就得到了所需要的代码。

再把代码进行编译:

编译着色器代码的程序

代码很简单,出了添加了一个编译和连接的成功判断,都是我们之前写过的东西,没啥难度。

使用着色器程序以及设置简单数据的功能也没啥好说的,就是单纯的函数调用而已,直接放代码:

使用着色器以及设置简单值

好,功能实现完毕,编译一下,没有问题。Very Good!

等等,这就好了?还没完呢!弄了个东西不弄不就浪费了,我们来改造一下代码。

五、使用着色器类

先创建两个文件,Shader.vs和Shader.fs,分别表示顶点着色器和片元着色器。使用本文第二节中显示为红色的着色器代码。

然后,将冗长的着色器实现代码和加载编译的代码删除掉,用Shader对象来代替:

创建着色器代码

最后,将使用着色器程序的代码删除,调用着色器对象的use函数

使用着色器对象

编译运行,效果和第二节的一样,说明我们的工作是有成效的!

运行结果

总结

嗯,到现在为止,我们的着色器程序算是走上正轨了,手写一遍代码的读者想必也累了,休息一下吧。

下一篇
目录
上一篇

参考资料:

www.learningopengl.com(非常好的学习站点,强烈推荐)

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

推荐阅读更多精彩内容