From 7195ca0ec61830ea95010740bd744ebf3ef6d1b4 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Tue, 4 Aug 2020 00:42:13 -0700 Subject: [PATCH] Add simple_render_pass class and add task support to logger --- CMakeLists.txt | 4 +- src/animation/animation.cpp | 6 - src/animation/animation.hpp | 24 ++-- src/animation/animator.cpp | 26 ++++ src/animation/animator.hpp | 35 ++++++ src/application.cpp | 189 +++++++++++++++++----------- src/application.hpp | 57 ++++++--- src/debug/logger.cpp | 43 ++++++- src/debug/logger.hpp | 20 +++ src/nest.cpp | 4 +- src/renderer/renderer.cpp | 6 + src/renderer/renderer.hpp | 6 + src/renderer/simple-render-pass.cpp | 115 +++++++++++++++++ src/renderer/simple-render-pass.hpp | 74 +++++++++++ src/resources/resource-manager.cpp | 8 +- src/resources/resource-manager.hpp | 25 ++++ src/state/loading-state.cpp | 8 +- src/state/play-state.cpp | 12 +- src/state/splash-state.cpp | 40 ++++-- src/state/title-state.cpp | 19 +-- src/systems/ui-system.cpp | 10 ++ src/systems/ui-system.hpp | 5 + 22 files changed, 599 insertions(+), 137 deletions(-) create mode 100644 src/animation/animator.cpp create mode 100644 src/animation/animator.hpp create mode 100644 src/renderer/simple-render-pass.cpp create mode 100644 src/renderer/simple-render-pass.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a77be21..7273e10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.7) option(VERSION_STRING "Project version string" "0.0.0") -project(antkeeper VERSION ${VERSION_STRING}) +project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) # Set compiler flags if(CMAKE_COMPILER_IS_GNUCC) @@ -15,6 +15,7 @@ elseif(MSVC) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /Ox") endif() + # Find dependency packages find_package(vmq REQUIRED CONFIG) find_package(dr_wav REQUIRED CONFIG) @@ -119,3 +120,4 @@ elseif(PACKAGE_PLATFORM MATCHES "win") endif() install(FILES ${OPENAL_DLL} DESTINATION .) endif() + diff --git a/src/animation/animation.cpp b/src/animation/animation.cpp index 1fcb933..53a9b1d 100644 --- a/src/animation/animation.cpp +++ b/src/animation/animation.cpp @@ -21,9 +21,3 @@ void animation_base::animate(float dt) {} - -void animator::animate(float dt) -{ - -} - diff --git a/src/animation/animation.hpp b/src/animation/animation.hpp index 17b7c06..ff104a3 100644 --- a/src/animation/animation.hpp +++ b/src/animation/animation.hpp @@ -22,6 +22,18 @@ #include +class animation_channel_base +{ + +}; + +template +class animation_channel: public animation_channel_base +{ +public: + void insert_keyframe(float position, const T& value); +}; + class animation_base { public: @@ -49,16 +61,4 @@ class skeletal_animation: public animation }; -class animator -{ -public: - /** - * Progresses all active animations by @p dt. - * - * @param dt Delta time by which the animations will be progressed. - */ - void animate(float dt); -}; - #endif // ANTKEEPER_ANIMATION_HPP - diff --git a/src/animation/animator.cpp b/src/animation/animator.cpp new file mode 100644 index 0000000..b537368 --- /dev/null +++ b/src/animation/animator.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#include "animator.hpp" + +void animator::animate(float dt) +{ + +} + diff --git a/src/animation/animator.hpp b/src/animation/animator.hpp new file mode 100644 index 0000000..f93ff7c --- /dev/null +++ b/src/animation/animator.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_ANIMATOR_HPP +#define ANTKEEPER_ANIMATOR_HPP + +class animator +{ +public: + /** + * Progresses all active animations by @p dt. + * + * @param dt Delta time by which the animations will be progressed. + */ + void animate(float dt); +}; + +#endif // ANTKEEPER_ANIMATOR_HPP + diff --git a/src/application.cpp b/src/application.cpp index 22951e8..0d9e2ff 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -62,6 +62,7 @@ #include "rasterizer/texture-filter.hpp" // Renderer +#include "renderer/simple-render-pass.hpp" #include "renderer/passes/shadow-map-pass.hpp" #include "renderer/passes/sky-pass.hpp" #include "renderer/passes/clear-pass.hpp" @@ -70,6 +71,10 @@ #include "renderer/passes/final-pass.hpp" #include "renderer/vertex-attributes.hpp" #include "renderer/material-flags.hpp" +#include "renderer/material-property.hpp" + +// Animation +#include "animation/animator.hpp" // Scene #include "scene/billboard.hpp" @@ -148,20 +153,21 @@ application::application(int argc, char** argv): { if (!path_exists(path)) { - logger.log("Creating directory \"" + path + "\"... "); + int create_path_task = logger.open_task("Creating directory \"" + path + "\""); if (create_directory(path)) { - logger.success("success\n"); + logger.close_task(create_path_task, EXIT_SUCCESS); } else { - logger.error("failed\n"); + logger.close_task(create_path_task, EXIT_FAILURE); } } } // Setup resource manager resource_manager = new ::resource_manager(); + resource_manager->set_logger(&logger); // Include resource search paths in order of priority resource_manager->include(config_path); @@ -188,26 +194,26 @@ application::application(int argc, char** argv): logger.log("Linking against SDL " + sdl_linked_version_string + "\n"); // Init SDL - logger.log("Initializing SDL... "); + int sdl_init_task = logger.open_task("Initializing SDL"); if (SDL_Init(SDL_INIT_VIDEO) != 0) { - logger.log("failed\n"); + logger.close_task(sdl_init_task, EXIT_FAILURE); throw std::runtime_error("Failed to initialize SDL"); } else { - logger.log("success\n"); + logger.close_task(sdl_init_task, EXIT_SUCCESS); } // Load default OpenGL library - logger.log("Loading OpenGL library... "); + int load_gl_task = logger.open_task("Loading OpenGL library"); if (SDL_GL_LoadLibrary(nullptr) != 0) { - logger.log("failed\n"); + logger.close_task(load_gl_task, EXIT_FAILURE); } else { - logger.log("success\n"); + logger.close_task(load_gl_task, EXIT_SUCCESS); } // Set window creation hints @@ -231,61 +237,71 @@ application::application(int argc, char** argv): int window_width = 1920; int window_height = 1080; fullscreen = true; + + window_width = 1280; + window_height = 720; + fullscreen = false; viewport = {0.0f, 0.0f, static_cast(window_width), static_cast(window_height)}; + + int window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; + if (fullscreen) + { + window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + } // Create window - logger.log("Creating " + std::to_string(window_width) + "x" + std::to_string(window_height) + " window... "); + int window_creation_task = logger.open_task("Creating " + std::to_string(window_width) + "x" + std::to_string(window_height) + " window"); window = SDL_CreateWindow ( "Antkeeper", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, - SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_FULLSCREEN_DESKTOP + window_flags ); if (!window) { - logger.error("failed\n"); + logger.close_task(window_creation_task, EXIT_FAILURE); throw std::runtime_error("Failed to create SDL window"); } else { - logger.success("success\n"); + logger.close_task(window_creation_task, EXIT_SUCCESS); } // Create OpenGL context - logger.log("Creating OpenGL 3.3 context... "); + int create_gl_context_task = logger.open_task("Creating OpenGL 3.3 context"); context = SDL_GL_CreateContext(window); if (!context) { - logger.error("failed\n"); + logger.close_task(create_gl_context_task, EXIT_FAILURE); throw std::runtime_error("Failed to create OpenGL context"); } else { - logger.success("success\n"); + logger.close_task(create_gl_context_task, EXIT_SUCCESS); } // Load OpenGL functions via GLAD - logger.log("Loading OpenGL functions... "); + int load_gl_functions_task = logger.open_task("Loading OpenGL functions"); if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { - logger.error("failed\n"); + logger.close_task(load_gl_functions_task, EXIT_FAILURE); } else { - logger.success("success\n"); + logger.close_task(load_gl_functions_task, EXIT_SUCCESS); } // Set v-sync mode int swap_interval = 1; - logger.log((swap_interval) ? "Enabling v-sync... " : "Disabling v-sync... "); + int set_vsync_task = logger.open_task((swap_interval) ? "Enabling v-sync" : "Disabling v-sync"); if (SDL_GL_SetSwapInterval(swap_interval) != 0) { - logger.error("failed\n"); + logger.close_task(set_vsync_task, EXIT_FAILURE); } else { - logger.success("success\n"); + logger.close_task(set_vsync_task, EXIT_SUCCESS); } // Setup rasterizer @@ -303,27 +319,27 @@ application::application(int argc, char** argv): SDL_ShowCursor(SDL_DISABLE); // Init SDL joystick and game controller subsystems - logger.log("Initializing SDL Joystick and Game Controller subsystems... "); + int init_sdl_subsystems_task = logger.open_task("Initializing SDL Joystick and Game Controller subsystems"); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) != 0) { - logger.log("failed\n"); + logger.close_task(init_sdl_subsystems_task, EXIT_FAILURE); throw std::runtime_error("Failed to initialize SDL Joystick or Game Controller subsystems"); } else { - logger.success("success\n"); + logger.close_task(init_sdl_subsystems_task, EXIT_SUCCESS); } // Load SDL game controller mappings - logger.log("Loading SDL game controller mappings from database... "); + int load_controller_db_task = logger.open_task("Loading SDL game controller mappings from database"); std::string gamecontrollerdb_path = data_path + "controls/gamecontrollerdb.txt"; if (SDL_GameControllerAddMappingsFromFile(gamecontrollerdb_path.c_str()) == -1) { - logger.error("failed\n"); + logger.close_task(load_controller_db_task, EXIT_FAILURE); } else { - logger.success("success\n"); + logger.close_task(load_controller_db_task, EXIT_SUCCESS); } // Setup billboard VAO @@ -355,7 +371,6 @@ application::application(int argc, char** argv): // Load fallback material fallback_material = resource_manager->load("fallback.mtl"); - // Create shadow map depth texture and framebuffer shadow_map_resolution = 4096; shadow_map_depth_texture = new texture_2d(shadow_map_resolution, shadow_map_resolution, pixel_type::float_32, pixel_format::d); @@ -388,7 +403,7 @@ application::application(int argc, char** argv): framebuffer_bloom = new framebuffer(bloom_width, bloom_height); framebuffer_bloom->attach(framebuffer_attachment_type::color, bloom_texture); - // Setup default compositor + // Setup overworld passes shadow_map_clear_pass = new ::clear_pass(rasterizer, shadow_map_framebuffer); shadow_map_clear_pass->set_cleared_buffers(false, true, false); shadow_map_pass = new ::shadow_map_pass(rasterizer, shadow_map_framebuffer, resource_manager); @@ -402,35 +417,65 @@ application::application(int argc, char** argv): material_pass->set_focal_point_tween(&focal_point_tween); material_pass->shadow_map_pass = shadow_map_pass; material_pass->shadow_map = shadow_map_depth_texture; - bloom_pass = new ::bloom_pass(rasterizer, framebuffer_bloom, resource_manager); bloom_pass->set_source_texture(framebuffer_hdr_color); bloom_pass->set_brightness_threshold(1.0f); bloom_pass->set_blur_iterations(4); bloom_pass->set_enabled(false); - final_pass = new ::final_pass(rasterizer, &rasterizer->get_default_framebuffer(), resource_manager); final_pass->set_color_texture(framebuffer_hdr_color); final_pass->set_bloom_texture(bloom_texture); - default_compositor.add_pass(shadow_map_clear_pass); - default_compositor.add_pass(shadow_map_pass); - default_compositor.add_pass(clear_pass); - default_compositor.add_pass(sky_pass); - default_compositor.add_pass(material_pass); - default_compositor.add_pass(bloom_pass); - default_compositor.add_pass(final_pass); + // Setup overworld compositor + overworld_compositor.add_pass(shadow_map_clear_pass); + overworld_compositor.add_pass(shadow_map_pass); + overworld_compositor.add_pass(clear_pass); + overworld_compositor.add_pass(sky_pass); + overworld_compositor.add_pass(material_pass); + overworld_compositor.add_pass(bloom_pass); + overworld_compositor.add_pass(final_pass); + + // Setup overworld camera + overworld_camera.set_perspective(45.0f * vmq::pi / 180.0f, (float)window_width / (float)window_height, 0.1f, 1000.0f); + overworld_camera.set_compositor(&overworld_compositor); + overworld_camera.set_composite_index(0); + overworld_camera.set_active(true); + + // Setup underworld passes + underworld_clear_pass = new ::clear_pass(rasterizer, framebuffer_hdr); + underworld_clear_pass->set_cleared_buffers(true, true, false); + + + underworld_material_pass = new ::material_pass(rasterizer, framebuffer_hdr, resource_manager); + underworld_material_pass->set_fallback_material(fallback_material); + underworld_material_pass->set_time_tween(&time); + underworld_material_pass->set_focal_point_tween(&focal_point_tween); + + shader_program* underworld_final_shader = resource_manager->load("underground-final.glsl"); + underworld_final_pass = new simple_render_pass(rasterizer, &rasterizer->get_default_framebuffer(), underworld_final_shader); + underworld_final_pass->set_time_tween(&time); + underground_transition_property = underworld_final_pass->get_material()->add_property("transition"); + underground_color_texture_property = underworld_final_pass->get_material()->add_property("color_texture"); + underground_color_texture_property->set_value(framebuffer_hdr_color); + + // Setup underworld compositor + underworld_compositor.add_pass(underworld_clear_pass); + underworld_compositor.add_pass(underworld_material_pass); + underworld_compositor.add_pass(underworld_final_pass); - // Setup default camera - default_camera.set_perspective(45.0f * vmq::pi / 180.0f, (float)window_width / (float)window_height, 0.1f, 1000.0f); - default_camera.set_compositor(&default_compositor); - default_camera.set_composite_index(1); + // Setup underworld camera + underworld_camera.set_perspective(45.0f * vmq::pi / 180.0f, (float)window_width / (float)window_height, 0.1f, 1000.0f); + underworld_camera.look_at({0, 50, 0}, {0, 0, 0}, {0, 0, -1}); + underworld_camera.set_compositor(&underworld_compositor); + underworld_camera.set_composite_index(0); + underworld_camera.set_active(false); // Setup timeline system timeline.set_autoremove(true); // Setup animation system // ... + animator = new ::animator(); // ECS terrain_system = new ::terrain_system(ecs_registry, resource_manager); @@ -444,7 +489,7 @@ application::application(int argc, char** argv): tool_system = new ::tool_system(ecs_registry); - tool_system->set_camera(&default_camera); + tool_system->set_camera(&overworld_camera); tool_system->set_orbit_cam(&orbit_cam); tool_system->set_viewport(viewport); camera_system = new ::camera_system(ecs_registry); @@ -479,14 +524,14 @@ application::application(int argc, char** argv): systems.push_back([this](double t, double dt){ this->subterrain_light.set_translation(orbit_cam.get_focal_point()); this->lantern.set_translation(orbit_cam.get_focal_point()); - this->spotlight.set_transform(default_camera.get_transform()); + this->spotlight.set_transform(overworld_camera.get_transform()); this->focal_point_tween[1] = orbit_cam.get_focal_point(); }); systems.push_back([this](double t, double dt){ this->ui_system->update(dt); }); systems.push_back(std::bind(&tool_system::update, tool_system, std::placeholders::_1, std::placeholders::_2)); systems.push_back(std::bind(&model_system::update, model_system, std::placeholders::_1, std::placeholders::_2)); - systems.push_back([this](double t, double dt){ this->animator.animate(dt); }); + systems.push_back([this](double t, double dt){ this->animator->animate(dt); }); systems.push_back([this](double t, double dt){ this->application_controls.update(); this->menu_controls.update(); this->camera_controls->update(); }); // Setup FSM states @@ -533,7 +578,7 @@ application::application(int argc, char** argv): // Setup input event routing input_event_router.set_event_dispatcher(&event_dispatcher); input_mapper.set_event_dispatcher(&event_dispatcher); - + // Setup input devices keyboard.set_event_dispatcher(&event_dispatcher); mouse.set_event_dispatcher(&event_dispatcher); @@ -553,7 +598,7 @@ application::application(int argc, char** argv): menu_controls.add_control(&menu_back_control); menu_controls.add_control(&menu_select_control); - orbit_cam.attach(&default_camera); + orbit_cam.attach(&overworld_camera); control_system = new ::control_system(); control_system->set_orbit_cam(&orbit_cam); control_system->set_viewport(viewport); @@ -585,14 +630,20 @@ application::application(int argc, char** argv): control_system->get_toggle_view_control()->set_activated_callback( [this]() { - this->active_scene->remove_object(&this->default_camera); - this->active_scene = (this->active_scene == &this->overworld_scene) ? &this->underworld_scene : &this->overworld_scene; - this->active_scene->add_object(&this->default_camera); - if (this->active_scene == &this->overworld_scene) - this->sky_pass->set_enabled(true); + { + // Switch to underworld + //this->overworld_camera.set_active(false); + this->underworld_camera.set_active(true); + this->active_scene = &this->underworld_scene; + } else - this->sky_pass->set_enabled(false); + { + // Switch to overworld + this->underworld_camera.set_active(false); + this->overworld_camera.set_active(true); + this->active_scene = &this->overworld_scene; + } }); input_event_router.add_mapping(game_controller_axis_mapping(control_system->get_move_forward_control(), nullptr, game_controller_axis::left_y, true)); @@ -738,32 +789,27 @@ application::application(int argc, char** argv): // Setup overworld scene - overworld_scene.add_object(&default_camera); + overworld_scene.add_object(&overworld_camera); overworld_scene.add_object(&sun_indirect); overworld_scene.add_object(&sun_direct); overworld_scene.add_object(&spotlight); overworld_scene.add_object(&cloud); overworld_scene.add_object(arrow_billboard); - underworld_scene.add_object(portal_billboard); - - model_instance* larva = new model_instance(resource_manager->load("larva.obj")); - underworld_scene.add_object(larva); - - model_instance* samara = new model_instance(resource_manager->load("samara.obj")); - samara->set_translation({2, -1, 0}); - underworld_scene.add_object(samara); - - // Setup underworld scene + underworld_scene.add_object(&underworld_camera); underworld_scene.add_object(&underworld_ambient_light); //underworld_scene.add_object(&darkness_volume); underworld_scene.add_object(&lantern); underworld_scene.add_object(&subterrain_light); + underworld_scene.add_object(portal_billboard); + //model_instance* larva = new model_instance(resource_manager->load("larva.obj")); + //underworld_scene.add_object(larva); + model_instance* flashlight = new model_instance(resource_manager->load("flashlight.obj")); + underworld_scene.add_object(flashlight); - + // Set overworld as active scene active_scene = &overworld_scene; - } application::~application() @@ -785,7 +831,7 @@ void application::close(int status) int application::execute() { // Enter inital state - state_machine.change_state(play_state); + state_machine.change_state(splash_state); // Perform initial update update(0.0, 0.0); @@ -833,7 +879,9 @@ void application::render(double alpha) std::cout << performance_sampler.mean_frame_duration() * 1000.0 << std::endl; */ - renderer.render(alpha, *active_scene); + renderer.render(alpha, overworld_scene); + renderer.render(alpha, underworld_scene); + //renderer.render(alpha, *active_scene); renderer.render(alpha, *ui_system->get_scene()); SDL_GL_SwapWindow(window); @@ -1022,7 +1070,8 @@ void application::window_resized() viewport = {0.0f, 0.0f, static_cast(width), static_cast(height)}; rasterizer->window_resized(width, height); - default_camera.set_perspective(default_camera.get_fov(), aspect_ratio, default_camera.get_clip_near(), default_camera.get_clip_far()); + overworld_camera.set_perspective(overworld_camera.get_fov(), aspect_ratio, overworld_camera.get_clip_near(), overworld_camera.get_clip_far()); + underworld_camera.set_perspective(underworld_camera.get_fov(), aspect_ratio, underworld_camera.get_clip_near(), underworld_camera.get_clip_far()); control_system->set_viewport(viewport); camera_system->set_viewport(viewport); tool_system->set_viewport(viewport); diff --git a/src/application.hpp b/src/application.hpp index e1a00af..cd502ff 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -61,7 +61,6 @@ // Animation #include "animation/timeline.hpp" -#include "animation/animation.hpp" #include "animation/tween.hpp" // Misc @@ -93,6 +92,10 @@ class sky_pass; class bloom_pass; class final_pass; + class simple_render_pass; + + // Animation + class animator; // Systems class behavior_system; @@ -109,6 +112,9 @@ class tool_system; class control_system; class ui_system; + + template + class material_property; //} class application @@ -149,7 +155,9 @@ public: const fsm::state& get_pause_state() const; timeline* get_timeline(); animator* get_animator(); - camera* get_camera(); + camera* get_overworld_camera(); + camera* get_underworld_camera(); + orbit_cam* get_orbit_cam(); control_system* get_control_system(); @@ -193,7 +201,7 @@ private: // Updatable systems timeline timeline; - animator animator; + animator* animator; std::list> systems; int shadow_map_resolution; @@ -210,16 +218,8 @@ private: // Rendering rasterizer* rasterizer; material* fallback_material; - ::clear_pass* clear_pass; - ::sky_pass* sky_pass; - ::material_pass* material_pass; - compositor default_compositor; - ::clear_pass* shadow_map_clear_pass; - ::shadow_map_pass* shadow_map_pass; - ::bloom_pass* bloom_pass; - ::final_pass* final_pass; + - camera default_camera; ambient_light sun_indirect; directional_light sun_direct; point_light subterrain_light; @@ -232,9 +232,29 @@ private: vertex_buffer* billboard_vbo; vertex_array* billboard_vao; ::renderer renderer; + scene* active_scene; + + // Overworld scene overworld_scene; + camera overworld_camera; + ::clear_pass* clear_pass; + ::sky_pass* sky_pass; + ::material_pass* material_pass; + ::clear_pass* shadow_map_clear_pass; + ::shadow_map_pass* shadow_map_pass; + ::bloom_pass* bloom_pass; + ::final_pass* final_pass; + compositor overworld_compositor; + + // Underworld scene underworld_scene; - scene* active_scene; + camera underworld_camera; + ::clear_pass* underworld_clear_pass; + ::material_pass* underworld_material_pass; + simple_render_pass* underworld_final_pass; + material_property* underground_transition_property; + material_property* underground_color_texture_property; + compositor underworld_compositor; // FSM fsm::machine state_machine; @@ -354,12 +374,17 @@ inline timeline* application::get_timeline() inline animator* application::get_animator() { - return &animator; + return animator; +} + +inline camera* application::get_overworld_camera() +{ + return &overworld_camera; } -inline camera* application::get_camera() +inline camera* application::get_underworld_camera() { - return &default_camera; + return &underworld_camera; } inline orbit_cam* application::get_orbit_cam() diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp index daceef5..8db6867 100644 --- a/src/debug/logger.cpp +++ b/src/debug/logger.cpp @@ -29,7 +29,8 @@ logger::logger(): error_prefix(std::string("Error: ")), error_postfix(std::string()), success_prefix(std::string("Success: ")), - success_postfix(std::string()) + success_postfix(std::string()), + next_task_id(0) {} logger::~logger() @@ -120,3 +121,43 @@ void logger::pop_prefix() prefix_stack.pop_back(); } +int logger::open_task(const std::string& text) +{ + tasks[next_task_id] = text; + + std::string indent; + for (std::size_t i = 0; i < tasks.size() - 1; ++i) + indent += " "; + + log(indent + text + "...\n"); + + return next_task_id++; +} + +bool logger::close_task(int id, int status) +{ + auto it = tasks.find(id); + if (it == tasks.end()) + return false; + + std::string message = it->second + "... "; + + + std::string indent; + for (std::size_t i = 0; i < tasks.size() - 1; ++i) + indent += " "; + + if (status == EXIT_SUCCESS) + { + message += "success\n"; + log(indent + message); + } + else + { + message += "failed (" + std::to_string(status) + ")\n"; + log(indent + message); + } + + tasks.erase(it); +} + diff --git a/src/debug/logger.hpp b/src/debug/logger.hpp index 86e73ff..97c2a42 100644 --- a/src/debug/logger.hpp +++ b/src/debug/logger.hpp @@ -23,6 +23,7 @@ #include #include #include +#include class logger { @@ -56,6 +57,22 @@ public: void push_prefix(const std::string& prefix); void pop_prefix(); + + /** + * Opens a task and outputs it to the log. + * + * @return Task ID used to close the task later. + */ + int open_task(const std::string& text); + + /** + * Closes a task and outputs its status to the log. + * + * @param id ID of the task to close. + * @param status Exit status of the task. A value of `0` or `EXIT_SUCCESS` indicates the task exited successfully. A non-zero exit status indicates the task failed. + * @return `true` if the task was closed, `false` if no task with the specified ID was found. + */ + bool close_task(int id, int status); private: std::ostream* os; @@ -68,6 +85,9 @@ private: std::string success_prefix; std::string success_postfix; std::list prefix_stack; + int next_task_id; + + std::unordered_map tasks; }; #endif // ANTKEEPER_LOGGER_HPP diff --git a/src/nest.cpp b/src/nest.cpp index 90dd59f..3b5bcf3 100644 --- a/src/nest.cpp +++ b/src/nest.cpp @@ -74,7 +74,7 @@ float nest::get_shaft_angle(const shaft& shaft, float depth) const float shaft_length = shaft.depth[1] - shaft.depth[0]; float depth_factor = (depth - shaft.depth[0]) / shaft_length; float pitch = ease_linear(shaft.pitch[0], shaft.pitch[1], depth_factor); - return shaft.rotation + (depth / pitch) * shaft.chirality; + return shaft.rotation + (depth / pitch) * shaft.chirality * vmq::two_pi; } float3 nest::get_shaft_position(const shaft& shaft, float depth) const @@ -86,7 +86,7 @@ float3 nest::get_shaft_position(const shaft& shaft, float depth) const float radius = ease_out_expo(shaft.radius[0], shaft.radius[1], depth_factor); float translation_x = ease_linear(shaft.translation[0][0], shaft.translation[1][0], depth_factor); float translation_z = ease_linear(shaft.translation[0][1], shaft.translation[1][1], depth_factor); - float angle = shaft.rotation + (depth / pitch) * shaft.chirality; + float angle = shaft.rotation + (depth / pitch) * shaft.chirality * vmq::two_pi; float3 position; position[0] = std::cos(angle) * radius + translation_x; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 311545d..69fff3f 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -70,6 +70,12 @@ void renderer::render(float alpha, const scene& scene) const // Process cameras in order for (const camera* camera: sorted_cameras) { + // Skip inactive cameras + if (!camera->is_active()) + { + continue; + } + // Skip cameras with no compositors const compositor* compositor = camera->get_compositor(); if (!compositor) diff --git a/src/renderer/renderer.hpp b/src/renderer/renderer.hpp index 1724b20..a281de1 100644 --- a/src/renderer/renderer.hpp +++ b/src/renderer/renderer.hpp @@ -49,6 +49,12 @@ class renderer public: renderer(); + /** + * Renders a scene. + * + * @param alpha Subframe interpolation factor. + * @parma scene Scene to render. + */ void render(float alpha, const scene& scene) const; /** diff --git a/src/renderer/simple-render-pass.cpp b/src/renderer/simple-render-pass.cpp new file mode 100644 index 0000000..5768c75 --- /dev/null +++ b/src/renderer/simple-render-pass.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#include "renderer/simple-render-pass.hpp" +#include "rasterizer/rasterizer.hpp" +#include "rasterizer/framebuffer.hpp" +#include "rasterizer/shader-program.hpp" +#include "rasterizer/shader-input.hpp" +#include "rasterizer/vertex-buffer.hpp" +#include "rasterizer/vertex-array.hpp" +#include "rasterizer/vertex-attribute-type.hpp" +#include "rasterizer/drawing-mode.hpp" +#include "rasterizer/texture-2d.hpp" +#include "rasterizer/texture-wrapping.hpp" +#include "rasterizer/texture-filter.hpp" +#include "renderer/vertex-attributes.hpp" +#include "renderer/render-context.hpp" +#include "renderer/material.hpp" +#include "renderer/material-property.hpp" +#include +#include + +using namespace vmq; + +simple_render_pass::simple_render_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, ::shader_program* shader_program): + render_pass(rasterizer, framebuffer), + shader_program(shader_program), + time_tween(nullptr) +{ + // Create material + material = new ::material(shader_program); + + // Add standard properties to material + time_property = material->add_property("time"); + resolution_property = material->add_property("resolution"); + + const float vertex_data[] = + { + -1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f + }; + + std::size_t vertex_size = 3; + std::size_t vertex_stride = sizeof(float) * vertex_size; + std::size_t vertex_count = 6; + + quad_vbo = new vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data); + quad_vao = new vertex_array(); + quad_vao->bind_attribute(VERTEX_POSITION_LOCATION, *quad_vbo, 3, vertex_attribute_type::float_32, vertex_stride, 0); +} + +simple_render_pass::~simple_render_pass() +{ + delete material; + delete quad_vao; + delete quad_vbo; +} + +void simple_render_pass::render(render_context* context) const +{ + // Bind framebuffer + rasterizer->use_framebuffer(*framebuffer); + + // Setup graphics context + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + // Setup viewport + auto viewport = framebuffer->get_dimensions(); + rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport)); + + // Change shader program + rasterizer->use_program(*shader_program); + + // Get interpolated time + float time = (time_tween) ? time_tween->interpolate(context->alpha) : 0.0f; + + // Update material properties + time_property->set_value(time); + resolution_property->set_value({static_cast(std::get<0>(viewport)), static_cast(std::get<1>(viewport))}); + + // Upload material properties + material->upload(); + + // Draw quad + rasterizer->draw_arrays(*quad_vao, drawing_mode::triangles, 0, 6); +} + +void simple_render_pass::set_time_tween(const tween* time) +{ + this->time_tween = time; +} diff --git a/src/renderer/simple-render-pass.hpp b/src/renderer/simple-render-pass.hpp new file mode 100644 index 0000000..0cd5595 --- /dev/null +++ b/src/renderer/simple-render-pass.hpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_SIMPLE_RENDER_PASS_HPP +#define ANTKEEPER_SIMPLE_RENDER_PASS_HPP + +#include "renderer/render-pass.hpp" +#include "animation/tween.hpp" +#include + +using namespace vmq::types; + +class shader_program; +class shader_input; +class vertex_buffer; +class vertex_array; +class material; +template +class material_property; + +/** + * Simple render passes are associated with a single shader and a single material. + */ +class simple_render_pass: public render_pass +{ +public: + simple_render_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, ::shader_program* shader_program); + virtual ~simple_render_pass(); + virtual void render(render_context* context) const final; + + void set_time_tween(const tween* time); + + const ::material* get_material() const; + ::material* get_material(); + +private: + shader_program* shader_program; + material* material; + material_property* time_property; + material_property* resolution_property; + + const tween* time_tween; + + vertex_buffer* quad_vbo; + vertex_array* quad_vao; +}; + +inline const ::material* simple_render_pass::get_material() const +{ + return material; +} + +inline ::material* simple_render_pass::get_material() +{ + return material; +} + +#endif // ANTKEEPER_SIMPLE_RENDER_PASS_HPP diff --git a/src/resources/resource-manager.cpp b/src/resources/resource-manager.cpp index 11fed76..0cbd739 100644 --- a/src/resources/resource-manager.cpp +++ b/src/resources/resource-manager.cpp @@ -19,7 +19,8 @@ #include "resources/resource-manager.hpp" -resource_manager::resource_manager() +resource_manager::resource_manager(): + logger(nullptr) {} resource_manager::~resource_manager() @@ -55,3 +56,8 @@ void resource_manager::include(const std::string& path) paths.push_back(path); } +void resource_manager::set_logger(::logger* logger) +{ + this->logger = logger; +} + diff --git a/src/resources/resource-manager.hpp b/src/resources/resource-manager.hpp index 9357f3a..4246214 100644 --- a/src/resources/resource-manager.hpp +++ b/src/resources/resource-manager.hpp @@ -22,6 +22,7 @@ #include "resource-handle.hpp" #include "resource-loader.hpp" +#include "debug/logger.hpp" #include #include #include @@ -80,11 +81,14 @@ public: void save(const T* resource, const std::string& path); entt::registry& get_archetype_registry(); + + void set_logger(::logger* logger); private: std::map resource_cache; std::list paths; entt::registry archetype_registry; + ::logger* logger; }; template @@ -103,6 +107,12 @@ T* resource_manager::load(const std::string& path) // Return resource data return resource->data; } + + int task_id; + if (logger) + { + task_id = logger->open_task("Loading resource \"" + path + "\""); + } // Resource not found, load resource data T* data = nullptr; @@ -138,11 +148,21 @@ T* resource_manager::load(const std::string& path) if (!opened) { + if (logger) + { + logger->close_task(task_id, EXIT_FAILURE); + } + throw std::runtime_error("resource_manager::load(): Unable to open file \"" + path + "\""); } } catch (const std::exception& e) { + if (logger) + { + logger->close_task(task_id, EXIT_FAILURE); + } + std::string error = std::string("resource_manager::load(): Failed to load resource \"") + path + std::string("\": \"") + e.what() + std::string("\""); throw std::runtime_error(error.c_str()); } @@ -154,6 +174,11 @@ T* resource_manager::load(const std::string& path) // Add resource to the cache resource_cache[path] = resource; + + if (logger) + { + logger->close_task(task_id, EXIT_SUCCESS); + } return resource->data; } diff --git a/src/state/loading-state.cpp b/src/state/loading-state.cpp index 50c7d38..b6e2e18 100644 --- a/src/state/loading-state.cpp +++ b/src/state/loading-state.cpp @@ -24,9 +24,9 @@ void enter_loading_state(application* app) { logger* logger = app->get_logger(); - logger->log("Entering loading state...\n"); + int task_id = logger->open_task("Entering loading state"); - logger->success("Entering loading state... success\n"); + logger->close_task(task_id, EXIT_SUCCESS); app->get_state_machine()->change_state(app->get_title_state()); } @@ -34,8 +34,8 @@ void enter_loading_state(application* app) void exit_loading_state(application* app) { logger* logger = app->get_logger(); - logger->log("Exiting loading state...\n"); + int task_id = logger->open_task("Exiting loading state"); - logger->success("Exiting loading state... success\n"); + logger->close_task(task_id, EXIT_SUCCESS); } diff --git a/src/state/play-state.cpp b/src/state/play-state.cpp index 77ad665..d0015c7 100644 --- a/src/state/play-state.cpp +++ b/src/state/play-state.cpp @@ -44,7 +44,7 @@ using namespace vmq::operators; void enter_play_state(application* app) { logger* logger = app->get_logger(); - logger->log("Entering play state...\n"); + int enter_state_task = logger->open_task("Entering play state"); resource_manager* resource_manager = app->get_resource_manager(); @@ -138,8 +138,8 @@ void enter_play_state(application* app) ecs_registry.get(grass_entity_2).transform.rotation = vmq::angle_axis(vmq::radians(120.0f), float3{0, 1, 0}); */ - // Setup camera - camera* camera = app->get_camera(); + // Setup overworld camera + camera* camera = app->get_overworld_camera(); orbit_cam* orbit_cam = app->get_orbit_cam(); orbit_cam->attach(camera); orbit_cam->set_target_focal_point({0, 0, 0}); @@ -227,14 +227,16 @@ void enter_play_state(application* app) control_system->set_nest(nest); orbit_cam->update(0.0f); - logger->success("Entering play state... success\n"); + logger->close_task(enter_state_task, EXIT_SUCCESS); } void exit_play_state(application* app) { logger* logger = app->get_logger(); logger->log("Exiting play state...\n"); + + int exit_state_task = logger->open_task("Exiting play state"); - logger->success("Exiting play state... success\n"); + logger->close_task(exit_state_task, EXIT_SUCCESS); } diff --git a/src/state/splash-state.cpp b/src/state/splash-state.cpp index a58cd58..76e6c5f 100644 --- a/src/state/splash-state.cpp +++ b/src/state/splash-state.cpp @@ -19,32 +19,52 @@ #include "application-states.hpp" #include "application.hpp" + +#include #include void enter_splash_state(application* app) { - logger* logger = app->get_logger(); - logger->log("Entering splash state...\n"); + logger* logger = app->get_logger(); + int task_id = logger->open_task("Entering splash state"); + + auto fade_in = [logger]() + { + logger->log("cue logo fade-in\n"); + }; + + auto fade_out = [logger]() + { + logger->log("cue logo fade-out\n"); + }; + auto change_state = [app]() + { + app->get_state_machine()->change_state(app->get_title_state()); + }; + + // Get timeline timeline* timeline = app->get_timeline(); - float t = timeline->get_position(); + // Create splash sequence + float t = timeline->get_position(); sequence splash_sequence = { - {t + 0.0f, [logger](){ logger->log("cue logo fade-in\n"); }}, - {t + 3.0f, [logger](){ logger->log("cue logo fade-out\n"); }}, - {t + 8.0f, [app](){ app->get_state_machine()->change_state(app->get_play_state()); }} + {t + 0.0f, fade_in}, + {t + 3.0f, fade_out}, + {t + 8.0f, change_state} }; + // Add splash sequence to timeline timeline->add_sequence(splash_sequence); - logger->success("Entering splash state... success\n"); + logger->close_task(task_id, EXIT_SUCCESS); } void exit_splash_state(application* app) { logger* logger = app->get_logger(); - logger->log("Exiting splash state...\n"); - logger->success("Exiting splash state... success\n"); + int task_id = logger->open_task("Exiting splash state"); + + logger->close_task(task_id, EXIT_SUCCESS); } - diff --git a/src/state/title-state.cpp b/src/state/title-state.cpp index ae742dd..3834fa9 100644 --- a/src/state/title-state.cpp +++ b/src/state/title-state.cpp @@ -19,17 +19,18 @@ #include "application-states.hpp" #include "application.hpp" -#include void enter_title_state(application* app) { logger* logger = app->get_logger(); - logger->log("Entering title state...\n"); + int task_id = logger->open_task("Entering title state"); + // Get timeline timeline* timeline = app->get_timeline(); + + // Create title sequence float t = timeline->get_position(); - - sequence startup_sequence = + sequence title_sequence = { {t + 0.0f, [logger](){ logger->log("cue sound fade-in\n"); }}, {t + 3.0f, [logger](){ logger->log("cue scene fade-in from black\n"); }}, @@ -37,17 +38,17 @@ void enter_title_state(application* app) {t + 10.0f, [logger](){ logger->log("cue menu fade-in\n"); }} }; - timeline->add_sequence(startup_sequence); + // Add title sequence to timeline + timeline->add_sequence(title_sequence); - logger->success("Entering title state... success\n"); + logger->close_task(task_id, EXIT_SUCCESS); } void exit_title_state(application* app) { logger* logger = app->get_logger(); - logger->log("Exiting title state...\n"); - + int task_id = logger->open_task("Exiting title state"); - logger->success("Exiting title state... success\n"); + logger->close_task(task_id, EXIT_SUCCESS); } diff --git a/src/systems/ui-system.cpp b/src/systems/ui-system.cpp index 4668ad2..9a5d5e7 100644 --- a/src/systems/ui-system.cpp +++ b/src/systems/ui-system.cpp @@ -158,3 +158,13 @@ void ui_system::close_tool_menu() scene.remove_object(&tool_selector_bg); scene.remove_object(&tool_selector_ant); } + +void ui_system::open_elevator_menu() +{ + +} + +void ui_system::close_elevator_menu() +{ + +} diff --git a/src/systems/ui-system.hpp b/src/systems/ui-system.hpp index 14a311b..1a53752 100644 --- a/src/systems/ui-system.hpp +++ b/src/systems/ui-system.hpp @@ -58,6 +58,9 @@ private: void open_tool_menu(); void close_tool_menu(); + + void open_elevator_menu(); + void close_elevator_menu(); ::resource_manager* resource_manager; ::scene scene; @@ -69,6 +72,8 @@ private: material modal_bg_material; billboard modal_bg; + billboard underground_bg; + model_instance energy_symbol; float2 mouse_position;