Cocos Shader入门基础三:可编程管线浅析与Hello World

Tony is Coding

一、写在前面


你没看错,这篇文章重新发了。

因为C姐说,之前的版本没头没尾。

现在想想,确实有点突兀了。

可编程管线基础在后面的学习中至关重要,所以我觉得有必要认认真真优化一次。

昨天朋友跟我说:好汉不提当年勇,何况当初那么菜鸡,你写公众号里干啥?

我回答说:菜鸡怎么了?菜鸡就不是鸡了?

每当写这个系列文章的时候,脑海中就有一种奇特的画面。

但具体是什么,我抓不住,一种似曾相识却又恍如隔世的感觉。

我总是忍不住要把自己当初学Shader时候的窘迫分享出来。

目的是为了激励大家:没有人生来就会,但不去学,就永远都不会。

二、最简单的shader


在上一篇《Cocos Shader入门基础二:初识Cocos Shader》中我提到说,以后的Cocos Shader将在builtin-unlit.effect基础上逐步添加内容,渐进式学习。

但有不少C友反馈:

麒麟子,这就是你说的教程?只是粗浅的介绍了各个部分的含义,Google翻译也能做啊。

麒麟子,能不能讲讲基础知识啊,你这么一讲,还是啥也不懂啊。

麒麟子,照顾一下新人呗,麻烦从零开始啦。

于是我做了一个大胆的决定,删除不必要的东西,从最最最最简单的effect开始,简单到缺少任何一行代码,就跑不起来的地步。

我把它命名为cocos-shader-helloworld.effect,它将渲染出下面的效果。

它目前很简单,但随着教程的进行,它将变得越来越胡里花哨。

为了使大家更好地理解各个细节,麒麟子在shader中加了注释,请看下图:

三、可编程管线浅析


麒麟子一直在想,3D可编程管线到底应该以什么样的方式,什么样的程度讲给大家听。

看到上面的截图时我灵机一动。

我们不如就从上到下,以讲解Cocos Shader的角度,对涉及到的3D管线知识进行讲解。

3.1、定义部分

在cocos shader effect中,可以定义多个technique,每一个technique主要的属性就是name和pass。

在上面的cocos-shaer-helloworld.effect中我们定义了一个叫opaque的technique,且这个technique只有一个pass。

如果你不喜欢,可以改掉technique的名字,这不会对效果造成任何影响。

3.2、vert函数(顶点着色器)

在本案例中,顶点着色器的入口函数是 vert()。

在pass中,通过 vert:unlit-vs:vert 引用。

unlit-vs 就是CCProgram的名字,在一个effect文件中,我们可以定义多个CCProgram,每一个CCProgram中可以有多个函数,然后根据配置来决定入口函数。

在本文所示例的vert函数中,我们只做了最基本的位置信息输出:顶点坐标信息在经历了世界变换,摄像机变换,投影变换后,作为vert函数的返回值。

3.3、顶点坐标从本地到屏幕的经过

很多朋友误以为经过投影变换后的坐标就是屏幕坐标,那是不对的。

vert函数输出的坐标并不是屏幕坐标,在有些书上把这个叫 裁剪坐标。不管叫什么,大家记住它就是投影后的坐标就行。

这个投影后的坐标,为了适应不同的显示设备,会做一次规范化设备坐标系(NDC)处理。

NDC处理过后,会进行视口映射。

视口映射结束后,才是显示到窗口上。

麒麟子用拙劣的绘图能力给大家绘制了下面这张变换图。可以清晰的看到顶点坐标需要经历的变换步骤。

注:投影变换之后,坐标信息就不受Shader控制了。

3D变换流程

3.4、光栅化

顶点着色器之后,并不会直接传递给像素着色器,而是会先把顶点着色器输出的东西进行插值、像素化。

这个过程有一个术语叫:光栅化

如下图所示,三角形经过光栅化后,变成了一个个像素。

图片来源于网络

除了顶点位置信息,顶点法线、颜色、纹理坐标等都会先经过光栅化,再传递给像素着色器。

由于所有vert输出的值都会被光栅化,所以顶点着色器传递到像素着色器的法线向量,在使用的时候,记得先normalize,否则会有意想不到的效果。

关于光栅化的内容,建议大家多在网上搜索资料看看,有一个更深入的了解。

3.5、frag函数 (像素着色器)

光栅化之后的顶点信息会被传递给像素着色器。

