diff --git a/Shader/particle_render.gs b/Shader/particle_render.gs index da62be7..a904448 100644 --- a/Shader/particle_render.gs +++ b/Shader/particle_render.gs @@ -3,6 +3,7 @@ uniform mat4 projection; uniform mat4 view; +uniform vec3 camera_pos; uniform vec3 quad1, quad2; @@ -22,7 +23,7 @@ void main() { if(type_pass[0] != 0) { // This is not a generator particle - vec3 old_pos = gl_in[0].gl_Position.xyz; + vec3 old_pos = gl_in[0].gl_Position.xyz - camera_pos; float size = size_pass[0]; mat4 view_projection_matrix = projection * view; diff --git a/cpp/ParticleSystem.cpp b/cpp/ParticleSystem.cpp index b36daf8..795ee59 100644 --- a/cpp/ParticleSystem.cpp +++ b/cpp/ParticleSystem.cpp @@ -107,6 +107,8 @@ void ParticleSystem::set_camera(const Camera &camera) { quad2 = glm::cross(camera.forward(), quad1); quad2 = glm::normalize(quad2); + + camera_pos = camera.get_translation(); } void ParticleSystem::render() { @@ -120,6 +122,7 @@ void ParticleSystem::render() { render_shader.setMat4("view", view_matrix); render_shader.setVec3("quad1", quad1); render_shader.setVec3("quad2", quad2); + render_shader.setVec3("camera_pos", camera_pos); texture->bind_to(0); diff --git a/include/Gedeng/Camera.h b/include/Gedeng/Camera.h index 731f45b..2e27e34 100644 --- a/include/Gedeng/Camera.h +++ b/include/Gedeng/Camera.h @@ -1,9 +1,13 @@ #pragma once +#include +#include #include #include #include +#include "Gedeng/Logger.h" +#include "Input.h" #include "Spatial.h" namespace Gedeng { @@ -28,4 +32,56 @@ class Camera : public Spatial { glm::mat4 projection; }; +class FPSCamera : public Camera { + public: + FPSCamera(float fov, float width, float height, float near, float far) + : Camera(fov, width, height, near, far), move_speed(glm::vec3(5.0, 5.0, 5.0)), mouse_sensitivity(0.1), + last_mouse_position(Input::get_mouse_position()), pitch(0.0), yaw(0.0) { + } + + void update(float delta) { + if (Input::is_key_down(GLFW_KEY_W)) { + translate(glm::vec3(0.0, 0.0, -1.0) * move_speed * delta); + } + if (Input::is_key_down(GLFW_KEY_S)) { + translate(-glm::vec3(0.0, 0.0, -1.0) * move_speed * delta); + } + if (Input::is_key_down(GLFW_KEY_D)) { + translate(glm::vec3(1.0, 0.0, 0.0) * move_speed * delta); + } + if (Input::is_key_down(GLFW_KEY_A)) { + translate(-glm::vec3(1.0, 0.0, 0.0) * move_speed * delta); + } + if (Input::is_key_down(GLFW_KEY_Q)) { + translate(glm::vec3(0.0, 1.0, 0.0) * move_speed * delta); + } + if (Input::is_key_down(GLFW_KEY_E)) { + translate(-glm::vec3(0.0, 1.0, 0.0) * move_speed * delta); + } + + glm::vec2 mouse_difference = Input::get_mouse_position() - last_mouse_position; + + yaw -= mouse_difference.x * mouse_sensitivity; + pitch -= mouse_difference.y * mouse_sensitivity; + + if (pitch > 80.0f) pitch = 80.0f; + if (pitch < -80.0f) pitch = -80.0f; + + glm::qua rotation = glm::angleAxis(glm::radians((float)yaw), glm::vec3(0.f, 1.f, 0.f)); + rotation *= glm::angleAxis(glm::radians((float)pitch), glm::vec3(1.f, 0.f, 0.f)); + + set_rotation_from_quat(rotation); + + last_mouse_position = Input::get_mouse_position(); + } + + private: + glm::vec3 move_speed; + float mouse_sensitivity; + + glm::vec2 last_mouse_position; + float pitch; + float yaw; +}; + } // namespace Gedeng \ No newline at end of file diff --git a/include/Gedeng/Input.h b/include/Gedeng/Input.h index 1212999..f990441 100644 --- a/include/Gedeng/Input.h +++ b/include/Gedeng/Input.h @@ -7,6 +7,8 @@ #include #include "RenderBackend.h" +#include +#include #include namespace Gedeng { @@ -15,6 +17,10 @@ class Input { public: static void initialize(GLFWwindow *window) { glfwSetKeyCallback(window, key_callback); + glfwSetCursorPosCallback(window, mouse_callback); + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + is_mouse_active = true; } // FIXME: Ignore warnings produced by these unused variables -- they're required for the callback to work: @@ -25,6 +31,11 @@ class Input { Input::set_key_down(key, action == GLFW_RELEASE ? false : true); } + static void mouse_callback(GLFWwindow *window, double xpos, double ypos) { + mouse_position.x = xpos; + mouse_position.y = ypos; + } + static void poll_input() { glfwPollEvents(); } @@ -37,7 +48,14 @@ class Input { return keys_down[key]; } + static glm::vec2 get_mouse_position() { + return is_mouse_active ? mouse_position : glm::vec2(0.0, 0.0); + } + + private: inline static std::map keys_down; + inline static glm::vec2 mouse_position; + inline static bool is_mouse_active; }; } // namespace Gedeng \ No newline at end of file diff --git a/include/Gedeng/ParticleSystem.h b/include/Gedeng/ParticleSystem.h index cffe764..223d24c 100644 --- a/include/Gedeng/ParticleSystem.h +++ b/include/Gedeng/ParticleSystem.h @@ -57,6 +57,7 @@ class ParticleSystem { glm::mat4 projection_matrix, view_matrix; glm::vec3 quad1, quad2; + glm::vec3 camera_pos; float elapsed_time; float next_generation_time; diff --git a/include/Gedeng/Spatial.h b/include/Gedeng/Spatial.h index f43db31..c8357cb 100644 --- a/include/Gedeng/Spatial.h +++ b/include/Gedeng/Spatial.h @@ -16,7 +16,7 @@ class Spatial { matrix = glm::translate(matrix, offset); } - glm::vec3 get_translation() { + glm::vec3 get_translation() const { return glm::vec3(matrix[3]); } diff --git a/test/particle-demo/main.cpp b/test/particle-demo/main.cpp index 6294dff..553a72a 100644 --- a/test/particle-demo/main.cpp +++ b/test/particle-demo/main.cpp @@ -9,72 +9,76 @@ class ParticleApp : public Gedeng::Application { public: ParticleApp(unsigned long ms_per_update, unsigned int window_size_x, unsigned int window_size_y, Gedeng::String window_name) - : Application(ms_per_update, window_size_x, window_size_y, window_name), - camera(Gedeng::Camera(90, 1920, 1080, 0.1, 1000.0)), + : Application(ms_per_update, window_size_x, window_size_y, window_name), number_of_steps(10.0), + number_of_refinement_steps(10.0), bump_depth(0.1), + render_shader(Gedeng::Shader("Shader/bump.vs", "Shader/bump.fs")), + camera(Gedeng::FPSCamera(90, 1920, 1080, 0.1, 1000.0)), albedo("Resources/Textures/PavingStones/PavingStones070_2K_Color.jpg", Gedeng::Texture::Settings()), bump("Resources/Textures/PavingStones/PavingStones070_2K_Displacement.jpg", Gedeng::Texture::Settings()), normal("Resources/Textures/PavingStones/PavingStones070_2K_Normal.jpg", Gedeng::Texture::Settings()) { - // Move and rotate the camera so we see the quad well - // camera.translate(glm::vec3(0.0, 0.0, -1.0)); - // camera.rotate(180, glm::vec3(0.0, 1.0, 0.0)); - - particles.set_position(glm::vec3(0.0f, 0.0f, -5.0f)); + particles.set_position(glm::vec3(0.0f, 0.0f, -10.0f)); particles.set_velocity(glm::vec3(-5, 0, -5), glm::vec3(5, 20, 5)); particles.set_gravity(glm::vec3(0, -5, 0)); particles.set_color(glm::vec3(0.0f, 0.5f, 1.0f)); particles.set_lifetime(1.5f, 3.0f); particles.set_size(0.75f); - particles.set_interval(0.2f); + particles.set_interval(0.5f); particles.set_number_of_particles(30); particles.set_texture(&albedo); + + camera.translate(glm::vec3(0.0, 0.0, 1.0)); + // camera.rotate(30, glm::vec3(1.0, 0.0, 0.0)); } ~ParticleApp() = default; void fixed_update(double delta) override { // camera.rotate(delta * 180, glm::vec3(0.0, 1.0, 0.0)); + camera.update(delta); } void dynamic_update(double delta) override { - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClearColor(0.85f, 0.9f, 0.94f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - /* render_shader.use(); + render_shader.use(); - // Camera - render_shader.setMat4("projection", camera.get_projection()); - render_shader.setMat4("view", camera.get_view()); - render_shader.setVec3("viewPos", camera.get_translation()); + // Camera + render_shader.setMat4("projection", camera.get_projection()); + render_shader.setMat4("view", camera.get_view()); + render_shader.setVec3("viewPos", camera.get_translation()); - // Lighting - render_shader.setVec3("lightPos", glm::vec3(0.0, 1.0, 5.0)); + // Lighting + render_shader.setVec3("lightPos", glm::vec3(0.0, 1.0, 5.0)); - render_shader.setFloat("number_of_steps", glm::max(0.0f, number_of_steps)); - render_shader.setFloat("number_of_refinement_steps", glm::max(0.0f, number_of_refinement_steps)); - render_shader.setFloat("bump_depth", glm::max(0.0f, bump_depth)); + render_shader.setFloat("number_of_steps", glm::max(0.0f, number_of_steps)); + render_shader.setFloat("number_of_refinement_steps", glm::max(0.0f, number_of_refinement_steps)); + render_shader.setFloat("bump_depth", glm::max(0.0f, bump_depth)); - // Textures - albedo.bind_to(0); - normal.bind_to(1); - bump.bind_to(2); + // Textures + albedo.bind_to(0); + normal.bind_to(1); + bump.bind_to(2); - // Quad which is rendered onto - quad_mesh.rotate(delta * 25.0f, glm::normalize(glm::vec3(0.0, 0.0, 1.0))); - quad_mesh.render(render_shader); - - debug_text.render_text(25.0f, 25.0f, 1.0f, Gedeng::Vector3(1.0, 1.0, 0.0)); */ + // Quad which is rendered onto + quad_mesh.render(render_shader); + // Particles particles.set_camera(camera); particles.update(delta); particles.render(); } private: - Gedeng::ParticleSystem particles; + float number_of_steps; + float number_of_refinement_steps; + float bump_depth; + + Gedeng::Shader render_shader; Gedeng::VertexBuffer vertex_rectangle; - Gedeng::Camera camera; + Gedeng::FPSCamera camera; Gedeng::Texture albedo; Gedeng::Texture bump; @@ -82,7 +86,7 @@ class ParticleApp : public Gedeng::Application { Gedeng::QuadMesh quad_mesh; - Gedeng::TextLabel debug_text; + Gedeng::ParticleSystem particles; }; Gedeng::Application *Gedeng::create_application() {