前言
Shader,中文名为着色器,对很多开发者来说它是⼀个神秘的存在,想学但是不知道如何去学,或者学了一段时间发现Get不到它的点,始终感觉游离在外,无法开窍。那么本文将讲下如何从零基础入门Shader,目的在于让初学Shader的程序员或者美术师可以快速进入这个丰富多彩的世界。
正文
什么是Shader?
虽然上面简单说了Shader就是着色器,但还是有必要详细说明⼀下具体什么是Shader。
Shader其实就是专门用来渲染图形的⼀种技术,通过shader,我们可以自定义显卡渲染画面的算法,使画面达到我们想要的效果。小到每⼀个像素点,大到整个屏幕,比如下面这两个游戏内比较常见的效果:
Shader分为两类:
1.顶点Shader(3D图形都是由⼀个个三角面片组成的,顶点Shader就是计算每个三角面片上的顶点,并为最终像素渲染做准备)
2.像素Shader,顾名思义,就是以像素为单位,计算光照、颜色的⼀系列算法。
几个不同的图形API都有各自的Shader语言,在DirectX中,顶点shader叫做Vertex Shader,像素Shader叫做Pixel Shader;在OpenGL中,顶点Shader也叫做Vertex Shader,但像素Shader叫做Fragment Shader,也就是我们常说的片断Shader或者片元Shader。说白了,Shader其实就是一段代码,这段代码的作用是告诉GPU具体怎样去绘制模型的每一个顶点的颜色以及最终每一个像素点的颜色。
Shader编程语言
既然Shader是一段代码,那必然要用一种语言来书写它,目前主流的有三种语言:
1.基于OpenGL的OpenGL Shading Language,简称 GLSL。
2.基于DirectX的High Level Shading Language,简称 HLSL。
3. 还有NVIDIA公司的C for Graphic,简称 Cg语言。
GLSL与HLSL分别是基于OpenGL和Direct3D的接口,两者不能混用。而 Cg语言是用于图形的C语言,这其实说明了当时设计人员的一个初衷:
让基于图形硬件的编程变得和C语言编程一样方便、自由,让基于图形硬件的编程变得和C语言编程一样方便、自由。(正如 C++ 和 Java 的语法是基于C的,Cg语言本身也是基于C语言的。如果您使用过C、C++、Java其中任意一个,那么Cg的语法也是比较容易掌握的)
Cg语言极力保留了C语言的大部分语义,力图让开发人员从硬件细节中解脱出来,Cg同时拥有高级语言的好处,如代码的易重用性,可读性高等。Cg语言是Microsoft和NVIDIA相互协作在标准硬件光照语言的语法和语义上达成了一致,所以,HLSL和Cg其实是同一种语言。
(有关基础语法可以先移步至unity shader 之基础五 基本语法_TO_ZRG的博客-CSDN博客)
Unity Shader严格来说并不是传统上的Shader,而是Unity自身封装后的一种便于书写的Shader,又称为Shader Lab。
在Unity中有3种Shader(其实就是三种不同的写法):
Surface Shaders 表面着色器
Vertex Fragment Shaders 顶点/片断着色器
Fixed Function Shaders 固定管线着色器
其中Fixed Function Shaders已经被淘汰,完全没有学习的必要了。
Surface Shader其实就是Unity对Vertex Fragment Shader的又一层包装,以使Shader的制作方式更符合人类的思维模式,同时可以以极少的代码来完成不同的光照模型与不同平台下需要考虑的事情。
一个Unity Shader的基本结构如下:
Shader "ShaderName" { Properties {//属性 } SubShader {//显卡A使用的子着色器 } SubShader {//显卡B使用的子着色器} }
而Unity会在背后根据使用的平台来把这些结构编译成真正的代码和Shader文件。
材质和Unity Shader的桥梁
Properties语义块中包含了一系列属性(Property),这些属性将会出现在材质面板中。
Properties { Name {"Display name", PropertyType} } = DefaultValue
其中Name是Shader中调用需要的属性,display name是出现在材质面板山的名字,PropertyType则是属性的类型。
答疑解惑
Unity Shader和CG/HLSL之间的关系
Unity Shader是用Shader Lab语言编写的,但对于表面着色器和顶点/片元着色器,我们可以在ShaderLab内部嵌套CG/HLSL语言来编写着色器代码。
通常CG代码块是位于Pass语义块内部的,如下所示:
GLSL
Unity Shader同样支持用GLSL进行编写,但是编写的产品则只能上架支持OpenGL的平台。
参考文档
NVIDIA提供的CG文档
NVIDIA提供的系列教程
Unity官方手册提供的Shader教学文档