117 lines
3.8 KiB
HLSL
117 lines
3.8 KiB
HLSL
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
|
|
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
|
|
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
|
|
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
|
|
|
|
#ifndef WATER_GERSTNER_INCLUDED
|
|
#define WATER_GERSTNER_INCLUDED
|
|
|
|
#define MAX_AMPLITUDE 5.0
|
|
#define GRAVITY 9.8f
|
|
|
|
float3 _GlobalWaveOriginOffset;
|
|
|
|
#if !defined(UNITY_CORE_SAMPLERS_INCLUDED)
|
|
//Do not want linear interpolation between texels, forcing the usage of a point sampler
|
|
SamplerState sampler_PointClamp;
|
|
#endif
|
|
|
|
struct WaveParameters
|
|
{
|
|
uint enabled;
|
|
float amplitude;
|
|
float waveLength;
|
|
float steepness;
|
|
uint mode;
|
|
float direction;
|
|
float2 origin;
|
|
};
|
|
|
|
//Sample parameters from LUT, stored in two horizontal rows
|
|
void SampleWaveParameters(inout WaveParameters data, uint index, Texture2D tex, uint columns)
|
|
{
|
|
//Each layer's data is stored in a texel, from left to right. The horizontal position corresponds to the array element, so that's the UV
|
|
const float2 lutUV = float2((float)index / (float)columns, 0);
|
|
|
|
const float4 row0 = SAMPLE_TEXTURE2D_LOD(tex, sampler_PointClamp, lutUV, 0);
|
|
data.amplitude = row0.x;
|
|
data.waveLength = row0.y;
|
|
data.direction = row0.z; //Rotation angle in radians
|
|
data.enabled = row0.w;
|
|
|
|
const float4 row1 = SAMPLE_TEXTURE2D_LOD(tex, sampler_PointClamp, lutUV + float2(0, 0.5), 0);
|
|
data.origin = row1.xy + _GlobalWaveOriginOffset.xz;
|
|
data.mode = row1.z;
|
|
data.steepness = row1.w;
|
|
}
|
|
|
|
//LUT texture is passed in as a parameter, since it may differ on a per-material basis
|
|
void CalculateGerstnerWaves_float(in Texture2D<float4> lutTex, in uint layerCount, in float2 position, in float frequency, in float time, in float normalStrength, in float2 baseDirection, in uint count, out float3 offset, out float3 tangent, out float3 bitangent)
|
|
{
|
|
//Defaults
|
|
offset = float3(0,0,0);
|
|
tangent = float3(1,0,0);
|
|
bitangent = float3(0,0,1);
|
|
|
|
//Clamp to maximum number of layers
|
|
count = min(count - 1, layerCount);
|
|
|
|
WaveParameters layer = (WaveParameters)0;
|
|
|
|
uint waveCount = 0;
|
|
for(uint i = 0; i <= count; i++)
|
|
{
|
|
SampleWaveParameters(layer, i, lutTex, layerCount);
|
|
|
|
if(layer.enabled > 0)
|
|
{
|
|
waveCount += 1;
|
|
|
|
const float w = TWO_PI / (layer.waveLength * frequency);
|
|
const float freq = sqrt(GRAVITY * w);
|
|
//As amplitude scales down, so should the steepness
|
|
half ampRCP = (layer.amplitude/MAX_AMPLITUDE);
|
|
//Both divide and scale by amplitude
|
|
float steepness = (layer.steepness / layer.amplitude) * ampRCP;
|
|
|
|
//Rotation already pre-converted into radians
|
|
float2 direction = float2(sin(layer.direction), cos(layer.direction)) * baseDirection;
|
|
|
|
//Radial mode
|
|
if(layer.mode == 1)
|
|
{
|
|
direction = (position - layer.origin);
|
|
direction = normalize(direction);
|
|
}
|
|
|
|
const float dir = dot(direction, position - (layer.origin * layer.mode));
|
|
|
|
const float t = dir * w + (freq * -time);
|
|
|
|
float proximalSine = sin(t); //Y
|
|
float lateralSine = cos(t); //XZ
|
|
|
|
//Relative XYZ offsets
|
|
offset.x += direction.x * layer.amplitude * lateralSine * steepness;
|
|
offset.y += proximalSine * layer.amplitude;
|
|
offset.z += direction.y * layer.amplitude * lateralSine * steepness;
|
|
|
|
tangent += float3(
|
|
-direction.x * direction.x * (steepness * proximalSine),
|
|
offset.x,
|
|
-direction.x * direction.y * (steepness * proximalSine)
|
|
);
|
|
|
|
bitangent += float3(
|
|
-direction.x * direction.y * (steepness * proximalSine),
|
|
offset.z,
|
|
-direction.y * -direction.y * (steepness * proximalSine)
|
|
);
|
|
}
|
|
}
|
|
waveCount = max(waveCount, 1);
|
|
|
|
tangent = lerp(float3(1,0,0), tangent, normalStrength / waveCount);
|
|
bitangent = lerp(float3(0,0,1), bitangent, normalStrength / waveCount);
|
|
}
|
|
#endif |