From 77c418b7a8174a1076990d4fc092626af6141404 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Tue, 28 Jun 2022 12:58:40 +0800 Subject: [PATCH] Add infinite ground render pass. Move camera exposure normaliztion factor into render context --- CMakeLists.txt | 1 + src/config.hpp.in | 2 +- src/game/context.hpp | 5 +- src/game/state/boot.cpp | 16 ++- src/game/state/nuptial-flight.cpp | 49 +++++--- src/game/world.cpp | 9 +- src/render/context.hpp | 3 + src/render/passes/ground-pass.cpp | 189 ++++++++++++++++++++++++++++ src/render/passes/ground-pass.hpp | 69 ++++++++++ src/render/passes/material-pass.cpp | 14 +-- src/render/passes/sky-pass.cpp | 13 +- src/render/renderer.cpp | 3 +- 12 files changed, 327 insertions(+), 46 deletions(-) create mode 100644 src/render/passes/ground-pass.cpp create mode 100644 src/render/passes/ground-pass.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c6dd9d4..6159500 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.7) option(VERSION_STRING "Project version string" "0.0.0") + project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) # Find dependency packages diff --git a/src/config.hpp.in b/src/config.hpp.in index 8527dff..c13004c 100644 --- a/src/config.hpp.in +++ b/src/config.hpp.in @@ -56,7 +56,7 @@ constexpr float4 menu_inactive_color{1.0f, 1.0f, 1.0f, 0.5f}; constexpr float title_fade_in_duration = 1.0f; /// Duration of the fade out when quitting the game or returning to the main menu, in seconds. -constexpr float quit_fade_out_duration = 1.0f; +constexpr float quit_fade_out_duration = 0.5f; /// Duration of the fade out when a new colony is started, in seconds. constexpr float new_colony_fade_out_duration = 1.0f; diff --git a/src/game/context.hpp b/src/game/context.hpp index f2f8370..bbba11f 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -112,6 +112,7 @@ namespace render class shadow_map_pass; class simple_render_pass; class sky_pass; + class ground_pass; } namespace game { @@ -208,10 +209,12 @@ struct context render::clear_pass* surface_shadow_map_clear_pass; render::shadow_map_pass* surface_shadow_map_pass; render::clear_pass* surface_clear_pass; - render::sky_pass* surface_sky_pass; + render::sky_pass* sky_pass; render::material_pass* surface_material_pass; render::outline_pass* surface_outline_pass; render::compositor* surface_compositor; + render::ground_pass* ground_pass; + // Scene utilities scene::collection* active_scene; diff --git a/src/game/state/boot.cpp b/src/game/state/boot.cpp index 5a30fbe..7943ea5 100644 --- a/src/game/state/boot.cpp +++ b/src/game/state/boot.cpp @@ -47,6 +47,7 @@ #include "render/passes/outline-pass.hpp" #include "render/passes/shadow-map-pass.hpp" #include "render/passes/sky-pass.hpp" +#include "render/passes/ground-pass.hpp" #include "render/passes/simple-pass.hpp" #include "render/vertex-attribute.hpp" #include "render/compositor.hpp" @@ -500,8 +501,12 @@ void boot::setup_rendering() ctx.surface_clear_pass->set_cleared_buffers(true, true, true); ctx.surface_clear_pass->set_clear_depth(0.0f); - ctx.surface_sky_pass = new render::sky_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); - ctx.app->get_event_dispatcher()->subscribe(ctx.surface_sky_pass); + ctx.sky_pass = new render::sky_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); + ctx.sky_pass->set_enabled(false); + ctx.app->get_event_dispatcher()->subscribe(ctx.sky_pass); + + ctx.ground_pass = new render::ground_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); + ctx.ground_pass->set_enabled(false); ctx.surface_material_pass = new render::material_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); ctx.surface_material_pass->set_fallback_material(ctx.fallback_material); @@ -517,7 +522,8 @@ void boot::setup_rendering() ctx.surface_compositor->add_pass(ctx.surface_shadow_map_clear_pass); ctx.surface_compositor->add_pass(ctx.surface_shadow_map_pass); ctx.surface_compositor->add_pass(ctx.surface_clear_pass); - ctx.surface_compositor->add_pass(ctx.surface_sky_pass); + ctx.surface_compositor->add_pass(ctx.sky_pass); + ctx.surface_compositor->add_pass(ctx.ground_pass); ctx.surface_compositor->add_pass(ctx.surface_material_pass); //ctx.surface_compositor->add_pass(ctx.surface_outline_pass); ctx.surface_compositor->add_pass(ctx.common_bloom_pass); @@ -913,7 +919,7 @@ void boot::setup_systems() // Setup astronomy system ctx.astronomy_system = new entity::system::astronomy(*ctx.entity_registry); - ctx.astronomy_system->set_sky_pass(ctx.surface_sky_pass); + ctx.astronomy_system->set_sky_pass(ctx.sky_pass); // Setup proteome system ctx.proteome_system = new entity::system::proteome(*ctx.entity_registry); @@ -1100,7 +1106,7 @@ void boot::setup_loop() [&ctx = this->ctx](double t, double dt) { // Update tweens - ctx.surface_sky_pass->update_tweens(); + ctx.sky_pass->update_tweens(); ctx.surface_scene->update_tweens(); ctx.underground_scene->update_tweens(); ctx.ui_scene->update_tweens(); diff --git a/src/game/state/nuptial-flight.cpp b/src/game/state/nuptial-flight.cpp index d54502f..de1d936 100644 --- a/src/game/state/nuptial-flight.cpp +++ b/src/game/state/nuptial-flight.cpp @@ -20,9 +20,8 @@ #include "game/state/nuptial-flight.hpp" #include "game/state/pause-menu.hpp" #include "entity/archetype.hpp" -#include "entity/systems/astronomy.hpp" -#include "entity/systems/orbit.hpp" #include "entity/systems/camera.hpp" +#include "entity/systems/astronomy.hpp" #include "entity/components/observer.hpp" #include "entity/components/transform.hpp" #include "entity/components/terrain.hpp" @@ -37,8 +36,7 @@ #include "game/world.hpp" #include "application.hpp" #include "render/passes/clear-pass.hpp" -#include -#include +#include "render/passes/ground-pass.hpp" #include "state-machine.hpp" #include "config.hpp" @@ -53,6 +51,16 @@ nuptial_flight::nuptial_flight(game::context& ctx): // Disable UI color clear ctx.ui_clear_pass->set_cleared_buffers(false, true, false); + // Setup and enable sky pass + ctx.sky_pass->set_sky_model(ctx.resource_manager->load("celestial-hemisphere.mdl")); + ctx.sky_pass->set_enabled(true); + + // Setup and enable ground pass + render::model* terrestrial_hemisphere_model = ctx.resource_manager->load("terrestrial-hemisphere.mdl"); + (*terrestrial_hemisphere_model->get_groups())[0]->set_material(ctx.resource_manager->load("scrub-terrestrial-hemisphere.mtl")); + ctx.ground_pass->set_ground_model(terrestrial_hemisphere_model); + ctx.ground_pass->set_enabled(true); + // Create world game::world::create_stars(ctx); game::world::create_sun(ctx); @@ -65,10 +73,6 @@ nuptial_flight::nuptial_flight(game::context& ctx): // Freeze time game::world::set_time_scale(ctx, 0.0); - // Switch to surface camera - ctx.underground_camera->set_active(false); - ctx.surface_camera->set_active(true); - // Find planet EID by name entity::id planet_eid = ctx.entities["planet"]; @@ -77,9 +81,10 @@ nuptial_flight::nuptial_flight(game::context& ctx): // ctx.entity_registry->remove(planet_eid); // Enable clouds in sky pass - //ctx.surface_sky_pass->set_clouds_model(ctx.resource_manager->load("cloud-plane.mdl")); + //ctx.sky_pass->set_clouds_model(ctx.resource_manager->load("cloud-plane.mdl")); // Create biome terrain component + /* entity::component::terrain biome_terrain; biome_terrain.max_lod = 18; biome_terrain.patch_material = ctx.resource_manager->load("desert-terrain.mtl"); @@ -89,6 +94,7 @@ nuptial_flight::nuptial_flight(game::context& ctx): }; // Replace planet terrain component with biome terrain component ctx.entity_registry->replace(planet_eid, biome_terrain); + */ // Create observer entity::id observer_eid = ctx.entity_registry->create(); @@ -218,7 +224,7 @@ void nuptial_flight::setup_camera() ctx.entity_registry->assign(camera_eid, constraint_stack); } - float ev100 = 14.5f; + float ev100 = 13.5f; ctx.surface_camera->set_exposure(ev100); } @@ -229,11 +235,13 @@ void nuptial_flight::enable_controls() entity::id target_eid = ctx.entities["surface_cam_target"]; entity::id three_dof_eid = ctx.entities["surface_cam_3dof"]; + const float min_elevation = 0.1f; + const float max_elevation = 100.0f; const float slow_modifier = 0.25f; const float fast_modifier = 4.0f; - const float dolly_speed = 20.0f; + const float dolly_speed = 5.0f; const float truck_speed = dolly_speed; - const float pedestal_speed = 30.0f; + const float pedestal_speed = 5.0f; float mouse_tilt_sensitivity = 1.0f; float mouse_pan_sensitivity = 1.0f; bool mouse_invert_tilt = false; @@ -348,14 +356,17 @@ void nuptial_flight::enable_controls() // Pedestal up ctx.controls["move_up"]->set_active_callback ( - [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier, max_elevation](float value) { if (move_slow->is_active()) value *= slow_modifier; if (move_fast->is_active()) value *= fast_modifier; - const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + auto transform = entity::command::get_world_transform(*ctx.entity_registry, target_eid); + if (transform.translation.y + movement.y > max_elevation) + movement.y = max_elevation - transform.translation.y; entity::command::translate(*ctx.entity_registry, target_eid, movement); } ); @@ -363,14 +374,18 @@ void nuptial_flight::enable_controls() // Pedestal down ctx.controls["move_down"]->set_active_callback ( - [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier, min_elevation](float value) { if (move_slow->is_active()) value *= slow_modifier; if (move_fast->is_active()) value *= fast_modifier; - - const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + + float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + auto transform = entity::command::get_world_transform(*ctx.entity_registry, target_eid); + if (transform.translation.y + movement.y < min_elevation) + movement.y = min_elevation - transform.translation.y; + entity::command::translate(*ctx.entity_registry, target_eid, movement); } ); diff --git a/src/game/world.cpp b/src/game/world.cpp index 4c1fcb2..f32a55c 100644 --- a/src/game/world.cpp +++ b/src/game/world.cpp @@ -180,7 +180,7 @@ void create_stars(game::context& ctx) stars_model_group->set_index_count(star_count); // Pass stars model to sky pass - ctx.surface_sky_pass->set_stars_model(stars_model); + ctx.sky_pass->set_stars_model(stars_model); } void create_sun(game::context& ctx) @@ -224,13 +224,10 @@ void create_planet(game::context& ctx) }; terrain.max_lod = 0; terrain.patch_material = nullptr; - ctx.entity_registry->assign(planet_eid, terrain); + //ctx.entity_registry->assign(planet_eid, terrain); // Pass planet to astronomy system as reference body ctx.astronomy_system->set_reference_body(planet_eid); - - // Load sky model - ctx.surface_sky_pass->set_sky_model(ctx.resource_manager->load("sky-dome.mdl")); } void create_moon(game::context& ctx) @@ -240,7 +237,7 @@ void create_moon(game::context& ctx) ctx.entities["moon"] = moon_eid; // Pass moon model to sky pass - ctx.surface_sky_pass->set_moon_model(ctx.resource_manager->load("moon.mdl")); + ctx.sky_pass->set_moon_model(ctx.resource_manager->load("moon.mdl")); } void set_time(game::context& ctx, double t) diff --git a/src/render/context.hpp b/src/render/context.hpp index 120eec1..dcc6c7e 100644 --- a/src/render/context.hpp +++ b/src/render/context.hpp @@ -56,6 +56,9 @@ struct context /// Near clipping plane of the camera geom::plane clip_near; + /// Camera exposure normalization factor. + float exposure; + /// Collection of scene objects being rendered. const scene::collection* collection; diff --git a/src/render/passes/ground-pass.cpp b/src/render/passes/ground-pass.cpp new file mode 100644 index 0000000..d96dfa8 --- /dev/null +++ b/src/render/passes/ground-pass.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2021 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 "render/passes/ground-pass.hpp" +#include "resources/resource-manager.hpp" +#include "resources/string-table.hpp" +#include "gl/rasterizer.hpp" +#include "gl/framebuffer.hpp" +#include "gl/shader-program.hpp" +#include "gl/shader-input.hpp" +#include "gl/vertex-buffer.hpp" +#include "gl/vertex-array.hpp" +#include "gl/vertex-attribute.hpp" +#include "gl/drawing-mode.hpp" +#include "gl/texture-2d.hpp" +#include "gl/texture-wrapping.hpp" +#include "gl/texture-filter.hpp" +#include "render/vertex-attribute.hpp" +#include "render/context.hpp" +#include "render/model.hpp" +#include "render/material.hpp" +#include "scene/camera.hpp" +#include "scene/collection.hpp" +#include "scene/directional-light.hpp" +#include "scene/ambient-light.hpp" +#include "utility/fundamental-types.hpp" +#include "color/color.hpp" +#include "math/interpolation.hpp" +#include +#include +#include + +namespace render { + +ground_pass::ground_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, resource_manager* resource_manager): + pass(rasterizer, framebuffer), + ground_model(nullptr), + ground_model_vao(nullptr), + ground_material(nullptr), + shader_program(nullptr) +{} + +ground_pass::~ground_pass() +{} + +void ground_pass::render(const render::context& ctx, render::queue& queue) const +{ + if (!ground_model) + return; + + rasterizer->use_framebuffer(*framebuffer); + + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + 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))}; + + const scene::camera& camera = *ctx.camera; + float clip_near = camera.get_clip_near_tween().interpolate(ctx.alpha); + float clip_far = camera.get_clip_far_tween().interpolate(ctx.alpha); + float3 model_scale = float3{1.0f, 1.0f, 1.0f} * (clip_near + clip_far) * 0.5f; + float4x4 model = math::scale(math::identity4x4, model_scale); + float4x4 view = math::resize<4, 4>(math::resize<3, 3>(camera.get_view_tween().interpolate(ctx.alpha))); + float4x4 model_view = view * model; + float4x4 projection = camera.get_projection_tween().interpolate(ctx.alpha); + //float4x4 view_projection = projection * view; + float4x4 model_view_projection = projection * model_view; + + float3 ambient_light_color = {0.0f, 0.0f, 0.0f}; + float3 directional_light_color = {0.0f, 0.0f, 0.0f}; + float3 directional_light_direction = {0.0f, 0.0f, 0.0f}; + + // Collect lights + const std::list* lights = ctx.collection->get_objects(scene::light::object_type_id); + for (const scene::object_base* object: *lights) + { + // Skip inactive lights + if (!object->is_active()) + continue; + + const scene::light* light = static_cast(object); + switch (light->get_light_type()) + { + // Add ambient light + case scene::light_type::ambient: + { + // Pre-expose light + ambient_light_color = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; + break; + } + + // Add directional light + case scene::light_type::directional: + { + const scene::directional_light* directional_light = static_cast(light); + + // Pre-expose light + directional_light_color = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; + + directional_light_direction = static_cast(light)->get_direction_tween().interpolate(ctx.alpha); + break; + } + + default: + break; + } + } + + // Draw ground + rasterizer->use_program(*shader_program); + + if (model_view_projection_input) + model_view_projection_input->upload(model_view_projection); + if (camera_position_input) + camera_position_input->upload(ctx.camera_transform.translation); + if (directional_light_colors_input) + directional_light_colors_input->upload(0, &directional_light_color, 1); + if (directional_light_directions_input) + directional_light_directions_input->upload(0, &directional_light_direction, 1); + if (ambient_light_colors_input) + ambient_light_colors_input->upload(0, &ambient_light_color, 1); + + ground_material->upload(ctx.alpha); + + + + rasterizer->draw_arrays(*ground_model_vao, ground_model_drawing_mode, ground_model_start_index, ground_model_index_count); +} + +void ground_pass::set_ground_model(const model* model) +{ + ground_model = model; + + if (ground_model) + { + ground_model_vao = model->get_vertex_array(); + + const std::vector& groups = *model->get_groups(); + for (model_group* group: groups) + { + ground_material = group->get_material(); + ground_model_drawing_mode = group->get_drawing_mode(); + ground_model_start_index = group->get_start_index(); + ground_model_index_count = group->get_index_count(); + } + + if (ground_material) + { + shader_program = ground_material->get_shader_program(); + + if (shader_program) + { + model_view_projection_input = shader_program->get_input("model_view_projection"); + camera_position_input = shader_program->get_input("camera.position"); + directional_light_colors_input = shader_program->get_input("directional_light_colors"); + directional_light_directions_input = shader_program->get_input("directional_light_directions"); + ambient_light_colors_input = shader_program->get_input("ambient_light_colors"); + } + } + } + else + { + ground_model_vao = nullptr; + } +} + +} // namespace render diff --git a/src/render/passes/ground-pass.hpp b/src/render/passes/ground-pass.hpp new file mode 100644 index 0000000..7a730b2 --- /dev/null +++ b/src/render/passes/ground-pass.hpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 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_RENDER_GROUND_PASS_HPP +#define ANTKEEPER_RENDER_GROUND_PASS_HPP + +#include "render/pass.hpp" +#include "utility/fundamental-types.hpp" +#include "animation/tween.hpp" +#include "gl/shader-program.hpp" +#include "gl/shader-input.hpp" +#include "gl/vertex-buffer.hpp" +#include "gl/vertex-array.hpp" +#include "gl/drawing-mode.hpp" + +class resource_manager; + +namespace render { + +class material; +class model; + +/** + * + */ +class ground_pass: public pass +{ +public: + ground_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, resource_manager* resource_manager); + virtual ~ground_pass(); + virtual void render(const render::context& ctx, render::queue& queue) const final; + + void set_ground_model(const model* model); + +private: + gl::shader_program* shader_program; + const gl::shader_input* model_view_projection_input; + const gl::shader_input* camera_position_input; + const gl::shader_input* directional_light_colors_input; + const gl::shader_input* directional_light_directions_input; + const gl::shader_input* ambient_light_colors_input; + + const model* ground_model; + const material* ground_material; + const gl::vertex_array* ground_model_vao; + gl::drawing_mode ground_model_drawing_mode; + std::size_t ground_model_start_index; + std::size_t ground_model_index_count; +}; + +} // namespace render + +#endif // ANTKEEPER_RENDER_GROUND_PASS_HPP diff --git a/src/render/passes/material-pass.cpp b/src/render/passes/material-pass.cpp index 29a0b69..302a500 100644 --- a/src/render/passes/material-pass.cpp +++ b/src/render/passes/material-pass.cpp @@ -132,10 +132,6 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con clip_depth[0] = ctx.camera->get_clip_near_tween().interpolate(ctx.alpha); clip_depth[1] = ctx.camera->get_clip_far_tween().interpolate(ctx.alpha); float log_depth_coef = 2.0f / std::log2(clip_depth[1] + 1.0f); - - float camera_exposure = std::exp2(-ctx.camera->get_exposure_tween().interpolate(ctx.alpha)); - //float camera_exposure = ctx.camera->get_exposure_tween().interpolate(ctx.alpha); - int active_material_flags = 0; const gl::shader_program* active_shader_program = nullptr; @@ -165,7 +161,7 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con if (ambient_light_count < max_ambient_light_count) { // Pre-expose light - ambient_light_colors[ambient_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * camera_exposure; + ambient_light_colors[ambient_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; ++ambient_light_count; } break; @@ -177,7 +173,7 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con if (point_light_count < max_point_light_count) { // Pre-expose light - point_light_colors[point_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * camera_exposure; + point_light_colors[point_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; float3 position = light->get_transform_tween().interpolate(ctx.alpha).translation; point_light_positions[point_light_count] = position; @@ -196,7 +192,7 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con const scene::directional_light* directional_light = static_cast(light); // Pre-expose light - directional_light_colors[directional_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * camera_exposure; + directional_light_colors[directional_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; float3 direction = static_cast(light)->get_direction_tween().interpolate(ctx.alpha); directional_light_directions[directional_light_count] = direction; @@ -236,7 +232,7 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con const scene::spot_light* spot_light = static_cast(light); // Pre-expose light - spot_light_colors[spot_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * camera_exposure; + spot_light_colors[spot_light_count] = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; float3 position = light->get_transform_tween().interpolate(ctx.alpha).translation; spot_light_positions[spot_light_count] = position; @@ -447,7 +443,7 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con if (parameters->camera_position) parameters->camera_position->upload(camera_position); if (parameters->camera_exposure) - parameters->camera_exposure->upload(camera_exposure); + parameters->camera_exposure->upload(ctx.exposure); if (parameters->view) parameters->view->upload(view); if (parameters->view_projection) diff --git a/src/render/passes/sky-pass.cpp b/src/render/passes/sky-pass.cpp index 4462c5c..74cbbf8 100644 --- a/src/render/passes/sky-pass.cpp +++ b/src/render/passes/sky-pass.cpp @@ -105,8 +105,6 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const float4x4 projection = camera.get_projection_tween().interpolate(ctx.alpha); float4x4 view_projection = projection * view; float4x4 model_view_projection = projection * model_view; - float exposure = std::exp2(-camera.get_exposure_tween().interpolate(ctx.alpha)); - //float exposure = camera.get_exposure_tween().interpolate(ctx.alpha); // Interpolate observer altitude float observer_altitude = observer_altitude_tween.interpolate(ctx.alpha); @@ -141,7 +139,7 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const if (time_input) time_input->upload(ctx.t); if (exposure_input) - exposure_input->upload(exposure); + exposure_input->upload(ctx.exposure); if (observer_altitude_input) observer_altitude_input->upload(observer_altitude); @@ -149,8 +147,11 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const sun_direction_input->upload(sun_direction); if (sun_angular_radius_input) sun_angular_radius_input->upload(sun_angular_radius); + + // Pre-exposure sun color if (sun_color_input) - sun_color_input->upload(sun_color_outer); + sun_color_input->upload(sun_color_outer * ctx.exposure); + if (scale_height_rm_input) scale_height_rm_input->upload(scale_height_rm); if (rayleigh_scattering_input) @@ -181,7 +182,7 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const if (cloud_camera_position_input) cloud_camera_position_input->upload(ctx.camera_transform.translation); if (cloud_camera_exposure_input) - cloud_camera_exposure_input->upload(exposure); + cloud_camera_exposure_input->upload(ctx.exposure); cloud_material->upload(ctx.alpha); @@ -210,7 +211,7 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const if (star_distance_input) star_distance_input->upload(star_distance); if (star_exposure_input) - star_exposure_input->upload(exposure); + star_exposure_input->upload(ctx.exposure); star_material->upload(ctx.alpha); diff --git a/src/render/renderer.cpp b/src/render/renderer.cpp index 18b8e9a..6125ca1 100644 --- a/src/render/renderer.cpp +++ b/src/render/renderer.cpp @@ -97,7 +97,8 @@ void renderer::render(float t, float dt, float alpha, const scene::collection& c ctx.camera_transform = camera->get_transform_tween().interpolate(alpha); ctx.camera_forward = ctx.camera_transform.rotation * config::global_forward; ctx.camera_up = ctx.camera_transform.rotation * config::global_up; - ctx.clip_near = camera->get_view_frustum().get_near(); ///< TODO: tween this + ctx.clip_near = camera->get_view_frustum().get_near(); ///< @TODO: tween this + ctx.exposure = std::exp2(-camera->get_exposure_tween().interpolate(alpha)); // Create render queue render::queue queue;