老规矩先上图

最近我在设计一个星球题材的独立游戏,其中一个特色是让怪物逐渐被冰冻,并在其下方生成冰柱的特效。在这里,我想和大家分享一下我的设计过程。


文章目录

  • 一、贴合冰面
  • 二、冰冻起始点
  • 三、连贯性逐渐冰冻
  • 四、下垂的冰柱
  • 五、半萤光效果
  • 六、下面是完整代码:

一、贴合冰面

首先这个特效需要和与原模型紧密贴合,需要将源模型基础上沿着法线方向向外扩大一些,以避免与原模型有交错。具体代码如下:

//因为是叠加在原本的材质上使用的,所以需要比原本的稍微大一些,我们使用向法线方向延展的方式
v.vertex += downNormal * stepNormal + _BaseVectorNormalScale*v.normal;

二、冰冻起始点

假设你要做的是一个类似冰冻枪的功能,射击后从击中点开始结冰,使用RaycastHit.textureCoord可以获得击中点的UV值,赋值给_CenterUv属性。

_CenterUv("裁剪中心",Vector)=(0.5,0.5,0,0)

三、连贯性逐渐冰冻

一般来说 UV 具有一定的连续性,这里可以将 UV 图中某一点作为圆心点,向外逐渐展开,以达到逐渐冰冻的效果。具体的实现方法是计算指定 UV 点与起点的距离,逐渐增大其值以达到效果。

//主图
half4 var_MainTex = tex2D(_MainTex, i.uv0);
//高光遮蔽图(用于区分哪部分有贴图内容)
half4 var_OcclusionTex = tex2D(_OcclusionTex, i.uv0);
//_CenterUv是指定中心,计算uv与中心点的距离,能修修改显示距离达到向外扩展效果
half dic =1- distance(i.uv0.xy, _CenterUv.xy)* var_OcclusionTex;
clip(dic- _ClipNum);

四、下垂的冰柱

我们需要制作一种向下的冰柱,可以先使用云彩图制作随机扰动效果,这些随机效果的色值通常为0-1。在这里,只有超过0.45的图案部分才能形成向下的冰柱。
为了让冰柱看起来更流畅,我们可以在顶点中使用o.nDirWS.g属性,这将根据冰柱方向下降的程度来调整每个顶点的Y坐标。
因此,在确定了UV映射后,我们需要将超过0.45的顶点向上移动指定的距离,这将产生类似于冰柱的形状。

//在顶点阶段读图需要用tex2DLod(这里是云彩干扰图)
half h = tex2Dlod(_CloudTex, float4(v.uv0.xy, 0, 0)).r;
//读云彩图色值,红色值大于0.45的做法线扩展,用于做冰刺效果
//o.nDirWS.g 得到向下的法线,因为冰刺只要向下的 g 也相当于Y轴
half stepNormal = step(h,0.45)*_VectorNormalScale*max(0,(_VectorNormalScale - o.nDirWS.g));

五、半萤光效果

通常,在冰面上通常会存在一些凹凸不平的效果。我们可以使用贴图来模拟这些效果。此外,有时冰面还会有一些闪闪发光的效果。在这种情况下,我们可以使用菲涅尔光来进行模拟。

//光源漫反射
half3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
half3 baseCol = var_MainTex.rgb*ambient*_LightColor0;//
half lambert = max(0.0, ndotl);
//光源镜面反射half specPow = _SpecPow;half phong = pow(max(0.0,vdotr), _SpecPow);//光源反射混合half3 baseLighting = (baseCol  + phong * _EnvSpecInt);//(baseCol * lambert + phong * _EnvSpecInt)//环境漫反身half3 envDiff = baseCol * _EnvDiffInt;half upMask = max(0.0, nDirTSOrigin.g);//环境镜面反射half3 fresnel = pow(max(0.0, 1.0 - vdotn), _FresnelPow) * _FresnelInt*ambient.rgb;//菲涅尔half3 envSpec = fresnel * _EnvSpecInt*ambient;//环境反射混合half3 envLighting = (envDiff + envSpec)*ambient*_LightColor0;//最终混合half3 finalRGB = (baseLighting+envLighting + fresnel )* var_OcclusionTex.r;// ;*(1 - scale)

六、下面是完整代码:

这里付上完整代码,大家可以结合代码和上面的讲解会更好理解。也可以扩展成更多的效果,希望对大家有帮助,谢谢。

Shader "Custom/IceAnimStandard" {Properties{[Header(Ground_Base)]_MainTex("基础色 ",2D) = "white"{}_CloudTex("干扰图 ",2D) = "white"{}_BaseColor("基础色",Color) = (1.0,1.0,1.0,1.0)_NormMap("法线贴图",2D) = "bump"{}[Header(Normal)]_NormalScale("法线缩放",Range(0.0,1)) = 1_VectorNormalScale("顶点法线缩放",Range(0,0.1)) = 0_BaseVectorNormalScale("基础顶点法线缩放",Range(0,1)) = 0.06[Header(Ground_Diffuse)]_EnvDiffInt("环境漫反射强度",Range(0,1)) = 0.2[Header(Ground_Specular)]_FresnelPow("菲涅尔次幂",Range(0,10)) = 1_FresnelInt("菲涅尔强度",Range(0,2)) = 1_SpecPow("高光次幂",Range(0,5)) = 30_EnvSpecInt("环境镜面反射强度",Range(0,5)) = 0.2_OcclusionTex("高光遮蔽",2D) = "white"{}_CenterUv("裁剪中心",Vector)=(0.5,0.5,0,0)_ClipNum("裁剪数值",Range(0,1)) = 1}SubShader{Tags{"RenderType" = "Opaque" "IgnoreProjector" = "True"}//Pass{Tags{"LightMode" = "ForwardBase"}//ZWrite off//Cull offCGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"#include "AutoLight.cginc"#include "UnityCG.cginc"#pragma target 3.0#pragma multi_compile_fwdbase//地面参数uniform sampler2D _MainTex;uniform sampler2D _CloudTex;uniform sampler2D _NormMap; uniform half4 _NormMap_ST;uniform half4 _BaseColor;uniform half _NormalScale;uniform half _VectorNormalScale;uniform half _BaseVectorNormalScale;uniform half _EnvDiffInt;uniform half _SpecPow;uniform half _EnvSpecInt;uniform half _FresnelPow;uniform half _FresnelInt;uniform sampler2D _OcclusionTex;uniform half2 _CenterUv;uniform half _ClipNum;//输入结构struct a2v {float4 vertex:       POSITION;                //顶点信息float2 uv0:          TEXCOORD0;               //UV信息float4 normal:       NORMAL;                  //法线信息float4 tangent:      TANGENT;                 //切线信息};//输出结构struct v2f {float4 pos:SV_POSITION;                       //屏幕定点位置float2 uv0:TEXCOORD0;                       //UV(不可动)保持默认float2 uv2:TEXCOORD2;                      //法线UV(用于重复平铺)float3 WorldPos:TEXCOORD7;                        //世界坐标位置float3 nDirWS:TEXCOORD4;                    //世界坐标法线float3 tDirWS:TEXCOORD5;                    //世界坐标切线float3 bDirWS:TEXCOORD6;                    //世界坐标副切线SHADOW_COORDS(3)};v2f vert(a2v v) {v2f o;                                                                          //新输出结构o.nDirWS = UnityObjectToWorldNormal(v.normal);                                  //法线位置   OS>WShalf h = tex2Dlod(_CloudTex, float4(v.uv0.xy, 0, 0)).r;half stepNormal = step(h,0.45)*_VectorNormalScale*max(0,(_VectorNormalScale - o.nDirWS.g));half4 downNormal = -half4(o.nDirWS,0);downNormal.y = max(0.1, downNormal.y);downNormal.x = 0;downNormal.z = 0;v.vertex += downNormal * stepNormal + _BaseVectorNormalScale*v.normal;o.pos = UnityObjectToClipPos(v.vertex);                                            //顶点位置    OS>CSo.uv0 = v.uv0;                                                                   //传弟UVo.uv2 = v.uv0 *_NormMap_ST.xy + _NormMap_ST.zw;                                                                 //传弟UVo.WorldPos = mul(unity_ObjectToWorld, v.vertex);                             //点位置     CS>WSo.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz,0)).xyz);    //切线方向o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS)*v.tangent.w);                       //副切方向TRANSFER_SHADOW(o);return o;}float4 frag(v2f i) :SV_TARGET{//纹理采样half4 var_MainTex = tex2D(_MainTex, i.uv0);half4 var_OcclusionTex = tex2D(_OcclusionTex, i.uv0);half dic =1- distance(i.uv0.xy, _CenterUv.xy)* var_OcclusionTex;clip(dic- _ClipNum);var_MainTex.rgb *= _BaseColor;//向量准备float3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS);float4 var_normapTex = tex2D(_NormMap,i.uv2);float3 nDirTS = UnpackNormal(var_normapTex).rgb;float3 nDirTSOrigin = normalize(mul(nDirTS, TBN));nDirTS.xy *= (_NormalScale - (abs(i.uv0.y - 0.5)*(_NormalScale)));nDirTS.z = max(0.5, sqrt(1.0 - saturate(dot(var_normapTex.xy, var_normapTex.xy))));float3 nDirWS = normalize(mul(nDirTS, TBN));float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.WorldPos.xyz);float3 lDirWS = _WorldSpaceLightPos0.xyz;float3 lrDirWS = reflect(-lDirWS,nDirWS);//中间量准备float ndotl = max(0.5, dot(nDirWS, lDirWS));float vdotr = dot(vDirWS, lrDirWS);float vdotn = dot(vDirWS, nDirWS);//光照模型//光源漫反射half3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;half3 baseCol = var_MainTex.rgb*ambient*_LightColor0;//half lambert = max(0.0, ndotl);//光源镜面反射half specPow = _SpecPow;half phong = pow(max(0.0,vdotr), _SpecPow);//光源反射混合half3 baseLighting = (baseCol  + phong * _EnvSpecInt);//(baseCol * lambert + phong * _EnvSpecInt)//环境漫反身half3 envDiff = baseCol * _EnvDiffInt;half upMask = max(0.0, nDirTSOrigin.g);//环境镜面反射half3 fresnel = pow(max(0.0, 1.0 - vdotn), _FresnelPow) * _FresnelInt*ambient.rgb;//菲涅尔half3 envSpec = fresnel * _EnvSpecInt*ambient;//环境反射混合half3 envLighting = (envDiff + envSpec)*ambient*_LightColor0;//最终混合half3 finalRGB = (baseLighting+envLighting + fresnel )* var_OcclusionTex.r;// ;*(1 - scale)//返回值//阴影衰减UNITY_LIGHT_ATTENUATION(atten, i, i.WorldPos);return half4((finalRGB)*atten,1);}ENDCG}}FallBack "Diffuse"
}

冰冻效果Shader案例相关推荐

  1. 冰shader_MatCap冰冻效果Shader

    Python的高级特性4:函数式编程 函数式编程的核心就是把函数当成对象来进行编程. 有两个常用到的方法:map/reduce,filter,其中map和filter是内建方法,而reduce不是,所 ...

  2. 【Unity Shader 描边效果_案例分享】

    1.实现逻辑 描边效果Shader有多种实现方式,可以通过后处理和MatCap实现. 这次主要想展示的是通过两个Pass实现. 当Shader中有多个Pass时,渲染流程会安装顺序依次执行,于是后面的 ...

  3. unity3d 地面印花_Unity Shader案例篇—角色动态地面印记

    下面和大家分享一个shader案例,如何实现角色动态地面印记.效果如下图所示:角色在地形上行走,地形上始终会有一个动态圆环跟随角色,类似于阴影的一个效果.但是这个 "阴影"是我们可 ...

  4. html中放大镜案列,Canvas实现放大镜效果完整案例分析(附代码)

    本文主要记录 canvas 在图像.文字处理.离屏技术和放大镜特效的实现过程中使用到的api.先看下效果吧: 一张模糊的图片: 鼠标点击任意位置,产生放大效果: 哇塞~ 一个帅哥,哈哈哈哈~ 1.放大 ...

  5. 破译营销最优解,2018E-UP效果营销案例大赛终审完美收官

    12月13日,由今日头条联合金鼠标数字营销大赛主办的2018 E-UP效果营销案例大赛终审在北京拉开帷幕.派瑞威行.凯丽隆.58同城.西安微聚.信淼传媒.乐推.品众互动.优矩互动.鲸鱼无限.睿道网络共 ...

  6. Unity从零开始实现一个全息效果Shader

    Unity从零开始实现一个全息效果Shader 前言 开始捣鼓 一.准备阶段 二.先从透明效果开始 三.顶点故障效果 四.扫描线效果 五.菲尼尔反射效果 六.颗粒效果 七.颜色故障效果 CustomE ...

  7. Unity ASE制作彩色流光马赛克 像素风 舞池DJ台效果Shader

    Unity ASE制作彩色流光马赛克 舞池DJ台效果 Shader@TOC 项目需求想写一个舞池DJ台的效果,尝试写了发现制作出好玩的效果. 首先想要得到这种棋盘格的效果,想到了马赛克像素平铺,平铺数 ...

  8. 马赛克效果(shader)

    马赛克是一种常用的图像处理手段,因为这种模糊效果看上去有一个个的小格子组,便形象的称这种画面为马赛克.当画面上的马赛克格子小到一定程度的时候,画面呈现出来的风格也叫像素风 demo 实现思路 核心思路 ...

  9. Shader案例篇二《镜子2》

    Shader案例篇二<镜子2> 二.Unity中制作原理 1.简单说明:其实这个原理就是用一个摄像机去拍镜子上面的物体将得到的图像投影给Plane,最后主摄像机就能看到Plane上物体的镜 ...

最新文章

  1. no no no.不要使用kill -9.
  2. 红帽虚拟化RHEV-安装RHEV-M
  3. 常微分方程I ODE的例子1 弹簧的振动、RLC电路与单摆
  4. 使用eclipse开发javaweb登录功能带验证码文件下载第几位登录使用servlet编写html
  5. Python---利用蒙特.卡罗方法计算圆周率近似值
  6. mysql 查看trige_mysql查看所有存储过程,函数,视图,触发器,表
  7. 崇天老师python123测验6_嵩天老师python123测验1: Python基本语法元素 (第1周)
  8. c# http请求执行超时,解决办法(给某个方法设定超时时间)
  9. 批处理删除文件夹下所有文件和文件夹
  10. 运动目标检测——研究现状
  11. 智能快递柜在小区的应用
  12. Discord账号被封怎么办?Discord账号解封申诉方案
  13. mongodb 服务器时区设置_关于MongoDB时区问题
  14. 《C++ Primer Plus》学习笔记-string类和标准模板库
  15. Shell中显示彩色二维码
  16. it 决策者用户_了解最终用户的安全决策
  17. win8 开发之旅(19) --足球游戏揭秘5
  18. 小白学习图像处理3——图像旋转原理
  19. modbusCRC 、CRC-CCITT(0xFFFF) 校验
  20. 简述你对计算机科学导论的看法,《计算机科学导论》(节选)翻译报告

热门文章

  1. 题目:有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问
  2. Java实现IP库归属地查询
  3. ESP-01S烧录MQTT固件连接阿里云
  4. (新型事件相机有关的论文解读)A Unifying Contrast Maximization Framework for Event Cameras
  5. 网站购买空间还是服务器,网站用空间还是服务器
  6. wordpress会员插件_最好的免费WordPress会员插件
  7. 微信消息推送神器【一封传话】介绍,让消息推送更简单
  8. dayday60-120
  9. 168640-82-2,Azide-PEG4-Tos含有叠氮化物(N3)基团和对甲苯磺酰基的杂功能交联剂
  10. CUDA C编程(五)并行性的表现以及避免分支分化