234 lines
8.6 KiB
HLSL
234 lines
8.6 KiB
HLSL
#include "LVLiquidPassBase.cginc"
|
|
|
|
float _DitherStrength;
|
|
float _SizeWorld;
|
|
|
|
float _MurkinessSpeed;
|
|
float3 _BubblesData; // x = scale, y = vertical speed, z = brightness
|
|
|
|
|
|
#if defined(WEBGL_OR_LEGACY)
|
|
sampler2D _LayersPropertiesTex;
|
|
sampler2D _LayersColorsTex;
|
|
sampler2D _LayersColors2Tex;
|
|
sampler2D _NoiseTexUnwrapped;
|
|
|
|
// Lower quality with a single texture fetch
|
|
/*
|
|
inline float4 GetNoiseUnwrapped(float4 pos) {
|
|
float4 f = frac(pos);
|
|
f.z = (floor(f.y * 64.0) + 0.5) / 64.0 + f.z / 64.0;
|
|
return tex2Dlod(_NoiseTexUnwrapped, float4(f.xz,0,0));
|
|
}
|
|
*/
|
|
|
|
inline float4 GetNoiseUnwrapped(float4 pos) {
|
|
float4 f = frac(pos);
|
|
float t = f.y * 64.0;
|
|
float by = floor(t);
|
|
float4 n0 = tex2Dlod(_NoiseTexUnwrapped, float4(f.x, (by + f.z) / 64.0,0,0));
|
|
float4 n1 = tex2Dlod(_NoiseTexUnwrapped, float4(f.x, (by + 1.0 + f.z) / 64.0,0,0));
|
|
return lerp(n0, n1, t-by);
|
|
}
|
|
|
|
|
|
#define SET_LAYER_INDEX(y) float layerIndex = -y / _SizeWorld;
|
|
#define UPDATE_LAYER_INDEX(y) layerIndex = -y / _SizeWorld;
|
|
#define SAMPLE_LAYER_PROPERTIES(index) tex2Dlod(_LayersPropertiesTex, float4(0,index,0,0))
|
|
#define SAMPLE_LAYER_COLOR(index) tex2Dlod(_LayersColorsTex, float4(0,index,0,0))
|
|
#define SAMPLE_LAYER_COLOR2(index) tex2Dlod(_LayersColors2Tex, float4(0,index,0,0))
|
|
#define SAMPLE_NOISE_UNWRAPPED(pos) GetNoiseUnwrapped(pos)
|
|
|
|
#else
|
|
half4 _LayersColors[256];
|
|
half4 _LayersColors2[256];
|
|
float4 _LayersProperties[256];
|
|
|
|
#define SET_LAYER_INDEX(y) int layerIndex = clamp((int)(-255.0 * y / _SizeWorld), 0, 255);
|
|
#define UPDATE_LAYER_INDEX(y) layerIndex = clamp((int)(-255.0 * y / _SizeWorld), 0, 255);
|
|
#define SAMPLE_LAYER_PROPERTIES(index) _LayersProperties[index]
|
|
#define SAMPLE_LAYER_COLOR(index) _LayersColors[index]
|
|
#define SAMPLE_LAYER_COLOR2(index) _LayersColors2[index]
|
|
#define SAMPLE_NOISE_UNWRAPPED(pos) tex3Dlod(_NoiseTex, pos)
|
|
|
|
#endif
|
|
|
|
inline float getRandomFast(float2 uv) {
|
|
float2 p = uv; // + _Time.ww;
|
|
p -= floor(p * 0.01408450704) * 71.0;
|
|
p += float2( 26.0, 161.0 );
|
|
p *= p;
|
|
return frac(p.x * p.y * 0.001051374728);
|
|
}
|
|
|
|
|
|
|
|
half4 raymarch(float4 vertex, float3 rd, float t0, float t1) {
|
|
|
|
float3 wpos = wsCameraPos + rd * t0;
|
|
|
|
float turbulence = (tex2D(_NoiseTex2D, vertex.xz).g - 0.5) * _Turbulence.x;
|
|
turbulence += sin(vertex.w) * _Turbulence.y;
|
|
turbulence *= 0.05 * _Size.y * _FoamTurbulence;
|
|
_LevelPos += turbulence;
|
|
_FoamMaxPos += turbulence;
|
|
|
|
// compute level of surface liquid (t2)
|
|
float2 rdy = rd.xz / rd.y;
|
|
float delta = sqrt(1.0 + dot (rdy, rdy));
|
|
float h = abs(wpos.y - _LevelPos);
|
|
float t2 = t0 + h * delta; // length(delta * h.xx);;
|
|
|
|
// compute foam level (t3)
|
|
float hf = abs(wpos.y - _FoamMaxPos);
|
|
float t3 = t0 + hf * delta;
|
|
|
|
// ray-march smoke
|
|
float tmin, tmax;
|
|
#if defined(LIQUID_VOLUME_SMOKE)
|
|
half4 sumSmoke = half4(0,0,0,0);
|
|
if (wpos.y > _LevelPos) {
|
|
tmin = t0;
|
|
tmax = rd.y<0 ? min(t2,t1) : t1;
|
|
float stepSize = (tmax - tmin) / (float)_SmokeRaySteps;
|
|
float4 dir = float4(rd * stepSize, 0);
|
|
float4 rpos = float4(wsCameraPos + rd * tmin, 0);
|
|
float4 disp = float4(0, _Time.x * _Turbulence.x * _Size.y * _SmokeSpeed, 0, 0);
|
|
BEGIN_LOOP(k,_SmokeRaySteps,5)
|
|
half n = SAMPLE_NOISE_3D(_NoiseTex, (rpos - disp) * _Scale.x).r;
|
|
float py = (_LevelPos - rpos.y)/_Size.y;
|
|
n = saturate(n + py * _SmokeHeightAtten);
|
|
half4 lc = half4(_SmokeColor.rgb, n * _SmokeColor.a);
|
|
lc.rgb *= lc.aaa;
|
|
half deep = exp(py * _SmokeAtten);
|
|
lc *= deep;
|
|
sumSmoke += lc * (1.0-sumSmoke.a);
|
|
rpos += dir;
|
|
END_LOOP
|
|
}
|
|
#endif
|
|
|
|
// ray-march foam
|
|
tmax = min(t3,t1), tmin = t0;
|
|
float sy = sign(rd.y);
|
|
if (wpos.y > _FoamMaxPos) {
|
|
tmin = tmax;
|
|
tmax = min(t2, t1) * -sy;
|
|
} else if (wpos.y < _LevelPos) {
|
|
tmin = min(t2,t1);
|
|
tmax *= _FoamBottom * sy;
|
|
} else if (rd.y<0) {
|
|
tmax = min(t2, t1);
|
|
}
|
|
half4 sumFoam = half4(0,0,0,0);
|
|
if (tmax>tmin) {
|
|
float stepSize = (tmax - tmin) / (float)_FoamRaySteps;
|
|
float4 dir = float4(rd * stepSize, 0);
|
|
float4 rpos = float4(wsCameraPos + rd * tmin, 0);
|
|
rpos.y -= _LevelPos;
|
|
float foamThickness = _FoamMaxPos - _LevelPos;
|
|
float4 disp = float4(_Time.x, 0, _Time.x, 0) * _Turbulence.x * _Size.w * _FoamTurbulence;
|
|
BEGIN_LOOP(k,_FoamRaySteps,7)
|
|
|
|
float h = saturate( rpos.y / foamThickness );
|
|
float n = saturate(SAMPLE_NOISE_3D(_NoiseTex, (rpos - disp) * _Scale.y ).r + _FoamDensity);
|
|
if (n>h) {
|
|
half4 lc = half4(_FoamColor.rgb, n-h);
|
|
lc.a *= _FoamColor.a;
|
|
lc.rgb *= lc.aaa;
|
|
half deep = saturate(rpos.y * _FoamWeight / foamThickness);
|
|
lc *= deep;
|
|
sumFoam += lc * (1.0 - sumFoam.a);
|
|
}
|
|
|
|
rpos += dir;
|
|
|
|
END_LOOP
|
|
sumFoam *= 1.0 + _FoamDensity;
|
|
}
|
|
|
|
// ray-march liquid
|
|
if (wpos.y > _LevelPos) {
|
|
tmin = t2;
|
|
tmax = t1 * -sy; // address case where ray does not cross liquid; this makes tmax < tmin in this case skipping the whole if block below
|
|
} else {
|
|
tmin = t0;
|
|
tmax = min(t2,t1);
|
|
}
|
|
half4 sum = half4(0,0,0,0);
|
|
if (tmax>tmin) {
|
|
float4 rpos = float4(wsCameraPos + rd * tmin, 0); // tmin or t0 ? does not matter to move to level pos; tmin will make bubbles position correct, so we stick with tmin (t0 may reduce banding on certain cases)
|
|
float stepSize = (t1-t0) / (float)_LiquidRaySteps;
|
|
float4 dir = float4(rd * stepSize, 0);
|
|
|
|
rpos += dir * (getRandomFast(rpos.xy * 100.0) * _DitherStrength);
|
|
float4 disp = float4(_Turbulence.y, 1.5, _Turbulence.y, 0) * (_MurkinessSpeed * _Size.y);
|
|
disp.y -= _LevelPos - turbulence;
|
|
rpos.y -= _LevelPos - turbulence;
|
|
|
|
BEGIN_LOOP(k,_LiquidRaySteps,10)
|
|
|
|
SET_LAYER_INDEX(rpos.y);
|
|
|
|
// turbulence
|
|
float layerTurbulence = SAMPLE_LAYER_PROPERTIES(layerIndex).z;
|
|
float4 xpos = float4(rpos.x, rpos.y + layerTurbulence * turbulence, rpos.z, 0);
|
|
UPDATE_LAYER_INDEX(xpos.y);
|
|
|
|
xpos.xyz -= _Center;
|
|
|
|
// murkiness
|
|
float4 properties = SAMPLE_LAYER_PROPERTIES(layerIndex);
|
|
float layerScale = properties.y;
|
|
half n = SAMPLE_NOISE_3D(_NoiseTex, (xpos - disp * layerTurbulence) * layerScale).r;
|
|
|
|
// accumulate color
|
|
half muddy = properties.x;
|
|
half4 layerColor = SAMPLE_LAYER_COLOR(layerIndex);
|
|
half4 layerColor2 = SAMPLE_LAYER_COLOR2(layerIndex);
|
|
half4 lc = lerp(layerColor, layerColor2, smoothstep(0, 1.0, n) * muddy);
|
|
lc.a = layerColor.a;
|
|
lc.rgb *= lc.aaa;
|
|
sum += lc * (1.0-sum.a);
|
|
|
|
// bubbles; uses tex3Dlod
|
|
#if defined(LIQUID_VOLUME_BUBBLES)
|
|
half4 ba = SAMPLE_NOISE_UNWRAPPED ( (xpos - float4(turbulence, 0, turbulence, 0)) * _BubblesData.x - float4(0, _BubblesData.y, 0,0) );
|
|
half4 bb = SAMPLE_NOISE_UNWRAPPED ( (xpos + float4(turbulence, 0, turbulence, 0)) * _BubblesData.x - float4(0.5, _BubblesData.y * 1.5 + 0.5, 0.5, 0) );
|
|
half4 b = ba+bb;
|
|
half3 bnorm = b.yzw - 1.0;
|
|
half fresnel = abs(dot(rd, bnorm));
|
|
lc.rgb += fresnel * _BubblesData.z;
|
|
lc.a = fresnel;
|
|
lc.rgb *= lc.aaa; // 0.1
|
|
lc *= properties.w;
|
|
sum += lc * (1.0-sum.a);
|
|
#endif
|
|
|
|
rpos += dir;
|
|
|
|
END_LOOP
|
|
}
|
|
|
|
// Final blend
|
|
if (wpos.y>_LevelPos) {
|
|
#if defined(LIQUID_VOLUME_SMOKE)
|
|
half4 lfoam = sumFoam * (1.0 - sumSmoke.a);
|
|
half4 liquid = sum * (1.0 - lfoam.a) * (1.0 - sumSmoke.a);
|
|
sum = sumSmoke + lfoam + liquid;
|
|
#else
|
|
half4 liquid = sum * (1.0 - sumFoam.a);
|
|
sum = sumFoam + liquid;
|
|
#endif
|
|
} else {
|
|
half4 lfoam = sumFoam * (1.0 - sum.a);
|
|
sum = sum + lfoam;
|
|
}
|
|
|
|
#if !UNITY_COLORSPACE_GAMMA
|
|
sum.rgb = SRGBToLinear(sum.rgb);
|
|
#endif
|
|
|
|
return sum;
|
|
}
|