From 1346f0cac296181601e5a7f40a678c1812e7931d Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 6 Aug 2020 19:29:46 -0700 Subject: [PATCH] Add screen transition class --- src/animation/animation.hpp | 17 +- src/animation/easings.hpp | 220 +++++++++++++------------- src/animation/screen-transition.cpp | 88 +++++++++++ src/animation/screen-transition.hpp | 65 ++++++++ src/application.cpp | 123 ++++++++------ src/application.hpp | 56 ++++++- src/renderer/material-property.hpp | 30 +++- src/renderer/passes/material-pass.cpp | 5 + src/renderer/passes/material-pass.hpp | 1 + src/state/play-state.cpp | 8 + src/state/splash-state.cpp | 47 ++++-- 11 files changed, 468 insertions(+), 192 deletions(-) create mode 100644 src/animation/screen-transition.cpp create mode 100644 src/animation/screen-transition.hpp diff --git a/src/animation/animation.hpp b/src/animation/animation.hpp index 6bd1865..0d0ae10 100644 --- a/src/animation/animation.hpp +++ b/src/animation/animation.hpp @@ -161,6 +161,9 @@ public: /// Creates an animation channel. animation_channel(const animation_channel& other); + /// Assigns the contents of another channel to this channel. + animation_channel& operator=(const animation_channel& other); + /** * Adds a keyframe to the animation. * @@ -232,6 +235,13 @@ animation_channel::animation_channel(const animation_channel& other): keyframes(other.keyframes) {} +template +animation_channel& animation_channel::operator=(const animation_channel& other) +{ + id = other.id; + keyframes = other.keyframes; +} + template void animation_channel::insert_keyframe(const keyframe& k) { @@ -367,7 +377,6 @@ public: /// @copydoc animation_base::get_duration() const virtual double get_duration() const; - private: std::unordered_map channels; @@ -449,9 +458,7 @@ void animation::advance(double dt) } } else - { - stopped = true; - + { // Call frame callback for end frame if (frame_callback != nullptr) { @@ -465,6 +472,8 @@ void animation::advance(double dt) } } + stopped = true; + // Call end callback if (end_callback) { diff --git a/src/animation/easings.hpp b/src/animation/easings.hpp index 5c34d78..ce8653c 100644 --- a/src/animation/easings.hpp +++ b/src/animation/easings.hpp @@ -54,231 +54,231 @@ #include #include -template -inline T ease_linear(const T& x, const T& y, float a) +template +inline T ease_linear(const T& x, const T& y, S a) { return (y - x) * a + x; } -template -T ease_in_sine(const T& x, const T& y, float a) +template +T ease_in_sine(const T& x, const T& y, S a) { - return -(y - x) * std::cos(a * vmq::half_pi) + (y - x) + x; + return -(y - x) * std::cos(a * vmq::half_pi) + (y - x) + x; } -template -T ease_out_sine(const T& x, const T& y, float a) +template +T ease_out_sine(const T& x, const T& y, S a) { - return (y - x) * std::sin(a * vmq::half_pi) + x; + return (y - x) * std::sin(a * vmq::half_pi) + x; } -template -T ease_in_out_sine(const T& x, const T& y, float a) +template +T ease_in_out_sine(const T& x, const T& y, S a) { - return -(y - x) * 0.5f * (std::cos(vmq::pi * a) - 1.0f) + x; + return -(y - x) * S(0.5) * (std::cos(vmq::pi * a) - S(1.0)) + x; } -template -T ease_in_quad(const T& x, const T& y, float a) +template +T ease_in_quad(const T& x, const T& y, S a) { return (y - x) * a * a + x; } -template -T ease_out_quad(const T& x, const T& y, float a) +template +T ease_out_quad(const T& x, const T& y, S a) { - return -(y - x) * a * (a - 2.0f) + x; + return -(y - x) * a * (a - S(2.0)) + x; } -template -T ease_in_out_quad(const T& x, const T& y, float a) +template +T ease_in_out_quad(const T& x, const T& y, S a) { - a *= 2.0f; - if (a < 1.0f) + a *= S(2.0); + if (a < S(1.0)) { - return (y - x) * 0.5f * a * a + x; + return (y - x) * S(0.5) * a * a + x; } - a -= 1.0f; - return -(y - x) * 0.5f * (a * (a - 2.0f) - 1.0f) + x; + a -= S(1.0); + return -(y - x) * S(0.5) * (a * (a - S(2.0)) - S(1.0)) + x; } -template -T ease_in_cubic(const T& x, const T& y, float a) +template +T ease_in_cubic(const T& x, const T& y, S a) { return (y - x) * a * a * a + x; } -template -T ease_out_cubic(const T& x, const T& y, float a) +template +T ease_out_cubic(const T& x, const T& y, S a) { - a -= 1.0f; - return (y - x) * (a * a * a + 1.0f) + x; + a -= S(1.0); + return (y - x) * (a * a * a + S(1.0)) + x; } -template -T ease_in_out_cubic(const T& x, const T& y, float a) +template +T ease_in_out_cubic(const T& x, const T& y, S a) { - a *= 2.0f; - if (a < 1.0f) + a *= S(2.0); + if (a < S(1.0)) { - return (y - x) * 0.5f * a * a * a + x; + return (y - x) * S(0.5) * a * a * a + x; } - a -= 2.0f; - return (y - x) * 0.5f * (a * a * a + 2.0f) + x; + a -= S(2.0); + return (y - x) * S(0.5) * (a * a * a + S(2.0)) + x; } -template -T ease_in_quart(const T& x, const T& y, float a) +template +T ease_in_quart(const T& x, const T& y, S a) { return (y - x) * a * a * a * a + x; } -template -T ease_out_quart(const T& x, const T& y, float a) +template +T ease_out_quart(const T& x, const T& y, S a) { - a -= 1.0f; - return -(y - x) * (a * a * a * a - 1.0f) + x; + a -= S(1.0); + return -(y - x) * (a * a * a * a - S(1.0)) + x; } -template -T ease_in_out_quart(const T& x, const T& y, float a) +template +T ease_in_out_quart(const T& x, const T& y, S a) { - a *= 2.0f; - if (a < 1.0f) + a *= S(2.0); + if (a < S(1.0)) { - return (y - x) * 0.5f * a * a * a * a + x; + return (y - x) * S(0.5) * a * a * a * a + x; } - a -= 2.0f; - return -(y - x) * 0.5f * (a * a * a * a - 2.0f) + x; + a -= S(2.0); + return -(y - x) * S(0.5) * (a * a * a * a - S(2.0)) + x; } -template -T ease_in_quint(const T& x, const T& y, float a) +template +T ease_in_quint(const T& x, const T& y, S a) { return (y - x) * a * a * a * a * a + x; } -template -T ease_out_quint(const T& x, const T& y, float a) +template +T ease_out_quint(const T& x, const T& y, S a) { - a -= 1.0f; - return (y - x) * (a * a * a * a * a + 1.0f) + x; + a -= S(1.0); + return (y - x) * (a * a * a * a * a + S(1.0)) + x; } -template -T ease_in_out_quint(const T& x, const T& y, float a) +template +T ease_in_out_quint(const T& x, const T& y, S a) { - a *= 2.0f; - if (a < 1.0f) + a *= S(2.0); + if (a < S(1.0)) { - return (y - x) * 0.5f * a * a * a * a * a + x; + return (y - x) * S(0.5) * a * a * a * a * a + x; } - a -= 2.0f; - return (y - x) * 0.5f * (a * a * a * a * a + 2.0f) + x; + a -= S(2.0); + return (y - x) * S(0.5) * (a * a * a * a * a + S(2.0)) + x; } -template -T ease_in_expo(const T& x, const T& y, float a) +template +T ease_in_expo(const T& x, const T& y, S a) { - if (a == 0.0f) + if (a == S(0.0)) { return x; } - return (y - x) * std::pow(2.0f, 10.0f * (a - 1.0f)) + x; + return (y - x) * std::pow(S(2.0), S(10.0) * (a - S(1.0))) + x; } -template -T ease_out_expo(const T& x, const T& y, float a) +template +T ease_out_expo(const T& x, const T& y, S a) { - if (a == 1.0f) + if (a == S(1.0)) { return y; } - return (y - x) * (-std::pow(2.0f, -10.0f * a) + 1.0f) + x; + return (y - x) * (-std::pow(S(2.0), -S(10.0) * a) + S(1.0)) + x; } -template -T ease_in_out_expo(const T& x, const T& y, float a) +template +T ease_in_out_expo(const T& x, const T& y, S a) { - if (a == 0.0f) + if (a == S(0.0)) { return x; } - else if (a == 1.0f) + else if (a == S(1.0)) { return y; } - a *= 2.0f; - if (a < 1.0f) + a *= S(2.0); + if (a < S(1.0)) { - return (y - x) * 0.5f * std::pow(2.0f, 10.0f * (a - 1.0f)) + x; + return (y - x) * S(0.5) * std::pow(S(2.0), S(10.0) * (a - S(1.0))) + x; } - a -= 1.0f; - return (y - x) * 0.5f * (-std::pow(2.0f, -10.0f * a) + 2.0f) + x; + a -= S(1.0); + return (y - x) * S(0.5) * (-std::pow(S(2.0), -S(10.0) * a) + S(2.0)) + x; } -template -T ease_in_circ(const T& x, const T& y, float a) +template +T ease_in_circ(const T& x, const T& y, S a) { - return -(y - x) * (std::sqrt(1.0f - a * a) - 1.0f) + x; + return -(y - x) * (std::sqrt(S(1.0) - a * a) - S(1.0)) + x; } -template -T ease_out_circ(const T& x, const T& y, float a) +template +T ease_out_circ(const T& x, const T& y, S a) { - a -= 1.0f; - return (y - x) * std::sqrt(1.0f - a * a) + x; + a -= S(1.0); + return (y - x) * std::sqrt(S(1.0) - a * a) + x; } -template -T ease_in_out_circ(const T& x, const T& y, float a) +template +T ease_in_out_circ(const T& x, const T& y, S a) { - a *= 2.0f; - if (a < 1.0f) + a *= S(2.0); + if (a < S(1.0)) { - return -(y - x) * 0.5f * (std::sqrt(1.0f - a * a) - 1.0f) + x; + return -(y - x) * S(0.5) * (std::sqrt(S(1.0) - a * a) - S(1.0)) + x; } - a -= 2.0f; - return (y - x) * 0.5f * (std::sqrt(1.0f - a * a) + 1.0f) + x; + a -= S(2.0); + return (y - x) * S(0.5) * (std::sqrt(S(1.0) - a * a) + S(1.0)) + x; } -template -T ease_in_back(const T& x, const T& y, float a) +template +T ease_in_back(const T& x, const T& y, S a) { - const float s = 1.70158f; - return (y - x) * a * a * ((s + 1.0f) * a - s) + x; + const S s = S(1.70158); + return (y - x) * a * a * ((s + S(1.0)) * a - s) + x; } -template -T ease_out_back(const T& x, const T& y, float a) +template +T ease_out_back(const T& x, const T& y, S a) { - const float s = 1.70158f; - a -= 1.0f; - return (y - x) * (a * a * ((s + 1.0f) * a + s) + 1.0f) + x; + const S s = S(1.70158); + a -= S(1.0); + return (y - x) * (a * a * ((s + S(1.0)) * a + s) + S(1.0)) + x; } -template -T ease_in_out_back(const T& x, const T& y, float a) +template +T ease_in_out_back(const T& x, const T& y, S a) { - const float s = 1.70158f * 1.525f; + const S s = S(1.70158) * S(1.525f); - a *= 2.0f; - if (a < 1.0f) + a *= S(2.0); + if (a < S(1.0)) { - return (y - x) * 0.5f * (a * a * ((s + 1.0f) * a - s)) + x; + return (y - x) * S(0.5) * (a * a * ((s + S(1.0)) * a - s)) + x; } - a -= 2.0f; - return (y - x) * 0.5f * (a * a * ((s + 1.0f) * a + s) + 2.0f) + x; + a -= S(2.0); + return (y - x) * S(0.5) * (a * a * ((s + S(1.0)) * a + s) + S(2.0)) + x; } #endif // ANTKEEPER_EASINGS_HPP diff --git a/src/animation/screen-transition.cpp b/src/animation/screen-transition.cpp new file mode 100644 index 0000000..c5bb975 --- /dev/null +++ b/src/animation/screen-transition.cpp @@ -0,0 +1,88 @@ +/* + * 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 "screen-transition.hpp" +#include "renderer/material-flags.hpp" +#include + +screen_transition::screen_transition() +{ + // Setup material + material.set_flags(MATERIAL_FLAG_TRANSLUCENT | MATERIAL_FLAG_X_RAY); + progress = material.add_property("progress"); + + // Setup billboard + billboard.set_material(&material); + billboard.set_active(false); + + // Add single channel to transition animation + channel = animation.add_channel(0); + + // Setup animation start callback to show transition billboard + animation.set_start_callback + ( + std::bind(&scene_object_base::set_active, &billboard, true) + ); + + // Setup animation end callback to hide transition billboard + animation.set_end_callback + ( + std::bind(&scene_object_base::set_active, &billboard, false) + ); + + // Setup animation frame callback to update transition progress material property + animation.set_frame_callback + ( + [this](int channel, float progress) + { + this->progress->set_value(progress); + } + ); + + // Setup animation frame callback to update transition progress material property + animation.set_frame_callback + ( + [this](int channel, float progress) + { + this->progress->set_value(progress); + } + ); +} + +void screen_transition::transition(float duration, bool reverse, ::animation::interpolator_type interpolator) +{ + float initial_state = (reverse) ? 1.0f : 0.0f; + float final_state = (reverse) ? 0.0f : 1.0f; + + // Build transition animation + channel->remove_keyframes(); + channel->insert_keyframe({0.0f, initial_state}); + channel->insert_keyframe({duration, final_state}); + + // Set transition animation interpolator + animation.set_interpolator(interpolator); + + // Update tweens + progress->set_value(initial_state); + material.update_tweens(); + + // Reset and play transition animation + animation.stop(); + animation.play(); +} diff --git a/src/animation/screen-transition.hpp b/src/animation/screen-transition.hpp new file mode 100644 index 0000000..9c4fcff --- /dev/null +++ b/src/animation/screen-transition.hpp @@ -0,0 +1,65 @@ +/* + * 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_SCREEN_TRANSITION_HPP +#define ANTKEEPER_SCREEN_TRANSITION_HPP + +#include "animation/animation.hpp" +#include "renderer/material.hpp" +#include "renderer/material-property.hpp" +#include "scene/billboard.hpp" + +/** + * Encapsulates a shader-based animated screen transition. + */ +class screen_transition +{ +public: + screen_transition(); + + void transition(float duration, bool reverse, animation::interpolator_type interpolator); + + ::billboard* get_billboard(); + ::material* get_material(); + ::animation* get_animation(); + +private: + ::billboard billboard; + ::material material; + material_property* progress; + ::animation animation; + ::animation::channel* channel; +}; + +inline billboard* screen_transition::get_billboard() +{ + return &billboard; +} + +inline material* screen_transition::get_material() +{ + return &material; +} + +inline animation* screen_transition::get_animation() +{ + return &animation; +} + +#endif // ANTKEEPER_SCREEN_TRANSITION_HPP diff --git a/src/application.cpp b/src/application.cpp index 609b44a..f44143f 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -77,6 +77,8 @@ // Animation #include "animation/animation.hpp" #include "animation/animator.hpp" +#include "animation/screen-transition.hpp" +#include "animation/easings.hpp" // Scene #include "scene/billboard.hpp" @@ -101,24 +103,6 @@ // Entity components #include "entity/components/cavity-component.hpp" -template -inline T ease_linear(const T& x, const T& y, double a) -{ - return (y - x) * a + x; -} - -template -T ease_in_quad(const T& x, const T& y, double a) -{ - return (y - x) * a * a + x; -} - -template -T ease_out_quad(const T& x, const T& y, double a) -{ - return -(y - x) * a * (a - 2.0f) + x; -} - using namespace vmq::operators; application::application(int argc, char** argv): @@ -431,6 +415,7 @@ application::application(int argc, char** argv): clear_pass = new ::clear_pass(rasterizer, framebuffer_hdr); clear_pass->set_cleared_buffers(true, true, false); sky_pass = new ::sky_pass(rasterizer, framebuffer_hdr, resource_manager); + sky_pass->set_enabled(false); material_pass = new ::material_pass(rasterizer, framebuffer_hdr, resource_manager); material_pass->set_fallback_material(fallback_material); material_pass->set_time_tween(&time); @@ -474,8 +459,6 @@ application::application(int argc, char** argv): 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_transition_property->set_value(0.0f); underground_color_texture_property = underworld_final_pass->get_material()->add_property("color_texture"); underground_color_texture_property->set_value(framebuffer_hdr_color); underworld_final_pass->get_material()->update_tweens(); @@ -498,26 +481,8 @@ application::application(int argc, char** argv): timeline.set_autoremove(true); // Setup animation system - // ... animator = new ::animator(); - float radial_transition_time = 0.5f; - radial_transition_in = new animation(); - radial_transition_in->set_frame_callback([this](int channel, float value){this->underground_transition_property->set_value(value);}); - radial_transition_in->set_interpolator(ease_in_quad); - animation::channel* channel = radial_transition_in->add_channel(0); - channel->insert_keyframe({0.0f, 0.0f}); - channel->insert_keyframe({radial_transition_time, 1.0f}); - animator->add_animation(radial_transition_in); - - radial_transition_out = new animation(); - radial_transition_out->set_frame_callback([this](int channel, float value){this->underground_transition_property->set_value(value);}); - radial_transition_out->set_interpolator(ease_out_quad); - channel = radial_transition_out->add_channel(0); - channel->insert_keyframe({0.0f, 1.0f}); - channel->insert_keyframe({radial_transition_time, 0.0f}); - animator->add_animation(radial_transition_out); - // ECS terrain_system = new ::terrain_system(ecs_registry, resource_manager); terrain_system->set_patch_size(TERRAIN_PATCH_SIZE); @@ -673,21 +638,33 @@ application::application(int argc, char** argv): { if (this->active_scene == &this->overworld_scene) { - // Switch to underworld - //this->overworld_camera.set_active(false); - this->underworld_camera.set_active(true); this->active_scene = &this->underworld_scene; - this->radial_transition_out->stop(); - this->radial_transition_in->play(); + this->radial_transition_inner->transition(0.5f, false, ease_in_quad); + + auto switch_cameras = [this]() + { + this->overworld_camera.set_active(false); + this->underworld_camera.set_active(true); + this->fade_transition->transition(0.25f, true, ease_out_quad); + }; + + float t = timeline.get_position(); + this->timeline.add_cue({t + 0.5f, switch_cameras}); } else { - // Switch to overworld - //this->underworld_camera.set_active(false); - this->overworld_camera.set_active(true); this->active_scene = &this->overworld_scene; - this->radial_transition_in->stop(); - this->radial_transition_out->play(); + this->fade_transition->transition(0.25f, false, ease_out_quad); + + auto switch_cameras = [this]() + { + this->overworld_camera.set_active(true); + this->underworld_camera.set_active(false); + this->radial_transition_inner->transition(0.5f, true, ease_out_quad); + }; + + float t = timeline.get_position(); + this->timeline.add_cue({t + 0.25f, switch_cameras}); } }); @@ -855,6 +832,50 @@ application::application(int argc, char** argv): // Set overworld as active scene active_scene = &overworld_scene; + + // Setup UI + const texture_2d* splash_texture = resource_manager->load("splash.png"); + auto splash_dimensions = splash_texture->get_dimensions(); + splash_billboard_material = new material(); + splash_billboard_material->set_shader_program(resource_manager->load("ui-element-textured.glsl")); + splash_billboard_material->add_property("background")->set_value(splash_texture); + splash_billboard_material->add_property("tint")->set_value(float4{1, 1, 1, 1}); + splash_billboard_material->update_tweens(); + splash_billboard = new billboard(); + splash_billboard->set_material(splash_billboard_material); + splash_billboard->set_scale({(float)std::get<0>(splash_dimensions) * 0.5f, (float)std::get<1>(splash_dimensions) * 0.5f, 1.0f}); + splash_billboard->set_translation({0.0f, 0.0f, 0.0f}); + splash_billboard->update_tweens(); + + // Create fade transition + fade_transition = new screen_transition(); + fade_transition->get_material()->set_shader_program(resource_manager->load("fade-transition.glsl")); + get_ui_scene()->add_object(fade_transition->get_billboard()); + animator->add_animation(fade_transition->get_animation()); + + // Create inner radial transition + radial_transition_inner = new screen_transition(); + radial_transition_inner->get_material()->set_shader_program(resource_manager->load("radial-transition-inner.glsl")); + get_ui_scene()->add_object(radial_transition_inner->get_billboard()); + animator->add_animation(radial_transition_inner->get_animation()); + + // Create outer radial transition + radial_transition_outer = new screen_transition(); + radial_transition_outer->get_material()->set_shader_program(resource_manager->load("radial-transition-outer.glsl")); + get_ui_scene()->add_object(radial_transition_outer->get_billboard()); + animator->add_animation(radial_transition_outer->get_animation()); + + // Determine initial state + initial_state = &splash_state; + std::string no_splash_flag = "--skip-splash"; + for (int i = 0; i < argc; ++i) + { + if (no_splash_flag == argv[i]) + { + initial_state = &play_state; + break; + } + } } application::~application() @@ -876,7 +897,7 @@ void application::close(int status) int application::execute() { // Enter inital state - state_machine.change_state(play_state); + state_machine.change_state(*initial_state); // Perform initial update update(0.0, 0.0); @@ -1147,3 +1168,7 @@ void application::save_image(const std::string& filename, int w, int h, const un delete[] pixels; } +scene* application::get_ui_scene() +{ + return ui_system->get_scene(); +} diff --git a/src/application.hpp b/src/application.hpp index 7201cad..172a3fe 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -63,6 +63,7 @@ // Animation #include "animation/timeline.hpp" #include "animation/tween.hpp" +#include "animation/animation.hpp" // Misc #include "state/fsm.hpp" @@ -94,9 +95,14 @@ class bloom_pass; class final_pass; class simple_render_pass; + template + class material_property; // Animation class animator; + template + class animation; + class screen_transition; // Systems class behavior_system; @@ -114,11 +120,8 @@ class control_system; class ui_system; - template - class material_property; - - template - class animation; + // Scene + class billboard; //} class application @@ -171,6 +174,16 @@ public: scene& get_scene(); void take_screenshot() const; + + // UI + scene* get_ui_scene(); + billboard* get_splash_billboard(); + + ::sky_pass* get_sky_pass(); + + screen_transition* get_fade_transition(); + screen_transition* get_radial_transition_inner(); + screen_transition* get_radial_transition_outer(); private: void update(double t, double dt); @@ -261,7 +274,6 @@ private: ::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; @@ -273,6 +285,7 @@ private: fsm::state title_state; fsm::state play_state; fsm::state pause_state; + fsm::state* initial_state; // Frame timing frame_scheduler frame_scheduler; @@ -326,9 +339,14 @@ private: compositor ui_compositor; ::clear_pass* ui_clear_pass; ::material_pass* ui_material_pass; + billboard* splash_billboard; + material* splash_billboard_material; // Animation tween focal_point_tween; + screen_transition* fade_transition; + screen_transition* radial_transition_inner; + screen_transition* radial_transition_outer; }; inline logger* application::get_logger() @@ -421,5 +439,29 @@ inline scene& application::get_scene() return overworld_scene; } -#endif // ANTKEEPER_APPLICATION_HPP +inline billboard* application::get_splash_billboard() +{ + return splash_billboard; +} + +inline sky_pass* application::get_sky_pass() +{ + return sky_pass; +} + +inline screen_transition* application::get_fade_transition() +{ + return fade_transition; +} +inline screen_transition* application::get_radial_transition_inner() +{ + return radial_transition_inner; +} + +inline screen_transition* application::get_radial_transition_outer() +{ + return radial_transition_outer; +} + +#endif // ANTKEEPER_APPLICATION_HPP diff --git a/src/renderer/material-property.hpp b/src/renderer/material-property.hpp index 4cf6eb4..9e31d41 100644 --- a/src/renderer/material-property.hpp +++ b/src/renderer/material-property.hpp @@ -127,7 +127,6 @@ public: * @param value Value to set. */ void set_value(const T& value); - void set_val(const T& value); /** * Sets the value of a single element in this array property. @@ -145,6 +144,17 @@ public: * @param count Number of elements to set. */ void set_values(std::size_t index, const T* values, std::size_t count); + + /// Returns the value of the first element in this property. + const T& get_value() const; + + /** + * Returns the value of the first element in this property. + * + * @param index Index of an array element. + * @return Value of the element at the specified index. + */ + const T& get_value(std::size_t index) const; /// @copydoc material_property_base::get_data_type() const virtual shader_variable_type get_data_type() const; @@ -210,12 +220,6 @@ void material_property::set_value(const T& value) values[0][1] = value; } -template -void material_property::set_val(const T& value) -{ - values[0][1] = value; -} - template void material_property::set_value(std::size_t index, const T& value) { @@ -231,6 +235,18 @@ void material_property::set_values(std::size_t index, const T* values, std::s } } +template +inline const T& material_property::get_value() const +{ + return values[0][1]; +} + +template +inline const T& material_property::get_value(std::size_t index) const +{ + return values[index][1]; +} + template <> inline shader_variable_type material_property::get_data_type() const { diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index 0dbd469..3fe41ca 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -116,6 +116,8 @@ void material_pass::render(render_context* context) const auto viewport = framebuffer->get_dimensions(); rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport)); + float2 resolution = {static_cast(std::get<0>(viewport)), static_cast(std::get<1>(viewport))}; + float time = (time_tween) ? time_tween->interpolate(context->alpha) : 0.0f; float3 focal_point = (focal_point_tween) ? focal_point_tween->interpolate(context->alpha) : float3{0, 0, 0}; float4x4 view = context->camera->get_view_tween().interpolate(context->alpha); @@ -356,6 +358,8 @@ void material_pass::render(render_context* context) const // Upload context-dependent shader parameters if (parameters->time) parameters->time->upload(time); + if (parameters->resolution) + parameters->resolution->upload(resolution); if (parameters->view) parameters->view->upload(view); if (parameters->view_projection) @@ -452,6 +456,7 @@ const material_pass::parameter_set* material_pass::load_parameter_set(const shad // Connect inputs parameters->time = program->get_input("time"); + parameters->resolution = program->get_input("resolution"); parameters->model = program->get_input("model"); parameters->view = program->get_input("view"); parameters->projection = program->get_input("projection"); diff --git a/src/renderer/passes/material-pass.hpp b/src/renderer/passes/material-pass.hpp index 18641db..1cc5636 100644 --- a/src/renderer/passes/material-pass.hpp +++ b/src/renderer/passes/material-pass.hpp @@ -60,6 +60,7 @@ private: struct parameter_set { const shader_input* time; + const shader_input* resolution; const shader_input* model; const shader_input* view; const shader_input* projection; diff --git a/src/state/play-state.cpp b/src/state/play-state.cpp index db844be..e60228e 100644 --- a/src/state/play-state.cpp +++ b/src/state/play-state.cpp @@ -20,10 +20,12 @@ #include "application-states.hpp" #include "configuration.hpp" #include "application.hpp" +#include "animation/screen-transition.hpp" #include "scene/model-instance.hpp" #include "resources/resource-manager.hpp" #include "renderer/model.hpp" #include "renderer/material.hpp" +#include "renderer/passes/sky-pass.hpp" #include "systems/control-system.hpp" #include "entity/components/model-component.hpp" #include "entity/components/transform-component.hpp" @@ -37,6 +39,7 @@ #include "math.hpp" #include "geometry/mesh-accelerator.hpp" #include "behavior/ebt.hpp" +#include "animation/easings.hpp" #include using namespace vmq::operators; @@ -46,6 +49,8 @@ void enter_play_state(application* app) logger* logger = app->get_logger(); logger->push_task("Entering play state"); + // Enable sky pass + app->get_sky_pass()->set_enabled(true); resource_manager* resource_manager = app->get_resource_manager(); entt::registry& ecs_registry = app->get_ecs_registry(); @@ -226,6 +231,9 @@ void enter_play_state(application* app) control_system->update(0.0f); control_system->set_nest(nest); orbit_cam->update(0.0f); + + // Start fade in + app->get_fade_transition()->transition(1.0f, true, ease_in_quad); logger->pop_task(EXIT_SUCCESS); } diff --git a/src/state/splash-state.cpp b/src/state/splash-state.cpp index 7517b21..70300a9 100644 --- a/src/state/splash-state.cpp +++ b/src/state/splash-state.cpp @@ -19,6 +19,14 @@ #include "application-states.hpp" #include "application.hpp" +#include "scene/billboard.hpp" +#include "renderer/material.hpp" +#include "renderer/material-property.hpp" +#include "animation/animation.hpp" +#include "animation/animator.hpp" +#include "animation/easings.hpp" +#include "animation/screen-transition.hpp" +#include "renderer/passes/sky-pass.hpp" #include #include @@ -28,34 +36,40 @@ void enter_splash_state(application* app) logger* logger = app->get_logger(); logger->push_task("Entering splash state"); - auto fade_in = [logger]() - { - logger->log("cue logo fade-in\n"); - }; + // Disable sky pass + app->get_sky_pass()->set_enabled(false); + + // Add splash billboard to UI scene + app->get_ui_scene()->add_object(app->get_splash_billboard()); + + // Setup timing + const float splash_fade_in_duration = 0.5f; + const float splash_hang_duration = 2.0f; + const float splash_fade_out_duration = 0.5f; - auto fade_out = [logger]() + // Start fade in + app->get_fade_transition()->transition(splash_fade_in_duration, true, ease_in_quad); + + // Crate fade out function + auto fade_out = [app, splash_fade_out_duration]() { - logger->log("cue logo fade-out\n"); + app->get_fade_transition()->transition(splash_fade_out_duration, false, ease_out_quad); }; + // Create change state function auto change_state = [app]() { - app->get_state_machine()->change_state(app->get_title_state()); + app->get_state_machine()->change_state(app->get_play_state()); }; - // Get timeline + // Schedule fade out and change state events timeline* timeline = app->get_timeline(); - - // Create splash sequence float t = timeline->get_position(); timeline::sequence splash_sequence = { - {t + 0.0f, fade_in}, - {t + 3.0f, fade_out}, - {t + 8.0f, change_state} + {t + splash_fade_in_duration + splash_hang_duration, fade_out}, + {t + splash_fade_in_duration + splash_hang_duration + splash_fade_out_duration, change_state} }; - - // Add splash sequence to timeline timeline->add_sequence(splash_sequence); logger->pop_task(EXIT_SUCCESS); @@ -66,5 +80,8 @@ void exit_splash_state(application* app) logger* logger = app->get_logger(); logger->push_task("Exiting splash state"); + // Remove splash billboard from UI scene + app->get_ui_scene()->remove_object(app->get_splash_billboard()); + logger->pop_task(EXIT_SUCCESS); }