Notifications
Article
ShaderLab入门实践2
Updated a month ago
587
1
从实践来认识ShaderLab编程--开始第一个Shader
好啦好啦,上次我们已经看清了ShaderLab(vertex and fragment shaders以后简称Shader)的大概样子,这次,我们来写属于我们的第一个拥有基本功能的shader。
由于我们是实践入门,所以汪汪只会对编写过程中遇到的一些知识点进行讲解,不会太过拓展,希望以后如果汪汪加入了新的知识点,大家一定要要做好笔记哦,并记住怎么去用。这样一来,我们就可以边实践边拓展知识点了哦。如果想有体系的学习的话,大家一定得多查资料,毕竟学无止境嘛。(ง •_•)ง
OK!今天呢,我们会编写我们的第一个shader,虽然是最简单的,甚至我们可以直接通过在Unity里右键创建shader的方式就搞定,但是,我们的目的是去了解其语法。我们要自己完全写出来一个完整的shader,才能达到实践中融会贯通。
在上一篇文章里,我们在Properties中声明了一个“2D”类型的用户属性接口,但是可能有的同学会发现,当我们丢上贴图的时候,其实并没有在我们的模型上面显示。
“白色的。。。。。我的贴图呢??”
今天呢,我们要做的就是把我们的贴图显示出来,这些都是在Pass里实现的。
今天我们通过对贴图的显示,来认识Pass的真实容貌。
(*记模板)既然我们已经要开始写shader了,那么除了上篇文章中提到的基本结构外,我们还需要继续细化我们的shader结构,小伙伴们以后写shader都可以参考这个模板哦,有了这个模板,汪汪接下来就只对Pass代码块进行展示哦,大家以后参考其他人写的shader的时候,也是重点看Pass代码块。可选内容代码块汪汪已经简化省去,以后我们写一些效果用到的时候,再对其进行补充。
在学习之前,希望小伙伴们知道下面的美术基本常识。
  • 在计算机图形里(或许所有图形?),图形都是由点线面构成。
  • uv:通俗的说,就是把三维模型,通过切割,拆分的方式,展平成一个二维的图形(大家都知道有些猎人喜欢把动物剥皮,然后平铺成一个地毯吧,一个道理),这样,三维空间中的色彩,就转换成了二维空间的。
  • 建过模型的小伙伴应该都知道,三维模型,由点线面构成,颜色展示,则是由UV,贴图来实现(简单说)。
好了,接下来,我们在这个模板上继续我们上一篇文章的内容,只显示Pass:
----------------------------------------------------------------------
Pass
{
CGPROGRAM //必须声明,向编译器说明,我们的CG代码块开始了!!
#pragma vertex vert //下面的是编译指令,大家想了解可以去深入研究一下
#pragma fragment frag
#include "UnityCG.cginc" //包含文件,有了这个声明,才能使用一些内置函数,功能,类似C#里的using指令哦
sampler2D _BaseTex; //声明贴图
struct v2f //vertex to fragment 可以理解为这是一个自定义数据类型,它的存在,是为了把数据从顶点函数传递到片元函数(可自定义名字)
{
float4 pos:SV_POSITION; //定义顶点,并给其语义:SV_POSITION,SV的意思是“SystemValue”的简写,就是系统数值
float2 uv:TEXCOORD0; //定义uv,并给其语义:TEXCOORD0,这是声明uv的常用语义哦
}; //*重点,别忘了分号
v2f vert(appdata_base v) //顶点函数,并输入来自v(数据类型为appdata_base,这里是系统数据类型,可自定义)的数据
{
v2f o; //既然要转换,必定会使用,则需要声明;
o.pos=UnityObjectToClipPos(v.vertex); //坐标转换,把坐标点从模型空间转换到裁剪空间
o.uv=v.texcoord; //texcoord是appdata_base里的uv声明哦,下面有结构体原型
return o; //返回我们转换好的数据
}
fixed4 frag (v2f i):SV_TARGET
{
float4 col=tex2D(_BaseTex,i.uv); //tex2D是对图片(上一篇文章已经声明过)进行输出点采集,并在对应uv点进行输出
return col; //返回已经采集好的颜色值
}

ENDCG //结束代码块
}
-------------------------------------------------------------------------------------------------------------------
下面汪汪对代码进行一些说明:
  • 运行流程
“嘛,汪汪,这代码运行流程我怎么看不懂啊,虽然我声明了函数,但是,我没调用,也没给参数赋值,这就运行了?”
(*重)在shader里,我们的代码都会依次执行和赋值,如果上面做了声明,只要我们return了以后,如果下面的函数参数声明了我们return的数据类型,那么这个函数就会稳稳接住我们return的值,并执行函数体代码,是直接执行哦。一般情况下,我们不会过多声明自定义函数,用的最多的就是点函数和片元函数了。
  • sampler2D _BaseTex;
小伙伴们可能会说:“??我之前不是声明过了吗,就在开头呐,这里为什么还需要声明?”
(*重)在Shader里,如果我们需要使用我们暴露的数据,我们必须在pass里再次声明,且名字(脚本内变量名)和开始一样,且必须“_”开头。
  • struct v2f
这是结构体声明,属于一种自定义数据类型,如果想深入了解的小伙伴,建议可以学习一下C/C++哦,因为Shader的语法大多和C/C++一样。
  • float4
这是一个三维数据类型,float大家应该熟悉,这里的float4其实里面有四个值(x,y,z,w),x,y,z是坐标值,容易理解,w是什么?这是为了方便进行矩阵运算的(计算机图形学里有详细说明哦,另外,如果学习过计算机图形的小伙伴,学习起来更容易哦)。那么大家知道,那么后面的数字是几,它就对应依次往后存储xyzw。
  • appdata_base原型
---------------------------------------------------------
struct appdata_base {
float4 vertex : POSITION;//顶点位置
float3 normal : NORMAL;//法线
float4 texcoord : TEXCOORD0;//纹理坐标
UNITY_VERTEX_INPUT_INSTANCE_ID
};
————————————————
这是系统提供的哦,也可以自己声明和定义,如果小伙伴们看到其他人写的类似的的,说明就是在写appdata结构体哦
  • 语义
SV_POSITION:
裁剪空间中的顶点坐标 结构体必须包含一个该词修饰的变量
COLOR0:
通常用于输出第一组顶点颜色
COLOR1:
通常用于输出第二组顶点颜色
TEXCOORDN(0~7):
通常用于输出纹理坐标
好啦,我们来看一下我们的第一个shader写得如何吧!!
我们看到,我们的贴图都已经显示出来了!!
小伙伴们要是以后熟练了,是可以不敲这些代码的,直接在片元函数中编写特效代码即可,但对于刚接触的小伙伴们来说,还是不能偷懒哦,得完整敲一遍才行。
后言:对于有编程基础的小伙伴而言,理解这些代码块应该是很容易的,但是小伙伴们还是需要上手多练习哦,会语法,不代表会写代码。另外,汪汪在代码块后面的说明其实有些是不全面的,大家有兴趣可以多上网搜索了解其内涵。
对于完全不会编程的同学来说,汪汪的学习建议是:C/C++,计算机图形学中的图形变换,坐标转换,线性代数中的矩阵运算。
好啦,基础到现在就讲完了,大家有什么意见可以留言,我会在后面补充。
后面的系列我们将在我们现有代码的基础上,进行一些shader补充,以及特效的实现,比如旋转,溶解,描边等,以及实现这些效果的原理说明,并在实现的过程中,渐渐学习更多函数和语句。
汪汪
技术美术 - Artist
4
Comments
middle
a month ago
👍
0