先看效果:

飘动全是使用shader偏移顶点

的位置做的

几个点:

1、顶点数据的alpha值,标识了受风的权重。alpha越大,受风越厉害。

通过观察模型可以看出这点。而shader里这句也有说明。

以_Time作为参数,使用frac来取模,形成周期性的动画。

下面是注释后的shader

// - Unlit
// - Per-vertex (virtual) camera space specular light
// - SUPPORTS lightmap

Shader "MADFINGER/Environment/Lightmap + Wind" {
Properties {
    _MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
    _Wind("Wind params",Vector) = (1,1,1,1)
    _WindEdgeFlutter("Wind edge fultter factor", float) = 0.5
    _WindEdgeFlutterFreqScale("Wind edge fultter freq scale",float) = 0.5
}

SubShader {
    Tags {"Queue"="Transparent" "RenderType"="Transparent" "LightMode"="ForwardBase"}
    LOD 100
    
    Blend SrcAlpha OneMinusSrcAlpha
    Cull Off ZWrite Off
    
    
    CGINCLUDE
    #include "UnityCG.cginc"
    #include "TerrainEngine.cginc"
    sampler2D _MainTex;
    float4 _MainTex_ST;
    samplerCUBE _ReflTex;
    
    #ifndef LIGHTMAP_OFF        //lightmap是否开启。如果没有关闭lightmap。就给lightmap支持下。
    float4 unity_LightmapST;
    sampler2D unity_Lightmap;
    #endif
    
    float _WindEdgeFlutter;            //风导致旗帜震动的振幅
    float _WindEdgeFlutterFreqScale;  //风的时间流逝速度,影响频率,控制旗子反复摆动的周期

struct v2f {
        float4 pos : SV_POSITION;
        float2 uv : TEXCOORD0;
        #ifndef LIGHTMAP_OFF        //开启lightmap的时候,要使用
        float2 lmap : TEXCOORD1;
        #endif
        fixed3 spec : TEXCOORD2;
    };

inline float4 AnimateVertex2(float4 pos, float3 normal, float4 animParams,float4 wind,float2 time)
{    
    // animParams stored in color
    // animParams.x = branch phase
    // animParams.y = edge flutter factor
    // animParams.z = primary factor
    // animParams.w = secondary factor

float fDetailAmp = 0.1f;
    float fBranchAmp = 0.3f;
    
    // Phases (object, vertex, branch)
    float fObjPhase = dot(_Object2World[3].xyz, 1);  //这一行直接写1也行,_Object2World[3],一般情况下应该是0,0,0,1
    float fBranchPhase = fObjPhase + animParams.x;   //由于animParams.x是0,这个也是1
    
    float fVtxPhase = dot(pos.xyz, animParams.y + fBranchPhase);  //根据x,y,z,和振幅+1点乘。离远点越远,这个值越大。受振幅影响
    
    // x is used for edges; y is used for branches
    float2 vWavesIn = time  + float2(fVtxPhase, fBranchPhase );  //vWavesIn第一项是点的相位*时间流逝率,第二项就是时间+1.
    
    // 1.975, 0.793, 0.375, 0.193 are good frequencies
    float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0); // 将结果乘以频率,对一取模,然后乘以2,再减一
    
    vWaves = SmoothTriangleWave( vWaves );   //一个优化的正弦波计算。
    float2 vWavesSum = vWaves.xz + vWaves.yw; //振幅叠加,以免太正弦了。

// Edge (xz) and branch bending (y)
    float3 bend = animParams.y * fDetailAmp * normal.xyz; //沿法线方向根据振幅和参数缩放一个值
    bend.y = animParams.w * fBranchAmp;                      //y根据受风能力,乘以一个参数
    pos.xyz += ((vWavesSum.xyx * bend) + (wind.xyz * vWavesSum.y * animParams.w)) * wind.w;  //再次根据受风能力进行影响。

// Primary bending
    // Displace position
    pos.xyz += animParams.z * wind.xyz;  //根据受风能力,再次扩大。
    
    return pos;
}

v2f vert (appdata_full v)
    {
        v2f o;
        
        float4    wind;
        
        float            bendingFact    = v.color.a;
        
        wind.xyz    = mul((float3x3)_World2Object,_Wind.xyz);      //风的方向转为物体坐标。wind参数的xyz表示风的世界坐标的方向。_Wind为风的个方向强度
        wind.w        = _Wind.w  * bendingFact;                        //每个顶点的颜色的alpha值表示此点受风变化的强度。旗子底部这个值较大。wind参数的w表示风力
        
        
        float4    windParams    = float4(0,_WindEdgeFlutter,bendingFact.xx);  //0,旗子振幅,每个顶点的受风强度值
        float         windTime         = _Time.y * float2(_WindEdgeFlutterFreqScale,1);  //风的时间流逝速度
        float4    mdlPos            = AnimateVertex2(v.vertex,v.normal,windParams,wind,windTime); //计算受风之后的位置
        
        o.pos = mul(UNITY_MATRIX_MVP,mdlPos);
        o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
        
        o.spec = v.color;
        
        #ifndef LIGHTMAP_OFF
        o.lmap = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
        #endif
        
        return o;
    }
    ENDCG

Pass {
        CGPROGRAM
        #pragma debug
        #pragma vertex vert
        #pragma fragment frag
        #pragma fragmentoption ARB_precision_hint_fastest        //片元着色器选择低精度的计算方式。5.0以后抛弃掉 fragmentoption的声明。
        fixed4 frag (v2f i) : COLOR
        {
            fixed4 tex = tex2D (_MainTex, i.uv);
            
            fixed4 c;
            c.rgb = tex.rgb;
            c.a = tex.a;
            
            #ifndef LIGHTMAP_OFF
            fixed3 lm = DecodeLightmap (tex2D(unity_Lightmap, i.lmap));
            c.rgb *= lm;
            #endif
            
            return c;
        }
        ENDCG 
    }    
}
}

