2019-04-11

shader

Shader "Unlit/Ocean"
{
    Properties
    {
        _MainColor("MainColor",Color)=(0,0,1,1)
        _Smoothness("Smoothness",Range(0,1))=0.7
        _Metallic("Metallic",Range(0,1))=0
        _WaveFoamDir("Wave foam dirction",Vector)=(0,0,0,0)
        
        [Header(Distortions1)]
        _NormalMap("NormalMap1",2D)="bump"{}
        _NormalMapMoveDir("NormalMapMoveDir",vector)=(1,1,1,1)
        _NormalMapMoveSpeed("NormalMapMoveSpeed",float)=0
        _HeightMap("HeightMap",2D)="black"{}
        [Space(30)]

        [Header(Distortions2)]
        _NormalMap2("NormalMap2",2D)="bump"{}
        _NormalMapMoveDir2("NormalMapMoveDir2",vector)=(-1,1,1,1)
        _NormalMapMoveSpeed2("NormalMapMoveSpeed2",float)=0
        _HeightMap2("HeightMap",2D)="black"{}
        [Space(30)]

        [Header(Distortion Setting)]
        _NormalScale("NormalScale",Range(0,1))=0.6
        _HeightScale("HeightScale",Range(0,1))=1.0
        _HeightMapFoamScale("FoamScale",Range(0,5))=1.0
        _FoamSpread("FoamSpread",float)=1.0


        //-------Wave Set-------
            [Header(Base Wave)]
            _PointBumpScale("PointBumpScale",Range(0,1))=1
            [Toggle(ENABLE_BASEWAVE)]_baseWave("baseWave",float)=1
            _waveLength("waveLength",float)=5
            _amplitude("amplitude",float)=3
            _steepness("steepness",float)=1
            _dirX("dirX",Range(-1,1))=1
            _dirZ("dirZ",Range(-1,1))=1
            _speed("speed",float)=5
            _fadeSpeed("fadespeed",float)=1
            [space(20)]

            [Header(Wave1)]
            [Toggle(ENABLE_WAVE1)]_wave1("wave1",float)=1
            _waveLength1("waveLength",float)=5
            _amplitude1("amplitude",float)=3
            _steepness1("steepness",float)=1
            _dirX1("dirX",Range(-1,1))=1
            _dirZ1("dirZ",Range(-1,1))=1
            _speed1("speed",float)=5
            _fadeSpeed1("fadespeed",float)=1
            [space(20)]

            [Header(Wave2)]
            [Toggle(ENABLE_WAVE2)]_wave2("wave2",float)=1
            _waveLength2("waveLength",float)=5
            _amplitude2("amplitude",float)=3
            _steepness2("steepness",float)=1
            _dirX2("dirX",Range(-1,1))=1
            _dirZ2("dirZ",Range(-1,1))=1
            _speed2("speed",float)=5
            _fadeSpeed2("fadespeed",float)=1
            [space(20)]

            [Header(Wave3)]
            [Toggle(ENABLE_WAVE3)]_wave3("wave3",float)=1
            _waveLength3("waveLength",float)=5
            _amplitude3("amplitude",float)=3
            _steepness3("steepness",float)=1
            _dirX3("dirX",Range(-1,1))=1
            _dirZ3("dirZ",Range(-1,1))=1
            _speed3("speed",float)=5
            _fadeSpeed3("fadespeed",float)=1
            [space(20)]

            [Header(Wave4)]
            [Toggle(ENABLE_WAVE4)]_wave4("wave4",float)=1
            _waveLength4("waveLength",float)=5
            _amplitude4("amplitude",float)=3
            _steepness4("steepness",float)=1
            _dirX4("dirX",Range(-1,1))=1
            _dirZ4("dirZ",Range(-1,1))=1
            _speed4("speed",float)=5
            _fadeSpeed4("fadespeed",float)=1
        //
    }
    SubShader
    {
        //-------pass 1---------
        ZWrite on 
        Cull back 
        Colormask 0
        Lighting off 
        CGPROGRAM
        
        #pragma surface surf Standard vertex:vert nometa
        #include "UnityCG.cginc"
        #include "WaterIncludes2.cginc"
        #pragma shader_feature ENABLE_BASEWAVE
        #pragma shader_feature ENABLE_WAVE1
        #pragma shader_feature ENABLE_WAVE2
        #pragma shader_feature ENABLE_WAVE3
        #pragma shader_feature ENABLE_WAVE4

        struct Input{
            float2 uv_MainTex;
        };
        //NormalMap1
        float4 _NormalMapMoveDir;
        float _NormalMapMoveSpeed;
        sampler2D _HeightMap;
        //Normalmap2
        float4 _NormalMapMoveDir2;
        float _NormalMapMoveSpeed2;
        sampler2D _HeightMap2;
        //Normal set
        float _HeightScale;

        //Wave set
        float _PointBumpScale;

        void vert(inout appdata_full v){
            //position
            float4 worldPos=mul(unity_ObjectToWorld,v.vertex);
            float4 worldPos1=GetWaveOffset(worldPos);
    
            //------heightMap-------------
            float height1=tex2Dlod(_HeightMap,float4(v.texcoord.xy+_NormalMapMoveDir.xy*_NormalMapMoveSpeed*_Time.x,0,0)).r;
            height1=(height1-1)*2;
            float height2=tex2Dlod(_HeightMap2,float4(v.texcoord.xy+_NormalMapMoveDir2.xy*_NormalMapMoveSpeed2*_Time.x,0,0)).r;
            height2=(height2-0.5)*2;
            worldPos1.y+= (height1+height2)*_HeightScale;
            worldPos1.y=lerp(0,worldPos1.y,_PointBumpScale);
            
            //output to Object Data
            v.vertex=mul(unity_WorldToObject,float4(worldPos1.xyz,1.0));
        }

        void surf(Input IN, inout SurfaceOutputStandard o) {}


        ENDCG

        //------end pass---------
        GrabPass{"_WaterBackground"}

        //------pass 2 -----------
        Tags { "RenderType"="Transparent""Queue"="Transparent" }
        ZWrite off  
        Cull back 
        Blend SrcAlpha OneMinusSrcAlpha
        Colormask RGBA 

        CGPROGRAM

        #pragma surface surf Standard vertex:vert alpha:fade nometa novertexlights noforwardadd 
        #include"UnityCG.cginc"
        #include "UnityPBSLighting.cginc"
        #include"WaterIncludes2.cginc"
        #pragma target 3.0
        #pragma shader_feature ENABLE_BASEWAVE
        #pragma shader_feature ENABLE_WAVE1
        #pragma shader_feature ENABLE_WAVE2
        #pragma shader_feature ENABLE_WAVE3
        #pragma shader_feature ENABLE_WAVE4

        struct Input {
            float2 uv_MainTex;
            float2 uv_NormalMap;
            float2 uv_NormalMap2;
            float worldDirNormal;
            float crestFactor;
        };
        //Base Set
        float4 _MainColor;
        float _Metallic;
        float _Smoothness;
        float3 _WaveFoamDir;


        //NormalMap1
        sampler2D _NormalMap;
        float4 _NormalMapMoveDir;
        float _NormalMapMoveSpeed;
        sampler2D _HeightMap;
        //Normalmap2
        sampler2D _NormalMap2;
        float4 _NormalMapMoveDir2;
        float _NormalMapMoveSpeed2;
        sampler2D _HeightMap2;
        //Normal set
        float _NormalScale;
        float _HeightScale;
        float _HeightMapFoamScale;

        //Wave set
        float _PointBumpScale;

        void vert(inout appdata_full v,out Input o){
            UNITY_INITIALIZE_OUTPUT(Input,o);
            //position
            float4 worldPos=mul(unity_ObjectToWorld,v.vertex);
            float4 worldPos1=GetWaveOffset(worldPos);
            o.crestFactor=worldPos1.w;
            //--------heightMap--------
            float height1=tex2Dlod(_HeightMap,float4(v.texcoord.xy+_NormalMapMoveDir.xy*_NormalMapMoveSpeed*_Time.x,0,0)).r;
            height1=(height1-1)*2;
            float height2=tex2Dlod(_HeightMap2,float4(v.texcoord.xy+_NormalMapMoveDir2.xy*_NormalMapMoveSpeed2*_Time.x,0,0)).r;
            height2=(height2-0.5)*2;
            worldPos1.y+= (height1+height2)*_HeightScale;

            worldPos1.y=lerp(0,worldPos1.y,_PointBumpScale);
            worldPos1.y+= 0.01;

            o.worldDirNormal=normalize(GetNormalNum(worldPos).xyz);
            
            //output to Object Data
            v.vertex=mul(unity_WorldToObject,float4(worldPos1.xyz,1.0));
            v.normal=normalize(GetNormalNum(worldPos)) ;
        }

        void surf(Input IN, inout SurfaceOutputStandard o) {
            float noFoam= saturate(dot(IN.worldDirNormal,normalize(_WaveFoamDir)));
            
            //--------NormalMap---------------
            float3 normal=UnpackScaleNormal(tex2D(_NormalMap,IN.uv_NormalMap+_NormalMapMoveDir.xy*_NormalMapMoveSpeed*_Time.x),_NormalScale);
            float3 normal2=UnpackScaleNormal(tex2D(_NormalMap2,IN.uv_NormalMap2+_NormalMapMoveDir.xy*_NormalMapMoveSpeed*_Time.x),_NormalScale);
            float3 totalNormal=normalize(float3(normal.xy+normal2.xy,normal.z*normal2.z));

            //--------Height map foam---------
            float heightMapAdd1=pow(tex2D(_HeightMap,IN.uv_NormalMap+_NormalMapMoveDir.xy*_NormalMapMoveSpeed*_Time.x).r,4);
            float heightMapAdd2=pow(tex2D(_HeightMap2,IN.uv_NormalMap2+_NormalMapMoveDir.xy*_NormalMapMoveSpeed*_Time.x).r,4);
            float totalHeightAdd=((heightMapAdd1+heightMapAdd2)/2)*_HeightScale*_HeightMapFoamScale;

            //---------Total water foam-------
            float3 foam= ((totalHeightAdd+IN.crestFactor)/2)*(1-noFoam);

            o.Albedo=_MainColor+foam;
            o.Alpha= saturate(_MainColor.w+foam.r);
            o.Normal=totalNormal;
            o.Metallic=_Metallic;
            o.Smoothness=saturate(_Smoothness-foam);
        }

        ENDCG
    }
}

