Hi,
I try to code a 2d fluid shader using this article as a base :
https://developer.nvidia.com/content/gpu-gems-chapter-38-fast-fluid-dynamics-simulation-gpu
But the result is far from expected.
First, all F2texRECT, H4texRECT, H1texRECT and other similar functions are missing in unity’s library texRECT wich I replaced by tex2D. But does it gives the same result ?
Secondly the logarythm sequence is not clear. I did this :
advect(coords, xNew, timestep, rdx, _VelocityMap, _MainTex);
jacobi(coords, xNew, alpha, rBeta, _VelocityMap, _VelocityMap);
divergence(coords, xNew, halfrdx, _VelocityMap);
gradient(coords, xNew, halfrdx, _VelocityMap, _VelocityMap);
I didn’t find how to get what they call Gridscale.
I try to achieve the attached image.
My code :
float4 f4texRECTbilerp(sampler2D tex, float2 s) {
float4 st;
st.xy = floor(s - 0.5) + 0.5;
st.zw = st.xy + 1;
float2 t = s - st.xy; //interpolating factors
float4 tex11 = tex2D(tex, st.xy);
float4 tex21 = tex2D(tex, st.zy);
float4 tex12 = tex2D(tex, st.xw);
float4 tex22 = tex2D(tex, st.zw);
// bilinear interpolation
return lerp(lerp(tex11, tex21, t.x), lerp(tex12, tex22, t.x), t.y);
}
void advect(float2 coords : WPOS, out float4 xNew : COLOR, uniform float timestep, uniform float rdx, uniform sampler2D u, uniform sampler2D x) {
// Follow The Velocity Field "Back In Time"
float2 pos = coords - timestep * rdx * tex2D(u, coords);
// Interpolate And Write To The Output Fragment
xNew = f4texRECTbilerp(x, pos);
}
void jacobi(half2 coords : WPOS, out float4 xNew : COLOR, uniform half alpha, uniform half rBeta, uniform sampler2D x, uniform sampler2D b) {
// Left, Right, Bottom, And Top X Samples
half4 xL = tex2D(x, coords - half2(1, 0));
half4 xR = tex2D(x, coords + half2(1, 0));
half4 xB = tex2D(x, coords - half2(0, 1));
half4 xT = tex2D(x, coords + half2(0, 1));
// B Sample, From Center
half4 bC = tex2D(b, coords);
// Evaluate Jacobi Iteration
xNew = (xL + xR + xB + xT + alpha * bC) * rBeta;
}
void divergence(half2 coords : WPOS, out float4 div : COLOR, uniform half halfrdx, uniform sampler2D w) {
half4 wL = tex2D(w, coords - half2(1, 0));
half4 wR = tex2D(w, coords + half2(1, 0));
half4 wB = tex2D(w, coords - half2(0, 1));
half4 wT = tex2D(w, coords + half2(0, 1));
div = halfrdx * ((wR.x - wL.x) + (wT.y - wB.y));
}
void gradient(half2 coords : WPOS, out float4 uNew : COLOR, uniform half halfrdx, uniform sampler2D p, uniform sampler2D w) {
half pL = tex2D(p, coords - half2(1, 0));
half pR = tex2D(p, coords + half2(1, 0));
half pB = tex2D(p, coords - half2(0, 1));
half pT = tex2D(p, coords + half2(0, 1));
uNew = tex2D(w, coords);
uNew.xy -= halfrdx * half2(pR - pL, pT - pB);
}
void boundary(half2 coords : WPOS, half2 offset : TEX1, out float4 bv : COLOR, uniform half scale, uniform sampler2D x) {
bv = scale * tex2D(x, coords + offset);
}
void surf (Input IN, inout EditorSurfaceOutput o)
{
o.Normal = float3(0.0,0.0,1.0);
o.Alpha = 1.0;
o.Albedo = 0.0;
o.Emission = 0.0;
o.Gloss = 0.0;
o.Specular = 0.0;
o.Custom = 0.0;
// Apply The First 3 Operators In Equation 12.
//u = advect(u);
//u = diffuse(u);
//u = addForces(u);
// Now Apply The Projection Operator To The Result.
//p = computePressure(u);
//u = subtractPressureGradient(u, p);
//uTemp = advect(u);
//swap(u, uTemp);
float gridScale = 1;
float2 coords = (IN.uv_VelocityMap.xyxy).xy;
float4 xNew;
float timestep = _Time * _HSpeed.xxxx;
float rdx = 1.0 / gridScale;
advect(coords, xNew, timestep, rdx, _VelocityMap, _MainTex);
half alpha = 1;
half rBeta = 1;
half4 div;
jacobi(coords, xNew, alpha, rBeta, _VelocityMap, _VelocityMap);
half halfrdx = rdx * 0.5;
divergence(coords, xNew, halfrdx, _VelocityMap);
half4 uNew;
gradient(coords, xNew, halfrdx, _VelocityMap, _VelocityMap);
o.Albedo = xNew;
o.Normal = normalize(o.Normal);
}