From cdde99b9487a8f3103c2d066890215136358ca63 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 6 May 2021 16:18:23 +0800 Subject: [PATCH] Add configurable exposure to camera class --- src/ecs/systems/astronomy-system.cpp | 11 ++++------- src/ecs/systems/camera-system.hpp | 7 +++++++ src/ecs/systems/control-system.cpp | 20 ++++++++++++++++++++ src/ecs/systems/control-system.hpp | 14 ++++++++++++++ src/game/bootloader.cpp | 7 +++++-- src/game/states/play-state.cpp | 3 ++- src/renderer/passes/material-pass.cpp | 2 +- src/renderer/passes/sky-pass.cpp | 18 ++++++++++++++++++ src/renderer/passes/sky-pass.hpp | 6 ++++++ src/scene/camera.cpp | 9 ++++++++- src/scene/camera.hpp | 25 ++++++++++++++++++++++++- 11 files changed, 109 insertions(+), 13 deletions(-) diff --git a/src/ecs/systems/astronomy-system.cpp b/src/ecs/systems/astronomy-system.cpp index c09e35a..e7e9e7f 100644 --- a/src/ecs/systems/astronomy-system.cpp +++ b/src/ecs/systems/astronomy-system.cpp @@ -87,15 +87,12 @@ void astronomy_system::update(double t, double dt) //sun_light->look_at({0, 0, 0}, {0, -1, 0}, {0, 0, 1}); // Set sun color - float factor = std::cos(spherical.y); - factor = 1.0f - factor * factor; - - float correlated_temperature = math::lerp(3000.0f, 8000.0f, factor); + float correlated_temperature = 3000.0f + std::sin(spherical.y) * 5000.0f; float3 correlated_color = math::type_cast(astro::blackbody(correlated_temperature)); - - float intensity = math::lerp(100.0f, 1000.0f, factor); - sun_light->set_color(correlated_color); + + // Set sun intensity (in lux) + float intensity = std::max(0.0, std::sin(spherical.y) * 108000.0f); sun_light->set_intensity(intensity); diff --git a/src/ecs/systems/camera-system.hpp b/src/ecs/systems/camera-system.hpp index d2fef8b..f77cdc0 100644 --- a/src/ecs/systems/camera-system.hpp +++ b/src/ecs/systems/camera-system.hpp @@ -55,6 +55,8 @@ public: const orbit_cam* get_orbit_cam() const; orbit_cam* get_orbit_cam(); + + scene::camera* get_camera(); private: virtual void handle_event(const mouse_moved_event& event); @@ -77,6 +79,11 @@ inline orbit_cam* camera_system::get_orbit_cam() return &orbit_cam; } +inline scene::camera* camera_system::get_camera() +{ + return camera; +} + } // namespace ecs #endif // ANTKEEPER_ECS_CAMERA_SYSTEM_HPP diff --git a/src/ecs/systems/control-system.cpp b/src/ecs/systems/control-system.cpp index a719234..c312cd3 100644 --- a/src/ecs/systems/control-system.cpp +++ b/src/ecs/systems/control-system.cpp @@ -26,6 +26,7 @@ #include "ecs/commands.hpp" #include "ecs/systems/camera-system.hpp" #include "animation/orbit-cam.hpp" +#include namespace ecs { @@ -63,6 +64,8 @@ control_system::control_system(ecs::registry& registry): control_set.add_control(&use_tool_control); control_set.add_control(&fast_forward_control); control_set.add_control(&rewind_control); + control_set.add_control(&exposure_increase_control); + control_set.add_control(&exposure_decrease_control); // Set deadzone at 15% for all controls const std::list* controls = control_set.get_controls(); @@ -111,6 +114,23 @@ void control_system::update(double t, double dt) if (rotate_cw_control.is_active()) camera_system->pan(-rotation_speed * dt * std::min(1.0f, rotate_cw_control.get_current_value())); + // Exposure + if (camera_system->get_camera()) + { + const float exposure = camera_system->get_camera()->get_exposure(); + const float exposure_rate = 0.1f; + if (exposure_increase_control.is_active()) + { + camera_system->get_camera()->set_exposure(exposure + exposure_rate); + std::cout << "exposure: " << (exposure + exposure_rate) << std::endl; + } + if (exposure_decrease_control.is_active()) + { + camera_system->get_camera()->set_exposure(exposure - exposure_rate); + std::cout << "exposure: " << (exposure - exposure_rate) << std::endl; + } + } + // Move camera float3 movement{0.0f, 0.0f, 0.0f}; if (move_right_control.is_active()) diff --git a/src/ecs/systems/control-system.hpp b/src/ecs/systems/control-system.hpp index a5c0fd1..3677e3d 100644 --- a/src/ecs/systems/control-system.hpp +++ b/src/ecs/systems/control-system.hpp @@ -86,6 +86,8 @@ public: input::control* get_use_tool_control(); input::control* get_fast_forward_control(); input::control* get_rewind_control(); + input::control* get_exposure_increase_control(); + input::control* get_exposure_decrease_control(); private: virtual void handle_event(const mouse_moved_event& event); @@ -118,6 +120,8 @@ private: input::control use_tool_control; input::control fast_forward_control; input::control rewind_control; + input::control exposure_increase_control; + input::control exposure_decrease_control; float zoom_speed; float min_elevation; @@ -287,6 +291,16 @@ inline input::control* control_system::get_rewind_control() return &rewind_control; } +inline input::control* control_system::get_exposure_increase_control() +{ + return &exposure_increase_control; +} + +inline input::control* control_system::get_exposure_decrease_control() +{ + return &exposure_decrease_control; +} + } // namespace ecs #endif // ANTKEEPER_ECS_CONTROL_SYSTEM_HPP diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index 2f89992..580d52f 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -1059,6 +1059,9 @@ void setup_controls(game_context* ctx) ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_fast_forward_control(), nullptr, input::scancode::dot)); ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_rewind_control(), nullptr, input::scancode::comma)); + ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_exposure_increase_control(), nullptr, input::scancode::right_brace)); + ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_exposure_decrease_control(), nullptr, input::scancode::left_brace)); + ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_equip_brush_control(), nullptr, input::scancode::one)); ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_equip_twig_control(), nullptr, input::scancode::two)); @@ -1067,8 +1070,8 @@ void setup_controls(game_context* ctx) ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_equip_lens_control(), nullptr, input::scancode::five)); ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_equip_marker_control(), nullptr, input::scancode::six)); - ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_next_marker_control(), nullptr, input::scancode::right_brace)); - ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_previous_marker_control(), nullptr, input::scancode::left_brace)); + //ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_next_marker_control(), nullptr, input::scancode::right_brace)); + //ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_previous_marker_control(), nullptr, input::scancode::left_brace)); ctx->input_event_router->add_mapping(input::mouse_button_mapping(ctx->control_system->get_use_tool_control(), nullptr, 1)); ctx->control_system->get_use_tool_control()->set_activated_callback diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 033b04f..0d923bf 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -95,7 +95,7 @@ void play_state_enter(game_context* ctx) sky_pass->set_sky_model(ctx->resource_manager->load("sky-dome.mdl")); sky_pass->set_moon_model(ctx->resource_manager->load("moon.mdl")); - sky_pass->set_horizon_color({0.1f, 0.1f, 0.1f}); + sky_pass->set_horizon_color({1.1f, 1.1f, 1.1f}); sky_pass->set_zenith_color({0.0f, 0.0f, 0.0f}); sky_pass->set_time_of_day(0.0f); sky_pass->set_julian_day(0.0f); @@ -105,6 +105,7 @@ void play_state_enter(game_context* ctx) sky_pass->set_sun_coordinates({0, 1, 0}, {0, 3.1415f / 2.0f}); sky_pass->set_moon_coordinates({1, 0, 0}, {0, 0}); sky_pass->set_moon_rotation(math::identity_quaternion); + sky_pass->set_sky_gradient(resource_manager->load("sky-gradient.tex"), resource_manager->load("sky-gradient2.tex")); diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index 8608142..7b83499 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -136,7 +136,7 @@ void material_pass::render(render_context* context) const clip_depth[1] = context->camera->get_clip_far_tween().interpolate(context->alpha); float log_depth_coef = 2.0f / std::log2(clip_depth[1] + 1.0f); - float camera_exposure = std::exp2(-7.0f); + float camera_exposure = std::exp2(context->camera->get_exposure_tween().interpolate(context->alpha)); int active_material_flags = 0; diff --git a/src/renderer/passes/sky-pass.cpp b/src/renderer/passes/sky-pass.cpp index be4ca0b..ef586f4 100644 --- a/src/renderer/passes/sky-pass.cpp +++ b/src/renderer/passes/sky-pass.cpp @@ -52,6 +52,8 @@ sky_pass::sky_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffe moon_model_vao(nullptr), moon_shader_program(nullptr), blue_noise_map(nullptr), + sky_gradient(nullptr), + sky_gradient2(nullptr), observer_location{0.0f, 0.0f, 0.0f}, time_tween(nullptr), time_of_day_tween(0.0, math::lerp), @@ -92,6 +94,7 @@ void sky_pass::render(render_context* context) const float4x4 model_view = view * model; float4x4 projection = camera.get_projection_tween().interpolate(context->alpha); float4x4 model_view_projection = projection * model_view; + float exposure = std::exp2(camera.get_exposure_tween().interpolate(context->alpha)); float time_of_day = time_of_day_tween.interpolate(context->alpha); float julian_day = julian_day_tween.interpolate(context->alpha); @@ -123,6 +126,10 @@ void sky_pass::render(render_context* context) const time_of_day_input->upload(time_of_day); if (blue_noise_map_input) blue_noise_map_input->upload(blue_noise_map); + if (sky_gradient_input && sky_gradient) + sky_gradient_input->upload(sky_gradient); + if (sky_gradient2_input && sky_gradient2) + sky_gradient2_input->upload(sky_gradient2); if (observer_location_input) observer_location_input->upload(observer_location); if (sun_position_input) @@ -139,6 +146,8 @@ void sky_pass::render(render_context* context) const cos_moon_angular_radius_input->upload(cos_moon_angular_radius); if (cos_sun_angular_radius_input) cos_sun_angular_radius_input->upload(cos_sun_angular_radius); + if (exposure_input) + exposure_input->upload(exposure); sky_material->upload(context->alpha); @@ -209,6 +218,8 @@ void sky_pass::set_sky_model(const model* model) time_input = sky_shader_program->get_input("time"); time_of_day_input = sky_shader_program->get_input("time_of_day"); blue_noise_map_input = sky_shader_program->get_input("blue_noise_map"); + sky_gradient_input = sky_shader_program->get_input("sky_gradient"); + sky_gradient2_input = sky_shader_program->get_input("sky_gradient2"); observer_location_input = sky_shader_program->get_input("observer_location"); sun_position_input = sky_shader_program->get_input("sun_position"); sun_az_el_input = sky_shader_program->get_input("sun_az_el"); @@ -217,6 +228,7 @@ void sky_pass::set_sky_model(const model* model) julian_day_input = sky_shader_program->get_input("julian_day"); cos_moon_angular_radius_input = sky_shader_program->get_input("cos_moon_angular_radius"); cos_sun_angular_radius_input = sky_shader_program->get_input("cos_sun_angular_radius"); + exposure_input = sky_shader_program->get_input("camera.exposure"); } } } @@ -289,6 +301,12 @@ void sky_pass::set_blue_noise_map(const gl::texture_2d* texture) blue_noise_map = texture; } +void sky_pass::set_sky_gradient(const gl::texture_2d* texture, const gl::texture_2d* texture2) +{ + sky_gradient = texture; + sky_gradient2 = texture2; +} + void sky_pass::set_julian_day(float jd) { julian_day_tween[1] = jd; diff --git a/src/renderer/passes/sky-pass.hpp b/src/renderer/passes/sky-pass.hpp index c8add96..780b4ba 100644 --- a/src/renderer/passes/sky-pass.hpp +++ b/src/renderer/passes/sky-pass.hpp @@ -55,6 +55,7 @@ public: void set_zenith_color(const float3& color); void set_time_of_day(float time); void set_blue_noise_map(const gl::texture_2d* texture); + void set_sky_gradient(const gl::texture_2d* texture, const gl::texture_2d* texture2); void set_time_tween(const tween* time); void set_moon_model(const model* model); @@ -87,6 +88,9 @@ private: const gl::shader_input* julian_day_input; const gl::shader_input* cos_sun_angular_radius_input; const gl::shader_input* cos_moon_angular_radius_input; + const gl::shader_input* sky_gradient_input; + const gl::shader_input* sky_gradient2_input; + const gl::shader_input* exposure_input; gl::shader_program* moon_shader_program; const gl::shader_input* moon_model_view_projection_input; @@ -109,6 +113,8 @@ private: std::size_t moon_model_index_count; const gl::texture_2d* blue_noise_map; + const gl::texture_2d* sky_gradient; + const gl::texture_2d* sky_gradient2; float2 mouse_position; float3 observer_location; diff --git a/src/scene/camera.cpp b/src/scene/camera.cpp index afa3dea..2f386c2 100644 --- a/src/scene/camera.cpp +++ b/src/scene/camera.cpp @@ -74,7 +74,8 @@ camera::camera(): aspect_ratio(1.0f, math::lerp), view(math::identity4x4, std::bind(&interpolate_view, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), projection(math::identity4x4, std::bind(&interpolate_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), - view_projection(math::identity4x4, std::bind(&interpolate_view_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) + view_projection(math::identity4x4, std::bind(&interpolate_view_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), + exposure(0.0f, math::lerp) {} float3 camera::project(const float3& object, const float4& viewport) const @@ -143,6 +144,11 @@ void camera::set_orthographic(float clip_left, float clip_right, float clip_bott view_frustum.set_matrix(view_projection[1]); } +void camera::set_exposure(float exposure) +{ + this->exposure[1] = exposure; +} + void camera::set_compositor(::compositor* compositor) { this->compositor = compositor; @@ -167,6 +173,7 @@ void camera::update_tweens() view.update(); projection.update(); view_projection.update(); + exposure.update(); } void camera::transformed() diff --git a/src/scene/camera.hpp b/src/scene/camera.hpp index 557ce01..65da8f5 100644 --- a/src/scene/camera.hpp +++ b/src/scene/camera.hpp @@ -78,9 +78,17 @@ public: */ void set_orthographic(float clip_left, float clip_right, float clip_bottom, float clip_top, float clip_near, float clip_far); + /** + * Sets the camera's exposure. + * + * @param exposure Exposure factor. + */ + void set_exposure(float exposure); + void set_compositor(compositor* compositor); void set_composite_index(int index); + virtual const bounding_volume_type& get_bounds() const; float is_orthographic() const; @@ -104,6 +112,9 @@ public: /// Returns the camera's view frustum. const view_frustum_type& get_view_frustum() const; + + /// Returns the camera's exposure. + float get_exposure() const; const compositor* get_compositor() const; compositor* get_compositor(); @@ -120,6 +131,7 @@ public: const tween& get_view_tween() const; const tween& get_projection_tween() const; const tween& get_view_projection_tween() const; + const tween& get_exposure_tween() const; /// @copydoc object_base::update_tweens(); virtual void update_tweens(); @@ -141,6 +153,7 @@ private: tween view; tween projection; tween view_projection; + tween exposure; view_frustum_type view_frustum; }; @@ -214,6 +227,12 @@ inline const typename camera::view_frustum_type& camera::get_view_frustum() cons return view_frustum; } +inline float camera::get_exposure() const +{ + return exposure[1]; +} + + inline const compositor* camera::get_compositor() const { return compositor; @@ -284,7 +303,11 @@ inline const tween& camera::get_view_projection_tween() const return view_projection; } +inline const tween& camera::get_exposure_tween() const +{ + return exposure; +} + } // namespace scene #endif // ANTKEEPER_SCENE_CAMERA_HPP -