diff options
| author | Adrian Kummerlaender | 2019-02-22 21:49:07 +0100 | 
|---|---|---|
| committer | Adrian Kummerlaender | 2019-02-22 21:49:07 +0100 | 
| commit | f0b536ac93b3a9a49dfff8a7637f09b153a3b955 (patch) | |
| tree | dbddeb503d50276fcee06d889d8c8b1edfd36a02 /src | |
| parent | 1870b510acb351b5956402a21572835aa0d2dee0 (diff) | |
| download | compustream-f0b536ac93b3a9a49dfff8a7637f09b153a3b955.tar compustream-f0b536ac93b3a9a49dfff8a7637f09b153a3b955.tar.gz compustream-f0b536ac93b3a9a49dfff8a7637f09b153a3b955.tar.bz2 compustream-f0b536ac93b3a9a49dfff8a7637f09b153a3b955.tar.lz compustream-f0b536ac93b3a9a49dfff8a7637f09b153a3b955.tar.xz compustream-f0b536ac93b3a9a49dfff8a7637f09b153a3b955.tar.zst compustream-f0b536ac93b3a9a49dfff8a7637f09b153a3b955.zip | |
Improvise interactive wall drawing
Internal wall cells need to be disabled to prevent delayed propagation
of the reflected populations.
This is just quickly thrown together - both the visual drawing and the backend's
material handling remain to be improved.
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer/vertex/material_buffer.cc | 51 | ||||
| -rw-r--r-- | src/buffer/vertex/material_buffer.h | 18 | ||||
| -rw-r--r-- | src/glfw/window.cc | 11 | ||||
| -rw-r--r-- | src/glfw/window.h | 2 | ||||
| -rw-r--r-- | src/main.cc | 7 | ||||
| -rw-r--r-- | src/shader/code/collide.glsl | 75 | ||||
| -rw-r--r-- | src/shader/code/stream.glsl | 15 | ||||
| -rw-r--r-- | src/shader/code/vertex.glsl | 16 | 
8 files changed, 157 insertions, 38 deletions
| diff --git a/src/buffer/vertex/material_buffer.cc b/src/buffer/vertex/material_buffer.cc new file mode 100644 index 0000000..82ccea2 --- /dev/null +++ b/src/buffer/vertex/material_buffer.cc @@ -0,0 +1,51 @@ +#include "material_buffer.h" + +#include <vector> + +MaterialBuffer::MaterialBuffer(GLuint nX, GLuint nY): +	_nX(nX), _nY(nY) { +	glGenVertexArrays(1, &_array); +	glGenBuffers(1, &_buffer); + +	glBindVertexArray(_array); +	glBindBuffer(GL_ARRAY_BUFFER, _buffer); + +	std::vector<GLint> data(nX*nY, GLint{1}); + +	for ( int x = 0; x < nX; ++x ) { +		data[     0*nX + x] = 0; +		data[(nY-1)*nX + x] = 0; +	} +	for ( int y = 0; y < nY; ++y ) { +		data[y*nX +    0] = 0; +		data[y*nX + nX-1] = 0; +	} + +	for ( int x = 1; x < nX-1; ++x ) { +		data[     1*nX + x] = 2; +		data[(nY-2)*nX + x] = 2; +	} +	for ( int y = 1; y < nY-1; ++y ) { +		data[y*nX +    1] = 2; +		data[y*nX + nX-2] = 2; +	} + +	glBufferData( +		GL_ARRAY_BUFFER, +		data.size() * sizeof(GLint), +		data.data(), +		GL_STATIC_DRAW +	); + +	glEnableVertexAttribArray(0); +	glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, nullptr); +} + +MaterialBuffer::~MaterialBuffer() { +	glDeleteBuffers(1, &_buffer); +	glDeleteVertexArrays(1, &_array); +} + +GLuint MaterialBuffer::getBuffer() const { +	return _buffer; +} diff --git a/src/buffer/vertex/material_buffer.h b/src/buffer/vertex/material_buffer.h new file mode 100644 index 0000000..eccf008 --- /dev/null +++ b/src/buffer/vertex/material_buffer.h @@ -0,0 +1,18 @@ +#pragma once + +#include <GL/glew.h> + +class MaterialBuffer { +private: +	const GLuint _nX; +	const GLuint _nY; + +	GLuint _array; +	GLuint _buffer; + +public: +	MaterialBuffer(GLuint nX, GLuint nY); +	~MaterialBuffer(); + +	GLuint getBuffer() const; +}; diff --git a/src/glfw/window.cc b/src/glfw/window.cc index 98890b7..4f14501 100644 --- a/src/glfw/window.cc +++ b/src/glfw/window.cc @@ -37,14 +37,19 @@ int Window::getHeight() const {  	return _height;  } -std::tuple<bool,int,int> Window::getMouse() const { -	const bool clicked = glfwGetMouseButton(_handle, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS; +std::tuple<int,int,int> Window::getMouse() const { +	int state = 0; +	if ( glfwGetMouseButton(_handle, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS ) { +		state = 1; +	} else if ( glfwGetMouseButton(_handle, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS ) { +		state = 2; +	}  	double x, y;  	glfwGetCursorPos(_handle, &x, &y);  	return std::make_tuple( -		clicked, +		state,  		x - int(getWidth()/2),  		int(getHeight()/2 - y)  	); diff --git a/src/glfw/window.h b/src/glfw/window.h index af7ba4d..143d457 100644 --- a/src/glfw/window.h +++ b/src/glfw/window.h @@ -27,7 +27,7 @@ public:  	int getWidth() const;  	int getHeight() const; -	std::tuple<bool,int,int> getMouse() const; +	std::tuple<int,int,int> getMouse() const;  	KeyWatcher getKeyWatcher(int key) const; diff --git a/src/main.cc b/src/main.cc index 3048979..0a400a5 100644 --- a/src/main.cc +++ b/src/main.cc @@ -10,6 +10,7 @@  #include "buffer/vertex/fluid_cell_buffer.h"  #include "buffer/vertex/lattice_cell_buffer.h" +#include "buffer/vertex/material_buffer.h"  #include "shader/wrap/graphic_shader.h"  #include "shader/wrap/compute_shader.h" @@ -66,6 +67,7 @@ int renderWindow() {  	std::unique_ptr<LatticeCellBuffer> lattice_a;  	std::unique_ptr<LatticeCellBuffer> lattice_b;  	std::unique_ptr<FluidCellBuffer>   fluid; +	std::unique_ptr<MaterialBuffer>    geometry;  	std::unique_ptr<ComputeShader> collide_shader;  	std::unique_ptr<ComputeShader> stream_shader; @@ -77,6 +79,7 @@ int renderWindow() {  		lattice_a = std::make_unique<LatticeCellBuffer>(nX, nY);  		lattice_b = std::make_unique<LatticeCellBuffer>(nX, nY);  		fluid     = std::make_unique<  FluidCellBuffer>(nX, nY); +		geometry  = std::make_unique<   MaterialBuffer>(nX, nY);  		collide_shader = std::make_unique<ComputeShader>(COLLIDE_SHADER_CODE);  		stream_shader  = std::make_unique<ComputeShader>(STREAM_SHADER_CODE); @@ -94,8 +97,8 @@ int renderWindow() {  	auto pause_key = window.getKeyWatcher(GLFW_KEY_SPACE); -	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(), geometry->getBuffer() }; +	auto tock_buffers = { lattice_b->getBuffer(), lattice_a->getBuffer(), fluid->getBuffer(), geometry->getBuffer() };  	window.render([&](bool window_size_changed) {  		if ( pause_key.wasClicked() ) { diff --git a/src/shader/code/collide.glsl b/src/shader/code/collide.glsl index cb950cb..b58bec3 100644 --- a/src/shader/code/collide.glsl +++ b/src/shader/code/collide.glsl @@ -3,9 +3,10 @@ static const std::string COLLIDE_SHADER_CODE = R"(  layout (local_size_x = 1, local_size_y = 1) in; -layout (std430, binding=1) buffer bufferCollide{ float collideCells[]; }; -layout (std430, binding=2) buffer bufferStream{  float streamCells[]; }; -layout (std430, binding=3) buffer bufferFluid{   float fluidCells[]; }; +layout (std430, binding=1) buffer bufferCollide  { float collideCells[];  }; +layout (std430, binding=2) buffer bufferStream   { float streamCells[];   }; +layout (std430, binding=3) buffer bufferFluid    { float fluidCells[];    }; +layout (std430, binding=4) buffer bufferGeometry { int   materialCells[]; };  /// external influence @@ -76,6 +77,22 @@ void setFluid(uint x, uint y, vec2 v, float d) {  	fluidCells[idx + 2] = d;  } +int getMaterial(uint x, uint y) { +	return materialCells[nX*y + x]; +} + +void setMaterial(uint x, uint y, int m) { +	materialCells[nX*y + x] = m; +} + +void disableFluid(uint x, uint y) { +	const uint idx = indexOfFluidVertex(x, y); +	fluidCells[idx + 0] = 0.0; +	fluidCells[idx + 1] = 0.0; +	fluidCells[idx + 2] = -2.0; +} + +  /// Moments  float density(uint x, uint y) { @@ -103,21 +120,19 @@ float equilibrium(float d, vec2 v, int i, int j) {  /// Determine external influence  float getExternalPressureInflux(uint x, uint y) { -	if ( mouseState == 1 && norm(vec2(x,y) - mousePos) < 4 ) { +	if ( mouseState == 1 && norm(vec2(x,y) - mousePos) < 2 ) {  		return 1.5;  	} else {  		return 0.0;  	}  } -/// Domain description - -bool isEndOfWorld(uint x, uint y) { -	return x == 0 || x == nX-1 || y == 0 || y == nY-1; -} - -bool isOuterWall(uint x, uint y) { -	return x == 1 || x == nX-2 || y == 1 || y == nY-2; +bool getExternalWallRequest(uint x, uint y) { +	if ( mouseState == 2 && norm(vec2(x,y) - mousePos) < 4 ) { +		return true; +	} else { +		return false; +	}  }  /// Actual collide kernel @@ -130,22 +145,38 @@ void main() {  		return;  	} -	if ( isEndOfWorld(x,y) ) { -		return; +	if ( getExternalWallRequest(x,y) ) { +		setMaterial(x,y,2); +		disableFluid(x,y);  	} -	if ( isOuterWall(x,y) ) { -		return; +	const int material = getMaterial(x,y); + +	if ( material == 2 ) { +		int wallNeighbors = 0; +		for ( int i = -1; i <= 1; ++i ) { +			for ( int j = -1; j <= 1; ++j ) { +				const int material = getMaterial(x+i,y+j); +				if ( material  == 0 || material == 2 ) { +					++wallNeighbors; +				} +			} +		} +		if ( wallNeighbors == 9 ) { +			setMaterial(x,y,0); +		}  	} -	const float d = max(getExternalPressureInflux(x,y), density(x,y)); -	const vec2  v = velocity(x,y,d); +	if ( material == 1 ) { // fluid +		const float d = max(getExternalPressureInflux(x,y), density(x,y)); +		const vec2  v = velocity(x,y,d); -	setFluid(x,y,v,d); +		setFluid(x,y,v,d); -	for ( int i = -1; i <= 1; ++i ) { -		for ( int j = -1; j <= 1; ++j ) { -			set(x,y,i,j, get(x,y,i,j) + omega * (equilibrium(d,v,i,j) - get(x,y,i,j))); +		for ( int i = -1; i <= 1; ++i ) { +			for ( int j = -1; j <= 1; ++j ) { +				set(x,y,i,j, get(x,y,i,j) + omega * (equilibrium(d,v,i,j) - get(x,y,i,j))); +			}  		}  	}  } diff --git a/src/shader/code/stream.glsl b/src/shader/code/stream.glsl index 345127d..a8aec1d 100644 --- a/src/shader/code/stream.glsl +++ b/src/shader/code/stream.glsl @@ -3,8 +3,9 @@ static const std::string STREAM_SHADER_CODE = R"(  layout (local_size_x = 1, local_size_y = 1) in; -layout (std430, binding=1) buffer bufferCollide{ float collideCells[]; }; -layout (std430, binding=2) buffer bufferStream{  float streamCells[]; }; +layout (std430, binding=1) buffer bufferCollide  { float collideCells[];  }; +layout (std430, binding=2) buffer bufferStream   { float streamCells[];   }; +layout (std430, binding=4) buffer bufferGeometry { int   materialCells[]; };  /// LBM constants @@ -33,6 +34,10 @@ void set(uint x, uint y, int i, int j, float v) {  	streamCells[indexOfLatticeCell(x,y) + indexOfDirection(i,j)] = v;  } +int getMaterial(uint x, uint y) { +	return materialCells[nX*y + x]; +} +  /// Domain description  bool isEndOfWorld(uint x, uint y) { @@ -63,11 +68,13 @@ void main() {  		return;  	} -	if ( isEndOfWorld(x,y) ) { +	const int material = getMaterial(x,y); + +	if ( material == 0 ) {  		return;  	} -	if ( isOuterWall(x,y) ) { +	if ( material == 2 ) {  		bounceBack(x,y);  	} diff --git a/src/shader/code/vertex.glsl b/src/shader/code/vertex.glsl index 700a9b7..52d9403 100644 --- a/src/shader/code/vertex.glsl +++ b/src/shader/code/vertex.glsl @@ -10,7 +10,7 @@ out VS_OUT {  uniform uint nX;  uniform uint nY; -const float displayAmplifier = 5.0; +const float displayAmplifier = 50.0;  float unit(float x) {  	return 1.0/(1.0+exp(-x)); @@ -42,10 +42,14 @@ void main() {  		1.  	); -	vs_out.color = mix( -		vec3(-0.5, 0.0, 1.0), -		vec3( 1.0, 0.0, 0.0), -		displayAmplifier * VertexPosition.z * norm(VertexPosition.xy) -	); +	if ( VertexPosition.z < -1.0 ) { +		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), +			displayAmplifier * VertexPosition.z * norm(VertexPosition.xy) +		); +	}  }  )"; | 
