aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buffer/vertex/fluid_cell_buffer.cc12
-rw-r--r--src/buffer/vertex/fluid_cell_buffer.h1
-rw-r--r--src/main.cc64
-rw-r--r--src/shader/code/extra.glsl53
-rw-r--r--src/shader/code/interact.glsl2
-rw-r--r--src/shader/code/vertex.glsl52
6 files changed, 164 insertions, 20 deletions
diff --git a/src/buffer/vertex/fluid_cell_buffer.cc b/src/buffer/vertex/fluid_cell_buffer.cc
index 8fdc579..d9af989 100644
--- a/src/buffer/vertex/fluid_cell_buffer.cc
+++ b/src/buffer/vertex/fluid_cell_buffer.cc
@@ -5,11 +5,8 @@
FluidCellBuffer::FluidCellBuffer(GLuint nX, GLuint nY, std::function<int(int,int)>&& geometry):
_nX(nX), _nY(nY) {
glGenBuffers(1, &_buffer);
- glBindVertexArray(_array);
+ enable();
init(std::forward<decltype(geometry)>(geometry));
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
-
}
FluidCellBuffer::~FluidCellBuffer() {
@@ -17,9 +14,14 @@ FluidCellBuffer::~FluidCellBuffer() {
glDeleteVertexArrays(1, &_array);
}
-void FluidCellBuffer::init(std::function<int(int,int)>&& geometry) {
+void FluidCellBuffer::enable() {
+ glBindVertexArray(_array);
glBindBuffer(GL_ARRAY_BUFFER, _buffer);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+}
+void FluidCellBuffer::init(std::function<int(int,int)>&& geometry) {
std::vector<GLfloat> data(3*_nX*_nY, GLfloat{});
for ( int x = 0; x < _nX; ++x ) {
diff --git a/src/buffer/vertex/fluid_cell_buffer.h b/src/buffer/vertex/fluid_cell_buffer.h
index 791ebea..5148606 100644
--- a/src/buffer/vertex/fluid_cell_buffer.h
+++ b/src/buffer/vertex/fluid_cell_buffer.h
@@ -16,6 +16,7 @@ public:
FluidCellBuffer(GLuint nX, GLuint nY, std::function<int(int,int)>&& geometry);
~FluidCellBuffer();
+ void enable();
void init(std::function<int(int,int)>&& geometry);
GLuint getBuffer() const;
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;
+ }
}
});
diff --git a/src/shader/code/extra.glsl b/src/shader/code/extra.glsl
new file mode 100644
index 0000000..5ba6207
--- /dev/null
+++ b/src/shader/code/extra.glsl
@@ -0,0 +1,53 @@
+static const std::string EXTRA_SHADER_CODE = R"(
+#version 430
+
+layout (local_size_x = 1, local_size_y = 1) in;
+
+layout (std430, binding=3) buffer bufferFluid { float fluidCells[]; };
+layout (std430, binding=4) buffer bufferExtra { float extraCells[]; };
+
+uniform uint nX;
+uniform uint nY;
+
+const float convLength = 1.0 / float(max(nX,nY));
+
+/// Array indexing
+
+uint indexOfDirection(int i, int j) {
+ return 3*(i+1) + (j+1);
+}
+
+uint indexOfFluidVertex(uint x, uint y) {
+ return 3*nX*y + 3*x;
+}
+
+/// Data access
+
+vec2 getFluidVelocity(uint x, uint y) {
+ const uint idx = indexOfFluidVertex(x, y);
+ return vec2(
+ fluidCells[idx + 0],
+ fluidCells[idx + 1]
+ );
+}
+
+void setFluidExtra(uint x, uint y, float curl) {
+ const uint idx = indexOfFluidVertex(x, y);
+ extraCells[idx + 0] = curl;
+}
+
+void main() {
+ const uint x = gl_GlobalInvocationID.x;
+ const uint y = gl_GlobalInvocationID.y;
+
+ if ( !(x < nX && y < nY) ) {
+ return;
+ }
+
+ // simple central difference discretization of the 2d curl operator
+ 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);
+}
+)";
diff --git a/src/shader/code/interact.glsl b/src/shader/code/interact.glsl
index 613c4cd..141673a 100644
--- a/src/shader/code/interact.glsl
+++ b/src/shader/code/interact.glsl
@@ -4,6 +4,7 @@ static const std::string INTERACT_SHADER_CODE = R"(
layout (local_size_x = 1, local_size_y = 1) in;
layout (std430, binding=3) buffer bufferFluid { float fluidCells[]; };
+layout (std430, binding=4) buffer bufferExtra { float extraCells[]; };
uniform uint nX;
uniform uint nY;
@@ -62,6 +63,7 @@ int getMaterial(uint x, uint y) {
void setMaterial(uint x, uint y, int m) {
const uint idx = indexOfFluidVertex(x, y);
fluidCells[idx + 2] = m;
+ extraCells[idx + 2] = m;
}
/// Geometry cleanup
diff --git a/src/shader/code/vertex.glsl b/src/shader/code/vertex.glsl
index 0f0e07c..5136023 100644
--- a/src/shader/code/vertex.glsl
+++ b/src/shader/code/vertex.glsl
@@ -11,6 +11,7 @@ uniform uint nX;
uniform uint nY;
uniform bool show_fluid_quality;
+uniform bool show_curl;
uniform int palette_factor;
float unit(float x) {
@@ -65,6 +66,38 @@ vec3 trafficLightPalette(float x) {
}
}
+vec3 blueBlackRedPalette(float x) {
+ if ( x < 0.5 ) {
+ return mix(
+ vec3(0.0, 0.0, 1.0),
+ vec3(0.0, 0.0, 0.0),
+ 2*x
+ );
+ } else {
+ return mix(
+ vec3(0.0, 0.0, 0.0),
+ vec3(1.0, 0.0, 0.0),
+ 2*(x - 0.5)
+ );
+ }
+}
+
+vec3 blackGoldPalette(float x) {
+ return mix(
+ vec3(0.0, 0.0, 0.0),
+ vec3(0.5, 0.35, 0.05),
+ x
+ );
+}
+
+vec3 blueRedPalette(float x) {
+ return mix(
+ vec3(0.0, 0.0, 1.0),
+ vec3(1.0, 0.0, 0.0),
+ x
+ );
+}
+
void main() {
const vec2 idx = fluidVertexAtIndex(gl_VertexID);
@@ -83,12 +116,21 @@ void main() {
vs_out.color = vec3(0.0, 0.0, 0.0);
} else {
if ( show_fluid_quality ) {
- vs_out.color = trafficLightPalette(restrictedQuality(VertexPosition.y));
+ vs_out.color = trafficLightPalette(
+ restrictedQuality(VertexPosition.y)
+ );
+ } else if ( show_curl ) {
+ const float factor = 1.0 / float(100*palette_factor);
+ if ( abs(VertexPosition.x) > 1.0 ) {
+ vs_out.color = blueBlackRedPalette(
+ 0.5 + (VertexPosition.x * factor)
+ );
+ } else {
+ vs_out.color = vec3(0.0,0.0,0.0);
+ }
} else {
- vs_out.color = mix(
- vec3(-0.5, 0.0, 1.0),
- vec3( 1.0, 0.0, 0.0),
- norm(VertexPosition.xy) / float(palette_factor)
+ vs_out.color = blueRedPalette(
+ norm(VertexPosition.xy) / palette_factor
);
}
}