第15章 使用噪音
很多时候,向规则的事物里添加一些“杂乱无章”的效果往往会有意想不到的效果。而这些“杂乱无章”的效果来源就是噪音。在本章中,我们将会学习如何使用噪音来模拟各种看似神奇的特效。在15.1中,我们将使用一张噪音纹理来模拟火焰的消融效果。15.2节则把噪音应用在模拟水面的波动上,从而产生波光粼粼的视觉效果。在15.3中,我们会回顾13.3中实现的全局雾效,并向其中添加噪音来模拟不均匀的缥缈雾效。

15.1 消融效果
消融(dissolve)效果常见于游戏中的角色死亡、地图烧毁等效果。消融往往从不同的区域开始,并向看似随机的方向扩张,最后整个物体都将消失不见。
消融原理:概括来说就是噪音纹理+透明度测试。我们使用对噪声纹理采样的结果和某个控制消融程度的阀值比较,如果小于阀值,就使用clip函数把它对应的像素裁减掉,这些部分就对应了图中被“烧毁”的区域。而镂空区域边缘的烧焦效果则是将两种颜色混合,再用pow函数处理后,与原纹理颜色混合后的结果。

实现
(1)新建场景(Scene_15_1)。
(2)新建材质(DissolveMat)。
(3)新建Unity Shader(Chapter15-Dissolve),并赋给第二步中创建的材质。
(4)搭建场景,创建对象,并把第二步中创建的材质拖拽给对象。

