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.
 
 
 
 
 

178 lines
6.7 KiB

Shader "Hidden/HDRP/WaterDeformation"
{
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
// Package includes
#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/WaterDeformer/WaterDeformer.cs.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/Shaders/WaterDeformationUtilities.hlsl"
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_WORLD;
int deformerID : DEFORMER_ID;
};
float2 GetDeformationUV(float2 transformedPositionAWS)
{
float2 deformationPosition = transformedPositionAWS - _DeformationRegionOffset;
float2 axis1 = _WaterForwardXZ;
float2 axis2 = float2(-axis1.y, axis1.x);
deformationPosition = float2(dot(deformationPosition, axis1), dot(deformationPosition, axis2));
return deformationPosition * _DeformationRegionScale;
}
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 = GetDeformationUV(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;
}
float EvaluateDeformerProperties(Varyings input)
{
// Grab the current deformer
WaterDeformerData deform = _WaterDeformerData[input.deformerID];
// Deformer specific code
float amplitude = 0.0;
if (deform.type == WATERDEFORMERTYPE_SPHERE)
{
float distanceToCenter = saturate(length(input.centeredPos));
amplitude = deform.amplitude * (1.0 - distanceToCenter * distanceToCenter);
}
else if (deform.type == WATERDEFORMERTYPE_BOX)
{
amplitude = deform.amplitude * EvaluateBoxBlendAttenuation(deform.regionSize,
input.deformerPosOS, deform.blendRegion, deform.cubicBlend);
}
else if (deform.type == WATERDEFORMERTYPE_BOW_WAVE)
{
// TODO: Move this into a shared file and refactor (BowWaveUtilities.hlsl)
// First we need to remap the coordinates for the function evaluation
float2 normPos = input.deformerPosOS / (deform.regionSize * 0.5);
float transitionSize = 0.1;
normPos.y = normPos.y * 0.5 + 0.5;
float2 parabolaPos = normPos;
parabolaPos.y -= transitionSize;
float dist = sdParabola(parabolaPos, 1);
if (dist > 0.0)
{
float transition = smoothstep(0, 1, saturate(dist / transitionSize));
amplitude = lerp(deform.bowWaveElevation, 0.0, transition);
}
else
{
float transition = smoothstep(0, 1, saturate(-dist / (transitionSize)));
amplitude = lerp(deform.bowWaveElevation, deform.amplitude, transition);
}
// Apply attenuation so that the tail has less deformation with a cubic profile
float lengthAttenuation = (1.0 - saturate(normPos.y));
amplitude *= lengthAttenuation * lengthAttenuation;
}
else if (deform.type == WATERDEFORMERTYPE_SHORE_WAVE)
{
// Evaluate the wave data
WaveData waveData = EvaluateWaveData(input.deformerPosOS.x - deform.waveOffset, deform.waveSpeed, deform.waveLength);
// Evaluate the round lobe
float firstShape = ShoreWaveFirstShape(waveData);
// Evaluate the breaking lobe
float secondShape = ShoreWaveSecondShape(waveData);
// Start from the target amplitude
amplitude = ShoreWaveAmplitudeVariation(input.positionWS) * deform.amplitude;
// Blend the lobes
amplitude *= ShoreWaveBlendShapes(firstShape, secondShape, deform.breakingRange, input.normalizedPos.x);
// Apply the activation function (code that skips some waves)
amplitude *= EvaluateSineWaveActivation(waveData.bellIndex, deform.waveRepetition);
// Apply the edge attenuation
amplitude *= EvaluateWaveBlendAttenuation(deform, input.normalizedPos);
}
else
{
float2 texUV = input.normalizedPos * deform.scaleOffset.xy + deform.scaleOffset.zw;
float texData = SAMPLE_TEXTURE2D_LOD(_WaterDeformerTextureAtlas, s_linear_clamp_sampler, texUV, 0);
amplitude = lerp(deform.blendRegion.x, deform.blendRegion.y, texData) * deform.amplitude;
}
return amplitude;
}
ENDHLSL
SubShader
{
Tags{ "RenderPipeline" = "HDRenderPipeline" }
Pass
{
// This program doesn't require any culling or ztesting
Cull Off
ZTest Off
ZWrite Off
Blend One One
HLSLPROGRAM
float Frag(Varyings input) : SV_Target
{
return EvaluateDeformerProperties(input);
}
ENDHLSL
}
}
Fallback Off
}