后期的教程中,我们为了实现一些高级效果,其实大部分情况下是对frag函数的增强。在本文的示例中,我们为了尽可能减少大家的理解成本,麒麟子连color都没有从外部传递过来,直接在代码中定义了颜色。

大家可以修改frag()函数中的颜色值来查看像素变化

这里顺便说一下,像素着色器(Pixel Shader)和片元着色器(Fragment Shader)是一个东西。前者来自于Direct3D圈,后者来自于OpenGL圈。

3.6、像素的一生

像素着色器处理之后,像素还会进行一系列的测试和操作,只有测试都通过的像素,才会被写入到目标缓冲区中。如下图所示:

图片来源于网络

3.6.1、模板测试(Stencil Test)

模板测试会根据预先设置好的模板测试参数进行工作,并决定是否要丢弃像素。

在本文里,麒麟子不打算进一步讲模板测试的细节。

如果后面的章节有用到模板测试的地方,会进行详细说明。

如果现在就想了解模板测试的朋友,请自行搜索。

3.6.2、深度测试(Depth Test)

深度测试需要深度缓冲区的配合,请先查看本文6.4小节中的深度缓冲区概念。

深度测试提供了 > >= == < <= != 总是,从不等比较运算符,默认是 <=。

当一个像素进入深度测试环节时,会进行如下操作。

深度测试流程

3.6.3、融合 (Alpha Blend)

如果一个像素以上所有测试都通过了,则会进入融合处理阶段。

融合就是我们经常说的透明混合。

它会将当前像素的值按照我们设置好的混合方式,与目标颜色缓冲区的值进行融合。

如果没有开启Alpha Blend开关,则这阶段自动跳过。

我们常见的alpha混合因子如src_alpha、one_minus_src_alpha等就是用在这个操作上面的。

关于alpha blend参数细节和使用技巧,我们会在后面的讲解中深入解释。

3.6.4、写入帧缓冲区

最终,像素会被写入缓冲区中。帧缓冲区有三个:颜色缓冲区、深度缓冲区、模板缓冲区。

颜色缓冲区(Color Buffer):

颜色缓冲区,故明思意,存储颜色的缓冲区。这个缓冲区就是我们屏幕上能看到的缓冲区。

深度缓冲区(Depth Buffer):

是一个看不见的缓冲区。

深度缓冲区存储的是一个与顶点z值相关的值(这个z值是摄影后的z值,由于它处于摄像机空间,由近即远,所以我们称它为深度)。

这个缓冲区使我们在渲染非透明物体的时候,不用管先后顺序,也能保证结果的正确性。

大大提高了绘制效率。

眼尖的朋友就会问,透明物体怎么办呢?

透明物体是需要从远到近进行渲染的,可以搜索“油画家算法”作进一步研究。

当然,cocos引擎已经做了这个排序的事情,不必过于担忧。

如果渲染状态 深度写未开启,则不会进行深度缓冲区写入。

模板缓冲区(Stencil Buffer):

这个缓冲区可以理解为一个标记缓冲区,他提供了一些比较运算操作,用于实现一些特殊效果。

如果渲染状态开关 模板缓冲未开启,则不会进行模板缓冲区写入

模板缓冲区的背景知识,建议大家多看其他资料。

这里只是简单介绍了颜色缓冲区、深度缓冲区、模板缓冲区的基本概念,如果要展开来讲各个细节,可能够写好几篇文章了。

想要了解更多细节的朋友,请自行搜索关键字。

四、总结


根据C友们的反馈,麒麟子在本文中直接将Cocos Shader的学习拉回到了原点,真正的从零开始。

虽然本文的cocos-shader-helloworld非常简单,但随着教程的进行,它会越来越丰富。

它越是华丽,代表你Shader的学习越有进步。

本文也对3D可编程管线做了一个简要的梳理。

然而由于篇幅有限,不可能详尽地讲每一个知识点。

好在网络上已经有很多相关优质的文章。

希望大家下来后,以本文为题纲,针对文中提到的各种术语和关键字进行搜索,去拓展自己的相关知识。

编程这个事情,只要下功夫多练,收获不会差的。

借卖油翁的一句话:

我亦无它,但手熟尔!

五、预告


斗破苍穹-3D动画截图

下一篇,我们将在cocos-shader-helloworld的基础上做如下操作

  1. 为shader添加外部变量

  2. 外部变量在Inspector面板上的控制

  3. 外部变量在代码中如何控制

敬请关注!

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

推荐阅读更多精彩内容