Core - 着色器&材质
有些图形渲染等方面的基础概念容易混淆或误解,这里把自己相关的个人笔记整理出来;以后自己的文章也可以用其作为词条引用;
着色器(Shader):
着色器是整个渲染流程的一个子部分;是GPU渲染流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在GPU上运行的;依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染;主要的着色器有:
- 顶点着色器(Vertex Shader),是完全可编程的,它通常用于实现顶点的空间变换、顶点着色等功能;
- 曲面细分着色器(Tessellation Shader)是一个渲染流程中可选的着色器,它用于细分图元(rendering primitives);
- 几何着色器(Geometry Shader)同样是一个可选的着色器,它可以被用于执行逐图元(Per-Primitive)的着色操作,或者被用于产生更多的图元;
- 片元着色器(Fragment Shader),是完全可编程的,它用于实现逐片元(Pre-Fragment)的着色操作;在DirectX中,片元着色器被称为像素着色器(Pixel Shader);
随着技术进步还加入了Compute Shader等着色器,但Compute Shader并非传统渲染流水线上一个阶段,相反它主要用来计算原本由CPU处理的通用计算任务,这些通用计算常常与图形处理没有任何关系,因此这种方式也被称为GPGPU——General-purpose computing on graphics processing units(图形处理器通用计算);
而我们在游戏引擎中如Unity中的Shader,则是对GPU渲染流程中这些特定阶段的抽象层:
Unity Shader为控制渲染过程提供了一层抽象;如果没有使用Unity Shader(左图),开发者需要和很多文件和设置打交道,才能让画面呈现出想要的效果;而在Unity Shader的帮助下(右图),开发者只需要使用ShaderLab来编写Unity Shader文件就可以完成所有的工作;
所以游戏引擎中的Shader不同于传统意义上的Shader,可以做的事情也远多于一个传统意义上的Shader:
- 在传统的Shader中,我们仅可以编写特定类型的Shader,例如顶点着色器、片元着色器等;而在游戏引擎的Shader中,我们可以在同一个文件里同时包含需要的顶点着色器和片元着色器代码;
- 在传统的Shader中,我们无法设置一些渲染设置,例如是否开启混合、深度测试等,这些是开发者在另外的代码中自行设置的;而在游戏引擎的Shader中,我们通过设置就可以完成;
- 在传统的Shader中,我们需要编写冗长的代码来设置着色器的输入和输出,要小心的处理这些输入输出的位置对应关系等;而在游戏引擎的Shader中,可以方便的改变这些属性,提供了直接访问顶点位置、纹理坐标、法线等模型自带数据的方法,不需要开发者自行编码来传给着色器;
材质(Material):
而以上所说的游戏引擎Shader只是Material的一部分;输入的贴图或者颜色等,加上对应的Shader文件,以及对顶点着色器、片元着色器等的特定的参数设置,将这些内容(游戏引擎Shader及输入参数等)打包存储在一起,得到的就是一个Material(材质);之后,我们便可以将材质进行渲染输出了;
游戏引擎中的材质可能会有多种模板(如UE4材质中Shading Model选项)供开发者选择,这些都是各种Shader配置和光照计算方式的不同组合而已;
参考资料: