diff options
author | Adrian Kummerlaender | 2019-04-28 12:53:27 +0200 |
---|---|---|
committer | Adrian Kummerlaender | 2019-04-28 14:22:15 +0200 |
commit | ecaf665a05bdfcd10937152c378cfaec7cdf1836 (patch) | |
tree | b161f5fa94a054b672b81ff1826fbf3ca388975e /src/main.cc | |
parent | fa708e6ed52115026f5dd09d270445cfb1b9f26a (diff) | |
download | compustream-ecaf665a05bdfcd10937152c378cfaec7cdf1836.tar compustream-ecaf665a05bdfcd10937152c378cfaec7cdf1836.tar.gz compustream-ecaf665a05bdfcd10937152c378cfaec7cdf1836.tar.bz2 compustream-ecaf665a05bdfcd10937152c378cfaec7cdf1836.tar.lz compustream-ecaf665a05bdfcd10937152c378cfaec7cdf1836.tar.xz compustream-ecaf665a05bdfcd10937152c378cfaec7cdf1836.tar.zst compustream-ecaf665a05bdfcd10937152c378cfaec7cdf1836.zip |
Experimental visualization of the velocity curl
Calculating the curl of our simulated velocity field requires an additional
compute shader step. Handling of buffer and shader switching depending on
the display mode is implemented rudimentarily for now.
Most of this commit is scaffolding, the actual computation is more or less
trivial:
```
const float dxvy = (getFluidVelocity(x+1,y).y - getFluidVelocity(x-1,y).y)
/ (2*convLength);
const float dyvx = (getFluidVelocity(x,y+1).x - getFluidVelocity(x,y-1).x)
/ (2*convLength);
setFluidExtra(x, y, dxvy - dyvx);
```
This implements the following discretization of the 2d curl operator:
Let $V : \mathbb{N}^2 \to \mathbb{R}^2$ be the simulated velocity field at
discrete lattice points spaced by $\Delta x \in \mathbb{R}_{\gt 0}$.
We want to approximate the $z$-component of the curl for visualization:
$$\omega := \partial_x F_y - \partial_y F_x$$
As we do not possess the actual function $F$ but only its values at a
set of discrete points we approximate the two partial derivatives using
a second order central difference scheme:
$$\overline{\omega}(i,j) := \frac{F_y(i+1,j) - F_y(i-1,j)}{2 \Delta x} - \frac{F_x(i,j+1) - F_x(i,j-1)}{2 \Delta x}$$
Note that the scene shader does some further rescaling of the curl to better
fit the color palette. One issue that irks me is the emergence of some
artefacts near boundaries as well as isolated "single-cell-vortices".
This might be caused by running the simulation too close to divergence
but as I am currently mostly interested in building an interactive fluid
playground it could be worth it to try running an additional smoothening
shader pass to straighten things out.
Diffstat (limited to 'src/main.cc')
-rw-r--r-- | src/main.cc | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/src/main.cc b/src/main.cc index 394248c..a98ca44 100644 --- a/src/main.cc +++ b/src/main.cc @@ -20,6 +20,7 @@ #include "shader/code/interact.glsl" #include "shader/code/collide.glsl" +#include "shader/code/extra.glsl" #include "timer.h" @@ -27,6 +28,12 @@ GLuint maxLUPS = 100; GLuint nX = 512; GLuint nY = 256; +enum DisplayMode { + VELOCITY, + QUALITY, + CURL +}; + float getWorldHeight(int window_width, int window_height, float world_width) { return world_width / window_width * window_height; } @@ -84,9 +91,11 @@ int render() { std::unique_ptr<LatticeCellBuffer> lattice_a; std::unique_ptr<LatticeCellBuffer> lattice_b; std::unique_ptr<FluidCellBuffer> fluid; + std::unique_ptr<FluidCellBuffer> extra; std::unique_ptr<ComputeShader> interact_shader; std::unique_ptr<ComputeShader> collide_shader; + std::unique_ptr<ComputeShader> extra_shader; window.init([&]() { scene_shader = std::make_unique<GraphicShader>( @@ -94,9 +103,11 @@ int render() { lattice_a = std::make_unique<LatticeCellBuffer>(nX, nY); lattice_b = std::make_unique<LatticeCellBuffer>(nX, nY); + extra = std::make_unique< FluidCellBuffer>(nX, nY, setupOpenGeometry); fluid = std::make_unique< FluidCellBuffer>(nX, nY, setupOpenGeometry); interact_shader = std::make_unique<ComputeShader>(INTERACT_SHADER_CODE); + extra_shader = std::make_unique<ComputeShader>(EXTRA_SHADER_CODE); collide_shader = std::make_unique<ComputeShader>(COLLIDE_SHADER_CODE); }); @@ -110,8 +121,10 @@ int render() { auto pause_key = window.getKeyWatcher(GLFW_KEY_SPACE); bool update_lattice = true; - auto toggle_key = window.getKeyWatcher(GLFW_KEY_T); - bool show_fluid_quality = false; + auto velocity_mode_key = window.getKeyWatcher(GLFW_KEY_V); + auto quality_mode_key = window.getKeyWatcher(GLFW_KEY_Q); + auto curl_mode_key = window.getKeyWatcher(GLFW_KEY_C); + DisplayMode display_mode = DisplayMode::VELOCITY; auto palette_factor_incr = window.getKeyWatcher(GLFW_KEY_UP); auto palette_factor_decr = window.getKeyWatcher(GLFW_KEY_DOWN); @@ -125,8 +138,8 @@ int render() { float currLatticeMouseX; float currLatticeMouseY; - auto tick_buffers = { lattice_a->getBuffer(), lattice_b->getBuffer(), fluid->getBuffer() }; - auto tock_buffers = { lattice_b->getBuffer(), lattice_a->getBuffer(), fluid->getBuffer() }; + auto tick_buffers = { lattice_a->getBuffer(), lattice_b->getBuffer(), fluid->getBuffer(), extra->getBuffer() }; + auto tock_buffers = { lattice_b->getBuffer(), lattice_a->getBuffer(), fluid->getBuffer(), extra->getBuffer() }; GLuint iT = 0; int statLUPS = 0; @@ -146,14 +159,22 @@ int render() { update_lattice = !update_lattice; } - if ( toggle_key.wasClicked() ) { - show_fluid_quality = !show_fluid_quality; + if ( velocity_mode_key.wasClicked() ) { + display_mode = DisplayMode::VELOCITY; + fluid->enable(); + } + if ( quality_mode_key.wasClicked() ) { + display_mode = DisplayMode::QUALITY; + fluid->enable(); + } + if ( curl_mode_key.wasClicked() ) { + display_mode = DisplayMode::CURL; + extra->enable(); } if ( palette_factor_incr.wasClicked() ) { palette_factor += 1; } - if ( palette_factor_decr.wasClicked() ) { palette_factor -= 1; } @@ -175,10 +196,12 @@ int render() { if ( tick ) { interact_shader->workOn(tick_buffers); collide_shader->workOn(tick_buffers); + extra_shader->workOn(tick_buffers); tick = false; } else { interact_shader->workOn(tock_buffers); collide_shader->workOn(tock_buffers); + extra_shader->workOn(tock_buffers); tick = true; } @@ -186,13 +209,18 @@ int render() { { auto guard = collide_shader->use(); - collide_shader->setUniform("show_fluid_quality", show_fluid_quality); + collide_shader->setUniform("show_fluid_quality", display_mode == DisplayMode::QUALITY); collide_shader->setUniform("iT", iT); iT += 1; collide_shader->dispatch(nX, nY); } + if ( display_mode == DisplayMode::CURL ) { + auto guard = extra_shader->use(); + extra_shader->dispatch(nX, nY); + } + last_lattice_update = timer::now(); } @@ -228,11 +256,27 @@ int render() { scene_shader->setUniform("MVP", MVP); scene_shader->setUniform("nX", nX); scene_shader->setUniform("nY", nY); - scene_shader->setUniform("show_fluid_quality", show_fluid_quality); scene_shader->setUniform("palette_factor", palette_factor); glClear(GL_COLOR_BUFFER_BIT); - fluid->draw(); + + switch ( display_mode ) { + case DisplayMode::VELOCITY: + scene_shader->setUniform("show_fluid_quality", false); + scene_shader->setUniform("show_curl", false); + fluid->draw(); + break; + case DisplayMode::QUALITY: + scene_shader->setUniform("show_fluid_quality", true); + scene_shader->setUniform("show_curl", false); + fluid->draw(); + break; + case DisplayMode::CURL: + scene_shader->setUniform("show_fluid_quality", false); + scene_shader->setUniform("show_curl", true); + extra->draw(); + break; + } } }); |