diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cc | 143 | ||||
-rw-r--r-- | src/window.h | 59 |
2 files changed, 130 insertions, 72 deletions
diff --git a/src/main.cc b/src/main.cc index a691322..7446609 100644 --- a/src/main.cc +++ b/src/main.cc @@ -8,6 +8,8 @@ #include <memory> #include <algorithm> +#include "window.h" + #include "particle_vertex_buffer.h" #include "texture_display_buffer.h" @@ -26,18 +28,11 @@ const unsigned int particle_count = 2500; const unsigned int max_ups = 100; const unsigned int texture_count = 20; -unsigned int window_width = 800; -unsigned int window_height = 600; -float world_width, world_height; -glm::mat4 MVP; - -std::vector<std::unique_ptr<TextureBuffer>> textureBuffers; -std::unique_ptr<ParticleVertexBuffer> particleBuffer; - -void updateMVP() { - world_width = 20.f; - world_height = world_width / window_width * window_height; +float getWorldHeight(int window_width, int window_height, float world_width) { + return world_width / window_width * window_height; +} +glm::mat4 getMVP(float world_width, float world_height) { glm::mat4 projection = glm::ortho( -(world_width /2), world_width/2, -(world_height/2), world_height/2, @@ -50,21 +45,10 @@ void updateMVP() { glm::vec3(0,1,0) ); - MVP = projection * view; -} - -void window_size_callback(GLFWwindow*, int width, int height) { - window_width = width; - window_height = height; - - for ( auto& textureBuffer : textureBuffers ) { - textureBuffer->resize(width, height); - } - - updateMVP(); + return projection * view; } -std::vector<GLfloat> makeInitialParticles(std::size_t count) { +std::vector<GLfloat> makeInitialParticles(std::size_t count, float world_width, float world_height) { std::vector<GLfloat> buffer; buffer.reserve(3*count); @@ -92,106 +76,121 @@ std::string getShaderFunction(const std::string& fx, const std::string& fy) { int main() { if( !glfwInit() ) { - std::cerr << "Failed to initialize GLFW" << std::endl; + std::cerr << "Failed to initialize GLFW." << std::endl; return -1; } - GLFWwindow* const window = glfwCreateWindow(window_width, window_height, "computicle", NULL, NULL); + Window window("computicle"); - if( window == nullptr ){ - std::cerr << "Failed to open GLFW window." << std::endl; + if ( !window.isGood() ) { + std::cerr << "Failed to open window." << std::endl; glfwTerminate(); return -1; } - glfwSetWindowSizeCallback(window, window_size_callback); - glfwMakeContextCurrent(window); - if ( glewInit() != GLEW_OK ) { - std::cerr << "Failed to initialize GLEW" << std::endl; - glfwTerminate(); - return -1; - } + int window_width = window.getWidth(); + int window_height = window.getHeight(); - updateMVP(); + float world_width = 20.0; + float world_height = getWorldHeight(window_width, window_height, world_width); - for ( unsigned int i = 0; i < texture_count; ++i ) { - textureBuffers.emplace_back( - new TextureBuffer(window_width, window_height)); - } + glm::mat4 MVP = getMVP(world_width, world_height); + + std::vector<std::unique_ptr<TextureBuffer>> texture_buffers; + + std::unique_ptr<ParticleVertexBuffer> particle_buffer; + std::unique_ptr<TextureDisplayBuffer> display_buffer; - particleBuffer = std::make_unique<ParticleVertexBuffer>( - makeInitialParticles(particle_count)); + std::unique_ptr<GraphicShader> scene_shader; + std::unique_ptr<ComputeShader> compute_shader; + std::unique_ptr<GraphicShader> display_shader; - GraphicShader sceneShader(VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE); + window.init([&]() { + for ( unsigned int i = 0; i < texture_count; ++i ) { + texture_buffers.emplace_back( + new TextureBuffer(window_width, window_height)); + } - ComputeShader computeShader( - getShaderFunction("cos(v.x*sin(v.y))", - "sin(v.x-v.y)")); - computeShader.workOn(particleBuffer->getBuffer()); + particle_buffer = std::make_unique<ParticleVertexBuffer>( + makeInitialParticles(particle_count, world_width, world_height)); + display_buffer = std::make_unique<TextureDisplayBuffer>(); - GraphicShader displayShader(DISPLAY_VERTEX_SHADER_CODE, - DISPLAY_FRAGMENT_SHADER_CODE); - TextureDisplayBuffer displayBuffer; + scene_shader = std::make_unique<GraphicShader>( + VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE); + compute_shader = std::make_unique<ComputeShader>( + getShaderFunction("cos(v.x*sin(v.y))", + "sin(v.x-v.y)")); + compute_shader->workOn(particle_buffer->getBuffer()); + display_shader = std::make_unique<GraphicShader>( + DISPLAY_VERTEX_SHADER_CODE, DISPLAY_FRAGMENT_SHADER_CODE); + }); auto lastFrame = std::chrono::high_resolution_clock::now(); auto lastRotate = std::chrono::high_resolution_clock::now(); bool justRotated = true; std::vector<GLuint> textures; - for ( const auto& textureBuffer : textureBuffers ) { - textures.emplace_back(textureBuffer->getTexture()); + for ( const auto& texture_buffer : texture_buffers ) { + textures.emplace_back(texture_buffer->getTexture()); } - do { + window.render([&]() { + if ( window.getWidth() != window_width + || window.getHeight() != window_height ) { + window_width = window.getWidth(); + window_height = window.getHeight(); + world_height = getWorldHeight(window_width, window_height, world_width); + + MVP = getMVP(world_width, world_height); + + for ( auto& texture_buffer : texture_buffers ) { + texture_buffer->resize(window_width, window_height); + } + } + if ( util::millisecondsSince(lastFrame) >= 1000/max_ups ) { - auto guard = computeShader.use(); + auto guard = compute_shader->use(); - computeShader.setUniform("world", world_width, world_height); - computeShader.dispatch(particle_count); + compute_shader->setUniform("world", world_width, world_height); + compute_shader->dispatch(particle_count); lastFrame = std::chrono::high_resolution_clock::now(); } if ( util::millisecondsSince(lastRotate) >= 1000/10 ) { std::rotate(textures.begin(), textures.end()-1, textures.end()); - std::rotate(textureBuffers.begin(), textureBuffers.end()-1, textureBuffers.end()); + std::rotate(texture_buffers.begin(), texture_buffers.end()-1, texture_buffers.end()); justRotated = true; lastRotate = std::chrono::high_resolution_clock::now(); } { - auto texGuard = textureBuffers[0]->use(); - auto sdrGuard = sceneShader.use(); + auto texGuard = texture_buffers[0]->use(); + auto sdrGuard = scene_shader->use(); - sceneShader.setUniform("MVP", MVP); + scene_shader->setUniform("MVP", MVP); if ( justRotated ) { glClear(GL_COLOR_BUFFER_BIT); justRotated = false; } - particleBuffer->draw(); + particle_buffer->draw(); } { - auto guard = displayShader.use(); + auto guard = display_shader->use(); - displayShader.setUniform("screen_textures", textures); - displayShader.setUniform("screen_textures_size", textures.size()); + display_shader->setUniform("screen_textures", textures); + display_shader->setUniform("screen_textures_size", textures.size()); glClear(GL_COLOR_BUFFER_BIT); - displayBuffer.draw(textures); + display_buffer->draw(textures); } - - glfwSwapBuffers(window); - glfwPollEvents(); - } - while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && - glfwWindowShouldClose(window) == 0 ); + }); glfwTerminate(); - return 0; } diff --git a/src/window.h b/src/window.h new file mode 100644 index 0000000..76f1e6a --- /dev/null +++ b/src/window.h @@ -0,0 +1,59 @@ +#pragma once + +class Window { +private: + bool _good = false; + int _width = 800; + int _height = 600; + + GLFWwindow* const _handle; + +public: + Window(const std::string& title): + _handle(glfwCreateWindow(_width, _height, title.c_str(), NULL, NULL)) { + if ( _handle != nullptr ) { + glfwMakeContextCurrent(_handle); + if ( glewInit() == GLEW_OK ) { + _good = true; + } + glfwMakeContextCurrent(nullptr); + } + } + + bool isGood() const { + return _good; + } + + int getWidth() const { + return _width; + } + + int getHeight() const { + return _height; + } + + template <class F> + void init(F f) { + glfwMakeContextCurrent(_handle); + f(); + glfwMakeContextCurrent(nullptr); + } + + template <class F> + void render(F loop) { + glfwMakeContextCurrent(_handle); + + while ( glfwGetKey(_handle, GLFW_KEY_ESCAPE ) != GLFW_PRESS && + glfwWindowShouldClose(_handle) == 0 ) { + glfwGetWindowSize(_handle, &_width, &_height); + + loop(); + + glfwSwapBuffers(_handle); + glfwPollEvents(); + } + + glfwMakeContextCurrent(nullptr); + } + +}; |