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
}