#if !defined(WATER_INCLUDED)
    #define WATER_INCLUDED

#define PI 3.14

//--------------Wave Data-------------------------
    float _FoamSpread;

    #if ENABLE_BASEWAVE
    float _waveLength;
    float _amplitude;
    float _steepness;
    float _dirX;
    float _dirZ;
    float _speed;
    float _fadeSpeed;
    #endif

    #if ENABLE_WAVE1
    float _waveLength1;
    float _amplitude1;
    float _steepness1;
    float _dirX1;
    float _dirZ1;
    float _speed1;
    float _fadeSpeed1;
    #endif

    #if ENABLE_WAVE2
    float _waveLength2;
    float _amplitude2;
    float _steepness2;
    float _dirX2;
    float _dirZ2;
    float _speed2;
    float _fadeSpeed2;
    #endif

    #if ENABLE_WAVE3
    float _waveLength3;
    float _amplitude3;
    float _steepness3;
    float _dirX3;
    float _dirZ3;
    float _speed3;
    float _fadeSpeed3;
    #endif

    #if ENABLE_WAVE4
    float _waveLength4;
    float _amplitude4;
    float _steepness4;
    float _dirX4;
    float _dirZ4;
    float _speed4;
    float _fadeSpeed4;
    #endif

//---------------Genter Wave-------
    float4 WavePointOffset(float3 worldPos,float waveLength,float amplitude,float steepness,float dirX,float dirZ ,float speed ,float fadeSpeed){
        float3 offset;
        float frequency=2*PI/waveLength;
        float dirDotPos = dot(worldPos.xz,normalize(float2(dirX,dirZ)) );
        float phaseConstantSpeed=speed*frequency; 
        float fi= _Time.x*phaseConstantSpeed; //一帧的相位

        float fade = cos(fadeSpeed*_Time.x)/2+0.5;
        amplitude*=fade;

        offset.x = steepness*amplitude*dirX * cos(frequency*dirDotPos + fi);
        offset.y = amplitude*sin(frequency*dirDotPos+fi);
        offset.z = steepness*amplitude*dirZ * cos(frequency*dirDotPos + fi);

        //后面应用齐次除法
        float creatFactor=sin(frequency*dirDotPos+fi)*saturate(steepness)*fade;

        return float4(offset,creatFactor);
    }

    float3 WaveNormal(float3 worldPos,float amplitude,float steepness,float dirX,float dirZ,float waveLength,float speed ){
        float frequency =2*PI/waveLength;
        float phaseConstantSpeed=speed*2*PI/waveLength;
        
        float fi=_Time.x*phaseConstantSpeed;
        float dirDotPos=dot(normalize(float2(dirX,dirZ)),worldPos.xz);

        float WA=frequency*amplitude;
        float S=sin(frequency*dirDotPos+fi);
        float C=cos(frequency*dirDotPos+fi);

        float3 normal=float3(normalize(float2(dirX,dirZ)).x * WA * C,
                            min( 0.2f , steepness * WA * S),
                            normalize(float2(dirX,dirZ)).y * WA * C
        );
        
        return normal;
    }

    float4 GetWaveOffset(float4 worldPos){
        worldPos.w=0;
        float totSteepness=0.001;
        #if ENABLE_BASEWAVE
        worldPos+=WavePointOffset(worldPos,_waveLength,_amplitude,_steepness,_dirX,_dirZ,_speed,_fadeSpeed);
        totSteepness+=_FoamSpread;
        #endif
        #if ENABLE_WAVE1
        worldPos+=WavePointOffset(worldPos,_waveLength1,_amplitude1,_steepness1,_dirX1,_dirZ1,_speed1,_fadeSpeed1);
        totSteepness+=_FoamSpread;
        #endif
        #if ENABLE_WAVE2
        worldPos+=WavePointOffset(worldPos,_waveLength2,_amplitude2,_steepness2,_dirX2,_dirZ2,_speed2,_fadeSpeed2);
        totSteepness+=_FoamSpread;
        #endif
        #if ENABLE_WAVE3
        worldPos+=WavePointOffset(worldPos,_waveLength3,_amplitude3,_steepness3,_dirX3,_dirZ3,_speed3,_fadeSpeed3);
        totSteepness+=_FoamSpread;
        #endif
        #if ENABLE_WAVE4
        worldPos+=WavePointOffset(worldPos,_waveLength4,_amplitude4,_steepness4,_dirX4,_dirZ4,_speed4,_fadeSpeed4);
        totSteepness+=_FoamSpread;
        #endif
        worldPos.w/=totSteepness;   
        return worldPos;
    }

    float3 GetNormalNum(float4 worldPos){
        //normal
        float3 normal=float3(0,0,0);
        #if ENABLE_BASEWAVE
        normal=WaveNormal(worldPos.xyz,_amplitude,_steepness,_dirX,_dirZ,_waveLength,_speed);
        #endif
        #if ENABLE_WAVE1
        normal+=WaveNormal(worldPos.xyz,_amplitude1,_steepness1,_dirX1,_dirZ1,_waveLength1,_speed1);
        #endif
        #if ENABLE_wAVE2
        normal+=WaveNormal(worldPos.xyz,_amplitude2,_steepness2,_dirX2,_dirZ2,_waveLength2,_speed2);
        #endif
        #if ENABLE_WAVE3
        normal+=WaveNormal(worldPos.xyz,_amplitude3,_steepness3,_dirX3,_dirZ3,_waveLength3,_speed3);
        #endif
        #if ENABLE_WAVE4
        normal+=WaveNormal(worldPos.xyz,_amplitude4,_steepness4,_dirX4,_dirZ4,_waveLength4,_speed4);
        #endif

        return float3(-normal.x,1-normal.y,-normal.z);
    }




