unity中的unity shader效果的效果有哪些

Unity3D教程:教你如何利用Shader来进行3D角色的渲染 | Unity3D教程手册
当前位置 :
>> Unity3D教程:教你如何利用Shader来进行3D角色的渲染
Unity3D教程:教你如何利用Shader来进行3D角色的渲染
本文主要介绍一下如何利用Shader来渲染游戏中的3D角色,以及如何利用Unity提供的Surface Shader来书写自定义Shader。
一、从Shader开始
1、通过Assets-&Create-&Shader来创建一个默认的Shader,并取名“MyShader”。
Unity3D教程:3D角色的渲染
2、将MyShader打开即可看见Unity默认的Shader代码
&&&01Shader &Custom/MyShader& {02Properties {03_MainTex (&Base (RGB)&, 2D) = &white& {}04}05SubShader {06Tags { &RenderType&=&Opaque& }07LOD 20008CGPROGRAM09#pragma surface surf Lambert10sampler2D _MainTex;11struct Input {12float2 uv_MainTex;13};14void surf (Input IN, inout SurfaceOutput o) {15half4 c = tex2D (_MainTex, IN.uv_MainTex);16o.Albedo = c.rgb;17o.Alpha = c.a;18}19ENDCG20}21FallBack &Diffuse&22}
3、将该Shader赋给一个角色,就可以看到该Shader所能表达出的Diffuse渲染效果。
Unity3D教程:3D角色的渲染
4、接来我们将以此默认Shader作为蓝本,编写出自定义的Shader。另外,该Shader所用到的参数,我们将在下一章节进行说明。
二、实现多种自定义渲染效果
1、 BumpMap效果
如果想实现Bump Map效果,可对上述的Shader做如下修改:
1.1 在属性Properties中加入:
&&&1Properties {2_MainTex (&Base (RGB)&, 2D) = &white& {}3_BumpMap(&Bumpmap&, 2D) = &bump& {}4}
1.2 在SubShader的变量中也进行相应修改:
&&&1sampler2D _MainTex;2sampler2D _BumpMap;3struct Input {4float2 uv_MainTex;5float2 uv_BumpMap;6};
1.3 最后修改surf函数,加入对Normal分量的计算:
&&&1void surf (Input IN, inout SurfaceOutput o) {2&white-space:&& half4 c = tex2D (_MainTex, IN.uv_MainTex);3o.Albedo = c.rgb;4o.Alpha = c.a;5o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));6}
这样,角色的材质部分即可变为如下形式(暂定BumpMap的Shader名为“MyShader1”):
Unity3D教程:3D角色的渲染
然后,根据Base图来创建其Normal Map图,并拖入到BumpMap中即可。BumpMap的效果显示如下:
Unity3D教程:3D角色的渲染
(1)首先是title的解释
&&&1Shader &Custom/MyShader1&
这种表示表明了该Shader在编辑器中的显示位置,例如我们可在如下地方找到该Shader。
Unity3D教程:3D角色的渲染
(2)其次是Properties
&&&1Properties {2_MainTex (&Base (RGB)&, 2D) = &white& {}3_BumpMap(&Bumpmap&, 2D) = &bump& {}4}
Properties可通过如下语义进行声明:
name ("displayname", property type) = default value
“name” 是与Shader脚本中对应的名字
“display name”是在材质视图中所显示的名字
“propertytype”是指该property的类型,一般可有如下几种类型:Range,Color,2D,Rect,Cube,Float和Vector
“defaultvalue”是指该property的默认值
这里需要注意的是,如果你在Properties中加入了新的属性,那么你需要在CGPROGRAM中的SubShader中加入同样名字的参数。
(3)接下来是“LOD”语义词的解释。
这里的“LOD”主要是指Shader的LOD程度,即对于超出该范围的物体将不再通过该Shader进行渲染,具体的Shader LOD说明可以参见:
(4)我们在SubShader中还加入了
&&&1sampler2D _BumpMap;2float2 uv_BumpMap;
其中,_BumpMap是为了关联Properties中的_BumpMap属性。
而uv_BumpMap,是为了获取BumpMap图中的uv坐标。
(5)最后,我们在surf函数中获取每个顶点的纹理信息以及法线信息,这些信息将被应用于接下来的Vertex Fragment和Pixel Fragment。
&&&1void surf (Input IN, inout SurfaceOutput o) {2half4 c = tex2D (_MainTex, IN.uv_MainTex);3o.Albedo = c.rgb;4o.Alpha = c.a;5o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));6}
其中,tex2D函数可以读取纹理_MainTex中的IN.uv_MainTex坐标位置的像素颜色值。
Albedo和Alpha分别获取该像素的RGB值和Alpha值,其中“Albedo”是一个漫反射参数,它表示一个表面的漫反射能力,即一个表面上出射光强与入射光强的比值。具体介绍可见:。
2、& Blinn-Phong效果
如果想实现Blinn-Phong效果,可对上述的Shader做如下修改:
2.1&&在属性Properties中加入:
&&&1_AmbientColor (&Ambient Color&, Color) = (0.1, 0.1, 0.1, 1.0)2_SpecularColor (&Specular Color&, Color) = (0.12, 0.31, 0.47, 1.0)3_Glossiness (&Gloss&, Range(1.0,512.0)) = 80.0
2.2&&在SubShader的变量中也加入相应修改:
&&&1fixed4 _AmbientColor;2fixed4 _SpecularColor;3half _Glossiness;
2.3&&最后修改surf函数,进行如下修改:
&&&1fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
这里将原有的half4替换为fixed4,这样做是为了提高渲染的性能,因为fixed的精度较之half要低,更高的精度意味着更大的计算量,而这里fixed的精度已经足够,所以使用fixed替代half4,从而来降低计算消耗,增加渲染性能。
2.4&&将“#pragma surface surf Lamber”改成“#pragma surfacesurf CustomBlinnPhong”,同时加入与其对应的LightingCustomBlinnPhong函数来计算顶点光照。
&&&01inline fixed4 LightingCustomBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten) 02{03fixed3 ambient = s.Albedo * _AmbientColor.rgb;04&05fixed NdotL = saturate(dot (s.Normal, lightDir)); 06fixed3 diffuse = s.Albedo * _LightColor0.rgb * NdotL;07&08fixed3 h = normalize (lightDir + viewDir); 09float nh = saturate(dot (s.Normal, h)); 10float specPower = pow (nh, _Glossiness);11fixed3 specular = _LightColor0.rgb * specPower * _SpecularColor.rgb;12&13fixed4 c;14c.rgb = (ambient + diffuse + specular) * (atten * 2);15c.a = s.Alpha + (_LightColor0.a * _SpecularColor.a * specPower * atten);16return c;17}
该函数的名称为什么不是“CustomBlinnPhong”呢?这是因为该函数虽然是由“#pragma surface surf CustomBlinnPhong”来调用,但是为了让该函数可以正常工作,我们需要在其名称前加入“Lighting”关键字,这样Unity才能识别出这是一个自定义的光照函数。
通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader2”):
Unity3D教程:3D角色的渲染
其显示效果如下:
Unity3D教程:3D角色的渲染
3、& 边缘光照(Rim Light)和卡通渲染(Toon Shading)
可以通过对上述Shader做以下改进,来达到这种效果:
3.1&&在属性Properties中加入:
&&&1_RimColor (&Rim Color&, Color) = (0.12, 0.31, 0.47, 1.0) 2_RimPower (&Rim Power&, Range(0.5, 8.0)) = 3.0 3_Ramp (&Shading Ramp&, 2D) = &gray& {}
3.2&&在SubShader的变量中也加入相应修改:
&&&01sampler2D _MainTex;02sampler2D _BumpMap;03sampler2D _Ramp;04&05fixed4 _AmbientColor;06fixed4 _SpecularColor;07half _Glossiness;08&09fixed4 _RimColor;10half _RimPower;11&12struct Input {13float2 uv_MainTex;14float2 uv_BumpMap;15half3 viewDir; 16};
3.3&&修改surf函数,进行如下修改:
&&&1void surf (Input IN, inout SurfaceOutput o) {2fixed4 c = tex2D (_MainTex, IN.uv_MainTex);3o.Albedo = c.rgb;4o.Alpha = c.a;5o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));6fixed rim = 1.0 - saturate (dot (normalize(IN.viewDir), o.Normal));7o.Emission = (_RimColor.rgb * pow (rim, _RimPower));8}
这里主要是用来计算边缘光照的,首先通过视线与法线的夹角来找到模型的边缘,然后再根据距离的远近来控制发射光的强度。
3.4&&将“#pragma surface surf CustomBlinnPhong”改成“#pragma surfacesurf CustomBlinnPhong exclude_path:prepass”,同时在LightingCustomBlinnPhong函数来修改漫反射光的计算,来达到卡通渲染的效果。
&&&1fixed NdotL = saturate(dot (s.Normal, lightDir)); 2fixed diff = NdotL * 0.5 + 0.5;3fixed3 ramp = tex2D (_Ramp, float2(diff, diff)).rgb;4fixed diffuse = s.Albedo * LightColor0.rgb * ramp;
通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader3”):
Unity3D教程:3D角色的渲染
其显示效果如下:
Unity3D教程:3D角色的渲染
可以看出边缘光照的效果,同时还可以看出明显的明暗变化的卡通渲染效果。
三、&&&&&&&小结
综上所述,本文已经给出了人物的几种基本渲染方法及其Shader实现,在这里我并没有去分析每种渲染效果的原理,而仅是从实际出发,直接给出对应的简单实现方法。如果想要对光照模型进行深入理解,可以Google搜索其原理进行了解。最后,给出各种渲染方法的对比图,显示如下:
Unity3D教程:3D角色的渲染
本系列文章由&Unity公司开发支持工程师Amazonzx&编写,。
【上一篇】
【下一篇】
您可能还会对这些文章感兴趣!【Unity Shaders】Transparency —— 使用alpha通道创建透明效果
本系列主要参考一书(感谢原书作者),同时会加上一点个人理解或拓展。
是本书所有的插图。是本书所需的代码和资源(当然你也可以从下载)。
========================================== 分割线&==========================================
从这篇开始是一个全新的章节:透明效果(Transparency)。之前在的时候就一直调不出来背景透明,就是那个时候决定要学一下Shader的基础知识,不求成为多么厉害的大神,只望对渲染的内部原理有些许了解~
开始正文。
在我们学习如何编写透明的Surface Shader的开始,我们需要理解应该包含哪些代码使得我们可以开启透明效果。Unity再一次慷慨地为我们提供了一些内置参数,我们可以通过包含这些参数来快速得到透明效果。
这是通过在Shader的#pragma声明中添加alpha参数来实现的。这句话告诉Unity我们想要在Shader中使用透明度。但当我们在创建透明Shaders时,需要仔细考虑一些事情,那就是代码中元素的绘制顺序。这篇文章将会讲述一些基本问题,来得到一个非常简单的透明物体。在下面的章节中,将会讲解其他有关透明度的问题。
和以前一样,我们需要创建一个新的场景。
创建一个新的场景,添加一个平行光以及一个球体(Sphere)。
创建一个新的Shader和新的Material,可以命名为SimpleAlpha。把Shader赋给Material后,再把该Material赋给第一步中的球体。
最后,我们需要一张贴图作为控制隐私,来控制哪些部分是透明的,哪些部分是不透明的。
下图是我们用到的贴图。这张贴图仅包含单纯的RGB和白色(自带资源中没有,可以自己画,很简单)。我们使用它的RGB通道作为一个取值为0或1的透明度值。
这篇Shader非常简单。
在Properties块中添加一个新的property,这使得我们可以全局控制透明度。 Properties {
_MainTex (&Base (RGB)&, 2D) = &white& {}
_TransVal (&Transparency Value&, Range(0,1)) = 0.5
然后,我们在#pragma声明中添加一个新的参数:alpha参数。
#pragma surface surf Lambert alpha解释:再解释一遍上面这句声明的意思。使用名为surf的Surface Function,使用内置的Lambert光照函数,开启透明通道。
最后,在surf()函数中添加控制透明度的代码。
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.
o.Alpha = c.b * _TransV
完整代码如下:
Shader &Custom/SimpleAlpha& {
Properties {
_MainTex (&Base (RGB)&, 2D) = &white& {}
_TransVal (&Transparency Value&, Range(0,1)) = 0.5
SubShader {
Tags { &RenderType&=&Opaque& }
#pragma surface surf Lambert alpha
sampler2D _MainT
float _TransV
struct Input {
float2 uv_MainT
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.
o.Alpha = c.b * _TransV
FallBack &Diffuse&
如果没有透明效果,如下所示:
最后效果如下(从左到右分别对应了o.Alpha = c.r * _TransVal, o.Alpha = c.g * _TransVal,&o.Alpha = c.b * _TransVal):
你可以看到,使用Unity的Surface Shaders得到透明效果是非常容易的。这类Shader依赖两个元素:#pragma声明中的alpha参数,以及在SurfaceOutput结构体中的Alpha值。
一旦我们在#pragma声明中添加了alpha参数,这就告诉了Unity:嘿,接下来你要允许我渲染一个透明的surface。然后,我们就仅仅需要逐像素地使用一个取值范围为0到1的值来填充SurfaceOutput结构体中的O.Alpha值。
从颜色角度讲(这里的颜色指一个灰度值,因为透明度可以用一个单通道的灰度值来表示),一个为1的透明度,即白色,将会产出一个完全不透明的效果。而0值,即黑色,表示一个完全透明的效果。
这就解释了上述的效果。例如,当我们使用如下语句控制透明度:
o.Alpha = c.r * _TransVal
则贴图中除了红色部分以及白色部分(白色的RGB通道值均为1)其R通道的值为1,其余(绿色和蓝色部分)均为0。因此只有红色和白色的部分才不透明。
尽管关于透明度有很多东西,但我们要知道,上述是其最基本的实现。在下面的章节中,我们将开始如何在实时渲染中使用alpha通道或者半透明的Shader。
我想要用shader过滤掉 视频中的透明通道
在你的shader中怎么改呢
candycat1992
[reply]summerzym[/reply]如果你能获取到视频里的每一帧图片就可以按上面那样做了
本分类共有文章47篇,更多信息详见
& 2012 - 2016 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";Posts - 107,
Articles - 0,
Comments - 1713
21:13 by 吴秦, ... 阅读,
Unity3D shader简介 可以肯定的说Unity3D使得很多开发者开发游戏更容易。毫无疑问,shader(着色器)编码,仍有很长的路要走。shader是一个专门运行在GPU的程序,经常被神秘包围,它最终绘制3D模型的三角形。如果你想给游戏一个特殊的显示,学习如何编写shader是必要的。Unity3D使用shader做后期处理,对2D游戏也是必不可少的。这个系列的文章将逐步介绍shader编程,并面向几乎没有任何shader知识的开发者。
简介 下图大致表示了在Unity3D渲染流程中发挥作用的3个不同实体:
3D模型本质上是,被称为顶点的3D坐标集合。他们连接在一起构成一些三角形。每个顶点包含一些其它的信息,如颜色、点指的方向(法线)、纹理映射坐标(UV数据)。 没有材质模型是不能被渲染的。材质包含一个shader和其属性值的封装。因此,不同材质可以共享相同的shader,赋予不同的数据。
shader剖析 Unity3D支持两种不同的shader:表面shader、片段和顶点shader。还有第三种类型:固定管线shader,但是如今已经过时了,将不包含在本系列文章。无论你需要的是哪种类型,shader的结构都一样:
Shader "MyShader" { & Properties & { &&& // The properties of your shaders &&& // - textures &&& // - colours &&& // - parameters &&& // ... & } & & SubShader & { &&& // The code of your shaders &&& // - surface shader &&& //&&& OR &&& // - vertex and fragment shader &&& //&&& OR &&& // - fixed function shader & }&
} 可以包含多个SubShader,一个接一个。他们包含GPU的实际指令。Unity3D将找到与你显卡兼容的SubShader,并顺序执行他们。这对多平台编码是非常有用,因为你可以在一个文件中编写同一shader的不同版本。 属性 shader的属性在某种程度上相当于C#脚本中的public字段,他们将出现在材质的inspector面板,给你机会来调整。但不像脚本,材质是资源:编辑中游戏运行时修改材质的属性值是永久的。甚至游戏停止后,修改的属性值也是有效的。 下面的代码片段涵盖了你可以在shader中使用的所有基本类型的定义:
3~4行中的2D,表示参数是纹理。他们可以初始化为white、black、gray。你也可以使用bump表示使用法线贴图,这种情况下,它将自动初始为颜色#808080,这用来表示没有任何凸凹。Vector和Color总是有4个元素(分别为xyzw和rgba)。 下图展示了一个shader附着到一个材质上之后,在inspector面板中是如何显示的。
不幸的是,这对我们使用属性还不够。事实上,Properties块被Unity3D用来从inspector访问shader隐藏变量。这些变量仍需定义在shader中,它们包含在SubShader块中。
纹理的类型为sampler2D。向量是float4、颜色一般是half4,分别使用32和16位表示。用来编写shader的语言为Cg/HLSL,很迂腐:参数的名称必须与先前定义的匹配。然而类型不需要,例如把_MyRange声明为half而不是float不会报任何错误。一些令人困惑的是,如果你定一个向量类型的属性,关联到一个float2变量,额外的2个值将被Unity3D忽略。 渲染顺序 正如已提到的,SubShader块包含实际代码,使用Cg/HLSL(非常像C)编写。不严格地说,一个shader为图像的每个像素执行,它的性能非常关键。由于GPU的体系结构,一个shader中能够执行的指令数量有限制。可以通过分割几个部分执行,但本教程不包含这块。 一个SubShader通常看起来像这样:
第8~11行包含实际的Cg代码,通过CGPROGRAM和ENDCG指令示意。 第3行,在实际代码之前,介绍tags的概念。tags用来告诉Unity3D我们写的shader的某些属性。例如,shader渲染的顺序(Queue)和应该如何渲染(RenderType)。 当渲染三角形时,GPU通常根据它们离摄像机的距离,远的先绘制。这在渲染不透明的几何形状时够用了,但是透明物体将失败。这也是为什么Unity3D运行指定Queue标签,可以控制每个材质的渲染顺序。Queue接受正整数(越小越先绘制),预定义(mnemonic)的标签也可以使用: lBackground(1000):用于背景和天空盒 lGeometry(2000):默认标签,用于大部分不透明物体 lTransparent(3000):用于包含透明属性的材质,例如玻璃、火、粒子、水 lOverlay(4000):用于镜头耀斑,GUI元素和文本 Unity3D还允许指定相关顺序,例如Background+2,表示1002队列值。搞乱了Queue值会导致恶劣的情况,一个对象总是被绘制,即使它应该被其他模型遮挡住了。 Ztest 记住,一个包含透明属性(Transparent)的对象并不总是显示在不透明(Geometry)对象上面。默认情况下,GPU执行ZTest避免隐藏的对象被绘制。原理是,它使用了一个额外的缓冲区,其大小与屏幕渲染的相同。每个像素包含绘制对象在该像素的深度(离相机的距离)。如果我们要绘制一个像素比当前深度更大,像素就被丢弃。ZTest剪裁被其它对象遮挡住的像素,无论他们绘制到屏幕上的顺序。
表面 VS 顶点和片段 shader代码的最后一部分。在渲染之前,需要决定使用那种类型的shader。本节将给出shader效果惊鸿一瞥的样子,但不会深入解释。表面、顶点和片段shader将在本教材的下一部分覆盖。 表面shader 当材质需要根据光照模拟实际效果时,那么你就需要一个表面shader。表面shader在函数surf中隐藏光线如何被反射的计算,并允许指定“直观”的属性,如反照率、法线、反射率等。然后将这些值插入到光照模型,将输出每个像素的最终RGB值。或者,当需要非常高级的效果是,你也可以编写自己的光照模型。 一个典型的表面shader的Cg代码如下所示:
第5行指定输入的纹理,然后在第12行将指定Albedo属性。第3行指定使用Lambertian光照模型,这个是非常典型光照如何影响对象的模型。shader仅使用反照率属性通常称为漫反射(diffuse)。 顶点和片段shader 顶点和片段shader的工作贴近GPU渲染三角形的方式,并没有光照如何表现的概念。模型的几何形状首先通过一个调用函数vert,改变他的顶点。然后各个三角形通过另一个调用函数frag,这决定了最终每个像素的RGB颜色。这对2D效果非常有用,后期处理和特殊的3D效果非常付出需要使用表面shader。 下面的顶点和片段shader简单只是使用红色,没有光照:
第15~17行,将原始的3D空间顶点转换到最终的2D屏幕位置。Unity3D使用UNITY_MATRIX_MVP实现,隐藏了底层的实现数学运算。在此之后,第22行,给定每个像素为红色。只需要记住,顶点和片段shader的Cg部分需要封装到Pass块中。它跟简单的表面shader不一样。
结论 本篇文章逐渐引入了两种类型的Unity3D shader,并说明何时需要使用。接下来四篇文章,将介绍实现它们的细节。还有一个附加篇,将介绍屏幕shader,用于2D图像的后期处理。
Part 1: Unity3D shader简介() Part 2: Unity3D表面shader() Part 3: Unity3D基于物理渲染和光照模型( ) Part 4: Unity3D顶点和片段shader(Vertex and fragment shader in Unity3D) Part 5: Unity3D传递数组给shader(Passing arrays to a shader: heatmaps in Unity3D) Part 6: Unity3D屏幕shader和效果后期处理(Screen shaders and postprocessing effects in Unity3D) &shader和Material的基本关系
Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出。绘图单元可以依据这个输出来将图像绘制到屏幕上。输入的贴图或者颜色等,加上对应的Shader,以及对Shader的特定的参数设置,将这些内容(Shader及输入参数)打包存储在一起,得到的就是一个Material(材质)。之后,我们便可以将材质赋予合适的renderer(渲染器)来进行渲染(输出)了。
所以说Shader并没有什么特别神奇的,它只是一段规定好输入(颜色,贴图等)和输出(渲染器能够读懂的点和颜色的对应关系)的程序。而Shader开发者要做的就是根据输入,进行计算变换,产生输出而已。
Unity中Shader的三种基本类型
按照渲染管线的分类,可以把Sharder分成3个类别:
固定功能着色器(Fixed Function Shader)
固定功能着色器为固定功能渲染管线的具体表现。
表面着色器
存在于Unity3D中由U3D发扬光大的一门技术。Untiy3D为我们把Shader的复杂性包装起来,降低shader的书写门槛。
顶点着色器和片段着色器
GPU上含有两个组件:可编程顶点处理器和可编程片段处理器,顶点和片段处理器被分离成可编程单元,可编程顶点处理器是一个硬件单元,可以运行顶点程序,而可编程片段处理器则是一个可以运行片段程序的单元。
顶点着色器
顶点着色程序从GPU前端(寄存器)中提取图元信息(顶点位置、法向量、纹理坐标),并完成顶点坐标空间变换、法向量空间转换、光照计算等操作,最后将计算数据传送到指定寄存器中。
片段着色器
片段程序从上述寄存器中获取需要的数据:纹理坐标与光照信息等,并根据这些信息以及从应用程序传递的纹理信息进行每个片段的颜色计算(纹理查询),最后将处理后的数据传送光栅操作模块。
三种着色器的共同点:
都必须从唯一一个根Shader开始
Prooerties参数部分,作用以及语法完全相同。
具体功能都在SubShader里。
都可以打标签
都可以Fallback
都可以处理基本的功能,例如光照漫反射以及镜面反射。但如uv计算效果等高级功能,固定功能着色器无法完成。
三种着色器的不同点
表面着色器没有通道pass{},加了会报错,该着色器已经把具体内容打包在光照模型中了。
固定渲染管线每句代码之后都没有“;”
核心结构不同:
固定渲染管线的核心是:
Material{}以及SetTexture[_MainTex]{}
顶点与片段着色器的核心是:
#pragma vertex vert
#pragma fragment frag
#include &UnityCG.cginc&
表面着色器的核心是:
1.表面着色器使用Unity3D自带光照模型Lambert,也不做顶点处理,只需要一个表面处理函数surf即可。
#Pragma surface surf Lambert
2.这套表示使用的是自己写的光照模型lsyLightModel,并且使用了顶点处理函数vert
#pragma surface surf lsyLightModel vertex:vert
在Unity中如何区分以上三种着色器
没有嵌套CG语言,即代码中没有CGPROGARAM和ENDCG关键字的,就是固定功能着色器。
嵌套CG语言,代码中有surf函数的为表面着色器
嵌套了CG语言,代码中有#pragma vertex name和 #pragma fragment frag声明的,就是顶点着色器&片段着色器。
Unity中Shader的基本框架
Unity中Shader整体的框架写法可以用如下的形式来概括:
Shader &name& { [Properties] SubShaders[Fallback] }
Unity中所有着色器都由关键字shader开始,随后的字符表示着色器的名字,这个名字会显示在Inspector检视面板中,所有的代码都应该放在{}里面。
该名字不需要和shader文件名同名,它应该是简单的描述性词语,在name后面加上/能够中Inspector面板中创造出二级菜单(多个/创建多级菜单)。
shader整体框架
如上面的整体框架,我们可以画出下面这图:
从这幅图可以看到,Unity中的shader可以分为以下三个模块:
属性Properties
Properties一般定义中着色器的起始部分。属性模块可以定义一些属性,用来指定那个这段代码有哪些输入。在使用shader的时候可以直接中材质面板里编辑这些属性。Properties块内的语法都是单行的。属性的定义格式如下所示:
属性可以划分为以下几类:
数字与滑动条
name (&display name&, Range (min, max)) = number //滑动条调节
name (&display name&, Float) = number//数字调节
name (&display name&, Int) = number//数字调节
颜色与向量(注意是四元数)
name (&display name&, Color) = (number,number,number,number)
name (&display name&, Vector) = (number,number,number,number)
name (&display name&, 2D) = &defaulttexture& {}
name (&display name&, Cube) = &defaulttexture& {}//立方体贴图
name (&display name&, 3D) = &defaulttexture& {}
Range与float的属性只能是单精度值。
在后面的着色器程序中,属性值通过[name]来访问。而display name将显示在材质检视器中。
可以使用在属性定义加上等号为每个属性提供缺省值。
对于纹理(2D, Rect, Cube) 缺省值既可以是一个空字符串也可以是某个内置的缺省纹理:&white&, &black&, &gray& or&bump&
// properties for a water shader
Properties
_WaveScale (&Wave scale&, Range (0.02,0.15)) = 0.07 // sliders
_ReflDistort (&Reflection distort&, Range (0,1.5)) = 0.5
_RefrDistort (&Refraction distort&, Range (0,1.5)) = 0.4
_RefrColor (&Refraction color&, Color) = (.34, .85, .92, 1) // color
_ReflectionTex (&Environment Reflection&, 2D) = && {} // textures
_RefractionTex (&Environment Refraction&, 2D) = && {}
_Fresnel (&Fresnel (A) &, 2D) = && {}
_BumpMap (&Bumpmap (RGB) &, 2D) = && {}
子着色器SubShader
可以有一个或者有多个子着色器SubShader(至少有一个),子着色器SubShader中含有一个或者多个通道Pass(也是至少要有一个)。
在Pass中一般可以写以下的代码
Color Color 设定对象的纯颜色,可以是括号中的四个值,也可以是被方框包围的颜色属性名称
Material{Material Block} 材质被用于定义对象的材质属性,关于材质块的内容可以看下面的介绍
Lighting On/Off 定义上述材质块的定义是否有效,On时材质块效果有效,Off时颜色通过Color命令直接给出
SeparateSpecular On/Off 开启独立镜面反射,这个命令会添加高光光照到着色器通道的末尾,因此贴图对高光没有影响。只在光照开启时有效。
ColorMaterial AmbientAndDiffuse | Emission
使用每顶点的颜色替代材质中的颜色集。AmbientAndDiffuse 替代材质的阴影光和漫反射值;Emission 替代 材质中的光发射值。
Pash中材质块Material{}代码写法
上面已经说了,在Pass中可以书写材质块代码用于定义对象的材质属性,如下的代码可以写在材质块中:
Diffuse Color(R,G,B,A);对象基本颜色,漫反射
Ambient Color(R,G,B,A);环境光,当对象被RenderSettings.中设定的环境色所照射时对象所表现的颜色。
Specular Color(R,G,B,A);对象反射高光的颜色
Emission Color 对象自发光
Shininess Number 取值在0-1之间表示加亮时的光泽度
对象完整光照的最终颜色是:
FinalColor=Ambient * RenderSettings ambientsetting + (Light Color * Diffuse + Light Color *Specular) + Emission
最终颜色=环境光反射颜色* 渲染设置环境设置 (灯光颜色漫反射颜色+灯光颜色*镜面反射颜色)+自发光
示例代码:
Shader "我的Shader"
Properties
_MainColor ("主颜色",Color)=(0,0,0,0)
_AmbientColor("环境光颜色",Color)=(0.8,0.2,0.2,0)
_SpecularColor("放射高光颜色",Color)=(0.8,0.2,0.2,0)
_ShininessNum("光泽度",Range(0,1))= 0.5 //滑动条
//---------------------------------【子着色器1】----------------------------------
//----------------通道---------------
Color(1,0,0,0) //当光照开启时无效。
//----------材质块------------
//将漫反射和环境光反射颜色设为相同
Diffuse[_MainColor]
Ambient[_AmbientColor]
Specular[_specularColor]
Shininess[_ShinnessNum]
//开启光照 //光照影响了颜色
Lighting On
SeparateSpecular On
回滚FallBack
Shader基本框架的最后是指定一个回滚函数Fallback,用来处理所有的子着色器都不能运行时的情况(当目标设备太老时,所有的设备都有其不支持的特性时使用了Fallback),可以认为是一种defult。
Fallback& Diffuse &
关于纹理的载入在下一节讲解。
阅读(...) 评论()

我要回帖

更多关于 unity 描边效果shader 的文章

 

随机推荐