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

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
}