unity 3d shaderlab 开发实战详解_[转]UnityShader 详解

v2-41d7452c888232e15ddf02f4ad156489_1440w.jpg?source=172ae18b

Unity的着色器有以下三种:

Fixed Function Shader 固定片段着色器

Surface Shader 表面着色器

Vertex&Fragment Shader 顶点与片段着色器

顶点与片段着色器可以把物体整个渲染管线流程通过代码的方式表现出来,可以说是最接近显卡语言的着色器写法。这里提到渲染管线,其实他是3D图形学的一个非常重要的概念,即一个3D物体如何绘制到屏幕上的显卡渲染流水线的过程。

不要以为这些都是理所当然的事情,没有任何功能是计算机理所当然会的,包括一个3D物体如何显示在屏幕上,是要经过一连串复杂的计算得到的画面效果,而我们学Shader的目的,其实就算去创作,去改变这种效果。

**Shader其实就算改变物体在屏幕上的形状和颜色的技术**

下面我们来看看Shader的真面目

Shader 

我们来一行一行解读一下每句的意思。首先这里可以看到他有四个关键字:

- Shader

- Properties

- SubShader

- Pass

我们来分开解读一下:

首先是Shader,后面双引号的内容是他在材质球中的位置,首先是根目录,然后是子目录。Unlit/NewUnlitShader就算去材质球找Unlit然后选NewUnlitShader就能选到本shader。

v2-7e8d1b6778e4e0ffdb79cbef8f79956f_b.jpg

接下来轮到Properties,他记录的是Shader中的变量,这些变量可以表现在Unity中,也可以在Shader里面参与计算,也就是Unity和Shader进行交互的工具。

v2-511d5cf73857da5ab7c30305659c1542_b.jpg

v2-54f8b99dda6c7ea6406e2dbf9b74c1a1_b.jpg

然后是SubShader,他是Shader的子着色器,一个Shader可以有多个子着色器,我们会把画面效果写在子着色器里面,每一个子着色器写一种效果,但是他们不能同时执行,一次只有一种效果能实现。

v2-8be219c27485abc6ad45c07aa11127d6_b.jpg

根据上图我们可以看到,子着色器可以有很多个,但是我们具体用哪个呢?其实他们在这里是逻辑或的关系,也就是前面如果有能执行的,后面就不会执行。也就是多种画面效果,只要前面有一种能执行的了,后面的都不会执行。特别适用于选择显卡,比如说我有种画面效果,一个显卡显示不了,没关系,我后面还有很多备用的,一个不行用第二个,再不行用第三个。如果都不行,看到有个Fallback吗?他叫回滚,也就是说所有都不行的情况下调用回滚。通常我们喜欢把画面效果好的写在最上面,然后依次把要求高的SubShader写下来,最后写个回滚,如果全部执行不了就执行回滚,也是最后的保底,通常写最简单通用的着色器。

**那SuaShader里面主要有什么呢?**

他主要有标签和一些子着色器的关键字还有Pass通道。这里案例里面标签有渲染类型,Opaque表示不透明,就是说在这里把他和不透明物体归到同一类。LOD表示细节层次,这里表示着色器的LOD是100,那么系统的LOD低于这个值,他将不渲染。

接着我们讲到最后一个关键字,Pass通道。可以从上图看到,他和Subshader一样可以有很多个,但是他们却不是SubShader那样只有一个生效,他们会共同影响最后的画面效果。通常Pass通道写得越多,显示出来的画面效果越多。而我们的CG语法主要就是在Pass通道展开。

v2-cf79f466327ea2f06e27e346c64ad543_b.jpg

v2-858cf675b03fefe75961f70eea65dbef_b.jpg

** CG语法简介: **

CG(Nvida公司开发的c for graphics计算机图形编程C语言超集):CG程序可以根据运行时的需要或者事先编译成GPU汇编代码;