#endif
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#region Editor

#if UNITY_EDITOR
using UnityEditor;

[CustomEditor(typeof(Builder))]
public class BuilderEditor:Editor
{
    public override void OnInspectorGUI()
    {
        Builder builder=(Builder)target;

        EditorGUI.BeginChangeCheck();

        //显示public 数据
        base.OnInspectorGUI();

        //当变动的时候更新
        if(EditorGUI.EndChangeCheck()){
            builder.UpdateMesh();
            Debug.Log("Updata Mesh!");
        }
    }
}

#endif

#endregion

[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
public class Builder : MonoBehaviour
{
    [SerializeField]
    private MeshFilter _meshFilter;
    [SerializeField]
    public MeshRenderer _meshRenderer;

    [SerializeField]
    private Vector2 _cellSize=new Vector2(1,1);

    [SerializeField]
    private Vector2Int _gridSize =new Vector2Int(2,2);

    public MeshRenderer MeshRenderer{
        get{
            return _meshRenderer;
        }
    }

    public MeshFilter MeshFilter{
        get{
            return _meshFilter;
        }
    }

    private void Awake() {
        _meshFilter=GetComponent<MeshFilter>();
        _meshRenderer=GetComponent<MeshRenderer>();
        UpdateMesh();
        //更新模型
    }

    public void UpdateMesh(){
        //target
        Mesh mesh =new Mesh();
        //data
        Vector2 size= new Vector2(0,0);
        size.x=_cellSize.x*_gridSize.x;
        size.y=_cellSize.y*_gridSize.y;

        Vector2 halfSize= size/2.0f;

        //obj
        List<Vector3> vertices=new List<Vector3>();
        List<Vector2> uvs=new List<Vector2>();
        //data
        Vector3 vertice=Vector3.zero;
        Vector2 uv=Vector2.zero;

        for(int iy=0;iy<_gridSize.y+1;iy++){
            vertice.z= iy*_cellSize.y -halfSize.y;
            uv.y= iy*_cellSize.y/size.y;

            for(int ix=0;ix<_gridSize.x+1;ix++){
                vertice.x=ix*_cellSize.x-halfSize.x;
                uv.x=ix*_cellSize.x/size.x;

                vertices.Add(vertice);
                uvs.Add(uv);
            }
        }

        int a=0;
        int b=0;
        int c=0;
        int d=0;

        //target
        int[] indexs=new int[_gridSize.x*_gridSize.y*2*3];
        int startIndex=0;
        for(int iy=0;iy<_gridSize.y;iy++){
            for(int ix=0;ix<_gridSize.x;ix++){
                a = iy*(_gridSize.x+1)+ix;
                b = (iy+1)*(_gridSize.x+1)+ix;
                c = b+1;
                d = a+1;

                startIndex = iy*(_gridSize.x*2*3) + ix*2*3;

                indexs[startIndex]=a;
                indexs[startIndex+1]=b;
                indexs[startIndex+2]=c;

                indexs[startIndex+3]=a;
                indexs[startIndex+4]=c;
                indexs[startIndex+5]=d;
            }
        }

        mesh.SetVertices(vertices);
        mesh.SetUVs(0,uvs);
        mesh.SetIndices(indexs,MeshTopology.Triangles,0);
        mesh.RecalculateBounds();
        mesh.RecalculateNormals();
        mesh.RecalculateTangents();

        _meshFilter.mesh=mesh;

    }

    #if UNITY_EDITOR

        private void OnValidate()
        {
            if (null == _meshFilter)
            {
                _meshFilter = GetComponent<MeshFilter>();
            }
            if (null == _meshRenderer)
            {
                _meshRenderer = GetComponent<MeshRenderer>();
                if (null == _meshRenderer.sharedMaterial)
                {
                    _meshRenderer.sharedMaterial = new Material(Shader.Find("Standard"));
                }
            }
        }

    #endif


}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 你不知道 这里夜 除了夜雨和风 还有我在想你
    闻人嘉树阅读 121评论 0 1
  • 就是如此自然 如此巧妙 如此神奇 原来我一直在等与寻觅 当它抵达不过是风和日丽而已 这样的天气很多 没什么特别的 ...
    下山饮茶阅读 122评论 1 0
  • 关于文艺! 文化艺术的最高抑或最好,不出在演艺界,他们代表不了,代表不了,又怎么可能需要有一追,一浪费工夫的必要?...
    纵情嬉戏天地间阅读 205评论 0 0
  • 我是熊熊燃烧在纸上的火 你是静静流淌在纸上的河 灼烧着我的疼痛 你却在无意中散落 如烟雾被夜色淹没 淹没那首朦胧的...
    泰安左眼皮跳跳阅读 333评论 3 8