uniform sampler2D surface_in;
uniform sampler2D velocity_in;
-uniform sampler2D clamping_in;
uniform sampler2D bottom_in;
layout(r32f) uniform image2D surface_out;
layout(rg32f) uniform image2D velocity_out;
-layout(r32f) uniform image2D clamping_out;
-float get_depth(ivec2 coord)
+vec2 get_depth(ivec2 coord)
{
- return texelFetch(surface_in, coord, 0).x-texelFetch(bottom_in, coord, 0).x;
+ float surface = texelFetch(surface_in, coord, 0).x;
+ float bottom = texelFetch(bottom_in, coord, 0).x;
+ return vec2(surface, surface-bottom);
+}
+
+vec4 get_data(ivec2 coord)
+{
+ vec2 velocity = texelFetch(velocity_in, coord, 0).xy;
+ return vec4(velocity, get_depth(coord));
}
+++ /dev/null
-import fluidsim;
-
-#pragma MSP stage(compute)
-void main()
-{
- ivec2 size = imageSize(clamping_out);
- ivec2 coord = ivec2(gl_GlobalInvocationID.xy)+ivec2(1, 1);
- if(coord.x>=size.x-1 || coord.y>=size.y-1)
- return;
-
- float depth = get_depth(coord);
- vec2 velocity = texelFetch(velocity_in, coord, 0).xy;
- float left_vx = texelFetch(velocity_in, coord-ivec2(1, 0), 0).x;
- float down_vy = texelFetch(velocity_in, coord-ivec2(0, 1), 0).y;
-
- // Clamping step: prevent fluid depth from going negative
- float total_out = max(velocity.x, 0.0)+max(velocity.y, 0.0)-min(left_vx, 0.0)-min(down_vy, 0.0);
- float scale = min(max_flow_fraction/(total_out*delta_time), depth/residual_depth);
-
- imageStore(clamping_out, coord, vec4(clamp(scale, 0.0, 1.0), 0.0, 0.0, 0.0));
-}
uniform sampler2D bottom;
layout(r32f) uniform image2D surface_out;
layout(rg32f) uniform image2D velocity_out;
-layout(r32f) uniform image2D clamping_out;
void main()
{
float surface = max(texelFetch(bottom, coord, 0).x, 0.0);
imageStore(surface_out, coord, vec4(surface, 0.0, 0.0, 0.0));
imageStore(velocity_out, coord, vec4(0.0));
- imageStore(clamping_out, coord, vec4(0.0));
}
if(coord.x>=size.x-1 || coord.y>=size.y-1)
return;
- float surface = texelFetch(surface_in, coord, 0).x;
- float bottom = texelFetch(bottom_in, coord, 0).x;
- float depth = surface-bottom;
- vec2 velocity = texelFetch(velocity_in, coord, 0).xy;
- float clamping = texelFetch(clamping_in, coord, 0).x;
- float left_depth = get_depth(coord-ivec2(1, 0));
- float left_clamping = texelFetch(clamping_in, coord-ivec2(1, 0), 0).x;
- float left_vx = texelFetch(velocity_in, coord-ivec2(1, 0), 0).x;
- float right_depth = get_depth(coord+ivec2(1, 0));
- float right_clamping = texelFetch(clamping_in, coord+ivec2(1, 0), 0).x;
- float down_depth = get_depth(coord-ivec2(0, 1));
- float down_clamping = texelFetch(clamping_in, coord-ivec2(0, 1), 0).x;
- float down_vy = texelFetch(velocity_in, coord-ivec2(0, 1), 0).y;
- float up_depth = get_depth(coord+ivec2(0, 1));
- float up_clamping = texelFetch(clamping_in, coord+ivec2(0, 1), 0).x;
+ vec4 data = get_data(coord);
+ vec4 right_data = get_data(coord+ivec2(1, 0));
+ vec4 up_data = get_data(coord+ivec2(0, 1));
+ vec4 left_data = get_data(coord-ivec2(1, 0));
+ vec4 down_data = get_data(coord-ivec2(0, 1));
+
+ float ul_vx = texelFetch(velocity_in, coord+ivec2(-1, 1), 0).x;
+ float left2_vx = texelFetch(velocity_in, coord-ivec2(2, 0), 0).x;
+ vec2 dl_velocity = texelFetch(velocity_in, coord-ivec2(1, 1), 0).xy;
+ float down2_vy = texelFetch(velocity_in, coord-ivec2(0, 2), 0).y;
+ float dr_vy = texelFetch(velocity_in, coord+ivec2(1, -1), 0).y;
+
+ float clamping = get_clamping(data.w, data.x, data.y, left_data.x, down_data.y);
+ float right_cl = get_clamping(right_data.w, right_data.x, right_data.y, data.x, dr_vy);
+ float up_cl = get_clamping(up_data.w, up_data.x, up_data.y, ul_vx, data.y);
+ float left_cl = get_clamping(left_data.w, left_data.x, left_data.y, left2_vx, dl_velocity.y);
+ float down_cl = get_clamping(down_data.w, down_data.x, down_data.y, dl_velocity.x, down2_vy);
// Integration step: change surface level based on velocities
- float total_flow = left_vx*mix(left_depth*left_clamping, depth*clamping, left_vx<0)-
- velocity.x*mix(depth*clamping, right_depth*right_clamping, velocity.x<0)+
- down_vy*mix(down_depth*down_clamping, depth*clamping, down_vy<0)-
- velocity.y*mix(depth*clamping, up_depth*up_clamping, velocity.y<0);
- float new_surface = surface+total_flow*delta_time;
+ float total_flow_out = data.x*mix(data.w*clamping, right_data.w*right_cl, data.x<0)+
+ data.y*mix(data.w*clamping, up_data.w*up_cl, data.y<0)-
+ left_data.x*mix(data.w*clamping, left_data.w*left_cl, left_data.x>0)-
+ down_data.y*mix(data.w*clamping, down_data.w*down_cl, down_data.y>0);
+ float new_surface = data.z-total_flow_out*delta_time;
imageStore(surface_out, coord, vec4(new_surface, 0.0, 0.0, 0.0));
}
if(coord.x>=size.x-1 || coord.y>=size.y-1)
return;
- float surface = texelFetch(surface_in, coord, 0).x;
- float depth = surface-texelFetch(bottom_in, coord, 0).x;
- float surface_left = texelFetch(surface_in, coord-ivec2(1, 0), 0).x;
- float surface_right = texelFetch(surface_in, coord+ivec2(1, 0), 0).x;
- float depth_right = surface_right-texelFetch(bottom_in, coord+ivec2(1, 0), 0).x;
- float surface_down = texelFetch(surface_in, coord-ivec2(0, 1), 0).x;
- float surface_up = texelFetch(surface_in, coord+ivec2(0, 1), 0).x;
- float depth_up = surface_up-texelFetch(bottom_in, coord+ivec2(0, 1), 0).x;
- vec2 velocity = texelFetch(velocity_in, coord, 0).xy;
+ vec4 data = get_data(coord);
+ vec2 sd_right = get_depth(coord+ivec2(1, 0));
+ vec2 sd_up = get_depth(coord+ivec2(0, 1));
// Advection step: move velocity vectors
vec2 uv_coord = (vec2(coord)+vec2(0.5))/size;
vec2 offset = vec2(0.5, -0.5)/size;
vec2 multi = delta_time/size;
- vec2 v_right = vec2(velocity.x, textureLod(velocity_in, uv_coord+offset, 0).y);
- vec2 v_up = vec2(textureLod(velocity_in, uv_coord-offset, 0).x, velocity.y);
+ vec2 v_right = vec2(data.x, textureLod(velocity_in, uv_coord+offset, 0).y);
+ vec2 v_up = vec2(textureLod(velocity_in, uv_coord-offset, 0).x, data.y);
vec2 new_velocity = vec2(textureLod(velocity_in, uv_coord-v_right*multi, 0).x,
textureLod(velocity_in, uv_coord-v_up*multi, 0).y)*velocity_damping;
// Update step: change velocities based on surface level differences
- vec2 source_depth = mix(vec2(depth_right, depth_up), vec2(depth), greaterThan(vec2(surface), vec2(surface_right, surface_up)));
- new_velocity += (vec2(surface)-vec2(surface_right, surface_up))*0.1*gravity*delta_time*min(source_depth/residual_depth, 1.0);
+ vec2 source_depth = mix(vec2(sd_right.y, sd_up.y), vec2(data.w), greaterThan(vec2(data.z), vec2(sd_right.x, sd_up.x)));
+ new_velocity += (vec2(data.z)-vec2(sd_right.x, sd_up.x))*0.1*gravity*delta_time*min(source_depth/residual_depth, 1.0);
- if(time>=drop_time && time<=drop_time+0.01 && depth>1.0)
+ if(time>=drop_time && time<=drop_time+0.01 && data.w>1.0)
{
ivec2 d = coord-drop_pos;
if(d.x*d.x+d.y*d.y<4)
sampler(resources.get<GL::Sampler>("linear_clip.samp")),
sim_integrate(resources.get<GL::Program>("fluidsim_integrate.glsl.shader")),
sim_velocity(resources.get<GL::Program>("fluidsim_velocity.glsl.shader")),
- sim_clamp(resources.get<GL::Program>("fluidsim_clamp.glsl.shader")),
normals_shader(resources.get<GL::Program>("water_normals.glsl.shader")),
variance_x_shader(resources.get<GL::Program>("water_variance_x.glsl.shader")),
variance_y_shader(resources.get<GL::Program>("water_variance_y.glsl.shader"))
state[i].surface.set_debug_name(format("Water surface[%d]", i));
state[i].velocity.storage(GL::RG32F, width, height, 1);
state[i].velocity.set_debug_name(format("Water velocity[%d]", i));
- state[i].clamping.storage(GL::R32F, width, height, 1);
- state[i].clamping.set_debug_name(format("Water clamping[%d]", i));
}
normals.storage(GL::RG8, width, height, 1);
{
renderer.set_storage_texture("surface_out", &state[i].surface);
renderer.set_storage_texture("velocity_out", &state[i].velocity);
- renderer.set_storage_texture("clamping_out", &state[i].clamping);
renderer.dispatch((width+7)/8, (height+7)/8);
}
renderer.end();
renderer.set_shader_program(&sim_integrate);
renderer.set_storage_texture("surface_out", &next->surface);
renderer.set_storage_texture("velocity_out", &next->velocity);
- renderer.set_storage_texture("clamping_out", &next->clamping);
renderer.set_texture("surface_in", ¤t->surface, &sampler);
renderer.set_texture("velocity_in", ¤t->velocity, &sampler);
- renderer.set_texture("clamping_in", ¤t->clamping, &sampler);
renderer.dispatch(groups_x, groups_y);
renderer.set_shader_program(&sim_velocity);
renderer.set_texture("surface_in", &next->surface, &sampler);
renderer.dispatch(groups_x, groups_y);
- renderer.set_shader_program(&sim_clamp);
- renderer.set_texture("velocity_in", &next->velocity, &sampler);
- renderer.dispatch(groups_x, groups_y);
-
time += stepsize;
swap(current, next);
}
{
Msp::GL::Texture2D surface;
Msp::GL::Texture2D velocity;
- Msp::GL::Texture2D clamping;
};
unsigned width;
const Msp::GL::Sampler &sampler;
const Msp::GL::Program &sim_integrate;
const Msp::GL::Program &sim_velocity;
- const Msp::GL::Program &sim_clamp;
const Msp::GL::Program &normals_shader;
const Msp::GL::Program &variance_x_shader;
const Msp::GL::Program &variance_y_shader;