中间多次根据风力进行修正的地方,作者写的蛮复杂,不写那么复杂,效果看起来也还行。

3D优化之ShadowGun系列一:旗子飘扬效果实现方法及shader注解相关推荐

  1. 查看linux内存优化,Linux性能优化和监控系列(三) 分析Memory使用状况

    Linux性能优化和监控系列(三) 分析Mem 分析Memory使用状况 内存是影响服务器性能的一个主要因素, 当进程已经驻留内存或者系能够分配给进程足够的内存给它, CPU能顺利自如的运行. 如果发 ...

  2. 数值优化(Numerical Optimization)学习系列-惩罚和增广拉格朗日方法(Augmented Lagrangian Methods)

    原文地址为: 数值优化(Numerical Optimization)学习系列-惩罚和增广拉格朗日方法(Augmented Lagrangian Methods) 概述 求解带约束的最优化问题,一类很 ...

  3. NVIDIA显卡3D设置 让你的游戏得到最佳效果

    NVIDIA显卡3D设置 让你的游戏得到最佳效果  来源:电脑软硬件应用网    编辑: 黄燕飞   发布时间: 12-02-24     很多朋友的n卡(NVIDIA英伟达,简称N卡) ,都是在wi ...

  4. Atitit 发帖机系列(7) 词法分析的方法attilax大总结)

    Atitit 发帖机系列(7) 词法分析的方法attilax大总结) 1.1. 词法分析貌似俩大方法,一个直接根据状态图转换,一个根据dfa1 1.2. switchcase或者ifelse 最原始方 ...

  5. Labview加载3D模型(.wrl)出现内存不足的解决方法

    Labview加载3D模型(.wrl)出现内存不足的解决方法 最近,由于项目的要求,需要做一个上位机,用于实时采集装备的状态信息.最终方案采用Labview数据流的方式构建应用程序.在加载wrl3D模 ...

  6. AREngine深度图优化之一基于两基带统计的补洞方法

    我们都知道AREngine返回的深度图质量并不高,大概率是直接返回的tof深度图,跟ARCORE返回的深度图差距还是比较大的.在我们当前AR云渲染项目中,需要用到AREngine返回的深度图,这就需要 ...

  7. UA SIE545 优化理论基础 函数凸性的一些有趣的判断方法

    UA SIE545 优化理论基础 函数凸性的一些有趣的判断方法 Convex function f:S→Rf:S \to \mathbb{R}f:S→R where SSS is a nonempty ...

  8. Py之urllib2:Python库之urllib、urllib2、urllib3系列简介、安装、使用方法之详细攻略

    Py之urllib2:Python库之urllib.urllib2.urllib3系列简介.安装.使用方法之详细攻略 目录 urllib2简介 urllib2安装 urllib2使用方法 urllib ...

  9. STM系列单片机中文参考手册下载方法

    在使用STM单片机编程的时候有时候需要查阅芯片手册,英文手册查阅起来比较麻烦,而搜索中文手册时,好多网站下载时需要注册或者需要积分,下载起来比较麻烦.现在就来说一下,如何在官方网站下载各个系列单片机的 ...

  10. Java之List系列--ArrayList保证线程安全的方法

    原文网址:Java之List系列--ArrayList保证线程安全的方法_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java中的ArrayList.LinkedList如何进行线程安全的操作.为 ...

最新文章

  1. java对象的访问定位_2、JVM-Java对象的创建、对象结构、对象访问定位-Go语言中文社区...
  2. exe文件添加为服务
  3. jQuery UI应用--滑块Slider
  4. 如何躲开技术人员35岁魔咒?【有惊喜系列】
  5. mysql 5.6 json查询_mysql5.6及以下版本如何查询数据库里的json
  6. 对于HTTP过程中POST内容加密的解决方案
  7. tipask mysql调取dedecms_如何实现dedecms外部数据库调用
  8. 百度手机输入法,如何使用五笔98版?
  9. transition animation
  10. java指定浏览器_java程序中指定某个浏览器打开的实现方法
  11. 你以为你在利用碎片化时间,实际上你的时间被碎片化了
  12. 曾用心并深度参与的一款游戏今天发布了关服通知,回顾一下我最初的工作日报
  13. java 数字大小写转换工具类--适用于打印收据
  14. 计算机中文件夹怎么上密码,怎样设置电脑文件夹密码
  15. 位图(BMP)文件格式(一)
  16. python x=[random.randint(0,100) for i in range(50)]什么意思?列表解析
  17. mac 下配置安装rz,sz
  18. CSDN积分获取方法(转载)
  19. 西门子精智屏下载触摸屏程序时提示缺少面板映像怎样解决?
  20. 切图工具GraphicsMagick安装

热门文章

  1. 15个网页数据采集中最常遇到的问题(干货)
  2. Pubwin EP常见问题(转)
  3. 3dMax模型的重置变换
  4. Java 在Excel中添加水印
  5. JButton与Button的区别
  6. 视频流(自适应算法)
  7. 3A锂电池充电管理芯片PW4035
  8. python制作指定区域截图工具_用python实现选择截图区域
  9. CNC加工老师傅的经验分享 这些你都知道吗?
  10. 计算机和网络邻居都不见 了,网上邻居看不到自己和别人电脑怎么办