Shader "Ocean/OceanShader"
{
Properties
{
[IntRange]_WaveCount("海浪数量",Range(1,6))=0
_LightDir("光照方向",vector)=(1,1,1,1)
_AvgSwell("海浪平局高度",Range(0,10))=0.5
_AvgWaveLength("海浪的波长",Range(0,10))=2.9
_WindDirection("海浪方向",Range(-180,180))=-177
_WindSpeed("WindSpeed",float)=0.1
_Metallic("金属度", Range(0,1)) = 1
_Roughness("粗糙度", Range(0,1)) = 1
[HDR]_Color("Color",Color)=(1,1,1,1)
_SurfaceMap("海浪法线",2D)="bump"{}
_BumpScale("海浪法线强度",Range(0,2))=0.25
_FoamMap("FomMap",2D)="bump"{}
_MaxWaveHeight("海浪显示的高度范围",Range(0.1,1))=1
_AdjustFoam("海浪范围",Range(0,3))=0.5
[Toggle(_OPENADJUST_ON)]_OpenACES("矫正",int)=0
_PostColor("PostcAdjust",float)=1
[Toggle(_CUSTOMREFLECT_ON)]_CustomReflectON("自定义环境球",int)=0
_ReflectCube("环境球",Cube)="gray"{}
}
SubShader
{
Tags { "Queue"="Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline" }
LOD 100
Pass
{
Name "Unlit"
Tags{"LightMode" = "UniversalForward"}
Blend SrcAlpha OneMinusSrcAlpha
Cull Back
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#define kDirSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04)
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#pragma shader_feature_local _CUSTOMREFLECT_ON
#pragma shader_feature_local _OPENADJUST_ON
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 texcoord : TEXCOORD0;
float3 normalWS : TEXCOORD1;
float4 texcoord1 : TEXCOORD2;
float3 posWS : TEXCOORD3;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct WaveStruct
{
float3 position;
float3 normal;
};
struct Wave
{
half amplitude;
half direction;
half wavelength;
half2 origin;
half omni;
int _WaveCount;
};
CBUFFER_START(UnityPerMaterial)
half _WaveCount;
half _WindDirection;
half _AvgSwell;
half _AvgWaveLength;
half _WindSpeed;
half4 _Color;
half _BumpScale;
half _Metallic;
float _Roughness;
float _PostColor;
float _MaxWaveHeight;
half _AdjustFoam;
half4 _ReflectCube_HDR;
half3 _LightDir;
static half3 randomSeedList[6]=
{
half3(0.5589265,88.53946f,0.6121008f),
half3(0.668604f,-87.46983f,0.8987388f),
half3(0.6767546f,-71.35088f,0.6283937f),
half3(1.05889f,42.03598f,1.174131f),
half3(1.012532f,-47.16227f,1.543352f),
half3(1.54227f,-3.399506f,1.147515f)
};
Wave _Wave[6];
CBUFFER_END
TEXTURE2D(_SurfaceMap);SAMPLER(sampler_SurfaceMap);
TEXTURE2D(_FoamMap);SAMPLER(sampler_FoamMap);
TEXTURECUBE(_ReflectCube); SAMPLER(sampler_ReflectCube);
float2 random(float2 st){
st = float2( dot(st,float2(127.1,311.7)), dot(st,float2(269.5,183.3)) );
return -1.0 + 2.0 * frac(sin(st) * 43758.5453123);
}
float Random(float n,float factor = 10000){
return frac(sin(n)*factor)*frac(cos(n)*factor);
}
float noise (float2 st) {
float2 i = floor(st);
float2 f = frac(st);
float2 u = f*f*(3.0-2.0*f);
return lerp( lerp( dot( random(i), f),
dot( random(i + float2(1.0,0.0) ), f - float2(1.0,0.0) ), u.x),
lerp( dot( random(i + float2(0.0,1.0) ), f - float2(0.0,1.0) ),
dot( random(i + float2(1.0,1.0) ), f - float2(1.0,1.0) ), u.x), u.y);
}
float3 ACESFilm(float3 LinearColor, float a, float b, float c, float d, float e)
{
const float ExposureMultiplier = _PostColor; // 曝光值
const float3x3 PRE_TONEMAPPING_TRANSFORM = // 色调映射矩阵
{
0.575961650, 0.344143820, 0.079952030,
0.070806820, 0.827392350, 0.101774690,
0.028035252, 0.131523770, 0.840242300
};
const float3x3 EXPOSED_PRE_TONEMAPPING_TRANSFORM = ExposureMultiplier * PRE_TONEMAPPING_TRANSFORM; // key 场景颜色乘 曝光度 整个场景的色调。
const float3x3 POST_TONEMAPPING_TRANSFORM =
{
1.666954300, -0.601741150, -0.065202855,
-0.106835220, 1.237778600, -0.130948950,
-0.004142626, -0.087411870, 1.091555000
};
float3 Color = mul(EXPOSED_PRE_TONEMAPPING_TRANSFORM, LinearColor); // 线性颜色转换
Color = saturate((Color * (a * Color + b)) / (Color * (c * Color + d) + e)); // 应用到ACES 颜色校正
return clamp(mul(POST_TONEMAPPING_TRANSFORM, Color), 0.0f, 1.0f); // 后置处理(颜色重构)
}
half GeMask(WaveStruct wave)
{
half mask = wave.position.y / _MaxWaveHeight * 0.5 + 0.5; // encode the normalized wave height into additional data
return mask;
}
WaveStruct GerstnerWave(half2 pos, float waveCountMulti, half amplitude, half direction, half wavelength, half omni, half2 omniPos)
{
WaveStruct waveOut;
float time = _Time.y*_WindSpeed;
wave value calculations//
half3 wave = 0; // wave vector
half w = 6.28318 / wavelength;
half wSpeed = sqrt(9.8 * w);
half peak = 1.5;
half qi = peak / (amplitude * w * _WaveCount);
direction = radians(direction);
half2 dirWaveInput = half2(sin(direction), cos(direction)) * (1 - omni);
half2 omniWaveInput = (pos - omniPos) * omni;
half2 windDir = normalize(dirWaveInput + omniWaveInput);
half dir = dot(windDir, pos - (omniPos * omni));
half calc = dir * w + -time * wSpeed;
half cosCalc = cos(calc);
half sinCalc = sin(calc);
wave.xz = qi * amplitude * windDir.xy * cosCalc;
wave.y = ((sinCalc * amplitude)) * waveCountMulti;
half wa = w * amplitude;
// normal vector
half3 n = half3(-(windDir.xy * wa * cosCalc),
1-(qi * wa * sinCalc));
waveOut.position = wave * saturate(amplitude * 10000);
waveOut.normal = (n.xzy * waveCountMulti);
return waveOut;
}
inline void SampleWaves(float3 position, half opacity, Wave Custom_w[6] ,inout WaveStruct waveOut)
{
half2 pos = position.xz;
waveOut.position = 0;
waveOut.normal = 0;
half waveCountMulti = 1.0 / _WaveCount;
half3 opacityMask = saturate(half3(3, 3, 1) * opacity);
UNITY_LOOP
for(int i = 0; i < _WaveCount; i++)
{
WaveStruct wave = GerstnerWave(pos,
waveCountMulti,
Custom_w[i].amplitude,
Custom_w[i].direction,
Custom_w[i].wavelength,
0,
half2(0,0)); // calculate the wave
waveOut.position += wave.position; // add the position
waveOut.normal += wave.normal; // add the normal
}
waveOut.position *= opacityMask;
waveOut.normal *= half3(opacity, 1, opacity);
}
Varyings vert(Attributes v)
{
Varyings o = (Varyings)0;
half time =_Time.y*_WindSpeed;
half3 normalWS=half3(0,1,0);
o.posWS =TransformObjectToWorld(v.positionOS.xyz);
o.texcoord1.x =((noise((o.posWS.xz * 0.5) + time) + noise((o.posWS.xz * 1) + time)) * 0.25 - 0.5) + 1;
o.texcoord.xy =o.posWS.xz * 0.1h + time * 0.05h + (o.texcoord1.x * 0.1);
_Wave[0] =(Wave)0;
_Wave[1] =(Wave)0;
_Wave[2] =(Wave)0;
_Wave[3] =(Wave)0;
_Wave[4] =(Wave)0;
_Wave[5] =(Wave)0;
for(int j = 0; j < _WaveCount; j++)
{
_Wave[j].amplitude =_AvgSwell*randomSeedList[j].x;
_Wave[j].direction =_WindDirection+randomSeedList[j].y;
_Wave[j].wavelength=_AvgWaveLength*randomSeedList[j].z;
}
WaveStruct wave;
SampleWaves( o.posWS ,1, _Wave,wave);
o.normalWS = wave.normal.xyz;
o.posWS += wave.position;
o.texcoord1.y= GeMask(wave);
o.positionCS = TransformWorldToHClip( o.posWS);
return o;
}
half4 frag(Varyings i) : SV_Target
{
half3 BaseColor=_Color.xyz;
half2 detailBump1 = SAMPLE_TEXTURE2D(_SurfaceMap, sampler_SurfaceMap, i.texcoord.xy).xy * 2 - 1;
half3 foamMap = SAMPLE_TEXTURE2D(_FoamMap, sampler_FoamMap, i.texcoord.xy).rgb;
half distance_foam= saturate(length(foamMap * i.texcoord1.yyy) * 1.5 - _AdjustFoam);
i.normalWS += half3(detailBump1.x, 0, detailBump1.y) * _BumpScale;
i.normalWS = normalize(i.normalWS);
half3 normalWS= i.normalWS;
Light mainLight = GetMainLight();
foamMap=mainLight.color;
float3 viewDir=GetWorldSpaceNormalizeViewDir(i.posWS);
half3 brdfDiffuse =BaseColor.xyz*(kDirSpec.a*(1-_Metallic));
half3 brdfSpec=lerp(kDirSpec.xyz,BaseColor.xyz,_Metallic);
half3 lightDir=normalize(_LightDir);
//NOL
half nl =saturate(dot(normalWS, lightDir));
float3 halfDir = normalize(viewDir + lightDir);
half nh = saturate(dot(normalWS, halfDir));
float nv = saturate(dot(normalWS, viewDir));
float vh = saturate(dot(viewDir, lightDir));
float hl = saturate(dot(halfDir, lightDir));
half3 radiance=mainLight.color*nl;
half3 brdf =brdfDiffuse.xyz;
half roughness2=max(_Roughness*_Roughness,HALF_MIN);
half d=nh*nh*(roughness2-1)+1.0001f;
half d2=d*d;
half LdotH2=hl*hl;
half specTerm=roughness2/(d2*max(half(0.1),LdotH2)*(_Roughness*4+2));
brdf =brdf*radiance;
half3 EnivormentSpecColor=half3(0,0,0);
half3 reflectVector=reflect(-viewDir, normalWS);
half NoV=saturate(dot(normalWS, viewDir));
half fresnelTerm = (1.0 - NoV)*(1.0 - NoV)*(1.0 - NoV)*(1.0 - NoV);
half mip = _Roughness*(1.7-0.7*_Roughness)*6;
half4 encodedIrradiance;
#if !defined(_CUSTOMREFLECT_ON)
encodedIrradiance= half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip));
#if defined(UNITY_USE_NATIVE_HDR)
EnivormentSpecColor =encodedIrradiance.rgb;
#else
EnivormentSpecColor =DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
#endif
#else
encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(_ReflectCube, sampler_ReflectCube, reflectVector, mip));
#if defined(UNITY_USE_NATIVE_HDR)
EnivormentSpecColor =encodedIrradiance.rgb;
#else
EnivormentSpecColor =DecodeHDREnvironment(encodedIrradiance, _ReflectCube_HDR);
#endif
#endif
half surfaceReduction=1/(_Roughness*_Roughness+1);
half grazingTerm=max(max(brdfSpec.r, brdfSpec.g), brdfSpec.b);
half3 environment_Spec=surfaceReduction*lerp(brdfSpec,grazingTerm,fresnelTerm);
half3 GIColor=half3(0,0,0);
#if !defined(_CUSTOMREFLECT_ON)
encodedIrradiance= half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip));
#if defined(UNITY_USE_NATIVE_HDR)
GIColor =encodedIrradiance.rgb;
#else
GIColor =DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
#endif
#else
encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(_ReflectCube, sampler_ReflectCube, reflectVector, mip));
#if defined(UNITY_USE_NATIVE_HDR)
GIColor =encodedIrradiance.rgb;
#else
GIColor =DecodeHDREnvironment(encodedIrradiance, _ReflectCube_HDR);
#endif
#endif
foamMap+=GIColor;
half3 diffuse_color=GIColor*brdfDiffuse;
diffuse_color+=EnivormentSpecColor*environment_Spec;
diffuse_color=diffuse_color+brdf.xyz;
diffuse_color=lerp(diffuse_color,foamMap,distance_foam);
#if defined(_OPENADJUST_ON)
diffuse_color= ACESFilm(diffuse_color,2.51,0.03,2.43,0.59,0.14)+specTerm*brdfSpec*radiance;
#else
diffuse_color+=specTerm*brdfSpec*radiance;
#endif
return half4(diffuse_color .xyz,1);
}
ENDHLSL
}
}
}
03-06
1310