HLSL(基于DirectX的High Level Shading Language):只能供微软的Direct3D以及XNA使用,移植性差;

GLSL(基于OpenGL的OpenGL Shading Language):供OpenGL使用,具有良好的跨平台和移植特性。

CG和HLSL的语法类似。GLSL语法体系自成一家。

CG是一个可以被OpenGL和Direct3D广泛支持的图形处理器编程语言。CG语言和OpenGL、DirectX并不是同一层次的语言,而是OpenGL和DirectX的上层,即CG程序是运行在OpenGL和 DirectX标准顶点和像素着色的基础上的。

简单说,CG就是C For Graphic,是Nvidia的一套显卡语言,他可以像雇佣军一样嵌套在DX和OpenGL里面使用,是移植性非常好的显卡语言。我们的ShaderLab是啥语言?他是隶属于DX的,也就是说他其实是在DX基础上的一个框架,那么他内部也是有CG这个雇佣军的。怎么看出来的?从Pass通道里面的CGPROGRAM开始,我们就看到CG语法的影子了。

注意从这里开始变成了CG语法,其实就是C语言,他嵌套在ShaderLab里面,那么上面的其实是ShaderLab的框架。细心的同学会发现,上面从来没有出现过分号,下面开始出现分号了,这也是他俩区别的标识。

那我们来看CG语法:

#pragma vertex vert

这两句主要是用你自己写的顶点函数和片段函数去替换系统自带的顶点函数和片段函数。

- 顶点函数负责处理物体形状(VS)

- 片段函数负责处理物体在屏幕的颜色(PS)

这里vert和frag是你自己定义的名字,可以改变,但是改变的话,下面必须声明两个同名的函数,否则编译器算你耍赖,要替换的函数找不到,就会报错。

v2-d69f3e161084e3bcffd5cc9db4e0031d_b.jpg
float4 

这个就是你要实现的顶点函数,首先我们返回的顶点要是float4,4唯的向量,函数名必须和上面的一样,appdata_base 是CPU传过来的数据块,也就是一次Draw Call传过来的数据,里面有物体的法线,物体的本地顶点,物体的贴图信息等等,最后的是语义,这里表示返回值是用来显示形状的,不是用来显示颜色的。为啥要有语义呢?因为返回的float4可以做任何事情,可以用来处理形状,也可以表示颜色,你给他语义,他就知道他要用来做啥了。那么我们这个函数什么时候调用呢?不需要关心,我们上面写好替换了,程序会自动调用。

如何理解mul(UNITY_MATRIX_MVP,v.vertex)这个代码呢?这个后面渲染管线我们会讲,这里其实是把物体的顶点坐标通过3D矩阵计算换算成屏幕投影的坐标,显示在屏幕上。

接下来是:

fixed4 

这个是我们实现的片段函数,返回的是fixed4,和上面float有点不同,fixed也是浮点,不过取值范围在-2-2,为啥要用fixed呢?首先我们知道这是片段函数,是用来处理颜色的。颜色有RGBA四个值,刚好对应fixed4?那为啥用fixed不用float呢?因为显卡的显存很珍贵,他发现颜色都是从0-1(其实把0~255做了个映射)的,那么就不需要用字节比较大的float.后面是COLOR语义,表示返回值是用来显示颜色的,不是处理形状的。

如何理解return fixed4(1,0,0,1);这个代码呢?其实就算返回一个颜色值,射回画笔工具里面的值就是,255,0,0,255,也就是红色,最后一个255表示透明度里面的不透明,与之相反的0就代表全透明。

最后最后有个ENDCG说明CG语言到底了,执行完了,回到ShaderLab的怀抱。

最后附一份实现水面效果的shader仅供参考:

Shader 

注:该篇文章为转载,略有所改动

原篇作者:时过敬迁

链接:

Shader第一讲——从Unlit说起​www.jianshu.com
v2-ad0496475177c6e05e0258868d7b9a3f_180x120.jpg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值