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.
 
 
 
 
 

143 lines
5.3 KiB

#ifndef WATER_CURRENT_UTILITIES_H
#define WATER_CURRENT_UTILITIES_H
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Water/ShaderVariablesWater.cs.hlsl"
// Water Current
// NOTE: This should be a structured buffer, however, due to a metal shader translation bug,
// we have to make it a texture. Which sucks, but we don't have a choice.
Texture2D<float4> _WaterSectorData;
// Current map of the first group
TEXTURE2D(_Group0CurrentMap);
SAMPLER(sampler_Group0CurrentMap);
// Current map of the second group
TEXTURE2D(_Group1CurrentMap);
SAMPLER(sampler_Group1CurrentMap);
// Quadrant description
#define NUM_SECTORS 8u
#define SECTOR_SIZE ((2.0 * PI) / NUM_SECTORS)
#define SECTOR_DATA_SAMPLING_OFFSET 0
#define SECTOR_DATA_OTHER_OFFSET 8
// This define uses a LOD sample for vertex and compute
#ifdef SHADER_STAGE_FRAGMENT
#define SAMPLE_TEX2D(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2)
#else
#define SAMPLE_TEX2D(textureName, samplerName, coord2) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, 0)
#endif
float ConvertAngle_0_2PI(float angle)
{
angle = angle % (2.0 * PI);
return angle < 0.0 ? angle + 2.0 * PI : angle;
}
float ConvertAngle_NPI_PPI(float angle)
{
angle = angle % (2.0 * PI);
return angle > PI ? angle - 2.0 * PI : (angle < -PI ? angle + 2.0 * PI : angle);
}
float EvaluateAngle(float3 cmpDir, float orientation, float influence, float2 flipDir)
{
float3 dir = float3((cmpDir.xy * 2.0 - 1.0) * flipDir, cmpDir.z);
float angle = ConvertAngle_NPI_PPI(atan2(dir.y, dir.x) - orientation);
return angle * influence * dir.z;
}
struct CurrentData
{
uint quadrant;
float proportion;
float angle;
};
void DecompressDirection(float3 cmpDir, float orientation, float influence, float2 flipDir, out CurrentData currentData)
{
float angle = EvaluateAngle(cmpDir, orientation, influence, flipDir);
angle = (angle < 0.0 ? angle + 2.0 * PI : angle);
float data = angle / SECTOR_SIZE;
float relativeAngle = frac(data);
// NOTE: We need to do it this way otherwise metal doesn't compile silently.
uint uintData = (uint)data;
currentData.angle = angle;
currentData.quadrant = uintData > NUM_SECTORS ? uintData - NUM_SECTORS : uintData;
currentData.proportion = PositivePow((currentData.quadrant % 2u == 0) ? relativeAngle : 1.0 - relativeAngle, 0.75);
}
float2 EvaluateWaterGroup0CurrentUV(float2 currentUV)
{
return float2(currentUV.x - _Group0CurrentRegionScaleOffset.z, currentUV.y + _Group0CurrentRegionScaleOffset.w) * _Group0CurrentRegionScaleOffset.xy + float2(0.5f, 0.5f);
}
float2 EvaluateWaterGroup1CurrentUV(float2 currentUV)
{
return float2(currentUV.x - _Group1CurrentRegionScaleOffset.z, currentUV.y + _Group1CurrentRegionScaleOffset.w) * _Group1CurrentRegionScaleOffset.xy + float2(0.5f, 0.5f);
}
void EvaluateGroup0CurrentData(float2 currentUV, out CurrentData currentData)
{
float2 flipDir = sign(_Group0CurrentRegionScaleOffset.xy);
float2 uv = EvaluateWaterGroup0CurrentUV(currentUV);
float3 cmpDir = SAMPLE_TEX2D(_Group0CurrentMap, sampler_Group0CurrentMap, uv).xyz;
DecompressDirection(cmpDir, _GroupOrientation.x, _CurrentMapInfluence.x, flipDir, currentData);
}
void EvaluateGroup1CurrentData(float2 currentUV, out CurrentData currentData)
{
float2 flipDir = sign(_Group1CurrentRegionScaleOffset.xy);
float2 uv = EvaluateWaterGroup1CurrentUV(currentUV);
float3 cmpDir = SAMPLE_TEX2D(_Group1CurrentMap, sampler_Group1CurrentMap, uv).xyz;
DecompressDirection(cmpDir, _GroupOrientation.y, _CurrentMapInfluence.y, flipDir, currentData);
}
float2 SampleWaterGroup0CurrentMap(float2 currentUV)
{
float2 flipDir = sign(_Group0CurrentRegionScaleOffset.xy);
float2 uv = EvaluateWaterGroup0CurrentUV(currentUV);
float3 cmpDir = SAMPLE_TEX2D(_Group0CurrentMap, sampler_Group0CurrentMap, uv).xyz;
float angle = EvaluateAngle(cmpDir, _GroupOrientation.x, _CurrentMapInfluence.x, flipDir);
return float2(cos(angle), sin(angle));
}
float2 SampleWaterGroup1CurrentMap(float2 currentUV)
{
float2 flipDir = sign(_Group1CurrentRegionScaleOffset.xy);
float2 uv = EvaluateWaterGroup1CurrentUV(currentUV);
float3 cmpDir = SAMPLE_TEX2D(_Group1CurrentMap, sampler_Group1CurrentMap, uv).xyz;
float angle = EvaluateAngle(cmpDir, _GroupOrientation.y, _CurrentMapInfluence.y, flipDir);
return float2(cos(angle), sin(angle));
}
void SwizzleSamplingCoordinates(float2 coord, uint quadrant, out float4 tapCoord)
{
int tapIndex = quadrant + SECTOR_DATA_SAMPLING_OFFSET;
float4 dir = _WaterSectorData[int2(tapIndex, 0)];
tapCoord.xy = float2(dot(coord.xy, dir.xy), dot(coord.xy, float2(-dir.y, dir.x)));
tapCoord.zw = float2(dot(coord.xy, dir.zw), dot(coord.xy, float2(-dir.w, dir.z)));
}
// Current debug
#define ARROW_TILE_SIZE 4.0
float EvaluateArrow(float2 positionAWS, float2 dir, float2 tileSize)
{
// Tile coordinate
float2 tileCoord = frac(positionAWS / tileSize) * 2.0 - 1.0;
float x = dot(dir, tileCoord);
float y = dot(float2(dir.y, -dir.x), tileCoord);
float mask = 0.0;
// Arrow body
if (y > -0.1 && y < 0.1 && x > -0.9 && x < 0.5)
mask = 1.0;
// Arrow head
else if (y > -0.4 && y < 0.4 && x > 0.5 && x < 0.9 && (0.4 - (x - 0.5)) / abs(y) > 1)
mask = 1.0;
return mask;
}
#endif // WATER_CURRENT_UTILITIES_H