Shader "Unity Shaders Book/Chapter 15/Dissolve" {Properties {//用于控制消融程度,当值为0时,物体为正常效果,当值为1时,物体会完全消融。_BurnAmount ("Burn Amount", Range(0.0, 1.0)) = 0.0//控制模拟燃烧效果时的线宽,它的值越大,火焰边缘和蔓延范围。。_LineWidth("Burn Line Width", Range(0.0, 0.2)) = 0.1//漫反射纹理_MainTex ("Base (RGB)", 2D) = "white" {}//法线纹理。_BumpMap ("Normal Map", 2D) = "bump" {}//火焰边缘的两种颜色值,_BurnFirstColor("Burn First Color", Color) = (1, 0, 0, 1)_BurnSecondColor("Burn Second Color", Color) = (1, 0, 0, 1)//噪声纹理。_BurnMap("Burn Map", 2D) = "white"{}}SubShader {Tags { "RenderType"="Opaque" "Queue"="Geometry"}Pass {Tags { "LightMode"="ForwardBase" }Cull OffCGPROGRAM#include "Lighting.cginc"#include "AutoLight.cginc"#pragma multi_compile_fwdbase//为了得到正确的光照,我们设置了Pass的LightMode和multi_compile_fwdbase的编译指令。这得注意的是,//我们还使用了Cull命令关闭了了该Shader的面片剔除,也就是说,模型的正面和背面都会//被渲染。这是因为,消融会导致裸露模型内部的构造,如果只渲染正面会出现错误的结果。#pragma vertex vert#pragma fragment fragfixed _BurnAmount;fixed _LineWidth;sampler2D _MainTex;sampler2D _BumpMap;fixed4 _BurnFirstColor;fixed4 _BurnSecondColor;sampler2D _BurnMap;float4 _MainTex_ST;float4 _BumpMap_ST;float4 _BurnMap_ST;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;float4 texcoord : TEXCOORD0;};//定于顶点着色器:struct v2f {float4 pos : SV_POSITION;float2 uvMainTex : TEXCOORD0;float2 uvBumpMap : TEXCOORD1;float2 uvBurnMap : TEXCOORD2;float3 lightDir : TEXCOORD3;float3 worldPos : TEXCOORD4;SHADOW_COORDS(5)};v2f vert(a2v v) {v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex);o.uvBumpMap = TRANSFORM_TEX(v.texcoord, _BumpMap);o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);TANGENT_SPACE_ROTATION;o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;o.worldPos = mul(_Object2World, v.vertex).xyz;TRANSFER_SHADOW(o);return o;}//顶点着色器的代码很常规。我们使用宏TRANSFORM_TEX计算了三张纹理对应的纹理坐标,//再把光源方向从模型空间变换到了切线空间。最后,为了得到阴影信息,计算了世界空间下的顶点//位置和阴影纹理的坐标采样(使用了TRANSFER_SHADOW宏)(9.4)
)                // 我们还需要实现片元着色器来模拟消融效果:fixed4 frag(v2f i) : SV_Target {fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;clip(burn.r - _BurnAmount);float3 tangentLightDir = normalize(i.lightDir);fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uvBumpMap));fixed3 albedo = tex2D(_MainTex, i.uvMainTex).rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);fixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);burnColor = pow(burnColor, 5);UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);fixed3 finalColor = lerp(ambient + diffuse * atten, burnColor, t * step(0.0001, _BurnAmount));return fixed4(finalColor, 1);}//我们首先对噪音纹理进行采样,并将采样结果和用于控制消融程度的属性//_BurnAmout相减,传递给clip函数。但结果小于0时,该像素将会剔除,从而//不会显示到屏幕上。如果通过了测试,则进行正常的光照计算。我们首先根据漫反射得到//纹理得到材质的反射率(albedo)并由此计算得到环境光照,进而得到漫反射光照。然后,我们//计算了烧焦burnColor。我们像要在宽度为_Linewaned的范围内模拟一个烧焦的颜色变化,第一步//使用了smoothstep函数来计算混合系数t。当t值为1时,表示该像素位于消融的边界处,当t等于0时,表明该像素为//正常的模型颜色,而中间的插值则表示需要模拟一个烧焦效果。我们首先用t来混合两种火焰颜色_BurnFirstColor和//_LineWidth的范围内模拟一个烧焦的颜色变化,第一步就使用了smoothstep函数来计算混合系数t。当t值为1时,表明该//像素位于消融的边界处,当t值为0时,表明该像素为正常的模型颜色,而中间的插值//则表示需要一个烧焦效果。我们首先用t来混合两种火焰颜色_BurnFirstColor和//_BurnSecondColor,为了让效果更接近烧焦的痕迹,我们还使用了pow函数对结果进行处理。//然后,我们再次使用t来混合正常的光照颜色(环境光和漫反射)和烧焦演的。我这里又使用了//函数来保证当_BurnAmout为0时,不显示任何消融效果。//最后,返回混合后的颜色值finalColor。ENDCG}// 作为一个影子投射器传递给渲染对象//自定义一个用于投射阴影的Pass。Pass {Tags { "LightMode" = "ShadowCaster" }CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_shadowcaster//用于投射阴影的Pass的LightMode需要被设置为ShadowCaster,同时,还需要使用//#pragma multi_compile_shadowcaster#include "UnityCG.cginc"fixed _BurnAmount;sampler2D _BurnMap;float4 _BurnMap_ST;struct v2f {V2F_SHADOW_CASTER;float2 uvBurnMap : TEXCOORD1;};v2f vert(appdata_base v) {v2f o;//顶点着色部分,支持正常的偏移阴影。需要位置和法线在顶点输入中(TRANSFER_SHADOW_CASTER_NORMALOFFSET)//o作为输入结构体,其中包含顶点位置v.vertex和顶点法线v,normal的信息,我们可以直接//使用内置的appdata_base结构体(动态和静态光映射包含间接的漫射连接,因此忽略了SH)它包含了这些必需的顶点半两。TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)//通过比例/偏差属性转换2D UV(TRANSFORM_TEX)o.uvBurnMap = TRANSFORM_TEX(v.texcoord, _BurnMap);return o;}fixed4 frag(v2f i) : SV_Target {fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;clip(burn.r - _BurnAmount);SHADOW_CASTER_FRAGMENT(i)}//阴影投射的重点在于我们需要按正常Pass的处理来剔除片元或进行顶点动画,以便阴影可以和//物体正常渲染的结果相匹配。在自定义的阴影投射的Pass中,我们通常会使用Unity提供的内置宏//V2F_SHADOW_CASTER、TRANSFET_SHADOW_CASTER_NORMALOFFSET(旧版本中会使用TRANSFER_SHADOW_CASTER)和//SHADOW_CASTER_FRAGMENT来帮助我们计算阴影投射时需要的各种变量,而我们可以只关注自定义计算的部分。//在上面的代码中,我们首先在v2f结构体中利用V2F_SHADOW_CASTER_NORMALOFFSET来填充//V2F_SHADOW_CASTER在背后声明的一些变量,这是由Unity在背后为我们完成的。我们需要//在顶点着色器中关注自定义的计算部分,我们首先按之前的处理方法使用噪声纹理//的采样结果来剔除片元,最后再利用SHADOW_CASTER_FRAGMENT来让Unity为我们//完成阴影有些的部分,把结果输出到都深圳图和阴影印刷社映射文字l}}FallBack "Diffuse"
}

