X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=demos%2Fforestpond%2Fsource%2Fwater.cpp;fp=demos%2Fforestpond%2Fsource%2Fwater.cpp;h=03709034de838cfebce38dff512b4b03d2e6c807;hp=0000000000000000000000000000000000000000;hb=7efe2d35f5d53c0f086a1b85b7d3dea6a6c709ab;hpb=813301f2b342cd166461b2d266023d0292ba0f87 diff --git a/demos/forestpond/source/water.cpp b/demos/forestpond/source/water.cpp new file mode 100644 index 00000000..03709034 --- /dev/null +++ b/demos/forestpond/source/water.cpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include "water.h" + +using namespace std; +using namespace Msp; + +Water::Water(const GL::Object &o, DataFile::Collection &resources, const Region ®ion): + ObjectInstance(o), + width((region.right-region.left)*100.0f), + height((region.top-region.bottom)*100.0f), + current(&state[0]), + next(&state[1]), + sampler(resources.get("linear_clip.samp")), + sim_integrate(resources.get("fluidsim_integrate.glsl.shader")), + sim_velocity(resources.get("fluidsim_velocity.glsl.shader")), + sim_clamp(resources.get("fluidsim_clamp.glsl.shader")), + normals_shader(resources.get("water_normals.glsl.shader")), + variance_x_shader(resources.get("water_variance_x.glsl.shader")), + variance_y_shader(resources.get("water_variance_y.glsl.shader")) +{ + sim_shdata.set_debug_name("Water sim params"); + sim_shdata.uniform("delta_time", stepsize); + sim_shdata.uniform("velocity_damping", 0.99995f); + sim_shdata.uniform("gravity", 981.0f); + sim_shdata.uniform("max_flow_fraction", 0.9999f); + sim_shdata.uniform("residual_depth", 0.01f); + + shdata.uniform("Region.scale", 1.0f/(region.right-region.left), 1.0f/(region.top-region.bottom)); + shdata.uniform("Region.offset", -region.left/(region.right-region.left), -region.bottom/(region.top-region.bottom)); + shdata.uniform("Region.amplitude", 0.01f); + + bottom.storage(GL::R32F, width, height, 1); + bottom.set_debug_name("Water bottom"); + for(unsigned i=0; i<2; ++i) + { + state[i].surface.storage(GL::R32F, width, height, 1); + 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); + normals.set_debug_name("Water normals"); + + variance_x.storage(GL::R16F, width, height, 1); + variance_x.set_debug_name("Water variance X"); + variance_y.storage(GL::R16F, width, height, 1); + variance_y.set_debug_name("Water variance Y"); + + GL::Framebuffer bottom_fbo((GL::COLOR_ATTACHMENT,GL::R32F)); + bottom_fbo.attach(GL::COLOR_ATTACHMENT, bottom); + + GL::Camera bottom_camera; + bottom_camera.set_orthographic(region.right-region.left, region.top-region.bottom); + bottom_camera.set_position(GL::Vector3((region.left+region.right)/2, (region.bottom+region.top)/2, 0.0f)); + bottom_camera.set_depth_clip(-10.0f, 10.0f); + + const GL::Program &bottom_shprog = resources.get("fluidsim_bottom.glsl.shader"); + const GL::Program &fill_shprog = resources.get("fluidsim_fill.glsl.shader"); + + GL::Renderer renderer; + renderer.begin(); + renderer.set_camera(bottom_camera); + renderer.set_framebuffer(&bottom_fbo); + renderer.set_shader_program(&bottom_shprog); + region.terrain.draw(renderer); + + renderer.set_shader_program(&fill_shprog); + renderer.set_texture("bottom", &bottom, &sampler); + for(unsigned i=0; i<2; ++i) + { + 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(); +} + +void Water::setup_frame(GL::Renderer &renderer) +{ + if(simulated) + return; + + GL::Renderer::Push _push(renderer); + + unsigned groups_x = (width+5)/8; + unsigned groups_y = (height+5)/8; + + int drop_x = rng()%width; + int drop_y = rng()%height; + sim_shdata.uniform("drop_pos", drop_x, drop_y); + sim_shdata.uniform("drop_time", time); + + renderer.add_shader_data(sim_shdata); + renderer.set_texture("bottom_in", &bottom, &sampler); + for(unsigned i=0; i<16; ++i) + { + sim_shdata.uniform("time", time); + + 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); + } + + renderer.set_shader_program(&normals_shader); + renderer.set_texture("surface_in", ¤t->surface, &sampler); + renderer.set_storage_texture("normals_out", &normals); + renderer.dispatch(groups_x, groups_y); + + renderer.set_shader_program(&variance_x_shader); + renderer.set_texture("normals_in", &normals, &sampler); + renderer.set_storage_texture("variance_out", &variance_x); + renderer.dispatch((width-1)/8, groups_y); + + renderer.set_shader_program(&variance_y_shader); + renderer.set_texture("variance_in", &variance_x, &sampler); + renderer.set_storage_texture("variance_out", &variance_y); + renderer.dispatch(groups_x, (height-1)/8); + + simulated = true; +} + +void Water::finish_frame() +{ + simulated = false; +} + +void Water::setup_render(GL::Renderer &renderer, GL::Tag tag) const +{ + ObjectInstance::setup_render(renderer, tag); + renderer.add_shader_data(shdata); + renderer.set_texture("bottom", &bottom, &sampler); + renderer.set_texture("surface", ¤t->surface, &sampler); + renderer.set_texture("normals", &normals, &sampler); + renderer.set_texture("variance", &variance_y, &sampler); +}