update water for android build

This commit is contained in:
Le Duc Anh
2026-01-13 09:45:32 +07:00
parent a8a0e03498
commit 6dd0fd10cd
7 changed files with 309 additions and 217 deletions
@@ -1,250 +1,217 @@
Shader "Custom/ClearWaterShaderV3"
Shader "Custom/WaterWithShore_Unity6"
{
Properties
{
[Header(Water Colors)]
_ShallowColor ("Shallow Water Color", Color) = (0.325, 0.807, 0.971, 0.8)
_DeepColor ("Deep Water Color", Color) = (0.086, 0.407, 1, 0.95)
_DepthMaxDistance ("Depth Max Distance", Float) = 1
[Header(Shore Visibility)]
_ShoreDistance ("Shore Visibility Distance", Range(0, 5)) = 1.0
_ShoreFade ("Shore Fade Smoothness", Range(0.01, 2)) = 0.5
[Header(Foam)]
_FoamColor ("Foam Color", Color) = (1, 1, 1, 1)
_FoamDistance ("Foam Distance", Range(0, 2)) = 0.4
_FoamIntensity ("Foam Intensity", Range(0, 2)) = 1
_EdgeFoamWidth ("Edge Foam Width", Range(0.001, 0.5)) = 0.1
_VertexColorFoamWidth ("Vertex Color Foam Width", Range(0, 1)) = 0.3
_ShallowColor ("Shallow Color", Color) = (0.2, 0.6, 0.7, 0.8)
_DeepColor ("Deep Color", Color) = (0.0, 0.15, 0.25, 0.9)
_DepthMax ("Depth Max", Range(0.1, 10)) = 3
_WaveNormal ("Wave Normal", 2D) = "bump" {}
_NormalStrength ("Normal Strength", Range(0,2)) = 1
_WaveSpeed1 ("Wave Speed 1", Vector) = (0.05, 0.03, 0, 0)
_WaveSpeed2 ("Wave Speed 2", Vector) = (-0.03, 0.04, 0, 0)
_FoamNoise ("Foam Noise", 2D) = "white" {}
_FoamColor ("Foam Color", Color) = (1,1,1,1)
_FoamIntensity ("Foam Intensity", Range(0,2)) = 1
_FoamDepth ("Foam Depth", Range(0.01, 5)) = 0.6
_FoamNoiseScale ("Foam Noise Scale", Range(0.1, 5)) = 1
_FoamSpeed ("Foam Speed", Vector) = (0.1, 0.1, 0, 0)
_Smoothness ("Smoothness", Range(0,1)) = 0.85
[Header(Wave Animation)]
_WaveHeight ("Wave Height", Range(0, 0.5)) = 0.05
_WaveFrequency ("Wave Frequency", Range(0, 10)) = 2
_WaveSpeed ("Wave Speed", Range(0, 5)) = 1
_WaveDirection ("Wave Direction", Vector) = (1, 0, 0, 0)
[Header(Textures)]
_SurfaceNoise ("Surface Noise", 2D) = "white" {}
_SurfaceNoiseCutoff ("Surface Noise Cutoff", Range(0, 1)) = 0.6
_SurfaceNoiseScale ("Surface Noise Scale", Float) = 1
_NormalMap ("Normal Map", 2D) = "bump" {}
_NormalStrength ("Normal Strength", Range(0, 2)) = 0.5
_NormalScale ("Normal Scale", Float) = 1
[Header(Reflection)]
_Smoothness ("Smoothness", Range(0, 1)) = 0.9
_FresnelPower ("Fresnel Power", Range(0, 10)) = 5
_ReflectionStrength ("Reflection Strength", Range(0, 1)) = 0.3
[Header(Movement)]
_TextureSpeed ("Texture Speed", Float) = 0.1
_WaveHeight ("Wave Height", Range(0, 1)) = 0.1
_WaveFrequency ("Wave Frequency", Range(0, 20)) = 5
_WaveSpeed ("Wave Speed", Range(0, 10)) = 2
_WaveDirection ("Wave Direction", Vector) = (1, 1, 0, 0)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"RenderPipeline" = "UniversalRenderPipeline"
"RenderPipeline"="UniversalPipeline"
"Queue"="Transparent"
"RenderType"="Transparent"
}
Pass
{
Name "ForwardLit"
Tags { "LightMode"="UniversalForward" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#pragma prefer_hlslcc gles
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
TEXTURE2D(_WaveNormal);
SAMPLER(sampler_WaveNormal);
TEXTURE2D(_FoamNoise);
SAMPLER(sampler_FoamNoise);
TEXTURE2D_X_FLOAT(_CameraDepthTexture);
SAMPLER(sampler_CameraDepthTexture);
CBUFFER_START(UnityPerMaterial)
float4 _ShallowColor;
float4 _DeepColor;
float _DepthMax;
float4 _WaveSpeed1;
float4 _WaveSpeed2;
float _NormalStrength;
float4 _FoamColor;
float _FoamIntensity;
float _FoamDepth;
float _FoamNoiseScale;
float4 _FoamSpeed;
float _Smoothness;
float _WaveHeight;
float _WaveFrequency;
float _WaveSpeed;
float4 _WaveDirection;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float4 screenPos : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 tangentWS : TEXCOORD3;
float3 bitangentWS : TEXCOORD4;
float3 viewDirWS : TEXCOORD5;
float3 positionWS : TEXCOORD6;
float waveValue : TEXCOORD7;
float4 vertexColor : COLOR;
float3 positionWS : TEXCOORD2;
float3 normalWS : TEXCOORD3;
};
sampler2D _SurfaceNoise;
sampler2D _NormalMap;
CBUFFER_START(UnityPerMaterial)
float _SurfaceNoiseCutoff;
float _SurfaceNoiseScale;
float _FoamDistance;
float _FoamIntensity;
float _EdgeFoamWidth;
float _VertexColorFoamWidth;
float _DepthMaxDistance;
float _NormalStrength;
float _NormalScale;
float _Smoothness;
float _FresnelPower;
float _ReflectionStrength;
float _TextureSpeed;
float _ShoreDistance;
float _ShoreFade;
float _WaveHeight;
float _WaveFrequency;
float _WaveSpeed;
float4 _WaveDirection;
float4 _ShallowColor;
float4 _DeepColor;
float4 _FoamColor;
CBUFFER_END
float3 TriplanarSample(sampler2D tex, float3 worldPos, float3 worldNormal, float scale, float2 offset)
Varyings vert (Attributes v)
{
float3 blendWeights = abs(worldNormal);
blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z);
Varyings o;
float3 xSample = tex2D(tex, worldPos.zy * scale + offset).rgb;
float3 ySample = tex2D(tex, worldPos.xz * scale + offset).rgb;
float3 zSample = tex2D(tex, worldPos.xy * scale + offset).rgb;
return xSample * blendWeights.x + ySample * blendWeights.y + zSample * blendWeights.z;
}
float3 TriplanarNormal(sampler2D tex, float3 worldPos, float3 worldNormal, float scale, float2 offset)
{
float3 blendWeights = abs(worldNormal);
blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z);
float3 xNormal = UnpackNormal(tex2D(tex, worldPos.zy * scale + offset));
float3 yNormal = UnpackNormal(tex2D(tex, worldPos.xz * scale + offset));
float3 zNormal = UnpackNormal(tex2D(tex, worldPos.xy * scale + offset));
return xNormal * blendWeights.x + yNormal * blendWeights.y + zNormal * blendWeights.z;
}
Varyings vert(Attributes input)
{
Varyings output;
VertexPositionInputs positionInputs = GetVertexPositionInputs(input.positionOS.xyz);
VertexNormalInputs normalInputs = GetVertexNormalInputs(input.normalOS, input.tangentOS);
float3 worldPos = positionInputs.positionWS;
// Transform to world space first
float3 worldPos = TransformObjectToWorld(v.positionOS.xyz);
// === WAVE ANIMATION ===
float2 waveDir = normalize(_WaveDirection.xy);
float waveDist = dot(worldPos.xz, waveDir);
float wavePhase = waveDist * _WaveFrequency - _Time.y * _WaveSpeed;
float wave = sin(wavePhase);
worldPos.y += wave * _WaveHeight;
// Primary wave (moving wave)
float wave1 = sin(
dot(worldPos.xz, waveDir) * _WaveFrequency -
_Time.y * _WaveSpeed
) * _WaveHeight;
output.positionCS = TransformWorldToHClip(worldPos);
output.positionWS = worldPos;
output.screenPos = ComputeScreenPos(output.positionCS);
output.uv = input.uv;
output.normalWS = normalInputs.normalWS;
output.tangentWS = normalInputs.tangentWS;
output.bitangentWS = normalInputs.bitangentWS;
output.viewDirWS = GetWorldSpaceViewDir(worldPos);
output.waveValue = wave * 0.5 + 0.5;
output.vertexColor = input.color;
// Secondary wave (perpendicular, different frequency)
float2 waveDir2 = float2(-waveDir.y, waveDir.x); // Perpendicular
float wave2 = sin(
dot(worldPos.xz, waveDir2) * _WaveFrequency * 0.7 -
_Time.y * _WaveSpeed * 0.8
) * _WaveHeight * 0.5;
return output;
// Combine waves
worldPos.y += wave1 + wave2;
o.positionWS = worldPos;
o.positionCS = TransformWorldToHClip(worldPos);
o.screenPos = ComputeScreenPos(o.positionCS);
o.uv = v.uv;
o.normalWS = TransformObjectToWorldNormal(float3(0,1,0));
return o;
}
float4 frag(Varyings input) : SV_Target
half4 frag (Varyings input) : SV_Target
{
float3 worldNormal = normalize(input.normalWS);
float2 timeOffset1 = _Time.y * _TextureSpeed * float2(1, 0.5);
float2 timeOffset2 = _Time.y * _TextureSpeed * float2(-0.7, -0.3);
float3 normalMap1 = TriplanarNormal(_NormalMap, input.positionWS, worldNormal, _NormalScale, timeOffset1);
float3 normalMap2 = TriplanarNormal(_NormalMap, input.positionWS, worldNormal, _NormalScale * 1.3, timeOffset2);
float3 normalTS = normalize(normalMap1 + normalMap2);
// === NORMAL WAVES ===
float2 uv1 = input.uv + _Time.y * _WaveSpeed1.xy;
float2 uv2 = input.uv + _Time.y * _WaveSpeed2.xy;
float3 n1 = UnpackNormal(SAMPLE_TEXTURE2D(_WaveNormal, sampler_WaveNormal, uv1));
float3 n2 = UnpackNormal(SAMPLE_TEXTURE2D(_WaveNormal, sampler_WaveNormal, uv2));
float3 normalTS = n1 + n2;
normalTS.xy *= _NormalStrength;
float3x3 tangentToWorld = float3x3(input.tangentWS, input.bitangentWS, input.normalWS);
float3 normalWS = normalize(mul(normalTS, tangentToWorld));
normalTS = normalize(normalTS);
float3 normalWS = normalize(TransformTangentToWorld(
normalTS,
half3x3(
float3(1,0,0),
float3(0,0,1),
input.normalWS
)
));
// === DEPTH ===
float2 screenUV = input.screenPos.xy / input.screenPos.w;
float existingDepth01 = SampleSceneDepth(screenUV);
float existingDepthLinear = LinearEyeDepth(existingDepth01, _ZBufferParams);
float surfaceDepthLinear = LinearEyeDepth(input.positionCS.z, _ZBufferParams);
float depthDifference = existingDepthLinear - surfaceDepthLinear;
float waterDepthDifference01 = saturate(depthDifference / _DepthMaxDistance);
float3 waterColor = lerp(_ShallowColor.rgb, _DeepColor.rgb, waterDepthDifference01);
float shoreVisibility = saturate(depthDifference / _ShoreDistance);
shoreVisibility = smoothstep(0, _ShoreFade, shoreVisibility);
// VERTEX COLOR EDGE DETECTION
float vertexEdge = input.vertexColor.r;
float vertexEdgeFoam = smoothstep(_VertexColorFoamWidth, 0, vertexEdge);
// Depth-based edge detection (for objects like cylinder)
float depthEdge = saturate(depthDifference / _EdgeFoamWidth);
depthEdge = 1.0 - depthEdge;
depthEdge = pow(depthEdge, 2);
// Combine both methods
float edgeDetection = max(vertexEdgeFoam, depthEdge);
float wave = pow(input.waveValue, 2);
float foamArea = 1.0 - saturate(depthDifference / _FoamDistance);
float waveContribution = wave * max(foamArea, vertexEdgeFoam);
float foamNoise1 = TriplanarSample(_SurfaceNoise, input.positionWS, worldNormal, _SurfaceNoiseScale, timeOffset1).r;
float foamNoise2 = TriplanarSample(_SurfaceNoise, input.positionWS, worldNormal, _SurfaceNoiseScale * 1.5, timeOffset2).r;
float combinedNoise = foamNoise1 * foamNoise2;
float foamMask = smoothstep(_SurfaceNoiseCutoff - 0.1, _SurfaceNoiseCutoff + 0.1, combinedNoise);
float edgeFoam = edgeDetection * foamMask;
float waveFoam = waveContribution * foamMask;
float totalFoam = max(edgeFoam, waveFoam * 0.7) * _FoamIntensity;
totalFoam = saturate(totalFoam);
float3 viewDir = normalize(input.viewDirWS);
float fresnel = pow(1.0 - saturate(dot(normalWS, viewDir)), _FresnelPower);
float rawDepth = SAMPLE_TEXTURE2D_X(
_CameraDepthTexture,
sampler_CameraDepthTexture,
screenUV
).r;
float sceneDepth = LinearEyeDepth(rawDepth, _ZBufferParams);
float waterDepth = LinearEyeDepth(
input.screenPos.z / input.screenPos.w,
_ZBufferParams
);
float depthDiff = sceneDepth - waterDepth;
// === DEPTH COLOR BLEND ===
float depth01 = saturate(depthDiff / _DepthMax);
float3 waterColor = lerp(
_ShallowColor.rgb,
_DeepColor.rgb,
depth01
);
// === SHORE FOAM ===
float shoreMask = saturate(1.0 - depthDiff / _FoamDepth);
float2 foamUV =
input.positionWS.xz * _FoamNoiseScale +
_Time.y * _FoamSpeed.xy;
float foamNoise = SAMPLE_TEXTURE2D(
_FoamNoise,
sampler_FoamNoise,
foamUV
).r;
float foam = shoreMask * foamNoise * _FoamIntensity;
// === LIGHTING ===
Light mainLight = GetMainLight();
float3 halfVector = normalize(mainLight.direction + viewDir);
float specular = pow(saturate(dot(normalWS, halfVector)), _Smoothness * 128.0);
float3 reflection = fresnel * _ReflectionStrength;
float3 finalColor = waterColor;
finalColor += specular * mainLight.color * 0.5;
finalColor = lerp(finalColor, float3(0.7, 0.85, 1), reflection);
finalColor = lerp(finalColor, _FoamColor.rgb, totalFoam * 0.9);
float baseAlpha = lerp(_ShallowColor.a, _DeepColor.a, waterDepthDifference01);
float shoreAlpha = lerp(0.8, baseAlpha, shoreVisibility);
float finalAlpha = saturate(shoreAlpha + totalFoam * 0.5);
return float4(finalColor, finalAlpha);
float NdotL = saturate(dot(normalWS, mainLight.direction));
float3 finalColor =
waterColor * NdotL +
foam * _FoamColor.rgb;
float alpha = lerp(
_ShallowColor.a,
_DeepColor.a,
depth01
);
return float4(finalColor, alpha);
}
ENDHLSL
}
@@ -14,16 +14,42 @@ Material:
m_ValidKeywords: []
m_InvalidKeywords:
- _DEBUGDEPTH_ON
- _USEUVSHORE_ON
- _WAVE_SINE_ON
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
m_CustomRenderQueue: 3000
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _EdgeMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FoamNoise:
m_Texture: {fileID: 2800000, guid: b6f4fa4253519934f96d918d7c34bc8d, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FoamNoiseA:
m_Texture: {fileID: 2800000, guid: 064ebb4006db3934697a80619febcb44, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FoamNoiseB:
m_Texture: {fileID: 2800000, guid: 89c13dff71f555349bbeed61fd7f0402, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FoamTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NormalMap:
m_Texture: {fileID: 2800000, guid: 93c0aa606876cb04384552a948f281df, type: 3}
m_Scale: {x: 1, y: 1}
@@ -33,18 +59,49 @@ Material:
m_Scale: {x: 10, y: 10}
m_Offset: {x: 0, y: 0}
- _SurfaceNoise:
m_Texture: {fileID: 2800000, guid: b6f4fa4253519934f96d918d7c34bc8d, type: 3}
m_Texture: {fileID: 2800000, guid: 064ebb4006db3934697a80619febcb44, type: 3}
m_Scale: {x: 13.3, y: 10}
m_Offset: {x: 0, y: 0}
- _SurfaceNoise2:
m_Texture: {fileID: 2800000, guid: 89c13dff71f555349bbeed61fd7f0402, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _WaveNormal:
m_Texture: {fileID: 2800000, guid: 93c0aa606876cb04384552a948f281df, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _DebugFoam: 0
- _DebugUV2: 0
- _DeepAlpha: 0.9
- _DepthMaxDistance: 0.5
- _EdgeFoamWidth: 0.5
- _DepthMax: 3.06
- _DepthMaxDistance: 0.9
- _EdgeDebug: 0
- _EdgeFalloff: 2
- _EdgeFoamPower: 1.84
- _EdgeFoamWidth: 0.251
- _EdgeStrength: 0.485
- _EdgeThreshold: 0.1
- _EdgeWidth: 0.2
- _FoamCutoff: 0.397
- _FoamDepth: 0.92
- _FoamDistance: 1
- _FoamIntensity: 1
- _FoamFalloff: 2.94
- _FoamIntensity: 1.007
- _FoamMaxDistance: 1.2
- _FoamMinDistance: 0.1
- _FoamNoiseCutoff: 0.5
- _FoamNoiseScale: 3.13
- _FoamNoiseScaleA: 0.49
- _FoamNoiseScaleB: 1
- _FoamNoiseSpeed: 0.1
- _FoamNoiseSpeedA: 0.1
- _FoamNoiseSpeedB: -0.07
- _FoamScale: 1
- _FoamSpeed: 0
- _FoamTiling: 1
- _FoamWidth: 3.81
- _FresnelPower: 5
- _NormalScale: 0.4
- _NormalSpeed: 0.1
@@ -53,19 +110,37 @@ Material:
- _ShallowAlpha: 0.5
- _ShoreDistance: 1
- _ShoreFade: 1
- _Smoothness: 0.493
- _ShoreHeight: -4.3
- _ShoreUV2Threshold: 0.552
- _ShoreUVThreshold: 0.1
- _Smoothness: 0.555
- _SurfaceDistortionAmount: 0.257
- _SurfaceNoiseCutoff: 0
- _SurfaceNoiseScale: 1.7
- _SurfaceNoise2Scale: 1.6
- _SurfaceNoiseCutoff: 0.222
- _SurfaceNoiseScale: 1.25
- _TextureSpeed: 0.3
- _WaveFrequency: 5
- _WaveHeight: 0.1
- _WaveSpeed: 1
- _UseUVShore: 1
- _VertexColorFoamWidth: 0.3
- _WaveFrequency: 2.55
- _WaveGerstnerOn: 0
- _WaveHeight: 0.08
- _WaveSineOn: 1
- _WaveSpeed: 0.95
- _WaveSteepness: 0.5
- _WavesOn: 0
m_Colors:
- _DeepColor: {r: 0, g: 0.7264151, b: 0.67566013, a: 0.749}
- _BaseColor: {r: 0, g: 1, b: 0.9534545, a: 0.8509804}
- _Color: {r: 0, g: 0.5, b: 1, a: 0.8}
- _DeepColor: {r: 0, g: 0.9803924, b: 1, a: 0.78431374}
- _FoamColor: {r: 1, g: 1, b: 1, a: 1}
- _FoamSpeed: {r: 0.1, g: 0.1, b: 0, a: 0}
- _FoamSpeedA: {r: 0.1, g: 0.1, b: 0, a: 0}
- _FoamSpeedB: {r: -0.08, g: 0.06, b: 0, a: 0}
- _NormalTiling: {r: 40, g: 40, b: 0, a: 0}
- _ShallowColor: {r: 0.086908154, g: 0.8773585, b: 0.8218133, a: 1}
- _ShallowColor: {r: 0, g: 0.9806142, b: 1, a: 1}
- _WaterColor: {r: 0.19999996, g: 0.6, b: 0.8, a: 0.8}
- _WaveDirection: {r: 1, g: 1, b: 0, a: 0}
- _WaveSpeed1: {r: 0.05, g: 0.03, b: 0, a: 0}
- _WaveSpeed2: {r: -0.03, g: 0.04, b: 0, a: 0}
m_BuildTextureStacks: []
m_AllowLocking: 1
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7fa8f3034a9b2e34dbb43ab302864e9f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: 89c13dff71f555349bbeed61fd7f0402
IHVImageFormatImporter:
externalObjects: {}
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
isReadable: 0
sRGBTexture: 1
streamingMipmaps: 0
streamingMipmapsPriority: 0
ignoreMipmapLimit: 0
mipmapLimitGroupName:
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: 064ebb4006db3934697a80619febcb44
IHVImageFormatImporter:
externalObjects: {}
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
isReadable: 0
sRGBTexture: 1
streamingMipmaps: 0
streamingMipmapsPriority: 0
ignoreMipmapLimit: 0
mipmapLimitGroupName:
userData:
assetBundleName:
assetBundleVariant: