]> git.tdb.fi Git - libs/gl.git/commitdiff
Remove the separate clamping step from forest pond fluid simulation
authorMikko Rasa <tdb@tdb.fi>
Sun, 11 Sep 2022 17:23:52 +0000 (20:23 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 11 Sep 2022 17:23:52 +0000 (20:23 +0300)
Instead calculate clamping on the fly in the integration shader.  This
ends up using a few less texture reads in total.

demos/forestpond/data/fluidsim.glsl
demos/forestpond/data/fluidsim_clamp.glsl [deleted file]
demos/forestpond/data/fluidsim_fill.glsl
demos/forestpond/data/fluidsim_integrate.glsl
demos/forestpond/data/fluidsim_velocity.glsl
demos/forestpond/source/water.cpp
demos/forestpond/source/water.h

index c44002689a5d0a9d318746fe10f9bab9b54dfab1..0f58a9b225e815963f2dc194f1835dc2a94650e0 100644 (file)
@@ -19,13 +19,19 @@ layout(push_constant) uniform Time
 
 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));
 }
diff --git a/demos/forestpond/data/fluidsim_clamp.glsl b/demos/forestpond/data/fluidsim_clamp.glsl
deleted file mode 100644 (file)
index 93e8bbc..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-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));
-}
index 61f1f32045f4a9ee07c13a90226ce20f2cfca6c0..495ea1c39915b125f20066babf346ca27111197f 100644 (file)
@@ -6,7 +6,6 @@ layout(local_size_x=8, local_size_y=8) in;
 uniform sampler2D bottom;
 layout(r32f) uniform image2D surface_out;
 layout(rg32f) uniform image2D velocity_out;
-layout(r32f) uniform image2D clamping_out;
 
 void main()
 {
@@ -14,5 +13,4 @@ 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));
 }
index f3805e8a8e6d2ea809659b4ecc82ed78e61843c2..da3e8c18721a065ed671078649e1bdbba18b1238 100644 (file)
@@ -8,28 +8,30 @@ void main()
        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));
 }
index b564b23147f17eabb829205ca38f0c3143a19ffa..375e205e3077aea311de3ed025085011cd625f7d 100644 (file)
@@ -8,30 +8,24 @@ void main()
        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)
index 03709034de838cfebce38dff512b4b03d2e6c807..d44e70891a0f42c8c58a93889d366a26f1314d81 100644 (file)
@@ -17,7 +17,6 @@ Water::Water(const GL::Object &o, DataFile::Collection &resources, const Region
        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"))
@@ -41,8 +40,6 @@ Water::Water(const GL::Object &o, DataFile::Collection &resources, const Region
                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);
@@ -77,7 +74,6 @@ Water::Water(const GL::Object &o, DataFile::Collection &resources, const Region
        {
                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();
@@ -107,20 +103,14 @@ void Water::setup_frame(GL::Renderer &renderer)
                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", &current->surface, &sampler);
                renderer.set_texture("velocity_in", &current->velocity, &sampler);
-               renderer.set_texture("clamping_in", &current->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);
        }
index 88bf93590da6579189075553be1ff41bd384c6cb..3ef5862adabbdd45373145850796d21fd62ec435 100644 (file)
@@ -22,7 +22,6 @@ private:
        {
                Msp::GL::Texture2D surface;
                Msp::GL::Texture2D velocity;
-               Msp::GL::Texture2D clamping;
        };
 
        unsigned width;
@@ -40,7 +39,6 @@ private:
        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;