cgunity 顶点着色器和片段着色器怎么添加雾效

2-20位字母,数字,下划线组合,支持中文
提示:若邮箱里没有发现验证邮件,请到垃圾邮件内查找
邮件送达可能会有一定延迟,请耐心等待一下:)
希望接收来自花魁小站的最新信息
验证码发送中
还没有账号?
验证码发送中
欢迎来到花魁小站!CG就是这么小资~
共签到次,已连续签到天
签到1天,财富+2连续签到,财富双倍连续签到大于10次,每次财富+20连续签到30天,获得30天VIP
graphicriver - Smoke Photo Effect Photoshop Actions
Photoshop烟雾效果生成器 - 这组包含6 个Photoshop动作,允许你创建逼真的“烟的照片效果”。最终的结果是在新的图层里,以便您可以自定义和编辑烟雾效果,您可以为每个烟雾效果图层添加不同的颜色变化。
&&下载所需财富:
下载说明:&
1.如压缩包需要解压密码,请手动输入:& 。直接复制粘贴网址是会出错的。
2.如果您下载的文件出现解压不了或文件受损等情况,请留言给我们,我们会尽快修复下载链接。
3.本站资源大部分共享在百度和360网盘,可以下载使用网盘的客户端,这样下载资源才更稳定。(/)
4.加入本站的QQ交流群:
(1号群:5满)(2号群:满 )(3号群:)BTW:花魁目前官方只提供3个QQ交流群,谢谢。
5.如果下载资源没有财富金币,请在个人中心做下新人任务,或者坚持每日签到就可以获得财富值了,本站不提供充值或者交易方式,财富金币的概念只是让大家有个参与度而已,谢谢支持和理解。
特别说明:本站原创CG视频教程归花魁小站版权所有,转载请注明,本站有权利追究其法律责任,本站所有转载资源全部来源于本站会员,仅供学习与参考,请勿用于商业用途,如有条件请支持正版,谢谢。
插件如何安装,请说明一下。谢谢!!
2 条记录 1/1 页【浅墨Unity3D Shader编程】之四 热带雨林篇: 剔除、深度测试、Alpha测试以及基本雾效合辑 - 推酷
【浅墨Unity3D Shader编程】之四 热带雨林篇: 剔除、深度测试、Alpha测试以及基本雾效合辑
本系列文章由
@浅墨_毛星云&
出品,转载请注明出处。&
文章链接:
作者:毛星云(浅墨)& & &
本文介绍了Unity中Shader书写中会用到的剔除、深度测试、Alpha测试以及基本雾效相关的语法知识,然后以6个Shader的书写作为实战内容,最后创建了一个生机勃勃的热带雨林场景进行了Shader的测试。 依旧是国际惯例,先上本文配套程序的截图。
绿色的海洋:
满眼的生机:
参天大树:
飘到脸上的树叶:
OK,图先就上这么多。文章末尾有更多的运行截图,并提供了原工程的下载。可运行的exe下载在这里:
好的,我们正式开始。
一、剔除与深度测试(Culling & Depth Testing)相关内容
1.1 剔除(Culling)的概念
对于实时交互的3D环境而言,现实的速度和效率是非常重要的。虽然现在的硬件能力非常的快,但是要想保持30FPS的同时处理数十万的三角形,以现在的主流机器来说还是有些困难的。
为了解决这种问题,人们提出了很多方法,其中有LOD,有Culling。这两种方法并不矛盾,而且我们往往需要在culling的基础上再使用LOD进一步解决pipeline的负担。
剔除是一种通过避免渲染背对观察者的几何体面来提高性能的优化措施。所有几何体都包含正面和反面。剔除基于大多数对象都是封闭的事实;如果你有一个立方体,你不会看到背离你的那一面(总是只有一面在你的前方),因此我们不需要绘制出背面。因此也被称做背面剔除。
一言以蔽之,所谓剔除,就是被挡住或视角以外的我们看不到的物体,因为它们无关紧要,所以我们就不去绘制,以节省资源,提高场景的运行效率。
1.2 深度测试(Depth Testing)的概念
在复杂的场景中,通常有多个物体需要绘制,这些物体之间通常会存在遮挡关系,离观察点较远的物体会因为近处物体的者的遮挡而不可见或只有部分可见,Direct3D图形系统提供了深度测试功能来实现这种效果。深度测试可以简化复杂场景的绘制,确保只有场景内的对象的最靠近的表面参与绘制。
浅墨之前在写DirectX相关博文的时候写过对深度测试的形象化理解,在这边也列出来吧:
把深度测试看做在一口井的井口处向井中观望。把所有物体都赋予一个深度值,放到井中来显示。深度越深的物体,离井口就越远。深度越浅的物体,离井口就越近。井表面的深度值为0。离井口近而深度浅的物体,可能会把离井口远的物体遮挡住。最终显示在屏幕上的开启深度测试后的画面,就如在井口处向井中观望里面物体显示出的遮挡与层次的效果一样。当然,离井口的深度就是每个物体在世界坐标系中的矩阵的Z坐标值了。
1.3 剔除与深度测试
(Culling & DepthTesting)相关
语句之一:Cull Back | Front| Off
此语句用于控制几何体的哪一面会被剔除(也就是不被绘制) 。其中:
Cull Back——& 不绘制背离观察者的几何面
Cull Front——& 不绘制面向观察者的几何面,用于由内自外的旋转对象
Cull Off ——& 显示所有面。用于特殊效果。
语句之二:ZWrite On | Off
此语句用于控制是否将来之对象的像素写入深度缓冲(默认开启),如果需要绘制纯色物体,便将此项打开,也就是写上ZWrite On。如果要绘制半透明效果,关闭深度缓冲,则用ZWrite Off。
语句之三:ZTest Less |Greater | LEqual | GEqual | Equal | NotEqual | Always
此语句用于控制深度测试如何执行。
缺省值是LEqual (绘制和存在的对象一致或是在其中的对象;隐藏其背后的对象),含义列举对应如下:
只渲染大于AlphaValue值的像素
只渲染大于等于AlphaValue值的像素
只渲染小于AlphaValue值的像素
只渲染小于等于AlphaValue值的像素
只渲染等于AlphaValue值的像素
只渲染不等于AlphaValue值的像素
渲染所有像素,等于关闭透明度测试。等于用AlphaTest Off
不渲染任何像素
语句之四:Offset Factor ,Units
此语句用两个参数(Facto和Units)来定义深度偏移。
Factor参数表示 Z缩放的最大斜率的值。
Units参数表示可分辨的最小深度缓冲区的值。
于是,我们就可以强制使位于同一位置上的两个集合体中的一个几何体绘制在另一个的上层。例如偏移量Offset 设为0, -1(即Factor=0, Units=-1)的值使得靠近摄像机的几何体忽略几何体的斜率,而偏移量为-1,-1(即Factor =-1, Units=-1)时,则会让几何体偏移一个微小的角度,让观察使看起来更近些。
二、Alpha测试(Alpha testing)相关内容讲解
2.1 Alpha测试的概念
Unity中,Alpha测试(Alpha Testing)是阻止像素被写到屏幕的最后机会。在Pineline中Alpha测试的位置如下:
在最终渲染出的颜色被计算出来之后,可选择通过将颜色的透明度值和一个固定值比较。如果比较的结果失败,像素将不会被写到显示输出中。
Alpha测试在渲染凹形物体的透明部分时非常有用。显卡上有着每个像素写到屏幕上的深度记录。如果一个新的像素比原来的像素的深度深,那么新的像素就不会被写到屏幕中。
让我们看一幅图:
仔细看上图,会发现:
左边的树使用了透明度测试(AlphaTest),注意在它的图形上的像素是如何完全透明或不透明的。
中间的树只使用透明度混合(Alpha Blending)来渲染,注意由于深度缓冲的缘故靠近分支的透明部分是如何覆盖更远的叶子。
最右边的树是通过下文实战中的第六个Shader“6.简单的植被Shader”着色器来渲染的,实现了透明度混合和透明度测试的组合,细节没有粗糙之处,浑然天成。
2.2 Alpha测试相关句法
语句之一:AlphaTest& Off & & & & & & & &&
此语句用于渲染所有像素(缺省)
语句之二:AlphaTest& comparison AlphaValue
此语句用于设定透明度测试只渲染在某一确定范围内的透明度值的像素。其中的comparison取值为下表之一:
Only render pixels whose alpha is greater than& AlphaValue .&大于
Only render pixels whose alpha is greater than or equal to& AlphaValue .&大于等于
Only render pixels whose alpha value is less than& AlphaValue .&小于
Only render pixels whose alpha value is less than or equal to from& AlphaValue .&小于等于
Only render pixels whose alpha value equals& AlphaValue .&等于
Only render pixels whose alpha value differs from& AlphaValue .&不等于
Render all pixels. This is functionally equivalent to& AlphaTest Off .&
渲染所有像素,等于关闭透明度测试AlphaTest Off
Don't render any pixels.&不渲染任何像素
而AlphaValue为一个范围在0到1之间的浮点值。也可以是一个指向浮点属性或是一个范围属性,在后一种情况下需要使用标准的方括号写法标注索引名字,如([变量名]).
三、基本雾效(Fog)设置
3.1 雾效相关背景和概念理解
雾效(Fog)参数用于控制雾相关的渲染。
在计算机图形学中,雾化是通过混合已生成的像素的颜色和基于到镜头的距离来确定的最终的颜色来完成的。雾化不会改变已经混合的像素的透明度值,只是改变RGB值。
Unity中的缺省雾设定是基于Edit-&RenderSettings中的设置的,且雾模式既可以是Exp2也可以是关闭;密度和颜色完全取自设定。
注意如果使用了片段着色器的话,着色器中的雾设定仍然是有效的。如果平台没有对固定管线的雾功能支持,Unity会实时补上着色器以支持需要的雾模式。
3.2 雾效相关的句法
语句之一:Fog&{& FogCommands }
此语句用于设定雾命令的内容,具体的填在大括号之中的内容见下面的语句。
语句之二:Mode &Off | Global | Linear | Exp | Exp2
此语句用于 定义雾模式。缺省是全局的,依据雾在渲染设定中是否打开确定可从无变化到平方值
语句之三:Color& ColorValue
此语句用于 设定雾的颜色值。
语句之四:Density& FloatValue
此语句 以指数的方式设定雾的密度。
语句之五:Range&
FloatValue& , &FloatValue
此语句用于 为linear类型的雾设定远近距离值。
&OK,本文的基本知识就将这么多,接下来看看 QianMo's Toolkit的更新,然后开始基于上面讲解的基础知识的Shader实战。
四、QianMo's Toolkit迎来v1.2更新
如前面三篇文章中所言,QianMo's Toolkit是浅墨在Unity中写Shader时会用到的一些脚本小工具,用C#来实现。
此次在 QianMo's Toolkit& Ver1.2版中加入了新的特性——检测当前系统的cpu与显卡的型号和参数,并显示到游戏窗口中。其实现代码如下:
//-----------------------------------------------【脚本说明】-------------------------------------------------------
脚本功能:
在游戏运行时显示系统CPU、显卡信息
使用语言:
开发所用IDE版本:Unity4.5 06f 、Visual Studio 2010
2014年12月 Created by 浅墨
更多内容或交流,请访问浅墨的博客:http://blog.csdn.net/poem_qianmo
//---------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------【使用方法】-------------------------------------------------------
方法一:在Unity中拖拽此脚本到场景任意物体之上
方法二:在Inspector中[Add Component]-&[浅墨's Toolkit v1.2]-&[ShowSystemInfo]
//---------------------------------------------------------------------------------------------------------------------
using UnityE
using System.C
//添加组件菜单
[AddComponentMenu(&浅墨's Toolkit v1.2/ShowSystemInfo&)]
public class ShowSystemInfo : MonoBehaviour
string systemInfoL
public Rect rect = new Rect(10, 100, 300, 300);
void OnGUI()
//在指定位置输出参数信息
GUI.Label(rect,systemInfoLabel);
void Update ()
//获取参数信息
systemInfoLabel = & \n\n\nCPU型号:& + SystemInfo.processorType + &\n (& + SystemInfo.processorCount +
& cores核心数, & + SystemInfo.systemMemorySize + &MB RAM内存)\n & + &\n 显卡型号:& + SystemInfo.graphicsDeviceName + &\n & +
Screen.width + &x& + Screen.height + & @& + Screen.currentResolution.refreshRate +
& (& + SystemInfo.graphicsMemorySize + &MB VRAM显存)&;
添加此脚本到场景中的任意物体后,填一下其中的x和y坐标的值,用于设置输出在屏幕中的哪个位置。
接着点运行,于是在游戏窗口的指定区域中出现了CPU和显卡的信息:
于是,目前的QianMo's Toolkit v1.2拥有的功能如下所示:
ShowFPS :在游戏运行时显示帧率相关信息
ShowObjectInfo :在测试过程里,于场景中和游戏窗口中分别显示添加给任意物体文字标签信息。隐藏和显示可选,基于公告板技术实现。
ShowGameInfo :在游戏运行时显示GUI相关说明
ShowLogo :在游戏运行时显示Logo
ShowUI :在游戏运行时显示简单的镶边UI。
SetMaxFPS :用于突破Unity每秒渲染 60帧的设定,自由设置最大帧率。
ShowObjectInfoInGamePlay :用于发布游戏之后显示文本信息。
ShowSystemInfo :在游戏运行时显示系统CPU、显卡信息
五、写Shader实战
根据上文讲解的剔除、深度测试和Alpha测试操作的句法,我们将完成如下六个Shader的写法:
1.用剔除操作渲染对象背面
2.渲染对象背面v2
3.用剔除实现玻璃效果
4.基本Alpha测试
5.顶点光照+可调透明度
6.简单的植被Shader
让我们通过详细注释的代码一个一个将他们讲清楚。
1. 用剔除操作渲染对象背面
先写一个非常简单的只会渲染对象的背面的Shader:
Shader &浅墨Shader编程/Volume4/12.用剔除操作渲染对象背面&
//--------------------------------【子着色器】--------------------------------
//【1】设置顶点光照
Emission(0.3,0.3,0.3,0.3)
Diffuse (1,1,1,1)
//【2】开启光照
Lighting On
//【3】剔除正面(不绘制面向观察者的几何面)
Cull Front
我们将此Shader编译后赋给材质,得到如下效果,可以发现比原本默认的材质颜色暗,因为我们绘制的是物体的背面:
我们将材质赋给一个立方体,可以看到,通过此Shader我们可以渲染对象的背面,从而看到一个很奇怪立方体(因为我们看到的是它的内部)。效果如下:
2. 用剔除操作渲染对象背面(第二版)
让我们给上面写的这个Shader加上之前我们已经掌握的顶点光照的一些内容,并通过定义出第二个通道,采用亮蓝色来渲染物体的背面。代码如下:
Shader &浅墨Shader编程/Volume4/13.渲染对象背面v2&
//-------------------------------【属性】---------------------------------------
Properties
_Color (&主颜色&, Color) = (1,1,1,0)
_SpecColor (&高光颜色&, Color) = (1,1,1,1)
_Emission (&光泽颜色&, Color) = (0,0,0,0)
_Shininess (&光泽度&, Range (0.01, 1)) = 0.7
_MainTex (&基础纹理 (RGB)-透明度(A)&, 2D) = &white& {}
//--------------------------------【子着色器】--------------------------------
//---------------------------【通道一】------------------------------
说明:绘制对象的前面部分,使用简单的白色材质,并应用主纹理
//----------------------------------------------------------------------
//【1】设置顶点光照
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
//【2】开启光照
Lighting On
// 【3】将顶点颜色混合上纹理
SetTexture [_MainTex]
Combine Primary * Texture
//--------------------------【通道二】-------------------------------
说明:采用亮蓝色来渲染背面
//----------------------------------------------------------------------
Color (0,0,1,1)
Cull Front
同样是将Shader先赋给一个材质,得到的效果如下:
我们将材质赋给一个立方体,直接看是一个非常正常的立方体:
但一旦镜头靠近,看到物体的内部时,就发现了我们定义的蓝色部分了:
3. 用剔除实现玻璃效果
很多时候,控制剔除比背面调试(debugging backfaces)更有用。比如遇到需要渲染透明的物体,经常会想要显示一个对象的背面。如果不做任何剔除操作的话,我们会发现有时常有一部分背面会覆盖在前面的一部分之上。下面就是一个解决这个问题的用于凸物体(球,立方体,车窗)的简单玻璃效果的着色器:
Shader &浅墨Shader编程/Volume4/14.用剔除实现玻璃效果&
//-------------------------------【属性】---------------------------------------
Properties
_Color (&主颜色&, Color) = (1,1,1,0)
_SpecColor (&高光颜色&, Color) = (1,1,1,1)
_Emission (&光泽颜色&, Color) = (0,0,0,0)
_Shininess (&光泽度&, Range (0.01, 1)) = 0.7
_MainTex (&基础纹理 (RGB)-透明度(A)&, 2D) = &white& {}
//--------------------------------【子着色器】--------------------------------
//【1】定义材质
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
//【2】开启光照
Lighting On
//【3】开启独立镜面反射
SeparateSpecular On
//【4】开启透明度混合(alpha blending)
Blend SrcAlpha OneMinusSrcAlpha
//--------------------------【通道一】-------------------------------
说明:渲染对象的背面部分
//----------------------------------------------------------------------
// 如果对象是凸型, 那么总是离镜头离得比前面更远
Cull Front //不绘制面向观察者的几何面
SetTexture [_MainTex]
Combine Primary * Texture
//----------------------------【通道二】-----------------------------
说明:渲染对象背对我们的部分
//----------------------------------------------------------------------
// 如果对象是凸型,那么总是离镜头离得比背面更远
Cull Back //不绘制背离观察者的几何面
SetTexture [_MainTex]
Combine Primary * Texture
同样是将Shader先赋给一个材质,得到的效果如下,可以发现是透明的黄色玻璃的效果:
再将材质赋给一个物体,就让此物体实现了简单的玻璃效果:
4. 基本Alpha测试
先看一个最简单的能用的例子,使用一张带有透明度通道的纹理。对象只会在透明度大于0.6 时显示:
Shader &浅墨Shader编程/Volume4/15.基本Alpha测试&
//-------------------------------【属性】-----------------------------------------
Properties
_MainTex (&基础纹理 (RGB)-透明度(A)&, 2D) = &white& {}
//--------------------------------【子着色器】--------------------------------
//----------------------------【通道】-------------------------------
说明:进行Alpha测试操作,且只渲染透明度大于60%的像素
//----------------------------------------------------------------------
// 只渲染透明度大于60%的像素
AlphaTest Greater 0.6
SetTexture [_MainTex] { combine texture }
此Shader编译后赋给材质,材质又赋给物体的效果如下,且因为选取的纹理的透明度除了局部线条以外,其他的都小于了60%,于是就是只剩下这大概的轮廓了:
5. 顶点光照+可调透明度
让我们在上面这个Shader的基础上增加一些光照和并让Alpha的阈值可以调节,于是便写出了如下的Shader:
Shader &浅墨Shader编程/Volume4/16.顶点光照+可调透明度&
//-------------------------------【属性】-----------------------------------------
Properties
_Color (&主颜色&, Color) = (1,1,1,0)
_SpecColor (&高光颜色&, Color) = (1,1,1,1)
_Emission (&光泽颜色&, Color) = (0,0,0,0)
_Shininess (&光泽度&, Range (0.01, 1)) = 0.7
_MainTex (&基础纹理 (RGB)-透明度(A)&, 2D) = &white& { }
_Cutoff (&Alpha透明度阈值&, Range (0,1)) = 0.5
//--------------------------------【子着色器】--------------------------------
// 【1】使用Cutoff参数定义能被渲染的透明度阈值
AlphaTest Greater [_Cutoff]
//【2】设置顶点光照参数值
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
//【3】开启光照
Lighting On
// 【4】进行纹理混合
SetTexture [_MainTex] { combine texture * primary }
赋给材质后的效果如下,可以自由调节Alpha透明度的阈值:
通过调节Alpha透明度的阈值,得到了显示 效果 差异很大的材质:
将此材质赋给物体后的效果如下:
6. 简单的植被Shader
最后一个Shader,让我们实现一个简单的植物渲染Shader的写法。
当渲染树和植物时,透明度测试使许多游戏中出现尖锐的边缘。解决这个问题的方法之一是渲染对象两次。首次通道中,我们只渲染超过50%透明度的像素。在第二次通道中,我们使用透明度混合上次我们切除的部分,而不记录像素的深度。我们可能会使一些树枝覆盖近的其他树枝,以实现逼真的效果。于是,简单的植被Shader写法如下:
Shader &浅墨Shader编程/Volume4/17.简单的植被Shader&
//-------------------------------【属性】-----------------------------------------
Properties
_Color (&主颜色&, Color) = (.5, .5, .5, .5)
_MainTex (&基础纹理 (RGB)-透明度(A)&, 2D) = &white& {}
_Cutoff (&Alpha透明度阈值&, Range (0,.9)) = .5
//--------------------------------【子着色器】--------------------------------
//【1】定义材质
Diffuse [_Color]
Ambient [_Color]
//【2】开启光照
Lighting On
//【3】关闭裁剪,渲染所有面,用于接下来渲染几何体的两面
//--------------------------【通道一】-------------------------------
说明:渲染所有超过[_Cutoff] 不透明的像素
//----------------------------------------------------------------------
AlphaTest Greater [_Cutoff]
SetTexture [_MainTex] {
combine texture * primary, texture
//----------------------------【通道二】-----------------------------
说明:渲染半透明的细节
//----------------------------------------------------------------------
// 不写到深度缓冲中
ZWrite off
// 不写已经写过的像素
ZTest Less
// 深度测试中,只渲染小于或等于的像素值
AlphaTest LEqual [_Cutoff]
// 设置透明度混合
Blend SrcAlpha OneMinusSrcAlpha
// 进行纹理混合
SetTexture [_MainTex]
combine texture * primary, texture
我们将一棵树的叶子和树皮的材质替换成刚刚写好的Shader:
然后看看效果:
嗯,还是挺不错的,整体显示效果比用Unity自带的Bumped Diffuse要出色一些(Unity自带的Bumped Diffuse还可以在树叶上看到透过的光影,这部分内容我们以后以后学了再加)。
OK,我们就写如上的这六个Shader作为本次实战的内容吧。最后是构建本文配套的游戏场景,以及一些最终程序运行截图的欣赏。
五、最终游戏场景效果演示——热带雨林
上一次我们处于神秘的光之城堡,这次的场景,不妨让我们来到充满生机的热带雨林,领略一番不一样的味道。以大师级美工鬼斧神工的场景作品为基础,浅墨调整了场景布局,加入了音乐,并加入了更多高级特效,于是便得到了如此这次生机勃勃的场景。
运行游戏,我们来到充满各种绿色植物的热带雨林之中:
满满的绿色植物:
飘落到脸上的树叶:
被椰子树包围:
鹤立鸡群的铁树:
冲破云霄的树:
凸起树根的老树:
最后放一张这次Shader的全家福:
OK,美图就放这么多。游戏场景可运行的exe可以在文章开头中提供的链接下载。
本篇文章的示例程序请点击此处下载:
浅墨已经完成《OpenCV3编程入门》一书的技术修订工作,以及OpenCV2、OpenCV3双版本总计两百多个示例程序的注释和整理工作,书籍预计会在12月底印刷,1月上市。
最近应该可以没什么琐事了,没有特殊情况的话 Unity Shader系列博文 可以 保持 每周周一更新到明年2月份过年前。美剧都冬歇了咱们才刚上线:)
所以本周开始,Unity Shader系列博文宣告正式回归~
下周一,我们,不见不散。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致【浅墨Unity3D Shader编程】之九 深入理解Unity5中的Standard Shader (一)&屏幕水幕特效的实现_ vr虚拟现实技术,unity3d教程下载,虚幻4引擎教程-游戏蛮牛移动端官网
【浅墨Unity3D Shader编程】之九 深入理解Unity5中的Standard Shader (一)&屏幕水幕特效的实现
查看: 4267
本帖最后由 浅墨 于
21:45 编辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处。&&
文章链接: http://blog.csdn.net/poem_qianmo/article/details/
作者:毛星云(浅墨)& & 微博:/u/& && &&&
本文工程使用的3D版本: 5.2.1
概要:本文主要介绍了中的标准着色器,并且也涉及到了基于物理的着色、延迟渲染等高级着色技术,而在文章后半部分,也对屏幕水幕特效的实现方法进行了讲解与分析。
依然是附上一组本文配套工程的运行截图之后,便开始我们的正文。如下图。
打开水幕特效的效果图:
原始的城镇场景:
需要说明,这里的水幕特效是动态的水流效果。本来准备传GIF上来展示动态的效果,但受图片尺寸2M的限制,无法出色地表现出动态效果(帧数有限,图片清晰度也会大打折扣)。建议感兴趣的朋友们下载这里提供的游戏场景的exe,自己在机器上体验水幕效果,比看博文中贴出的图片效果好太多。
【可运行的本文配套exe游戏场景下载】: /s/1nt7w5aL
提示:在此游戏场景中按F键可以开关屏幕特效。
在文章末尾有更多的运行截图,并提供了源工程的下载。
好的,正文开始。
一、认识Unity5中的Standard Shader
Unity5中重点推出了一套基于物理的着色(Physically Based Shading,PBS)的多功能Shader,叫做标准着色器(Standard Shader)。这套Shader的设计初衷是化繁为简。想用这样的一个多功能Shader,来代替之前多种多样的Shader各司其职,对于不同的材质效果,需要不同的Shader的局面。
Unity 5中目前有两个标准着色器,一个名为Stardard,我们称它为标准着色器的标准版,另一个名为Stardard(Specular Setup),我们称它为标准着色器的高光版,它们共同组成了一个完整的PBS光照明模型,且非常易于使用。标准着色器主要是针对硬质表面(也就是建筑材质)而设计的,可以处理大多数现实世界的材质,例如石头、陶瓷、铜器、银器或橡胶等。同时,它也可以非常出色地处理一些非硬质表面的材质,例如皮肤、头发或布料等。
如下的一个Unity官方放出的名为VikingVillage的场景中,所有的物体材质都是使用的标准着色器,标准着色器的广泛适用性可见一斑。
而在Unity5的官方放出的演示demo视频中,也是用一个标准着色器,Stardard(Specular Setup),就完成了游戏场景中绝大多数物体的材质显示。
Unity5 Standard Shader的演示Demo可以看这里:
/w_19rquxac31.html
Unity5 PBS技术的演示Demo截图:
下面稍微对Standard shader中核心的概念——基于物理的着色做一个大概的了解。
1.1 基于物理的着色(Physically Based Shading)技术概览
基于物理的着色(Physically Based Shading,简称PBS)就是以某种方式模拟现实中材质和光照的相互作用的一种着色方法。这种方法在需要光照和材质更加直观和逼真地协同工作的场合下优势非常明显。基于物理的着色模拟了光线在现实中的行为,实现了在不同的光照条件下的逼真效果。为实现这种效果需要遵循各种物理原理,包括能量守恒(也就是物体反射出去的光量不可能超过所接收的光量),Fresnel反射(所有表面反射在掠射角(grazing angles)处更加强烈),以及物体表面是如何自我遮挡等原理。
其实,PBS技术在多年前于虚幻三中就已经被广泛使用,而Unity直到最近刚发布的第五代,才将此特性作为官方的特性实现出来。而在Unity5发布之前,Unity的Asset Store中,已经有不少的第三方插件,在Unity中实现了PBS技术。
关于PBS技术,知乎上有一个专栏,专门介绍PBS技术的一些相关原理,在这里推荐一下:
基于物理着色(一)
基于物理着色(二)- Microfacet材质和多层材质
基于物理着色(三)- Disney和UE4的实现
这边贴一张专栏中的配套渲染图,效果非常出色:
1.2 如何使用标准着色器
可以在Unity5中任意材质的Shader选项中的最前面看到两个Standard Shader字样的选项。其中第一个是普通版,第二个带Specularsetup是高光版。
标准着色器标准版材质界面:
标准着色器的高光版材质界面:
不难得知,标准着色器引入了新的材质编辑器,它使PBS的材质编辑工作比以前的非PBS材质更简单。新的编辑器不但简洁,还提供了材质的所有可能用到的选项。在新编辑器中,我们不需要选用不同的着色器来改变纹理通道;不会再出现 “texture unused, please choose another shader” 这样的提示;也不再需要通过切换着色器来改变混合模式。
所有的纹理通道都是备选的,无需强制使用,任何一个闲置通道的相关代码都会在编译时被优化掉,因此完全不用担心效率方面的。unity会根据我们输入到编辑器中的数据来生成正确的代码,并使整个过程保持高效。
另外,我们可以用ctrl+点击纹理的方式预览大图,并且还可以分别查看颜色和Alpha通道。
ctrl+点击纹理,得到的纹理放大的预览:
OK,关于Unity5中的StandardShader的概念,大概先就讲这么多。更多细节可以参考Unity官方文档:
http://docs..com/Manual/shader-StandardShader.html
以及这里Unity5 Standard Shader的官方文档论坛翻译版:
http://forum./thread-897-1-1.html
1.3 理解标准着色器的组成
上面说了很多标准着色器的强大之处,其实,作为一个着色器,它也没有什么神秘的地方,无非就是两个Shader源文件,加上一堆CG头文件组成的两个功能稍微复杂全面一些的Shader而已。其中,两个Shader源文件里,又按渲染路径分为了很多的SubShader,每个SubShader里面又分为了很多Pass。而CG文件中,主要包含了Shader的支持函数,相关的宏等为Shader源文件提供支持的代码。
Unity5中标准着色器的组成,归纳概括如下:
两个Shader源文件
七个CG头文件
一个脚本文件(用于自定义材质编辑器UI)
下面分别对每个文件进行一个简单的介绍。
1)两个Shader源文件
Stardard.shader着色器源文件 - 标准着色器的标准版
StardardSpecular.shader着色器源文件 - 标准着色器的高光版
2)七个CG头文件
UnityStandardBRDF.cginc头文件-用于存放标准着色器处理BRDF材质属性相关的函数与宏
UnityStandardConfig.cginc头文件-用于存放标准着色器配置相关的代码(其实里面就几个宏)
UnityStandardCore.cginc头文件-用于存放标准着色器的主要代码(如顶点着色函数、片段着色函数等相关函数)
UnityStandardInput.cginc头文件-用于存放标准着色器输入结构相关的工具函数与宏
UnityStandardMeta.cginc头文件-用于存放标准着色器meta通道中会用到的工具函数与宏
UnityStandardShadow.cginc头文件-用于存放标准着色器阴影贴图采样相关的工具函数与宏
UnityStandardUtils.cginc头文件-用于存放标准着色器共用的一些工具函数
在包括本文在内的接下来的几次更新中,本系列文章将试着花篇幅来剖析这两个Shader源文件,和依附的几个CG头文件的源码,从而一窥Unity5中新版Shader书写体系的究竟。
3)一个脚本文件
StandardShaderGUI.cs脚本文件——定义了特定的自定义编辑器UI界面
标准着色器对应材质的编辑器外观不同于一般的Shader,就是因为在Shader末尾书写了如下的代码:
[mw_shl_code=csharp,true]//使用特定的自定义编辑器UI界面&&
CustomEditor &StandardShaderGUI&&&[/mw_shl_code]
标准着色器对应材质的编辑器外观如下:
一般的着色器对应材质的编辑器外观如下:
二、Unity5标准着色器源代码剖析之一:架构分析篇
上文已经提到过,标准着色器源代码的剖析是一个小小的马拉松,完全解析起来篇幅会很长,所以本系列文章将对剖析的过程进行连载,此节为连载的第一部分。
在这里先贴出经过浅墨详细注释的标准着色器标准版的源代码,并对架构进行简单的分析,而对每个通道的剖析在稍后的更新中会进行。
[mw_shl_code=csharp,true]//-----------------------------------------------【Shader说明】---------------------------------------------------&&
//& && & Unity5.2.1 Built-in Standard Shader&&
//& && &2015年10月&&Commented by&&浅墨& && &
//& && &更多内容或交流,请访问浅墨的博客:http://blog.csdn.net/poem_qianmo&&
//---------------------------------------------------------------------------------------------------------------------&&
Shader &Standard&&&
& & //------------------------------------【属性值】------------------------------------&&
& & Properties&&
& && &&&//主颜色&&
& && &&&_Color(&Color&, Color) = (1,1,1,1)&&
& && &&&//主纹理&&
& && &&&_MainTex(&Albedo&, ) = &white& {}&&
& && &&&//Alpha剔除值&&
& && &&&_Cutoff(&Alpha Cutoff&, Range(0.0, 1.0)) = 0.5&&
& && &&&//平滑、光泽度&&
& && &&&_Glossiness(&Smoothness&, Range(0.0, 1.0)) = 0.5&&
& && &&&//金属性&&
& && &&&[Gamma] _Metallic(&Metallic&, Range(0.0, 1.0)) = 0.0&&
& && &&&//金属光泽纹理图&&
& && &&&_MetallicGlossMap(&Metallic&, 2D) = &white& {}&&
& && &&&//凹凸的尺度&&
& && &&&_BumpScale(&Scale&, Float) = 1.0&&
& && &&&//法线贴图&&
& && &&&_BumpMap(&Normal Map&, 2D) = &bump& {}&&
& && &&&//高度缩放尺度&&
& && &&&_Parallax (&Height Scale&, Range (0.005, 0.08)) = 0.02&&
& && &&&//高度纹理图&&
& && &&&_ParallaxMap (&Height Map&, 2D) = &black& {}&&
& && &&&//遮挡强度&&
& && &&&_OcclusionStrength(&Strength&, Range(0.0, 1.0)) = 1.0&&
& && &&&//遮挡纹理图&&
& && &&&_OcclusionMap(&Occlusion&, 2D) = &white& {}&&
& && &&&//自发光颜色&&
& && &&&_EmissionColor(&Color&, Color) = (0,0,0)&&
& && &&&//自发光纹理图&&
& && &&&_EmissionMap(&Emission&, 2D) = &white& {}&&
& && &&&//细节掩膜图&&
& && &&&_DetailMask(&Detail Mask&, 2D) = &white& {}&&
& && &&&//细节纹理图&&
& && &&&_DetailAlbedoMap(&Detail Albedo x2&, 2D) = &grey& {}&&
& && &&&//细节法线贴图尺度&&
& && &&&_DetailNormalMapScale(&Scale&, Float) = 1.0&&
& && &&&//细节法线贴图&&
& && &&&_DetailNormalMap(&Normal Map&, 2D) = &bump& {}&&
& && &&&//二级纹理的UV设置&&
& && &&&[Enum(UV0,0,UV1,1)] _UVSec (&UV Set for secondary textures&, Float) = 0&&
& && &&&//混合状态的定义&&
& && &&&[HideInInspector] _Mode (&__mode&, Float) = 0.0&&
& && &&&[HideInInspector] _SrcBlend (&__src&, Float) = 1.0&&
& && &&&[HideInInspector] _DstBlend (&__dst&, Float) = 0.0&&
& && &&&[HideInInspector] _ZWrite (&__zw&, Float) = 1.0&&
& & //===========开始CG着色器语言编写模块===========&&
& & CGINCLUDE&&
& && &&&//BRDF相关的一个宏&&
& && &&&#define UNITY_SETUP_BRDF_INPUT MetallicSetup&&
& & //===========结束CG着色器语言编写模块===========&&
& & ENDCG&&
& & //------------------------------------【子着色器1】------------------------------------&&
& & // 此子着色器用于Shader Model 3.0&&
& & //----------------------------------------------------------------------------------------&&
& & SubShader&&
& && &&&//渲染类型设置:不透明&&
& && &&&Tags { &RenderType&=&Opaque& &PerformanceChecks&=&False& }&&
& && &&&//细节层次设为:300&&
& && &&&LOD 300&&
& && &&&//--------------------------------通道1-------------------------------&&
& && &&&// 正向基础渲染通道(Base forward pass)&&
& && &&&// 处理方向光,自发光,光照贴图等 ...&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &FORWARD&& &
& && && && &//于通道标签中设置光照模型为ForwardBase,正向渲染基础通道&&
& && && && &Tags { &LightMode& = &ForwardBase& }&&
& && && && &//混合操作:源混合乘以目标混合&&
& && && && &Blend [_SrcBlend] [_DstBlend]&&
& && && && &// 根据_ZWrite参数,设置深度写入模式开关与否&&
& && && && &ZWrite [_ZWrite]&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//着色器编译目标:Model 3.0&&
& && && && &#pragma target 3.0&&
& && && && &//编译指令:不使用GLES渲染器编译&&
& && && && &#pragma exclude_renderers gles&&
& && && && &&&
& && && && &// ---------编译指令:着色器编译多样化--------&&
& && && && &#pragma shader_feature _NORMALMAP&&
& && && && &#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON&&
& && && && &#pragma shader_feature _EMISSION&&
& && && && &#pragma shader_feature _METALLICGLOSSMAP& &
& && && && &#pragma shader_feature ___ _DETAIL_MULX2&&
& && && && &#pragma shader_feature _PARALLAXMAP&&
& && && && &&&
& && && && &//--------着色器编译多样化快捷指令------------&&
& && && && &//编译指令:编译正向渲染基础通道(用于正向渲染中,应用环境光照、主方向光照和顶点/球面调和光照)所需的所有变体。&&
& && && && &//这些变体用于处理不同的光照贴图类型、主要方向光源的阴影选项的开关与否&&
& && && && &#pragma multi_compile_fwdbase&&
& && && && &//编译指令:编译几个不同变种来处理不同类型的雾效(关闭/线性/指数/二阶指数/)&&
& && && && &#pragma multi_compile_fog&&
& && && && &&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vertForwardBase&&
& && && && &#pragma fragment fragForwardBase&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardCore.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& && &&&//--------------------------------通道2-------------------------------&&
& && &&&// 正向附加渲染通道(Additive forward pass)&&
& && &&&// 以每个光照一个通道的方式应用附加的逐像素光照&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &FORWARD_DELTA&&&
& && && && &//于通道标签中设置光照模型为ForwardAdd,正向渲染附加通道&&
& && && && &Tags { &LightMode& = &ForwardAdd& }&&
& && && && &//混合操作:源混合乘以1&&
& && && && &Blend [_SrcBlend] One&&
& && && && &//附加通道中的雾效应该为黑色&&
& && && && &Fog { Color (0,0,0,0) }& &
& && && && &//关闭深度写入模式&&
& && && && &ZWrite Off&&
& && && && &//设置深度测试模式:小于等于&&
& && && && &ZTest LEqual&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//着色器编译目标:Model 3.0&&
& && && && &#pragma target 3.0&&
& && && && &//编译指令:不使用GLES渲染器编译&&
& && && && &#pragma exclude_renderers gles&&
& && && && &// ---------编译指令:着色器编译多样化--------&&
& && && && &#pragma shader_feature _NORMALMAP&&
& && && && &#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON&&
& && && && &#pragma shader_feature _METALLICGLOSSMAP&&
& && && && &#pragma shader_feature ___ _DETAIL_MULX2&&
& && && && &#pragma shader_feature _PARALLAXMAP&&
& && && && &&&
& && && && &//--------使用Unity内置的着色器编译多样化快捷指令------------&&
& && && && &//编译指令:编译正向渲染基础通道所需的所有变体,但同时为上述通道的处理赋予了光照实时阴影的能力。&&
& && && && &#pragma multi_compile_fwdadd_fullshadows&&
& && && && &//编译指令:编译几个不同变种来处理不同类型的雾效(关闭/线性/指数/二阶指数/)&&
& && && && &#pragma multi_compile_fog&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vertForwardAdd&&
& && && && &#pragma fragment fragForwardAdd&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardCore.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& && &&&// --------------------------------通道3-------------------------------&&
& && &&&//&&阴影渲染通道(Shadow Caster pass)&&
& && &&&//&&将将物体的深度渲染到阴影贴图或深度纹理中&&
& && &&&Pass& &
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &ShadowCaster&&&
& && && && &//于通道标签中设置光照模型为ShadowCaster。&&
& && && && &//此光照模型代表着将物体的深度渲染到阴影贴图或深度纹理。&&
& && && && &Tags { &LightMode& = &ShadowCaster& }&&
& && && && &//开启深入写入模式&&
& && && && &ZWrite On& &
& && && && &//设置深度测试模式:小于等于&&
& && && && &ZTest LEqual&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//着色器编译目标:Model 3.0&&
& && && && &#pragma target 3.0&&
& && && && &//编译指令:不使用GLES渲染器编译&&
& && && && &#pragma exclude_renderers gles&&
& && && && &&&
& && && && &// ---------编译指令:着色器编译多样化--------&&
& && && && &#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON&&
& && && && &&&
& && && && &//--------着色器编译多样化快捷指令------------&&
& && && && &//进行阴影投射相关的多着色器变体的编译&&
& && && && &#pragma multi_compile_shadowcaster&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vertShadowCaster&&
& && && && &#pragma fragment fragShadowCaster&&
& && && && &&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardShadow.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& && &&&// --------------------------------通道4-------------------------------&&
& && &&&//&&延迟渲染通道(Deferred Render Pass)&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &DEFERRED&&&
& && && && &//于通道标签中设置光照模型为Deferred,延迟渲染通道&&
& && && && &Tags { &LightMode& = &Deferred& }&&
& && && && &CGPROGRAM&&
& && && && &#pragma target 3.0&&
& && && && &// TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT&&
& && && && &#pragma exclude_renderers nomrt gles&&
& && && && &&&
& && && && &//---------编译指令:着色器编译多样化(shader_feature)--------&&
& && && && &#pragma shader_feature _NORMALMAP&&
& && && && &#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON&&
& && && && &#pragma shader_feature _EMISSION&&
& && && && &#pragma shader_feature _METALLICGLOSSMAP&&
& && && && &#pragma shader_feature ___ _DETAIL_MULX2&&
& && && && &#pragma shader_feature _PARALLAXMAP&&
& && && && &//---------编译指令:着色器编译多样化(multi_compile)--------&&
& && && && &#pragma multi_compile ___ UNITY_HDR_ON&&
& && && && &#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON&&
& && && && &#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE&&
& && && && &#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON&&
& && && && &&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vertDeferred&&
& && && && &#pragma fragment fragDeferred&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardCore.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& && &&&// --------------------------------通道5-------------------------------&&
& && &&&//元通道(Meta Pass)&&
& && &&&//为全局光照(GI),光照贴图等技术提取相关参数,如(emission, albedo等参数值)&&
& && &&&//此通道并不在常规的渲染过程中使用&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &META&& &
& && && && &//于通道标签中设置光照模型为Meta&&
& && && && &//(截止日,Unity 5.2.1的官方文档中并没有收录此光照模型,应该是Unity官方的疏漏)&&
& && && && &Tags { &LightMode&=&Meta& }&&
& && && && &//关闭剔除操作&&
& && && && &Cull Off&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vert_meta&&
& && && && &#pragma fragment frag_meta&&
& && && && &//---------编译指令:着色器编译多样化--------&&
& && && && &#pragma shader_feature _EMISSION&&
& && && && &#pragma shader_feature _METALLICGLOSSMAP&&
& && && && &#pragma shader_feature ___ _DETAIL_MULX2&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardMeta.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& & //------------------------------------【子着色器2】-----------------------------------&&
& & // 此子着色器用于Shader Model 2.0&&
& & //----------------------------------------------------------------------------------------&&
& & SubShader&&
& && &&&//渲染类型设置:不透明&&
& && &&&Tags { &RenderType&=&Opaque& &PerformanceChecks&=&False& }&&
& && &&&//细节层次设为:150&&
& && &&&LOD 150&&
& && &&&//--------------------------------通道1-------------------------------&&
& && &&&// 正向基础渲染通道(Base forward pass)&&
& && &&&// 处理方向光,自发光,光照贴图等 ...&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &FORWARD&& &
& && && && &//于通道标签中设置光照模型为ForwardBase,正向渲染基础通道&&
& && && && &Tags { &LightMode& = &ForwardBase& }&&
& && && && &//混合操作:源混合乘以目标混合,即结果为两者的混合&&
& && && && &Blend [_SrcBlend] [_DstBlend]&&
& && && && &// 根据_ZWrite参数,设置深度写入模式开关与否&&
& && && && &ZWrite [_ZWrite]&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//着色器编译目标:Model 2.0&&
& && && && &#pragma target 2.0&&
& && && && &// ---------编译指令:着色器编译多样化--------&&
& && && && &#pragma shader_feature _NORMALMAP&&
& && && && &#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON&&
& && && && &#pragma shader_feature _EMISSION& &
& && && && &#pragma shader_feature _METALLICGLOSSMAP& &
& && && && &#pragma shader_feature ___ _DETAIL_MULX2&&
& && && && &// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP&&
& && && && &//跳过如下变体的编译,简化编译过程&&
& && && && &#pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE&&
& && && && &&&
& && && && &//--------着色器编译多样化快捷指令------------&&
& && && && &#pragma multi_compile_fwdbase&&
& && && && &#pragma multi_compile_fog&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vertForwardBase&&
& && && && &#pragma fragment fragForwardBase&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardCore.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& && &&&//--------------------------------通道2-------------------------------&&
& && &&&// 正向附加渲染通道(Additive forward pass)&&
& && &&&// 以每个光照一个通道的方式应用附加的逐像素光照&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &FORWARD_DELTA&&&
& && && && &//于通道标签中设置光照模型为ForwardAdd,正向渲染附加通道&&
& && && && &Tags { &LightMode& = &ForwardAdd& }&&
& && && && &//混合操作:源混合乘以1&&
& && && && &Blend [_SrcBlend] One&&
& && && && &//附加通道中的雾效应该为黑色&&
& && && && &Fog { Color (0,0,0,0) }& &
& && && && &//关闭深度写入模式&&
& && && && &ZWrite Off&&
& && && && &//设置深度测试模式:小于等于&&
& && && && &ZTest LEqual&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//着色器编译目标:Model 2.0&&
& && && && &#pragma target 2.0&&
& && && && &// ---------编译指令:着色器编译多样化--------&&
& && && && &#pragma shader_feature _NORMALMAP&&
& && && && &#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON&&
& && && && &#pragma shader_feature _METALLICGLOSSMAP&&
& && && && &#pragma shader_feature ___ _DETAIL_MULX2&&
& && && && &//跳过一些变体的编译&&
& && && && &// SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP&&
& && && && &#pragma skip_variants SHADOWS_SOFT&&
& && && && &//--------使用Unity内置的着色器编译多样化快捷指令------------&&
& && && && &//编译指令:编译正向渲染基础通道所需的所有变体,但同时为上述通道的处理赋予了光照实时阴影的能力。&&
& && && && &#pragma multi_compile_fwdadd_fullshadows&&
& && && && &//编译指令:编译几个不同变种来处理不同类型的雾效(关闭/线性/指数/二阶指数/)&&
& && && && &#pragma multi_compile_fog&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vertForwardAdd&&
& && && && &#pragma fragment fragForwardAdd&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardCore.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& && &&&// --------------------------------通道3-------------------------------&&
& && &&&//&&阴影渲染通道(Shadow Caster pass)&&
& && &&&//&&将将物体的深度渲染到阴影贴图或深度纹理中&&
& && &&&Pass& &
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &ShadowCaster&&&
& && && && &//于通道标签中设置光照模型为ShadowCaster。&&
& && && && &//此光照模型代表着将物体的深度渲染到阴影贴图或深度纹理。&&
& && && && &Tags { &LightMode& = &ShadowCaster& }&&
& && && && &//开启深入写入模式&&
& && && && &ZWrite On&&
& && && && &//设置深度测试模式:小于等于&&
& && && && &ZTest LEqual&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//着色器编译目标:Model 2.0&&
& && && && &#pragma target 2.0&&
& && && && &//---------编译指令:着色器编译多样化(shader_feature)--------&&
& && && && &#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON&&
& && && && &&&
& && && && &//编译指令:跳过某些变体的编译&&
& && && && &#pragma skip_variants SHADOWS_SOFT&&
& && && && &//快捷编译指令:进行阴影投射相关的多着色器变体的编译&&
& && && && &#pragma multi_compile_shadowcaster&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vertShadowCaster&&
& && && && &#pragma fragment fragShadowCaster&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardShadow.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& && &&&// --------------------------------通道4-------------------------------&&
& && &&&//元通道(Meta Pass)&&
& && &&&//为全局光照(GI),光照贴图等技术提取相关参数,如(emission, albedo等参数值)&&
& && &&&//此通道并不在常规的渲染过程中使用&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置通道名称&&
& && && && &Name &META&& &
& && && && &//于通道标签中设置光照模型为Meta&&
& && && && &//(截止日,Unity 5.2.1的官方文档中并没有收录此光照模型,应该是Unity官方的疏漏)&&
& && && && &Tags { &LightMode&=&Meta& }&&
& && && && &//关闭剔除操作&&
& && && && &Cull Off&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vert_meta&&
& && && && &#pragma fragment frag_meta&&
& && && && &//---------编译指令:着色器编译多样化--------&&
& && && && &#pragma shader_feature _EMISSION&&
& && && && &#pragma shader_feature _METALLICGLOSSMAP&&
& && && && &#pragma shader_feature ___ _DETAIL_MULX2&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityStandardMeta.cginc&&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
& & //回退Shader为顶点光照Shader&&
& & FallBack &VertexLit&&&
& & //使用特定的自定义编辑器UI界面&&
& & CustomEditor &StandardShaderGUI&&&
}&&[/mw_shl_code]
标准着色器的源代码部分相对于着色器的体量来说,算是有点长的,加上注释后有近500行。先稍微把它的架构稍微理一下。
标准着色器由两个SubShader组成。第一个SubShader用于处理Shader Model 3.0,有5个通道,第二个SubShader用于处理Shader Model 2.0, 有4个通道,
详细的架构如下图:
OK,标准着色器的架构大致如上。今天就先讲这么多,上面代码的稍微有些看不懂没关系,从下次更新开始,就将深入到每个Pass的顶点和片段着色器函数之中,逐行注释与分析他们的指令细节。
而不难发现,标准着色器代码的第一个SubShader比第二个SubShader多出了一个延迟渲染通道(Deferred Render Pass),下面稍微提一下延迟渲染的基本概念。
三、关于延迟渲染(Deferred Render)
看过《GPU Gems2》的朋友们应该都有所了解,延迟渲染(Deferred Render,又称Deferred Shading)是次时代引擎必备的渲染方式之一。需要注意,Deferred Render和Deferred Shading有一点细微的差别。
Deferred Shading:将所有的Shading全部转到Deferred阶段进行。Deferred Render:只是有选择地将Lighting转到Deferred阶段进行。
Unity中默认使用的是Deferred Shading。
延迟渲染,一言以蔽之,就是将光照/渲染的计算延迟到第二步进行,避免多次渲染同一个像素,从而减少多余的计算操作,以提高渲染效率的一种先进的渲染方式。
延迟渲染最大的优势是可以实现同屏中数量众多的动态光源(十几到几十个),这在传统的渲染管线中是很难实现的。
更多延迟渲染的细节,这边不细说,只是提供一些链接,以作进一步了解延迟渲染的导论之用:
https://zh.wikipedia.org/wiki/%E5%BB%B6%E6%9C%9F%E7%9D%80%E8%89%B2
http://blog.csdn.net/noslopforever/article/details/3951273
.cn/s/blog_458f.html
/lancidie/archive//2144748.html
http://blog.csdn.net/pizi0475/article/details/7932920
/wangchengfeng/p/3440097.html
http://blog.csdn.net/bugrunner/article/details/7436600
四、屏幕水幕特效的实现
在上一篇文章中有提到过,Unity中的屏幕特效通常分为两部分来实现:
Shader实现部分
脚本实现部分
下面依然是从这两个方面对本次的特效进行实现。
而在这之前,需要准备好一张水滴(水滴太多了也就成了水幕了)的效果图片(google“water drop”一下,稍微筛选一下就有了,最好是能找到或者自己加工成无缝衔接的),放置于我们特效的脚本实现文件目录附加的一个Resources的文件夹中,那么我们在脚本中适当的地方写上一句:
Texture2 = Resources.Load(&ScreenWaterDrop&)as Texture2D;
就可以读取到这张图片了。
浅墨准备的图片如下(无水印本图片的可以在浅墨的Github中找到,或者直接下文章末尾的项目工程)。
ScreenWaterDrop.png:
4.1 Shader实现部分
老规矩,先上详细注释的代码。
[mw_shl_code=csharp,true]//-----------------------------------------------【Shader脚本说明】---------------------------------------------------&&
//& && & 屏幕水幕特效的实现代码-Shader脚本部分&&
//& && &2015年10月&&Created by&&浅墨&&
//& && &更多内容或交流,请访问浅墨的博客:http://blog.csdn.net/poem_qianmo&&
//---------------------------------------------------------------------------------------------------------------------&&
Shader &浅墨Shader编程/Volume9/ScreenWaterDropEffect&&&
& & //------------------------------------【属性值】------------------------------------&&
& & Properties&&
& && &&&//主纹理&&
& && &&&_MainTex (&Base (RGB)&, 2D) = &white& {}&&
& && &&&//屏幕水滴的素材图&&
& && &&&_ScreenWaterDropTex (&Base (RGB)&, 2D) = &white& {}&&
& && &&&//当前时间&&
& && &&&_CurTime (&Time&, Range(0.0, 1.0)) = 1.0&&
& && &&&//X坐标上的水滴尺寸&&
& && &&&_SizeX (&SizeX&, Range(0.0, 1.0)) = 1.0&&
& && &&&//Y坐标上的水滴尺寸&&
& && &&&_SizeY (&SizeY&, Range(0.0, 1.0)) = 1.0&&
& && &&&//水滴的流动速度&&
& && &&&_DropSpeed (&Speed&, Range(0.0, 10.0)) = 1.0&&
& && &&&//溶解度&&
& && &&&_Distortion (&_Distortion&, Range(0.0, 1.0)) = 0.87&&
& & //------------------------------------【唯一的子着色器】------------------------------------&&
& & SubShader&&
& && &&&Pass&&
& && &&&{&&
& && && && &//设置深度测试模式:渲染所有像素.等同于关闭透明度测试(AlphaTest Off)&&
& && && && &ZTest Always&&
& && && && &&&
& && && && &//===========开启CG着色器语言编写模块===========&&
& && && && &CGPROGRAM&&
& && && && &//编译指令:告知编译器顶点和片段着色函数的名称&&
& && && && &#pragma vertex vert&&
& && && && &#pragma fragment frag&&
& && && && &#pragma fragmentoption ARB_precision_hint_fastest&&
& && && && &//编译指令: 指定着色器编译目标为Shader Model 3.0&&
& && && && &#pragma target 3.0&&
& && && && &//包含辅助CG头文件&&
& && && && &#include &UnityCG.cginc&&&
& && && && &//外部变量的声明&&
& && && && &uniform sampler2D _MainT&&
& && && && &uniform sampler2D _ScreenWaterDropT&&
& && && && &uniform float _CurT&&
& && && && &uniform float _DropS&&
& && && && &uniform float _SizeX;&&
& && && && &uniform float _SizeY;&&
& && && && &uniform float _D&&
& && && && &uniform float2 _MainTex_TexelS&&
& && && && &&&
& && && && &//顶点输入结构&&
& && && && &struct vertexInput&&
& && && && &{&&
& && && && && & float4 vertex : POSITION;//顶点位置&&
& && && && && & float4 color : COLOR;//颜色值&&
& && && && && & float2 texcoord : TEXCOORD0;//一级纹理坐标&&
& && && && &};&&
& && && && &//顶点输出结构&&
& && && && &struct vertexOutput&&
& && && && &{&&
& && && && && & half2 texcoord : TEXCOORD0;//一级纹理坐标&&
& && && && && & float4 vertex : SV_POSITION;//像素位置&&
& && && && && & fixed4 color : COLOR;//颜色值&&
& && && && &};&&
& && && && &//--------------------------------【顶点着色函数】-----------------------------&&
& && && && &// 输入:顶点输入结构体&&
& && && && &// 输出:顶点输出结构体&&
& && && && &//---------------------------------------------------------------------------------&&
& && && && &vertexOutput vert(vertexInput Input)&&
& && && && &{&&
& && && && && & //【1】声明一个输出结构对象&&
& && && && && & vertexOutput O&&
& && && && && & //【2】填充此输出结构&&
& && && && && & //输出的顶点位置为模型视图投影矩阵乘以顶点位置,也就是将三维空间中的坐标投影到了二维窗口&&
& && && && && & Output.vertex = mul(UNITY_MATRIX_MVP, Input.vertex);&&
& && && && && & //输出的纹理坐标也就是输入的纹理坐标&&
& && && && && & Output.texcoord = Input.&&
& && && && && & //输出的颜色值也就是输入的颜色值&&
& && && && && & Output.color = Input.&&
& && && && && & //【3】返回此输出结构对象&&
& && && && && & return O&&
& && && && &}&&
& && && && &//--------------------------------【片段着色函数】-----------------------------&&
& && && && &// 输入:顶点输出结构体&&
& && && && &// 输出:float4型的颜色值&&
& && && && &//---------------------------------------------------------------------------------&&
& && && && &fixed4 frag(vertexOutput Input) : COLOR&&
& && && && &{&&
& && && && && & //【1】获取顶点的坐标值&&
& && && && && & float2 uv = Input.texcoord.&&
& && && && && & //【2】解决平台差异的问题。校正方向,若和规定方向相反,则将速度反向并加1&&
& && && && && & #if UNITY_UV_STARTS_AT_TOP&&
& && && && && & if (_MainTex_TexelSize.y & 0)&&
& && && && && && &&&_DropSpeed = 1 - _DropS&&
& && && && && & #endif&&
& && && && && & //【3】设置三层水流效果,按照一定的规律在水滴纹理上分别进行取样&&
& && && && && & float3 rainTex1 = tex2D(_ScreenWaterDropTex, float2(uv.x * 1.15* _SizeX, (uv.y* _SizeY *1.1) + _CurTime* _DropSpeed *0.15)).rgb / _D&&
& && && && && & float3 rainTex2 = tex2D(_ScreenWaterDropTex, float2(uv.x * 1.25* _SizeX - 0.1, (uv.y *_SizeY * 1.2) + _CurTime *_DropSpeed * 0.2)).rgb / _D&&
& && && && && & float3 rainTex3 = tex2D(_ScreenWaterDropTex, float2(uv.x* _SizeX *0.9, (uv.y *_SizeY * 1.25) + _CurTime * _DropSpeed* 0.032)).rgb / _D&&
& && && && && & //【4】整合三层水流效果的颜色信息,存于finalRainTex中&&
& && && && && & float2 finalRainTex = uv.xy - (rainTex1.xy - rainTex2.xy - rainTex3.xy) / 3;&&
& && && && && & //【5】按照finalRainTex的坐标信息,在主纹理上进行采样&&
& && && && && & float3 finalColor = tex2D(_MainTex, float2(finalRainTex.x, finalRainTex.y)).&&
& && && && && & //【6】返回加上alpha分量的最终颜色值&&
& && && && && & return fixed4(finalColor, 1.0);&&
& && && && &}&&
& && && && &//===========结束CG着色器语言编写模块===========&&
& && && && &ENDCG&&
& && &&&}&&
}&&[/mw_shl_code]
屏幕特效Shader中真正有营养的核心代码,一般都是位于像素着色器中。也就是这里的frag函数中,稍微聊一聊。
第一步,先从顶点着色器输出结构体中获取顶点的坐标:
[mw_shl_code=csharp,true]//【1】获取顶点的坐标值&&
float2 uv = Input.texcoord.&&[/mw_shl_code]
第二步,因为需要水幕纹理在屏幕中从上向下滚动,而不同平台的原点位置是不同的,Direct3D原点在左上角,OpenGL原点在左下角。所以在这边需要对情况进行统一。
统一的方法里用到了UNITY_UV_STARTS_AT_TOP宏,它是Unity中内置的宏,其值 取为1 或0 ; 在纹理 V 坐标在“纹理顶部”为零的平台上值取 1。如Direct3D;而OpenGL 平台上取 0。
另外,这边还用到了MainTex_TexelSize变量。
float2型的MainTex_TexelSize(其实是_TexelSize后缀,前面的名称会根据定义纹理变量的改变而改变)也是Unity中内置的一个变量,存放了纹理中单个像素的尺寸,也就是说,如果有一张2048 x 2048的纹理,那么x和y的取值都为1.0/2048.0。而且需要注意,当该纹理被Direct3D的抗锯齿操作垂直反转过后,xxx_TexelSize的值将为负数。
所以,第二步的代码就是如下:
[mw_shl_code=csharp,true]//【2】解决平台差异的问题。校正方向,若和规定方向相反,则将速度反向并加1&&
& & #if UNITY_UV_STARTS_AT_TOP&&
& &&&if(_MainTex_TexelSize.y & 0)&&
& && & _DropSpeed= 1 - _DropS&&
& && && &&&#endif&&[/mw_shl_code]
第三步,定义三层水流的纹理,按照不同的参数取值,进行采样:
[mw_shl_code=csharp,true]//【3】设置三层水流效果,按照一定的规律在水滴纹理上分别进行取样&&
float3 rainTex1 = tex2D(_ScreenWaterDropTex, float2(uv.x * 1.15* _SizeX, (uv.y* _SizeY*1.1) + _CurTime* _DropSpeed *0.15)).rgb / _D&&
float3 rainTex2 = tex2D(_ScreenWaterDropTex, float2(uv.x * 1.25* _SizeX - 0.1, (uv.y*_SizeY * 1.2) + _CurTime *_DropSpeed * 0.2)).rgb / _D&&
float3 rainTex3 = tex2D(_ScreenWaterDropTex, float2(uv.x* _SizeX *0.9, (uv.y *_SizeY *1.25) + _CurTime * _DropSpeed* 0.032)).rgb / _D&&[/mw_shl_code]
第四步,整合一下三层水流效果的颜色信息,用一个float2型的变量存放下来:
[mw_shl_code=csharp,true]//【4】整合三层水流效果的颜色信息,存于finalRainTex中&&
float2 finalRainTex = uv.xy - (rainTex1.xy - rainTex2.xy - rainTex3.xy) / 3;&&[/mw_shl_code]
第五步,自然是在屏幕所在的纹理_MainTex中进行一次最终的采样,算出最终结果颜色值,存放于float3型的finalColor中。
[mw_shl_code=csharp,true]//【5】按照finalRainTex的坐标信息,在主纹理上进行采样&&
float3 finalColor = tex2D(_MainTex, float2(finalRainTex.x, finalRainTex.y)).&&[/mw_shl_code]
第六步,因为返回的是一个fixed4型的变量,rgba。所以需要给float3型的finalColor配上一个alpha分量,并返回:
//【6】返回加上alpha分量的最终颜色值
[mw_shl_code=csharp,true]return fixed4(finalColor, 1.0);&&[/mw_shl_code]
OK,关于此Shader的实现细节,差不多就需要讲到这些。下面再看一下C#脚本文件的实现。
4.2 C#脚本实现部分
C#脚本文件的实现并没有什么好讲的,唯一的地方,水滴纹理的载入,上面已经提到过了,实现代码如下:
[mw_shl_code=csharp,true]//载入素材图&&
ScreenWaterDropTex = Resources.Load(&ScreenWaterDrop&) asTexture2D;& &[/mw_shl_code]
下面就直接贴出详细注释的实现此特效的C#脚本:
[mw_shl_code=csharp,true]//-----------------------------------------------【C#脚本说明】---------------------------------------------------&&
//&&屏幕水幕特效的实现代码-C#脚本部分&&
//& && &2015年10月&&Created by&&浅墨&&
//& && &更多内容或交流,请访问浅墨的博客:http://blog.csdn.net/poem_qianmo&&
//---------------------------------------------------------------------------------------------------------------------&&
using UnityE&&
using System.C&&
[ExecuteInEditMode]&&
[AddComponentMenu(&浅墨Shader编程/Volume9/ScreenWaterDropEffect&)]&&
public class ScreenWaterDropEffect : MonoBehaviour& &
& & //-------------------变量声明部分-------------------&&
& & #region Variables&&
& & //着色器和材质实例&&
& & public Shader CurS//着色器实例&&
& & private Material CurM//当前的材质&&
& & //时间变量和素材图的定义&&
& & private float TimeX = 1.0f;//时间变量&&
& & private Texture2D ScreenWaterDropT//屏幕水滴的素材图&&
& & //可以在编辑器中调整的参数值&&
& & [Range(5, 64), Tooltip(&溶解度&)]&&
& & public float Distortion = 8.0f;&&
& & [Range(0, 7), Tooltip(&水滴在X坐标上的尺寸&)]&&
& & public float SizeX = 1f;&&
& & [Range(0, 7), Tooltip(&水滴在Y坐标上的尺寸&)]&&
& & public float SizeY = 0.5f;&&
& & [Range(0, 10), Tooltip(&水滴的流动速度&)]&&
& & public float DropSpeed = 3.6f;&&
& & //用于参数调节的中间变量&&
& & public static float ChangeD&&
& & public static float ChangeSizeX;&&
& & public static float ChangeSizeY;&&
& & public static float ChangeDropS&&
& & #endregion&&
& & //-------------------------材质的get&set----------------------------&&
& & #region MaterialGetAndSet&&
& & Material material&&
& && &&&get&&
& && &&&{&&
& && && && &if (CurMaterial == null)&&
& && && && &{&&
& && && && && & CurMaterial = new Material(CurShader);&&
& && && && && & CurMaterial.hideFlags = HideFlags.HideAndDontS&&
& && && && &}&&
& && && && &return CurM&&
& && &&&}&&
& & #endregion&&
& & //-----------------------------------------【Start()函数】---------------------------------------------& &
& & // 说明:此函数仅在Update函数第一次被调用前被调用&&
& & //--------------------------------------------------------------------------------------------------------&&
& & void Start()&&
& && &&&//依次赋值&&
& && &&&ChangeDistortion = D&&
& && &&&ChangeSizeX = SizeX;&&
& && &&&ChangeSizeY = SizeY;&&
& && &&&ChangeDropSpeed = DropS&&
& && &&&//载入素材图&&
& && &&&ScreenWaterDropTex = Resources.Load(&ScreenWaterDrop&) as Texture2D;&&
& && &&&//找到当前的Shader文件&&
& && &&&CurShader = Shader.Find(&浅墨Shader编程/Volume9/ScreenWaterDropEffect&);&&
& && &&&//判断是否支持屏幕特效&&
& && &&&if (!SystemInfo.supportsImageEffects)&&
& && &&&{&&
& && && && &enabled =&&
& && && && &&&
& && &&&}&&
& & //-------------------------------------【OnRenderImage()函数】------------------------------------& &
& & // 说明:此函数在当完成所有渲染图片后被调用,用来渲染图片后期效果&&
& & //--------------------------------------------------------------------------------------------------------&&
& & void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)&&
& && &&&//着色器实例不为空,就进行参数设置&&
& && &&&if (CurShader != null)&&
& && &&&{&&
& && && && &//时间的变化&&
& && && && &TimeX += Time.deltaT&&
& && && && &//时间大于100,便置0,保证可以循环&&
& && && && &if (TimeX & 100) TimeX = 0;&&
& && && && &//设置Shader中其他的外部变量&&
& && && && &material.SetFloat(&_CurTime&, TimeX);&&
& && && && &material.SetFloat(&_Distortion&, Distortion);&&
& && && && &material.SetFloat(&_SizeX&, SizeX);&&
& && && && &material.SetFloat(&_SizeY&, SizeY);&&
& && && && &material.SetFloat(&_DropSpeed&, DropSpeed);&&
& && && && &material.SetTexture(&_ScreenWaterDropTex&, ScreenWaterDropTex);&&
& && && && &//拷贝源纹理到目标渲染纹理,加上我们的材质效果&&
& && && && &Graphics.Blit(sourceTexture, destTexture, material);&&
& && &&&}&&
& && &&&//着色器实例为空,直接拷贝屏幕上的效果。此情况下是没有实现屏幕特效的&&
& && &&&else&&
& && &&&{&&
& && && && &//直接拷贝源纹理到目标渲染纹理&&
& && && && &Graphics.Blit(sourceTexture, destTexture);&&
& && &&&}&&
& & //-----------------------------------------【OnValidate()函数】--------------------------------------& &
& & // 说明:此函数在编辑器中该脚本的某个值发生了改变后被调用&&
& & //--------------------------------------------------------------------------------------------------------&&
& & void OnValidate()&&
& && &&&ChangeDistortion = D&&
& && &&&ChangeSizeX = SizeX;&&
& && &&&ChangeSizeY = SizeY;&&
& && &&&ChangeDropSpeed = DropS&&
& & //-----------------------------------------【Update()函数】------------------------------------------& &
& & // 说明:此函数在每一帧中都会被调用&&
& & //--------------------------------------------------------------------------------------------------------& &
& & void Update()&&
& && &&&//若程序在运行,进行赋值&&
& && &&&if (Application.isPlaying)&&
& && &&&{&&
& && && && &//赋值&&
& && && && &Distortion = ChangeD&&
& && && && &SizeX = ChangeSizeX;&&
& && && && &SizeY = ChangeSizeY;&&
& && && && &DropSpeed = ChangeDropS&&
& && &&&}&&
& && &&&//找到对应的Shader文件,和纹理素材&&
#if UNITY_EDITOR&&
& && &&&if (Application.isPlaying != true)&&
& && &&&{&&
& && && && &CurShader = Shader.Find(&浅墨Shader编程/Volume9/ScreenWaterDropEffect&);&&
& && && && &ScreenWaterDropTex = Resources.Load(&ScreenWaterDrop&) as Texture2D;&&
& && &&&}&&
& & //-----------------------------------------【OnDisable()函数】---------------------------------------& &
& & // 说明:当对象变为不可用或非激活状态时此函数便被调用& &
& & //--------------------------------------------------------------------------------------------------------&&
& & void OnDisable()&&
& && &&&if (CurMaterial)&&
& && &&&{&&
& && && && &//立即销毁材质实例&&
& && && && &DestroyImmediate(CurMaterial);&&
& && &&&}&&
}&&[/mw_shl_code]
OK,水幕屏幕特效实现部分大致就是这样,下面看一下运行效果的对比。
五、最终的效果展示
贴几张场景的效果图和使用了屏幕特效后的效果图。在试玩场景时,除了类似CS/CF的FPS游戏控制系统以外,还可以使用键盘上的按键【F】,开启或者屏幕特效。
本次的场景还是使用上次更新中放出的城镇,只是出生地点有所改变。为了有更多的时间专注于Shader书写本身,以后的博文配套场景采取不定期大更新的形式(两次、三次一换)。
城镇野外(with 屏幕水幕特效):
城镇野外(原始图):
山坡上(with 屏幕水幕特效):
山坡上(原始图):
城镇中(with 屏幕水幕特效):
城镇中(原始图)
石桥上(with 屏幕水幕特效):
石桥上(原始图):
本次的更新大致如此,感谢各位捧场,我们下周再见。
附: 本博文相关下载链接清单
游客,如果您要查看本帖隐藏内容请
共 106 条评论
就是四个小酷妹和巨小
很棒的文章,找了好久都没有先关知识!!!
【浅墨Unity3D Shader编程】之九 深入理解Unity5中的Standard Shader (一)&屏幕水幕特效的实现 [修改
不错&&学习一下,不错&&学习一下,不错&&学习一下,不错&&学习一下,不错&&学习一下,不错&&学习一下,不错&&学习一下,
呵呵呵, 更新了, 支持,支持支持啊
好棒哦!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
浅神果然厉害啊,学习到了,学习到了
好棒,谢谢楼主分享~学习了
不错&&学习一下,不错&&学习一下,不错&&学习一下,不错&&学习一下,不错&&学习一下,不错&&学习一下,
会shader的大神
学习一下谢谢了,楼主,我正在学习这部分知识
谢谢分享谢谢分享谢谢分享谢谢分享谢谢分享
& Comsenz Inc.
Unity问答求助
开发者干货区
/每日程序员
Unity3d插件
教程视频分享
Cocos2D技术专区
HTML5技术专区

我要回帖

更多关于 unity3d 顶点着色器 的文章

 

随机推荐