]> git.tdb.fi Git - libs/gl.git/blob - demos/forestpond/source/water.cpp
Remove the separate clamping step from forest pond fluid simulation
[libs/gl.git] / demos / forestpond / source / water.cpp
1 #include <msp/gl/camera.h>
2 #include <msp/gl/framebuffer.h>
3 #include <msp/gl/mesh.h>
4 #include <msp/gl/renderer.h>
5 #include <msp/strings/format.h>
6 #include "water.h"
7
8 using namespace std;
9 using namespace Msp;
10
11 Water::Water(const GL::Object &o, DataFile::Collection &resources, const Region &region):
12         ObjectInstance(o),
13         width((region.right-region.left)*100.0f),
14         height((region.top-region.bottom)*100.0f),
15         current(&state[0]),
16         next(&state[1]),
17         sampler(resources.get<GL::Sampler>("linear_clip.samp")),
18         sim_integrate(resources.get<GL::Program>("fluidsim_integrate.glsl.shader")),
19         sim_velocity(resources.get<GL::Program>("fluidsim_velocity.glsl.shader")),
20         normals_shader(resources.get<GL::Program>("water_normals.glsl.shader")),
21         variance_x_shader(resources.get<GL::Program>("water_variance_x.glsl.shader")),
22         variance_y_shader(resources.get<GL::Program>("water_variance_y.glsl.shader"))
23 {
24         sim_shdata.set_debug_name("Water sim params");
25         sim_shdata.uniform("delta_time", stepsize);
26         sim_shdata.uniform("velocity_damping", 0.99995f);
27         sim_shdata.uniform("gravity", 981.0f);
28         sim_shdata.uniform("max_flow_fraction", 0.9999f);
29         sim_shdata.uniform("residual_depth", 0.01f);
30
31         shdata.uniform("Region.scale", 1.0f/(region.right-region.left), 1.0f/(region.top-region.bottom));
32         shdata.uniform("Region.offset", -region.left/(region.right-region.left), -region.bottom/(region.top-region.bottom));
33         shdata.uniform("Region.amplitude", 0.01f);
34
35         bottom.storage(GL::R32F, width, height, 1);
36         bottom.set_debug_name("Water bottom");
37         for(unsigned i=0; i<2; ++i)
38         {
39                 state[i].surface.storage(GL::R32F, width, height, 1);
40                 state[i].surface.set_debug_name(format("Water surface[%d]", i));
41                 state[i].velocity.storage(GL::RG32F, width, height, 1);
42                 state[i].velocity.set_debug_name(format("Water velocity[%d]", i));
43         }
44
45         normals.storage(GL::RG8, width, height, 1);
46         normals.set_debug_name("Water normals");
47
48         variance_x.storage(GL::R16F, width, height, 1);
49         variance_x.set_debug_name("Water variance X");
50         variance_y.storage(GL::R16F, width, height, 1);
51         variance_y.set_debug_name("Water variance Y");
52
53         GL::Framebuffer bottom_fbo((GL::COLOR_ATTACHMENT,GL::R32F));
54         bottom_fbo.attach(GL::COLOR_ATTACHMENT, bottom);
55
56         GL::Camera bottom_camera;
57         bottom_camera.set_orthographic(region.right-region.left, region.top-region.bottom);
58         bottom_camera.set_position(GL::Vector3((region.left+region.right)/2, (region.bottom+region.top)/2, 0.0f));
59         bottom_camera.set_depth_clip(-10.0f, 10.0f);
60
61         const GL::Program &bottom_shprog = resources.get<GL::Program>("fluidsim_bottom.glsl.shader");
62         const GL::Program &fill_shprog = resources.get<GL::Program>("fluidsim_fill.glsl.shader");
63
64         GL::Renderer renderer;
65         renderer.begin();
66         renderer.set_camera(bottom_camera);
67         renderer.set_framebuffer(&bottom_fbo);
68         renderer.set_shader_program(&bottom_shprog);
69         region.terrain.draw(renderer);
70
71         renderer.set_shader_program(&fill_shprog);
72         renderer.set_texture("bottom", &bottom, &sampler);
73         for(unsigned i=0; i<2; ++i)
74         {
75                 renderer.set_storage_texture("surface_out", &state[i].surface);
76                 renderer.set_storage_texture("velocity_out", &state[i].velocity);
77                 renderer.dispatch((width+7)/8, (height+7)/8);
78         }
79         renderer.end();
80 }
81
82 void Water::setup_frame(GL::Renderer &renderer)
83 {
84         if(simulated)
85                 return;
86
87         GL::Renderer::Push _push(renderer);
88
89         unsigned groups_x = (width+5)/8;
90         unsigned groups_y = (height+5)/8;
91
92         int drop_x = rng()%width;
93         int drop_y = rng()%height;
94         sim_shdata.uniform("drop_pos", drop_x, drop_y);
95         sim_shdata.uniform("drop_time", time);
96
97         renderer.add_shader_data(sim_shdata);
98         renderer.set_texture("bottom_in", &bottom, &sampler);
99         for(unsigned i=0; i<16; ++i)
100         {
101                 sim_shdata.uniform("time", time);
102
103                 renderer.set_shader_program(&sim_integrate);
104                 renderer.set_storage_texture("surface_out", &next->surface);
105                 renderer.set_storage_texture("velocity_out", &next->velocity);
106                 renderer.set_texture("surface_in", &current->surface, &sampler);
107                 renderer.set_texture("velocity_in", &current->velocity, &sampler);
108                 renderer.dispatch(groups_x, groups_y);
109
110                 renderer.set_shader_program(&sim_velocity);
111                 renderer.set_texture("surface_in", &next->surface, &sampler);
112                 renderer.dispatch(groups_x, groups_y);
113
114                 time += stepsize;
115                 swap(current, next);
116         }
117
118         renderer.set_shader_program(&normals_shader);
119         renderer.set_texture("surface_in", &current->surface, &sampler);
120         renderer.set_storage_texture("normals_out", &normals);
121         renderer.dispatch(groups_x, groups_y);
122
123         renderer.set_shader_program(&variance_x_shader);
124         renderer.set_texture("normals_in", &normals, &sampler);
125         renderer.set_storage_texture("variance_out", &variance_x);
126         renderer.dispatch((width-1)/8, groups_y);
127
128         renderer.set_shader_program(&variance_y_shader);
129         renderer.set_texture("variance_in", &variance_x, &sampler);
130         renderer.set_storage_texture("variance_out", &variance_y);
131         renderer.dispatch(groups_x, (height-1)/8);
132
133         simulated = true;
134 }
135
136 void Water::finish_frame()
137 {
138         simulated = false;
139 }
140
141 void Water::setup_render(GL::Renderer &renderer, GL::Tag tag) const
142 {
143         ObjectInstance::setup_render(renderer, tag);
144         renderer.add_shader_data(shdata);
145         renderer.set_texture("bottom", &bottom, &sampler);
146         renderer.set_texture("surface", &current->surface, &sampler);
147         renderer.set_texture("normals", &normals, &sampler);
148         renderer.set_texture("variance", &variance_y, &sampler);
149 }