You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
276 lines
11 KiB
276 lines
11 KiB
Shader "Hidden/HDRP/WaterFoam"
|
|
{
|
|
Properties {}
|
|
|
|
HLSLINCLUDE
|
|
#pragma target 4.5
|
|
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
|
|
|
|
// #pragma enable_d3d11_debug_symbols
|
|
|
|
#pragma vertex Vert
|
|
#pragma fragment Frag
|
|
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/WaterSystemDef.cs.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/ShaderVariablesWater.cs.hlsl"
|
|
|
|
float2 GetFoamUV(float2 transformedPositionAWS)
|
|
{
|
|
float2 deformationPosition = transformedPositionAWS - _FoamRegionOffset;
|
|
|
|
float2 axis1 = _WaterForwardXZ;
|
|
float2 axis2 = float2(-axis1.y, axis1.x);
|
|
deformationPosition = float2(dot(deformationPosition, axis1), dot(deformationPosition, axis2));
|
|
|
|
return deformationPosition * _FoamRegionScale;
|
|
}
|
|
|
|
ENDHLSL
|
|
|
|
SubShader
|
|
{
|
|
Tags{ "RenderPipeline" = "HDRenderPipeline" }
|
|
|
|
Pass
|
|
{
|
|
Name "ShoreWaveFoamGeneration"
|
|
|
|
// This program doesn't require any culling or ztesting
|
|
Cull Off
|
|
ZTest Off
|
|
ZWrite Off
|
|
Blend One One
|
|
|
|
HLSLPROGRAM
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/WaterDeformer/WaterDeformer.cs.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/Shaders/WaterDeformationUtilities.hlsl"
|
|
|
|
#define SURFACE_FOAM_MUTLIPLIER 2.0
|
|
#define DEEP_FOAM_MUTLIPLIER 1.0
|
|
|
|
struct Attributes
|
|
{
|
|
uint vertexID : VERTEXID_SEMANTIC;
|
|
uint instanceID : INSTANCEID_SEMANTIC;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionHS : SV_Position;
|
|
float2 deformerPosOS : DEFORMER_POSITION;
|
|
float2 centeredPos : DEFORMER_CENTERED_POSITION;
|
|
float2 normalizedPos : DEFORMER_NORMALIZED_POSITION;
|
|
float2 positionWS : DEFORMER_POSITION_WS;
|
|
int deformerID : DEFORMER_ID;
|
|
};
|
|
|
|
Varyings Vert(Attributes input)
|
|
{
|
|
Varyings varyings;
|
|
varyings.deformerID = input.instanceID;
|
|
|
|
// Grab the current deformer
|
|
WaterDeformerData currentDeformer = _WaterDeformerData[varyings.deformerID];
|
|
|
|
// Compute the object space position of the quad
|
|
varyings.deformerPosOS = deformerCorners[input.vertexID] * currentDeformer.regionSize * 0.5;
|
|
varyings.centeredPos = deformerCorners[input.vertexID].xy;
|
|
varyings.normalizedPos = varyings.centeredPos * 0.5 + 0.5;
|
|
|
|
// Evaluate the world space vertex position (add rotation here)
|
|
float cosRot = cos(currentDeformer.rotation);
|
|
float sinRot = sin(currentDeformer.rotation);
|
|
float x = varyings.deformerPosOS.x * cosRot - sinRot * varyings.deformerPosOS.y;
|
|
float y = varyings.deformerPosOS.x * sinRot + cosRot * varyings.deformerPosOS.y;
|
|
varyings.positionWS = currentDeformer.position.xz + float2(x, y);
|
|
|
|
// Remap the position into the normalized area space
|
|
float2 vertexPositionCS = GetFoamUV(varyings.positionWS);
|
|
|
|
vertexPositionCS *= 2.0f;
|
|
varyings.positionWS *= 2.0f;
|
|
|
|
// Output the clip space position
|
|
varyings.positionHS = float4(vertexPositionCS.x, -vertexPositionCS.y, 0.5, 1.0);
|
|
return varyings;
|
|
}
|
|
|
|
float2 Frag(Varyings input) : SV_Target
|
|
{
|
|
// Grab the current deformer
|
|
WaterDeformerData deform = _WaterDeformerData[input.deformerID];
|
|
|
|
// Deformer specific code
|
|
float2 foamData = 0.0;
|
|
if (deform.type == WATERDEFORMERTYPE_SHORE_WAVE)
|
|
{
|
|
// Evaluate the wave data
|
|
WaveData waveData = EvaluateWaveData(input.deformerPosOS.x - deform.waveOffset, deform.waveSpeed, deform.waveLength);
|
|
|
|
// Wave activation (only on for the waves that are actually displayed)
|
|
float waveActivation = EvaluateSineWaveActivation(waveData.bellIndex, deform.waveRepetition);
|
|
|
|
// We want the foam to only appear on the tip of the waves
|
|
float foamHeightThreshold = EvaluateWaveBlendAttenuation(deform, input.normalizedPos);
|
|
|
|
// Define where the foam appears on the wave
|
|
float surfacefoamWaveLocation = saturate((waveData.position - 0.1) / 0.1) * (1.0 - saturate((waveData.position - 0.5) / 0.02));
|
|
float deepFoamWaveLocation = saturate((waveData.position - 0.1) / 0.1) * (1.0 - saturate((waveData.position - 0.3) / 0.1));
|
|
|
|
// Define what amount of foam appears
|
|
float deepfoamAmount = EvaluateDeepFoamAmount(deform, input.normalizedPos.x);
|
|
float surfaceFoamAmount = EvaluateSurfaceFoamAmount(deform, input.normalizedPos);
|
|
|
|
// Evaluate the perlin noise
|
|
float perlinNoise = 0.2 + saturate(DeformerNoise2D(input.positionWS * 0.25));
|
|
|
|
// Combine to generate the foam
|
|
foamData.x = surfaceFoamAmount * surfacefoamWaveLocation;
|
|
foamData.y = deepfoamAmount * deepFoamWaveLocation;
|
|
foamData *= perlinNoise * waveActivation * foamHeightThreshold;
|
|
}
|
|
|
|
foamData.x *= deform.surfaceFoamDimmer * SURFACE_FOAM_MUTLIPLIER;
|
|
foamData.y *= deform.deepFoamDimmer * DEEP_FOAM_MUTLIPLIER;
|
|
return foamData * _DeltaTime * 2.0;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
|
|
Pass
|
|
{
|
|
Name "OtherFoamGeneration"
|
|
|
|
// This program doesn't require any culling or ztesting
|
|
Cull Off
|
|
ZTest Off
|
|
ZWrite Off
|
|
Blend One One
|
|
|
|
HLSLPROGRAM
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/Shaders/WaterGenerationUtilities.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/FoamGenerator/WaterFoamGenerator.cs.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/Shaders/WaterDeformationUtilities.hlsl"
|
|
|
|
#define SURFACE_FOAM_MUTLIPLIER 1.0
|
|
#define DEEP_FOAM_MUTLIPLIER 1.0
|
|
|
|
struct Attributes
|
|
{
|
|
uint vertexID : VERTEXID_SEMANTIC;
|
|
uint instanceID : INSTANCEID_SEMANTIC;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionHS : SV_Position;
|
|
float2 positionOS : GENERATOR_POSITION;
|
|
float2 centeredPos : GENERATOR_CENTERED_POSITION;
|
|
float2 normalizedPos : GENERATOR_NORMALIZED_POSITION;
|
|
float2 positionWS : GENERATOR_POSITION_WS;
|
|
int generatorID : GENERATOR_ID;
|
|
};
|
|
|
|
Varyings Vert(Attributes input)
|
|
{
|
|
Varyings varyings;
|
|
varyings.generatorID = input.instanceID;
|
|
|
|
// Grab the current deformer
|
|
WaterGeneratorData generator = _WaterGeneratorData[varyings.generatorID];
|
|
|
|
// Compute the object space position of the quad
|
|
varyings.positionOS = generatorCorners[input.vertexID] * generator.regionSize * 0.5;
|
|
varyings.centeredPos = generatorCorners[input.vertexID].xy;
|
|
varyings.normalizedPos = varyings.centeredPos * 0.5 + 0.5;
|
|
|
|
// Evaluate the world space vertex position (add rotation here)
|
|
float cosRot = cos(generator.rotation);
|
|
float sinRot = sin(generator.rotation);
|
|
float x = varyings.positionOS.x * cosRot - sinRot * varyings.positionOS.y;
|
|
float y = varyings.positionOS.x * sinRot + cosRot * varyings.positionOS.y;
|
|
varyings.positionWS = generator.position.xz + float2(x, y);
|
|
|
|
// Remap the position into the normalized area space
|
|
float2 vertexPositionCS = GetFoamUV(varyings.positionWS);
|
|
|
|
vertexPositionCS *= 2.0f;
|
|
varyings.positionWS *= 2.0f;
|
|
|
|
// Output the clip space position
|
|
varyings.positionHS = float4(vertexPositionCS.x, -vertexPositionCS.y, 0.5, 1.0);
|
|
return varyings;
|
|
}
|
|
|
|
float2 Frag(Varyings input) : SV_Target
|
|
{
|
|
// Grab the current deformer
|
|
WaterGeneratorData generator = _WaterGeneratorData[input.generatorID];
|
|
|
|
// Deformer specific code
|
|
float2 foamData = 0.0;
|
|
if (generator.type == WATERFOAMGENERATORTYPE_DISK)
|
|
{
|
|
float distanceToCenter = saturate(length(input.centeredPos));
|
|
foamData = (1.0 - distanceToCenter * distanceToCenter);
|
|
}
|
|
else if (generator.type == WATERFOAMGENERATORTYPE_RECTANGLE)
|
|
{
|
|
foamData = 1.0;
|
|
}
|
|
else
|
|
{
|
|
float2 texUV = input.normalizedPos * generator.scaleOffset.xy + generator.scaleOffset.zw;
|
|
foamData = SAMPLE_TEXTURE2D_LOD(_WaterGeneratorTextureAtlas, s_linear_clamp_sampler, texUV, 0).xy;
|
|
}
|
|
|
|
// Apply the multipliers
|
|
foamData.x *= generator.surfaceFoamDimmer * SURFACE_FOAM_MUTLIPLIER;
|
|
foamData.y *= generator.deepFoamDimmer * DEEP_FOAM_MUTLIPLIER;
|
|
|
|
return foamData * _DeltaTime;
|
|
}
|
|
ENDHLSL
|
|
}
|
|
|
|
Pass
|
|
{
|
|
Name "Attenuation"
|
|
// This program doesn't require any culling or ztesting
|
|
Cull Off
|
|
ZTest Off
|
|
ZWrite Off
|
|
Blend Zero SrcAlpha
|
|
|
|
HLSLPROGRAM
|
|
struct Attributes
|
|
{
|
|
uint vertexID : SV_VertexID;
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
float2 texcoord : TEXCOORD0;
|
|
};
|
|
|
|
Varyings Vert(Attributes input)
|
|
{
|
|
Varyings output;
|
|
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
|
|
output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID);
|
|
return output;
|
|
}
|
|
float4 Frag(Varyings input) : SV_Target
|
|
{
|
|
// Attenuation formula must be in sync with UpdateWaterFoamSimulation in C#
|
|
return float4(0.0, 0.0, 0.0, exp(-_DeltaTime * _FoamPersistenceMultiplier * 0.5));
|
|
}
|
|
ENDHLSL
|
|
}
|
|
}
|
|
Fallback Off
|
|
}
|