因为最近要尝试在untiy3d做写实海底的效果,上图为版本5.5里面实现的效果

为了让画面更加逼真,海底植物必不可少

然而海底的海藻海草之类需要加上动画就比较麻烦了

一般的骨骼动画加起来比较麻烦,而且效果比较单调,消耗也很大

更不用说动力学解算了,通常时间长,而且烘焙成顶点动画往往比较困难,而且无法很好循环

使用shader的uv动画或者序列帧动画又不适合写实场景

用unity3d自带风力的话更像是陆地上的植物,没有很好表现水下效果

所以这里使用了shader顶点动画来模拟海草在海底的波动

下面是效果图

主要思路就是对物体表面顶点进行移动

为了方便说明,下面用shaderforge来制作一个简单的世界空间波动效果

使用shaderforge好处不止是简单,因为它能带来更大的兼容性,比如说投影和雾效之类不用自己单独写了

这些效果上面与其他的兼容性还是挺容易犯错的

下图是简单连线方式,可以让一个mesh平面在世界空间内自动产生波的效果

当然这只是简单的效果

成品需要叠加更多的节点

为了让扭动更加自然,不能只用简单的正弦余弦,而是要组合起来,减少规律感觉

自然扭动效果,首先可以让水草有整体的偏移循环,然后是每一个叶子顶点的偏移,最后还可以加上每个叶子uv的扭曲动画,才会更加自然

另外当水草成批复制的时候也会有问题,因为水草的运动效果太一致了,

所以我还在里面加上了世界空间坐标作为产生扰动的参数,这样每一株水草的动画都会有稍许不同了

当然最终效果也是个手艺活,需要一边调一边看效果,还有shaderforge有些bug,比如有些顶点移动效果在scene窗口才看得到,预览里面并不正确

下面放上shaderforge里面的一个粗糙版本,貌似有很多多余节点,不过效果就是上面gif的效果