Unity_Shader高级篇_15_Unity Shader入门精要_消融效果相关推荐

  1. Unity_Shader高级篇_14_Unity Shader入门精要

    第14章 非真实感渲染 游戏渲染一般都是以照相写实主义(photorealism)作为主要目标,但也有许多游戏使用了非真实感渲染(Non-Photorealistic Rendering ,NPR)的 ...

  2. Unity_Shader中级篇_10_Unity Shader入门精要

    高级纹理 第七章学习了关于基础纹理的内容,这些纹理包括法线纹理.渐变纹理和遮罩纹理等.这些纹理尽管用处不同,但他们都属于低维(一维或二维)纹理.此时我们将学习一些更复杂的纹理.在10.1中我们会学习如 ...

  3. Unity_Shader中级篇_11_Unity Shader入门精要

    第十一章 让画面动起来 没有动画的画面往往让人觉得很无趣.在本章中,我们将学习如何向Unity Shader中引入时间变量,以实现各种动画效果.在11.1节中,我们首先会介绍Unity Shader内 ...

  4. Unity_Shader初级篇_8_Unity Shader入门精要

    透明效果 透明是游戏中经常要使用的一种效果.在实时渲染中要实现透明效果,通常会子渲染模型时控制它的透明通道(Alpha Channel).当开启透明混合后,当一个物体被渲染到屏幕上时,每个片元除了颜色 ...

  5. 《Unity Shader入门精要》笔记:高级篇(3)以及扩展

    本篇博客主要为个人学习所编写读书笔记,不用于任何商业用途,以及不允许任何人以任何形式进行转载. 本篇博客会补充一些扩展内容(例如其他博客链接). 本篇博客还会提供一些边读边做的效果截图.文章内所有数学 ...

  6. 《Unity Shader入门精要》笔记:初级篇(2)

    本篇博客主要为个人学习所编写读书笔记,不用于任何商业用途,以及不允许任何人以任何形式进行转载. 本篇博客会补充一些扩展内容(例如其他博客链接). 本篇博客还会提供一些边读边做的效果截图.文章内所有数学 ...

  7. 《Unity Shader入门精要》笔记:初级篇(1)

    本篇博客主要为个人学习所编写读书笔记,不用于任何商业用途,以及不允许任何人以任何形式进行转载. 本篇博客会补充一些扩展内容(例如其他博客链接). 本篇博客还会提供一些边读边做的效果截图.文章内所有数学 ...

  8. 《Unity Shader入门精要》笔记02 第1章+第2章

    基础篇 第1章+第2章 --本系列是基于人民邮电出版社<Unity Shader入门精要>(冯乐乐著 )的自学Unity Shader笔记,如果您发现了本文的纰漏,还望不吝指正. 基础篇 ...

  9. 《Unity Shader入门精要》笔记01 前言

    <Unity Shader入门精要>笔记01 前言 --本系列是基于人民邮电出版社<Unity Shader入门精要>(冯乐乐著 )的自学Unity Shader笔记,如果您发 ...

最新文章

  1. 16、设计模式-行为型模式-命令模式
  2. python在运行调试程序时常出现的错误有_Python 如何调试程序崩溃错误
  3. dubbo服务者配置说明
  4. html5 如何实现客户端验证上传文件的大小
  5. php 如何将字体转为gb,利用php怎么将utf-8与GB2312相互转换
  6. c语言ut8,C语言使用utlist实现的双向链表
  7. html 出现的错误
  8. 文件包含漏洞——DVWA练习
  9. 阿拉伯数字转化为中文汉字(大、小写) - PHP
  10. 前端一键复制粘贴插件——clipboard.js的使用
  11. AI永远不可能产生意识
  12. 大学精品课matlab,大学精品课件:Matlab绘图教程.ppt
  13. Re-ranking Person Re-identification with k-reciprocal Encoding笔记
  14. Linux下基于TCP的视频传输(c++ )
  15. 网页中使用阿里图标iconfont
  16. jenkins AWS CodeDeploy不停机部署
  17. 食物也疯狂!KOOCAN盘点因为食物毁掉的中国电视剧
  18. sci论文、ei论文和ieee论文三者之间有什么区别?
  19. PyTorch(二次元头像--GAN实战)
  20. 《信息安全工程师教程》学习笔记01(第一章)

热门文章

  1. Terminus终端设置Bracketed Paste Mode
  2. MangoDB与HBase对比
  3. 微信扫码拉起小程序手机号授权跨端登录
  4. 无焦望远镜系统的优化
  5. ffmpeg音视频相关资料
  6. CentOS无法添加组和用户
  7. VMware Workstation 15 语言修改
  8. 力扣之数据结构入门的刷题总结
  9. Android 8.0正式发布 奥利奥新功能惊人
  10. springboot快速开发框架推荐,接私活利器