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
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
|
|
}
|