Shader "Shader Forge/NewShader" {Properties {_color ("color", 2D) = "white" {}_norml ("norml", 2D) = "bump" {}_anbient ("anbient", Color) = (0.5,0.5,0.5,1)_specularColor ("specularColor", Color) = (0.5,0.5,0.5,1)_specular ("specular", Float ) = 1[HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5}SubShader {Tags {"Queue"="AlphaTest""RenderType"="TransparentCutout"}Pass {Name "FORWARD"Tags {"LightMode"="ForwardBase"}CGPROGRAM#pragma vertex vert#pragma fragment frag#define UNITY_PASS_FORWARDBASE#include "UnityCG.cginc"#include "AutoLight.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma multi_compile_fog#pragma exclude_renderers gles3 metal d3d11_9x xbox360 xboxone ps3 ps4 psp2 #pragma target 3.0uniform float4 _LightColor0;uniform float4 _TimeEditor;uniform sampler2D _color; uniform float4 _color_ST;uniform sampler2D _norml; uniform float4 _norml_ST;uniform float4 _anbient;uniform float4 _specularColor;uniform float _specular;struct VertexInput {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;float2 texcoord0 : TEXCOORD0;float4 vertexColor : COLOR;};struct VertexOutput {float4 pos : SV_POSITION;float2 uv0 : TEXCOORD0;float4 posWorld : TEXCOORD1;float3 normalDir : TEXCOORD2;float3 tangentDir : TEXCOORD3;float3 bitangentDir : TEXCOORD4;float4 vertexColor : COLOR;LIGHTING_COORDS(5,6)UNITY_FOG_COORDS(7)};VertexOutput vert (VertexInput v) {VertexOutput o = (VertexOutput)0;o.uv0 = v.texcoord0;o.vertexColor = v.vertexColor;o.normalDir = UnityObjectToWorldNormal(v.normal);o.tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w);float node_6620_ang = 1.57;float node_6620_spd = 1.0;float node_6620_cos = cos(node_6620_spd*node_6620_ang);float node_6620_sin = sin(node_6620_spd*node_6620_ang);float2 node_6620_piv = float2(0.5,0.5);float4 node_1583 = _Time + _TimeEditor;float2 node_6620 = (mul((o.uv0+node_1583.g*float2(0.25,0))-node_6620_piv,float2x2( node_6620_cos, -node_6620_sin, node_6620_sin, node_6620_cos))+node_6620_piv);float2 node_6051 = mul(unity_ObjectToWorld, v.vertex).rgb.rg;float2 node_6156_skew = node_6051 + 0.2127+node_6051.x*0.3713*node_6051.y;float2 node_6156_rnd = 4.789*sin(489.123*(node_6156_skew));float node_6156 = frac(node_6156_rnd.x*node_6156_rnd.y*(1+node_6156_skew.x));float4 node_2249 = _Time + _TimeEditor;v.vertex.xyz += (normalize((float3(2,1,1)+v.normal))*o.vertexColor.r*sin(((o.vertexColor.b*3.141592654*(abs(fmod(node_6620.r,5.0))*(7.5+node_6156)))+(node_6156*node_2249.g)))*0.056);o.posWorld = mul(unity_ObjectToWorld, v.vertex);float3 lightColor = _LightColor0.rgb;o.pos = mul(UNITY_MATRIX_MVP, v.vertex );UNITY_TRANSFER_FOG(o,o.pos);TRANSFER_VERTEX_TO_FRAGMENT(o)return o;}float4 frag(VertexOutput i) : COLOR {i.normalDir = normalize(i.normalDir);float3x3 tangentTransform = float3x3( i.tangentDir, i.bitangentDir, i.normalDir);float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);float3 _norml_var = UnpackNormal(tex2D(_norml,TRANSFORM_TEX(i.uv0, _norml)));float3 normalLocal = _norml_var.rgb;float3 normalDirection = normalize(mul( normalLocal, tangentTransform )); // Perturbed normalsfloat4 _color_var = tex2D(_color,TRANSFORM_TEX(i.uv0, _color));clip(_color_var.a - 0.5);float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);float3 lightColor = _LightColor0.rgb;float3 halfDirection = normalize(viewDirection+lightDirection);
// Lighting:float attenuation = LIGHT_ATTENUATION(i);float3 attenColor = attenuation * _LightColor0.xyz;
/ Gloss:float gloss = 0.5;float specPow = exp2( gloss * 10.0+1.0);
// Specular:float NdotL = max(0, dot( normalDirection, lightDirection ));float3 specularColor = _specularColor.rgb;float3 directSpecular = (floor(attenuation) * _LightColor0.xyz) * pow(max(0,dot(halfDirection,normalDirection)),specPow)*specularColor;float3 specular = directSpecular;
/// Diffuse:NdotL = max(0.0,dot( normalDirection, lightDirection ));float3 directDiffuse = pow(max( 0.0, NdotL), _specular) * attenColor;float3 indirectDiffuse = float3(0,0,0);indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient LightindirectDiffuse += _anbient.rgb; // Diffuse Ambient Lightfloat3 diffuseColor = _color_var.rgb;float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;
/// Final Color:float3 finalColor = diffuse + specular;fixed4 finalRGBA = fixed4(finalColor,1);UNITY_APPLY_FOG(i.fogCoord, finalRGBA);return finalRGBA;}ENDCG}Pass {Name "FORWARD_DELTA"Tags {"LightMode"="ForwardAdd"}Blend One OneCGPROGRAM#pragma vertex vert#pragma fragment frag#define UNITY_PASS_FORWARDADD#include "UnityCG.cginc"#include "AutoLight.cginc"#pragma multi_compile_fwdadd_fullshadows#pragma multi_compile_fog#pragma exclude_renderers gles3 metal d3d11_9x xbox360 xboxone ps3 ps4 psp2 #pragma target 3.0uniform float4 _LightColor0;uniform float4 _TimeEditor;uniform sampler2D _color; uniform float4 _color_ST;uniform sampler2D _norml; uniform float4 _norml_ST;uniform float4 _specularColor;uniform float _specular;struct VertexInput {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;float2 texcoord0 : TEXCOORD0;float4 vertexColor : COLOR;};struct VertexOutput {float4 pos : SV_POSITION;float2 uv0 : TEXCOORD0;float4 posWorld : TEXCOORD1;float3 normalDir : TEXCOORD2;float3 tangentDir : TEXCOORD3;float3 bitangentDir : TEXCOORD4;float4 vertexColor : COLOR;LIGHTING_COORDS(5,6)UNITY_FOG_COORDS(7)};VertexOutput vert (VertexInput v) {VertexOutput o = (VertexOutput)0;o.uv0 = v.texcoord0;o.vertexColor = v.vertexColor;o.normalDir = UnityObjectToWorldNormal(v.normal);o.tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w);float node_6620_ang = 1.57;float node_6620_spd = 1.0;float node_6620_cos = cos(node_6620_spd*node_6620_ang);float node_6620_sin = sin(node_6620_spd*node_6620_ang);float2 node_6620_piv = float2(0.5,0.5);float4 node_2231 = _Time + _TimeEditor;float2 node_6620 = (mul((o.uv0+node_2231.g*float2(0.25,0))-node_6620_piv,float2x2( node_6620_cos, -node_6620_sin, node_6620_sin, node_6620_cos))+node_6620_piv);float2 node_6051 = mul(unity_ObjectToWorld, v.vertex).rgb.rg;float2 node_6156_skew = node_6051 + 0.2127+node_6051.x*0.3713*node_6051.y;float2 node_6156_rnd = 4.789*sin(489.123*(node_6156_skew));float node_6156 = frac(node_6156_rnd.x*node_6156_rnd.y*(1+node_6156_skew.x));float4 node_2249 = _Time + _TimeEditor;v.vertex.xyz += (normalize((float3(2,1,1)+v.normal))*o.vertexColor.r*sin(((o.vertexColor.b*3.141592654*(abs(fmod(node_6620.r,5.0))*(7.5+node_6156)))+(node_6156*node_2249.g)))*0.056);o.posWorld = mul(unity_ObjectToWorld, v.vertex);float3 lightColor = _LightColor0.rgb;o.pos = mul(UNITY_MATRIX_MVP, v.vertex );UNITY_TRANSFER_FOG(o,o.pos);TRANSFER_VERTEX_TO_FRAGMENT(o)return o;}float4 frag(VertexOutput i) : COLOR {i.normalDir = normalize(i.normalDir);float3x3 tangentTransform = float3x3( i.tangentDir, i.bitangentDir, i.normalDir);float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);float3 _norml_var = UnpackNormal(tex2D(_norml,TRANSFORM_TEX(i.uv0, _norml)));float3 normalLocal = _norml_var.rgb;float3 normalDirection = normalize(mul( normalLocal, tangentTransform )); // Perturbed normalsfloat4 _color_var = tex2D(_color,TRANSFORM_TEX(i.uv0, _color));clip(_color_var.a - 0.5);float3 lightDirection = normalize(lerp(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz - i.posWorld.xyz,_WorldSpaceLightPos0.w));float3 lightColor = _LightColor0.rgb;float3 halfDirection = normalize(viewDirection+lightDirection);
// Lighting:float attenuation = LIGHT_ATTENUATION(i);float3 attenColor = attenuation * _LightColor0.xyz;
/ Gloss:float gloss = 0.5;float specPow = exp2( gloss * 10.0+1.0);
// Specular:float NdotL = max(0, dot( normalDirection, lightDirection ));float3 specularColor = _specularColor.rgb;float3 directSpecular = attenColor * pow(max(0,dot(halfDirection,normalDirection)),specPow)*specularColor;float3 specular = directSpecular;
/// Diffuse:NdotL = max(0.0,dot( normalDirection, lightDirection ));float3 directDiffuse = pow(max( 0.0, NdotL), _specular) * attenColor;float3 diffuseColor = _color_var.rgb;float3 diffuse = directDiffuse * diffuseColor;
/// Final Color:float3 finalColor = diffuse + specular;fixed4 finalRGBA = fixed4(finalColor * 1,0);UNITY_APPLY_FOG(i.fogCoord, finalRGBA);return finalRGBA;}ENDCG}Pass {Name "ShadowCaster"Tags {"LightMode"="ShadowCaster"}Offset 1, 1CGPROGRAM#pragma vertex vert#pragma fragment frag#define UNITY_PASS_SHADOWCASTER#include "UnityCG.cginc"#include "Lighting.cginc"#pragma fragmentoption ARB_precision_hint_fastest#pragma multi_compile_shadowcaster#pragma multi_compile_fog#pragma exclude_renderers gles3 metal d3d11_9x xbox360 xboxone ps3 ps4 psp2 #pragma target 3.0uniform float4 _TimeEditor;uniform sampler2D _color; uniform float4 _color_ST;struct VertexInput {float4 vertex : POSITION;float3 normal : NORMAL;float2 texcoord0 : TEXCOORD0;float4 vertexColor : COLOR;};struct VertexOutput {V2F_SHADOW_CASTER;float2 uv0 : TEXCOORD1;float4 posWorld : TEXCOORD2;float3 normalDir : TEXCOORD3;float4 vertexColor : COLOR;};VertexOutput vert (VertexInput v) {VertexOutput o = (VertexOutput)0;o.uv0 = v.texcoord0;o.vertexColor = v.vertexColor;o.normalDir = UnityObjectToWorldNormal(v.normal);float node_6620_ang = 1.57;float node_6620_spd = 1.0;float node_6620_cos = cos(node_6620_spd*node_6620_ang);float node_6620_sin = sin(node_6620_spd*node_6620_ang);float2 node_6620_piv = float2(0.5,0.5);float4 node_9812 = _Time + _TimeEditor;float2 node_6620 = (mul((o.uv0+node_9812.g*float2(0.25,0))-node_6620_piv,float2x2( node_6620_cos, -node_6620_sin, node_6620_sin, node_6620_cos))+node_6620_piv);float2 node_6051 = mul(unity_ObjectToWorld, v.vertex).rgb.rg;float2 node_6156_skew = node_6051 + 0.2127+node_6051.x*0.3713*node_6051.y;float2 node_6156_rnd = 4.789*sin(489.123*(node_6156_skew));float node_6156 = frac(node_6156_rnd.x*node_6156_rnd.y*(1+node_6156_skew.x));float4 node_2249 = _Time + _TimeEditor;v.vertex.xyz += (normalize((float3(2,1,1)+v.normal))*o.vertexColor.r*sin(((o.vertexColor.b*3.141592654*(abs(fmod(node_6620.r,5.0))*(7.5+node_6156)))+(node_6156*node_2249.g)))*0.056);o.posWorld = mul(unity_ObjectToWorld, v.vertex);o.pos = mul(UNITY_MATRIX_MVP, v.vertex );TRANSFER_SHADOW_CASTER(o)return o;}float4 frag(VertexOutput i) : COLOR {i.normalDir = normalize(i.normalDir);float3 normalDirection = i.normalDir;float4 _color_var = tex2D(_color,TRANSFORM_TEX(i.uv0, _color));clip(_color_var.a - 0.5);SHADOW_CASTER_FRAGMENT(i)}ENDCG}}FallBack "Diffuse"CustomEditor "ShaderForgeMaterialInspector"
}

还有要注意就是模型面数少的话调试的时候可能遇到动态批处理问题

shader测试使用很少面数物体比如box进行测试的时候可能会遇到动态批处理产生的错误效果问题,
常见的效果就是scene和game窗口看到的物体效果不一样,而且单个物体还行,多个物体的时候会发现有的物体会闪烁消失等等异常的发生都和动态批处理有关
关于disablebatching引起的shader问题,其实只有很少面数的物体才需要关心,因为顶点超过900的物体根本不会被动态批处理

下面普及下动态批处理,以当前版本为准,在老生常谈的里面加上一些新版本特性和自己的理解
1批处理动态物体需要在每个顶点上进行一定的消耗,支持小于900顶点的网格物体。
   -1着色器使用顶点位置,法线和UV值三种属性,那么你只能批处理300顶点以下的物体;
   -2着色器使用顶点位置,法线,UV0,UV1和切向量,那你只能批处理180顶点以下的物体。
   -3这些可能都会随着版本变化,另外300顶点限制不是那么具体,有时候支持面数很少
(这也意味着默认的有着标准材质的球体和胶囊体就没有动态批处理)

2不同轴的缩放物体也支持批处理了,但是不能出现缩放“镜像”物体,比如x缩放是1和-1的,以前不支持不等比例缩放的动态批处理,现在支持了,比如一个是方块1:1:1的,另一个是长方体也可以批处理

3使用不同材质的实例化物体(instance)将会导致批处理失败。但是物体可以在投影设置上随意不影响动态批处理。

4拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等。所以,拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一部分)。

5多pass的shader也影响动态批处理。比如说默认标准材质球有时候物体面数稍微高点是不能动态批处理的,但是用nature-speedtree的就可以批处理

当然动态批处理后并不意味性能一定提高,在有些显卡上性能反而是下降的

当然你模型面数多完全可以不考虑这个,这个一般是用在粒子之类有大量相同的物体上的,这里提到主要是因为box测试时遇到些问题

具体规则官方参考
https://docs.unity3d.com/Manual/DrawCallBatching.html

unity3d中水草海草摇动效果顶点动画材质相关推荐

  1. Unity3d中实现翻书效果(一)

    转自 GottaYiWanLiu 1.如何快速的在unity3d实现与现实中翻书类似的翻书动作,在这里借助一个插件,可以在unity3d中assetStore里找到 我们首先来看下效果,这是我们自定义 ...

  2. 【Unity3D小功能】Unity3D中实现UI擦除效果、刮刮卡功能

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦. 一.前言 ...

  3. Unity3D中如何调用序列帧图片为动画

    环境:Unity4.6.2 Win7 64bit 我这里一张图片就是一帧,不需要去把一张图片裁剪成几段.然后把这些png图片按顺序渲染.其实这样也可以用视频来代替,也可以有同样的效果. 实际操作其实是 ...

  4. 模板测试+一个好玩的顶点动画效果——UnityShader学习笔记

    文章目录 一.自言自语 效果 模板测试效果(图传错了就懒得继续换了) 模板测试代码 顶点动画面板 顶点动画效果 顶点动画shader代码 总结 一.自言自语 嗯,又是很久没写笔记了.学习的进度和效率没 ...

  5. unity3d怎么让模型动起来_让对象在Unity3D中动起来

    让对象动起来有两步: 1.在场景中移动对象 2.让对象播放动画 我们一步步来实现这个目标. 移动对象需要用到UnityScript,不过这里我们只是想要简单的移动,拿"Script Tuto ...

  6. unity3d双面材质_[转]unity3d中创建双面材质

    在其它三维软件中设置好的双面材质导入到unity3d中就失去了效果,不过我们可以通过自定义材质来在unity3d中实现双面材质的效果.步骤如下: 1.在资源库中新建一新shader:代码如下: Sha ...

  7. Unity3D游戏开发之Unity3D中的动态阴影

    http://blog.csdn.net/qinyuanpei/article/details/32355267 博主今天想和大家分享的是Unity3D中的动态阴影,昨天博主重温了一下自己喜欢的游戏& ...

  8. Unity3D中暂停时的动画及粒子效果实现

    暂停是游戏中经常出现的功能,而Unity3D中对于暂停的处理并不是很理想.一般的做法是将Time.timeScale设置为0.Unity的文档中对于这种情况有以下描述: The scale at wh ...

  9. 带顶点动画的护盾效果——UnityShader学习笔记

    文章目录 自言自语 一.效果 二.C# 三.Shader 总结 自言自语 最近又是很久没有更新笔记了.原因有二. 一.最近一直再啃一个看起来酷炫的护盾效果 啃了好久啊.直至效果满意 也理解了. 这个是 ...

最新文章

  1. HTML5中是否有浮点输入类型?
  2. ARMS企业级场景被集成场景介绍
  3. ev10aq190a采集电路图_EV10AQ190A数模转换器
  4. NOI数据结构:最小树形图
  5. C语言do while语句
  6. 结组开发项目(TD学生助手)
  7. Tree树结构java实现
  8. 1.1_简单递归 (汉诺塔问题 / 进制转换)
  9. nginx 反向代理时丢失端口的解决方案(转)
  10. 《编程之美》1.3一摞烙饼的排序
  11. 几个jquery分发库速度测评
  12. Spring Session + Redis 实现 Session 共享,附带 Nginx 集群
  13. 有哪些植树的优美句子 值得一起收藏的植树节手抄报or海报素材?
  14. 信息与通信的数学基础——第十三章 行波法
  15. 【转】FILE *fp fopen 参数
  16. 网站的 计算机主机作用是什么情况,运维堡垒主机是什么有什么作用
  17. 加百利号角/托里拆利小号
  18. 汉字转换拼音字头原理实践
  19. 编程基础篇:(已知:线段中点坐标公式为:(x,y)=(( x1+ x2)/2,(y1+y2)/2),线段长度公式为:L= sqrt((x1-x2)^2-(y1-y2))
  20. DeamNet||训练代码学习train.py注释与解析

热门文章

  1. Qt 内置对话框英文改成中文
  2. Android录屏实现
  3. TLP280-4 与 TLP281-4区别
  4. github merge request(MR)流程说明
  5. Matlab中keyboard函数用法
  6. Redis基础用法、高级特性与性能调优以及缓存穿透等分析
  7. 大话西游各服务器位置,大话西游手游时间服哪个区好_大话西游手游时间服哪个服务器人多_玩游戏网...
  8. 比例尺:地图比例尺和显示比例尺
  9. 色弱不能学计算机的哪些专业,高考体检色弱色盲不能报哪些专业?
  10. Content Aware ABR技术(三)