Minecraft GLSL Shader着色器基础教程#2.5 着色器是个啥?着色器相关名词的解释
注意:阅读本篇教程需要您有以下基础:
1.基本了解原版资源包的功能,包括方块状态调用、模型、纹理等内容
2.有编写过资源包json、mcmeta等文件
3.无论是利用软件建模还是“记事本”建模,了解原版模型文件的结构等

着色器
很多人学着色器面临的一大问题就是不明白着色器到底是个什么东西,着色器到底是干什么的?学起来模模糊糊,感觉很抽象。
其实着色器就是资源包的一个模块,就像blockstate文件夹下的方块状态文件控制方块的不同状态调用的不同模型;textures下的纹理决定了贴到模型上的贴图,shader文件夹下的着色器则控制了游戏中所有内容的渲染,这就是说,着色器是对游戏内容有实实在在的操作,它读取并在运算后输出,而不仅仅是其他内容如模型、纹理那样的“被调用”
控制渲染是什么意思?听它的中文译名,感觉是给游戏内容着色的,就像怪物蛋、药水、皮革套的着色。但着色器所控制的渲染程序不止于此。
着色器的工作,主要有两项:
取得游戏内容的顶点位置,通过一系列运算并输出顶点位置
取得游戏内容的颜色信息,通过一系列运算并输出颜色信息
但是这里要注意的是,尽管着色器的对象不止一个顶点,但是着色器在工作时只对一个点进行更改,而且也只能获得这个点的信息。但是别担心,这个顶点所在的整张纹理图片atlas也是顶点信息的一部分,这张atlas贴图包含了资源包内所有被加载的纹理,能够访问的信息还是比较客观的。甚至包含玩家摄像机看到这个顶点的视角、光线、雾等信息和一个比较特殊的全局量GameTime(或Time,可以访问时间)。但是着色器不能知道模型上相邻的顶点的信息,尽管我们知道、也可以调用处相邻顶点处“应该”调用的纹理信息,但是这不意味着我们访问了那个点。要记住:着色器每次只更改一个点的内容,它无法获得到其他点的内容!
注意:这里说的一个点并不是贴图上的一个像素,贴图的像素
着色器只需要更新gl_Position和gl_FragColor这两个变量,就可以做到对游戏内容渲染的控制。现在不理解这两个变量没关系,你将在以后的教程中了解着色器的编写。
此外,着色器目前有三个类别:核心着色器(Core Shader 负责渲染所有的游戏内容如方块、UI栏、实体等)、后处理着色器(Post Shader 负责渲染整个屏幕,在核心着色器之后开启,将整个屏幕作为一张2D的“照片”进行更改)、包含着色器(Include Shader 负责声明一些常量和函数,开发者将包含着色器引入vsh或fsh中,这样就可以利用包含着色器中的函数进行开发
着色器程序
在shader文件夹下,有许多json格式的着色器程序,游戏通过调用这些着色器程序来更新渲染。
着色器程序(json)本身不包含代码,而是和我们所熟悉的资源包中其他的json一样,负责指定一些类内容。
如模型的json文件中指定了每一个体素的位置、大小和贴图,着色器程序这个json文件则指定了一系列全局量(uniform),一个顶点着色器(vsh)和一个片段着色器(fsh)等内容,这些内容则涉及到GLSL的编写,也就是前文涉及到的“一系列运算”这个步骤。
游戏内容的顶点位置和颜色信息在每一个着色器程序中都不同,这些不同的内容可以被着色器程序传到相同或不同的顶点着色器。最终输出到屏幕上面。比如后处理着色器creeper,就将整个屏幕的内容(这是后处理着色器所负责渲染的游戏内容)通过着色器程序:color_convolve、scan_pincushion层层运算并最终输出的特殊的“苦力怕视角”效果。(其中还有两个blit程序,但blit程序的工作就是啥也不干)
后处理着色器和渲染管线(缓冲层)
后处理着色器的工作是在核心着色器之后对整个屏幕生效,也就是说它每次会读取一个屏幕上的像素并通过一系列着色器程序进行更改。
这个“一系列”着色器程序即为渲染管线,渲染管线也是一个json文件,其中声明了一些类缓冲层,并以列表形式声明了启用的着色器程序的顺序和参数,以及缓冲层的传递顺序。参数以全局量的形式被vsh和fsh调用。
缓冲层类似画布(也有直接将缓冲层翻译为画布的,json文件中叫做target,这里采用我第一次见到的翻译),画布的大小可以自定义,其中有几个特殊的画布如minecraft:main缓冲,它的大小是玩家的窗口大小(单位为像素),这个缓冲中则是之前所说的“整个屏幕的内容”,并且在渲染管线的最后也要将画面传回minecraft:main
之前说过,blit程序什么也不干,但是他还是有存在的意义:因为渲染管线的组成是:着色器程序+传入+传出+可选的参数,而且传入和传出的缓冲不能是同一个,所以在把A通过一定运算传到B后,需要一个什么也不干的着色器程序把B传回A(但是mojang做了很多个啥也不干的着色器程序,这点我确实是看不懂了)
顶点着色器和片段着色器
片段着色器(fragment shader)也可以翻译为帧着色器或按用法命名为颜色着色器,我这里采用了我首次见到而且我比较顺口的一种翻译即片段着色器
顶点着色器和片段着色器是实际包含GLSL代码的部分,它们可以被多个着色器程序共用,用uniform修饰的变量(译为全局量)来接收着色器程序传递给它的实参,用sampler采样器对缓冲或游戏内容进行采样,获得颜色信息或光照信息等,由于采样器与采样到的东西是一对应的,所以可以将采样器视为一个缓冲或一张纹理
顶点着色器和片段着色器的语法是一致的,它们的区别主要在顺序和“任务”上,顶点着色器比片段着色器要先执行,甚至在大多数着色器中,顶点的颜色是在顶点着色器中先初步运算再传入片段着色器的。片段着色器
在vsh和fsh之间还可以使用in和out来修饰变量,使其传递到下一个着色器中,如:游戏内容的一些信息如顶点位置在vsh中用in接收,vsh更新顶点位置并运算出纹理坐标和顶点颜色,用out传输到fsh中,又在fsh中用in接收这些变量以更新顶点颜色。
为了便于理解,可以这样来表示着色器变量的传输
着色器程序.json ->in 顶点着色器.vsh out->in 片段着色器.fsh out-> 屏幕,uniform变量则是共通的
着色器可以干什么
这个问题对已经有资源包制作经验的人可能更有意义,我们在制作资源包的时候常常遇到很多限制,比如:
制作模型的时候有大小、旋转限制:这可以用顶点着色器偏移顶点位置的功能解决
希望可以在UI界面的物品和手上的物品上调用两套模型:这可以通过检测不同位置和贴图的不同来决定是否渲染某一张贴图,做到不同模型的效果
希望可以实现自发光功能:通过检测需要自发光的纹理,更改颜色的计算过程,将顶点的颜色以原始亮度渲染,做到自发光的效果
此外着色器还可以检测到:玩家的视角使游戏内容随视角的变化而变化,甚至做到更改某些游戏内容被看到的视角和投影方式。或者检测游戏时间来做到模型动画等,由于偏移顶点的单位是以像素为单位的,这意味着可以利用着色器来制造一些曲面,让原版mc模型也出现球体。
后处理着色器则可以单独访问一些游戏内容,如粒子、深度等,以及通过采样器访问到屏幕某一点的颜色,甚至在屏幕上“打印文字”、记录过去某一帧的屏幕并再未来调用。

本篇教程先到这里,如果有错误或需要补充可以在评论区指出,我会找时间修改。
关于渲染管线、后处理着色器、着色器程序的结构和全局量、采样器的用法在前两篇教程中已经介绍过,请读者自行翻阅。