From 3023e75cf5d586b2a159bad5f7822a6e767b0b0f Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Fri, 23 Apr 2021 18:35:12 +0800 Subject: [PATCH] Apply temporary fix to astronomy system and sun position calculation --- src/ecs/systems/astronomy-system.cpp | 61 ++++++++++++++++++- src/ecs/systems/astronomy-system.hpp | 9 +++ src/game/bootloader.cpp | 16 +++-- src/game/states/play-state.cpp | 88 +++++++++++++++++++-------- src/renderer/passes/material-pass.cpp | 37 +++++++++-- src/renderer/passes/material-pass.hpp | 6 +- src/renderer/passes/sky-pass.cpp | 4 +- src/renderer/passes/sky-pass.hpp | 2 +- src/scene/directional-light.cpp | 20 +++++- src/scene/directional-light.hpp | 36 ++++++++++- src/scene/light.cpp | 1 - src/scene/light.hpp | 34 ++++++++++- src/scene/point-light.hpp | 3 + src/scene/spotlight.hpp | 4 ++ 14 files changed, 270 insertions(+), 51 deletions(-) diff --git a/src/ecs/systems/astronomy-system.cpp b/src/ecs/systems/astronomy-system.cpp index 6553bda..1e506bb 100644 --- a/src/ecs/systems/astronomy-system.cpp +++ b/src/ecs/systems/astronomy-system.cpp @@ -22,6 +22,9 @@ #include "astro/apparent-size.hpp" #include "ecs/components/celestial-body-component.hpp" #include "ecs/components/transform-component.hpp" +#include "renderer/passes/sky-pass.hpp" +#include "astro/blackbody.hpp" +#include namespace ecs { @@ -36,7 +39,9 @@ astronomy_system::astronomy_system(ecs::registry& registry): obliquity(0.0), axial_rotation(0.0), axial_rotation_at_epoch(0.0), - axial_rotation_speed(0.0) + axial_rotation_speed(0.0), + sky_pass(nullptr), + sun_light(nullptr) {} void astronomy_system::update(double t, double dt) @@ -69,7 +74,51 @@ void astronomy_system::update(double t, double dt) transform.local.translation = math::type_cast(translation); transform.local.rotation = math::type_cast(math::quaternion_cast(rotation)); transform.local.scale = math::type_cast(double3{body.radius, body.radius, body.radius}); + + if (sun_light != nullptr) + { + math::quaternion sun_azimuth_rotation = math::angle_axis(static_cast(spherical.z), float3{0, 1, 0}); + math::quaternion sun_elevation_rotation = math::angle_axis(static_cast(spherical.y), float3{-1, 0, 0}); + math::quaternion sun_az_el_rotation = math::normalize(sun_azimuth_rotation * sun_elevation_rotation); + + sun_az_el_rotation = math::angle_axis((float)universal_time * math::two_pi, float3{1, 0, 0}); + + // + //sun_light->look_at({0, 0, 0}, {0, -1, 0}, {0, 0, 1}); + + // Set sun color + float factor = std::cos(spherical.y); + + float correlated_temperature = math::lerp(8000.0f, 2000.0f, factor); + float3 correlated_color = math::type_cast(astro::blackbody(correlated_temperature)); + + float intensity = math::lerp(1000.0f, 100.0f, factor); + + sun_light->set_color(correlated_color); + sun_light->set_intensity(intensity); + + + sun_light->set_translation({0, 500, 0}); + //sun_light->set_rotation(math::look_rotation(math::normalize(transform.local.translation), {0, 1, 0})); + sun_light->set_rotation(sun_az_el_rotation); + //sun_light->set_rotation(sun_elevation_rotation); + + if (this->sky_pass) + { + this->sky_pass->set_sun_coordinates(sun_az_el_rotation * float3{0, 0, -1}, {static_cast(spherical.z), static_cast(spherical.y)}); + } + } }); + + if (sky_pass) + { + // Calculate local time + double time_correction = observer_location[2] / (math::two_pi / 24.0); + double local_jd = universal_time + time_correction / 24.0 - 0.5; + double local_time = (local_jd - std::floor(local_jd)) * 24.0; + + sky_pass->set_time_of_day(local_time); + } } void astronomy_system::set_universal_time(double time) @@ -107,6 +156,16 @@ void astronomy_system::set_axial_rotation_at_epoch(double angle) update_axial_rotation(); } +void astronomy_system::set_sky_pass(::sky_pass* pass) +{ + sky_pass = pass; +} + +void astronomy_system::set_sun_light(scene::directional_light* light) +{ + sun_light = light; +} + void astronomy_system::update_axial_rotation() { axial_rotation = math::wrap_radians(axial_rotation_at_epoch + universal_time * axial_rotation_speed); diff --git a/src/ecs/systems/astronomy-system.hpp b/src/ecs/systems/astronomy-system.hpp index 6d5f51b..9dbfa91 100644 --- a/src/ecs/systems/astronomy-system.hpp +++ b/src/ecs/systems/astronomy-system.hpp @@ -22,8 +22,11 @@ #include "entity-system.hpp" #include "ecs/entity.hpp" +#include "scene/directional-light.hpp" #include "utility/fundamental-types.hpp" +class sky_pass; + namespace ecs { /** @@ -85,6 +88,10 @@ public: */ void set_axial_rotation_at_epoch(double angle); + void set_sky_pass(sky_pass* pass); + + void set_sun_light(scene::directional_light* light); + private: /// Updates the axial rotation angle void update_axial_rotation(); @@ -104,6 +111,8 @@ private: double3 observer_location; double obliquity; double3x3 ecliptic_to_horizontal; + sky_pass* sky_pass; + scene::directional_light* sun_light; }; } // namespace ecs diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index 31a4a67..43dc670 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -865,6 +865,10 @@ void setup_systems(game_context* ctx) // Setup astronomy system ctx->astronomy_system = new ecs::astronomy_system(*ctx->ecs_registry); + ctx->astronomy_system->set_obliquity(math::radians(23.4365472133)); + ctx->astronomy_system->set_axial_rotation_speed(math::radians(360.9856)); + ctx->astronomy_system->set_axial_rotation_at_epoch(0.0); + ctx->astronomy_system->set_sky_pass(ctx->overworld_sky_pass); // Set time scale float time_scale = 60.0f; @@ -1170,9 +1174,9 @@ void setup_controls(game_context* ctx) ( [ctx, time_scale]() { - ctx->weather_system->set_time_scale(time_scale * 500.0f); - ctx->solar_system->set_time_scale(time_scale * 500.0f); - ctx->astronomy_system->set_time_scale(time_scale * 500.0f); + ctx->weather_system->set_time_scale(time_scale * 100.0f); + ctx->solar_system->set_time_scale(time_scale * 100.0f); + ctx->astronomy_system->set_time_scale(time_scale * 100.0f); } ); ctx->control_system->get_fast_forward_control()->set_deactivated_callback @@ -1188,9 +1192,9 @@ void setup_controls(game_context* ctx) ( [ctx, time_scale]() { - ctx->weather_system->set_time_scale(time_scale * -500.0f); - ctx->solar_system->set_time_scale(time_scale * -500.0f); - ctx->astronomy_system->set_time_scale(time_scale * -500.0f); + ctx->weather_system->set_time_scale(time_scale * -100.0f); + ctx->solar_system->set_time_scale(time_scale * -100.0f); + ctx->astronomy_system->set_time_scale(time_scale * -100.0f); } ); ctx->control_system->get_rewind_control()->set_deactivated_callback diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 1a38e4d..83b96a7 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -27,7 +27,6 @@ #include "ecs/components/copy-translation-component.hpp" #include "ecs/components/model-component.hpp" #include "ecs/components/snap-component.hpp" -#include "ecs/components/samara-component.hpp" #include "ecs/components/terrain-component.hpp" #include "ecs/components/tool-component.hpp" #include "ecs/components/transform-component.hpp" @@ -63,6 +62,7 @@ #include "game/biome.hpp" #include "utility/fundamental-types.hpp" #include "utility/gamma.hpp" +#include "astro/blackbody.hpp" #include "utility/bit-math.hpp" #include "genetics/genetics.hpp" @@ -76,14 +76,17 @@ void play_state_enter(game_context* ctx) debug::logger* logger = ctx->logger; logger->push_task("Entering play state"); + resource_manager* resource_manager = ctx->resource_manager; + entt::registry& ecs_registry = *ctx->ecs_registry; + // Load biome if (ctx->option_biome.has_value()) { - ctx->biome = ctx->resource_manager->load(ctx->option_biome.value() + ".bio"); + ctx->biome = resource_manager->load(ctx->option_biome.value() + ".bio"); } else { - ctx->biome = ctx->resource_manager->load("forest.bio"); + ctx->biome = resource_manager->load("forest.bio"); } // Apply biome parameters to scene @@ -92,13 +95,16 @@ 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({1.0f, 1.0f, 1.0f}); + sky_pass->set_horizon_color({0.1f, 0.1f, 0.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); - sky_pass->set_observer_location(0.0f, 0.0f, 0.0f); + sky_pass->set_observer_location(4.26352e-5, ctx->biome->location[0], ctx->biome->location[1]); sky_pass->set_moon_angular_radius(math::radians(1.0f)); sky_pass->set_sun_angular_radius(math::radians(1.0f)); + 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); @@ -108,10 +114,43 @@ void play_state_enter(game_context* ctx) ambient->update_tweens(); ctx->overworld_scene->add_object(ambient); + + + // Create sun + { + ecs::celestial_body_component sun_body; + sun_body.orbital_elements.a = 1.0; + sun_body.orbital_elements.ec = 0.016709; + sun_body.orbital_elements.w = math::radians(282.9404); + sun_body.orbital_elements.ma = math::radians(356.0470); + sun_body.orbital_elements.i = 0.0; + sun_body.orbital_elements.om = 0.0; + + sun_body.orbital_rate.a = 0.0; + sun_body.orbital_rate.ec = -1.151e-9; + sun_body.orbital_rate.w = math::radians(4.70935e-5); + sun_body.orbital_rate.ma = math::radians(0.9856002585); + sun_body.orbital_rate.i = 0.0; + sun_body.orbital_rate.om = 0.0; + + ecs::transform_component sun_transform; + sun_transform.local = math::identity_transform; + sun_transform.warp = true; + + auto sun_entity = ecs_registry.create(); + ecs_registry.assign(sun_entity, sun_transform); + ecs_registry.assign(sun_entity, sun_body); + + //ctx->astronomy_system->set_sun(sun_entity); + } + scene::directional_light* sun = new scene::directional_light(); - sun->set_color({1, 1, 1}); + + float3 sun_color = math::type_cast(astro::blackbody(6000.0)); // NOTE: this is linear sRGB, should be ACEScg + sun->set_color(sun_color); sun->set_intensity(750.0f); - sun->look_at({0, 1, 1}, {0, 0, 0}, {0, 1, 0}); + sun->set_light_texture(resource_manager->load("forest-gobo.tex")); + sun->look_at({2, 1, 0}, {0, 0, 0}, {0, 0, 1}); sun->update_tweens(); ctx->overworld_scene->add_object(sun); ctx->overworld_shadow_map_pass->set_light(sun); @@ -126,15 +165,15 @@ void play_state_enter(game_context* ctx) ctx->astronomy_system->set_obliquity(math::radians(23.4393)); ctx->astronomy_system->set_axial_rotation_at_epoch(math::radians(280.4606)); ctx->astronomy_system->set_axial_rotation_speed(math::radians(360.9856)); + ctx->astronomy_system->set_sun_light(sun); + - resource_manager* resource_manager = ctx->resource_manager; - entt::registry& ecs_registry = *ctx->ecs_registry; // Load entity archetypes ecs::archetype* ant_hill_archetype = resource_manager->load("ant-hill.ent"); ecs::archetype* nest_archetype = resource_manager->load("harvester-nest.ent"); - ecs::archetype* samara_archetype = resource_manager->load("samara.ent"); + ecs::archetype* redwood_archetype = resource_manager->load("redwood.ent"); ecs::archetype* forceps_archetype = resource_manager->load("forceps.ent"); ecs::archetype* lens_archetype = resource_manager->load("lens.ent"); ecs::archetype* brush_archetype = resource_manager->load("brush.ent"); @@ -145,6 +184,7 @@ void play_state_enter(game_context* ctx) ecs::archetype* flashlight_archetype = resource_manager->load("flashlight.ent"); ecs::archetype* flashlight_light_cone_archetype = resource_manager->load("flashlight-light-cone.ent"); ecs::archetype* lens_light_cone_archetype = resource_manager->load("lens-light-cone.ent"); + ecs::archetype* cube_archetype = resource_manager->load("unit-cube.ent"); // Create tools forceps_archetype->assign(ecs_registry, ctx->forceps_entity); @@ -190,7 +230,7 @@ void play_state_enter(game_context* ctx) // Creat nest auto nest_entity = nest_archetype->create(ecs_registry); - + // Create terrain int terrain_radius = 6; for (int x = -terrain_radius; x <= terrain_radius; ++x) @@ -206,26 +246,20 @@ void play_state_enter(game_context* ctx) } } - // Create samaras - for (int i = 0; i < 15; ++i) + // Create trees + for (int i = 0; i < 30; ++i) { - auto samara_entity = samara_archetype->create(ecs_registry); - - auto& transform = ecs_registry.get(samara_entity); - float zone = 200.0f; - transform.local = math::identity_transform; - transform.local.translation.x = math::random(-zone, zone); - transform.local.translation.y = math::random(50.0f, 150.0f); - transform.local.translation.z = math::random(-zone, zone); + auto redwood = redwood_archetype->create(ecs_registry); - ecs::samara_component samara_component; - samara_component.angle = math::random(0.0f, math::radians(360.0f)); - samara_component.direction = math::normalize(float3{math::random(-1.0f, 1.0f), math::random(-1.0f, -5.0f), math::random(-1.0f, 1.0f)}); - samara_component.chirality = (math::random(0.0f, 1.0f) < 0.5f) ? -1.0f : 1.0f; - - ecs_registry.assign_or_replace(samara_entity, samara_component); + auto& transform = ecs_registry.get(redwood); + float zone = 500.0f; + ecs::command::place(ecs_registry, redwood, {math::random(-zone, zone), math::random(-zone, zone)}); } + // Create unit cube + auto cube = cube_archetype->create(ecs_registry); + ecs::command::place(ecs_registry, cube, {10, 10}); + // Setup camera focal point ecs::transform_component focal_point_transform; focal_point_transform.local = math::identity_transform; diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index a87e1f6..7b3e407 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -62,8 +62,6 @@ material_pass::material_pass(gl::rasterizer* rasterizer, const gl::framebuffer* shadow_map(nullptr), shadow_strength(1.0f) { - soft_shadows_texture = resource_manager->load("forest-gobo.tex"); - max_ambient_light_count = MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT; max_point_light_count = MATERIAL_PASS_MAX_POINT_LIGHT_COUNT; max_directional_light_count = MATERIAL_PASS_MAX_DIRECTIONAL_LIGHT_COUNT; @@ -75,6 +73,8 @@ material_pass::material_pass(gl::rasterizer* rasterizer, const gl::framebuffer* point_light_attenuations = new float3[max_point_light_count]; directional_light_colors = new float3[max_directional_light_count]; directional_light_directions = new float3[max_directional_light_count]; + directional_light_matrices = new float4x4[max_directional_light_count]; + directional_light_textures = new const gl::texture_2d*[max_directional_light_count]; spotlight_colors = new float3[max_spotlight_count]; spotlight_positions = new float3[max_spotlight_count]; spotlight_directions = new float3[max_spotlight_count]; @@ -90,6 +90,8 @@ material_pass::~material_pass() delete[] point_light_attenuations; delete[] directional_light_colors; delete[] directional_light_directions; + delete[] directional_light_matrices; + delete[] directional_light_textures; delete[] spotlight_colors; delete[] spotlight_positions; delete[] spotlight_directions; @@ -189,6 +191,8 @@ void material_pass::render(render_context* context) const { if (directional_light_count < max_directional_light_count) { + const scene::directional_light* directional_light = static_cast(light); + directional_light_colors[directional_light_count] = light->get_scaled_color_tween().interpolate(context->alpha); // Transform direction into view-space @@ -196,6 +200,24 @@ void material_pass::render(render_context* context) const float3 view_space_direction = math::normalize(math::resize<3>(view * math::resize<4>(-direction))); directional_light_directions[directional_light_count] = view_space_direction; + // Calculate a view-projection matrix from the directional light's transform + math::transform light_transform = light->get_transform_tween().interpolate(context->alpha); + float3 forward = light_transform.rotation * global_forward; + float3 up = light_transform.rotation * global_up; + + float4x4 light_view = math::look_at(light_transform.translation, light_transform.translation + forward, up); + float4x4 light_projection = math::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); + float4x4 bias = math::translate(math::identity4x4, {0.5f, 0.5f, 0.5f}) * math::scale(math::identity4x4, {0.5f, 0.5f, 0.5f}); + + //float scale_u = 1.0f; + //float scale_v = 1.0f; + //float4x4 light_projection = math::ortho(-scale_u, scale_u, -scale_v, scale_v, -1.0f, 1.0f); + directional_light_matrices[directional_light_count] = bias * light_projection * light_view; + + + + directional_light_textures[directional_light_count] = directional_light->get_light_texture(); + ++directional_light_count; } break; @@ -245,7 +267,7 @@ void material_pass::render(render_context* context) const for (int i = 0; i < 4; ++i) shadow_map_split_distances[i] = shadow_map_pass->get_split_distances()[i + 1]; } - + // Sort render operations context->operations.sort(operation_compare); @@ -443,6 +465,10 @@ void material_pass::render(render_context* context) const parameters->directional_light_colors->upload(0, directional_light_colors, directional_light_count); if (parameters->directional_light_directions) parameters->directional_light_directions->upload(0, directional_light_directions, directional_light_count); + if (parameters->directional_light_matrices) + parameters->directional_light_matrices->upload(0, directional_light_matrices, directional_light_count); + if (parameters->directional_light_textures) + parameters->directional_light_textures->upload(0, directional_light_textures, directional_light_count); if (parameters->spotlight_count) parameters->spotlight_count->upload(spotlight_count); if (parameters->spotlight_colors) @@ -455,8 +481,6 @@ void material_pass::render(render_context* context) const parameters->spotlight_attenuations->upload(0, spotlight_attenuations, spotlight_count); if (parameters->spotlight_cutoffs) parameters->spotlight_cutoffs->upload(0, spotlight_cutoffs, spotlight_count); - if (parameters->soft_shadows) - parameters->soft_shadows->upload(soft_shadows_texture); if (parameters->focal_point) parameters->focal_point->upload(focal_point); if (parameters->shadow_map_matrices) @@ -548,13 +572,14 @@ const material_pass::parameter_set* material_pass::load_parameter_set(const gl:: parameters->directional_light_count = program->get_input("directional_light_count"); parameters->directional_light_colors = program->get_input("directional_light_colors"); parameters->directional_light_directions = program->get_input("directional_light_directions"); + parameters->directional_light_matrices = program->get_input("directional_light_matrices"); + parameters->directional_light_textures = program->get_input("directional_light_textures"); parameters->spotlight_count = program->get_input("spotlight_count"); parameters->spotlight_colors = program->get_input("spotlight_colors"); parameters->spotlight_positions = program->get_input("spotlight_positions"); parameters->spotlight_directions = program->get_input("spotlight_directions"); parameters->spotlight_attenuations = program->get_input("spotlight_attenuations"); parameters->spotlight_cutoffs = program->get_input("spotlight_cutoffs"); - parameters->soft_shadows = program->get_input("soft_shadows"); parameters->focal_point = program->get_input("focal_point"); parameters->shadow_map_matrices = program->get_input("shadow_map_matrices"); parameters->shadow_map_split_distances = program->get_input("shadow_map_split_distances"); diff --git a/src/renderer/passes/material-pass.hpp b/src/renderer/passes/material-pass.hpp index 91899a6..cbd41b5 100644 --- a/src/renderer/passes/material-pass.hpp +++ b/src/renderer/passes/material-pass.hpp @@ -89,6 +89,8 @@ private: const gl::shader_input* directional_light_count; const gl::shader_input* directional_light_colors; const gl::shader_input* directional_light_directions; + const gl::shader_input* directional_light_matrices; + const gl::shader_input* directional_light_textures; const gl::shader_input* spotlight_count; const gl::shader_input* spotlight_colors; const gl::shader_input* spotlight_positions; @@ -96,7 +98,6 @@ private: const gl::shader_input* spotlight_attenuations; const gl::shader_input* spotlight_cutoffs; - const gl::shader_input* soft_shadows; const gl::shader_input* focal_point; const gl::shader_input* shadow_map_matrices; @@ -112,7 +113,6 @@ private: const tween* time_tween; float2 mouse_position; const tween* focal_point_tween; - gl::texture_2d* soft_shadows_texture; float shadow_strength; int max_ambient_light_count; @@ -131,6 +131,8 @@ private: float3* point_light_attenuations; float3* directional_light_colors; float3* directional_light_directions; + float4x4* directional_light_matrices; + const gl::texture_2d** directional_light_textures; float3* spotlight_colors; float3* spotlight_positions; float3* spotlight_directions; diff --git a/src/renderer/passes/sky-pass.cpp b/src/renderer/passes/sky-pass.cpp index c14d707..e41300c 100644 --- a/src/renderer/passes/sky-pass.cpp +++ b/src/renderer/passes/sky-pass.cpp @@ -285,9 +285,9 @@ void sky_pass::set_julian_day(float jd) julian_day_tween[1] = jd; } -void sky_pass::set_observer_location(float latitude, float longitude, float altitude) +void sky_pass::set_observer_location(float altitude, float latitude, float longitude) { - observer_location = {latitude, longitude, altitude}; + observer_location = {altitude, latitude, longitude}; } void sky_pass::set_sun_coordinates(const float3& position, const float2& az_el) diff --git a/src/renderer/passes/sky-pass.hpp b/src/renderer/passes/sky-pass.hpp index 11f88f0..3cbcd3b 100644 --- a/src/renderer/passes/sky-pass.hpp +++ b/src/renderer/passes/sky-pass.hpp @@ -59,7 +59,7 @@ public: void set_moon_model(const model* model); void set_julian_day(float jd); - void set_observer_location(float latitude, float longitude, float altitude); + void set_observer_location(float altitude, float latitude, float longitude); void set_sun_coordinates(const float3& position, const float2& az_el); void set_moon_coordinates(const float3& position, const float2& az_el); void set_moon_rotation(const math::quaternion& rotation); diff --git a/src/scene/directional-light.cpp b/src/scene/directional-light.cpp index 6ff082f..cf78e1a 100644 --- a/src/scene/directional-light.cpp +++ b/src/scene/directional-light.cpp @@ -31,13 +31,31 @@ static float3 interpolate_direction(const float3& x, const float3& y, float a) } directional_light::directional_light(): - direction(global_forward, interpolate_direction) + direction(global_forward, interpolate_direction), + light_texture(nullptr), + light_texture_opacity(1.0f, math::lerp), + light_texture_translation({0.0f, 0.0f}, math::lerp), + light_texture_rotation(0.0f, math::lerp_angle), + light_texture_scale({1.0f, 1.0f}, math::lerp) {} +void directional_light::set_light_texture(const gl::texture_2d* texture) +{ + light_texture = texture; +} + void directional_light::update_tweens() { light::update_tweens(); direction.update(); + + if (light_texture) + { + light_texture_opacity.update(); + light_texture_translation.update(); + light_texture_rotation.update(); + light_texture_scale.update(); + } } void directional_light::transformed() diff --git a/src/scene/directional-light.hpp b/src/scene/directional-light.hpp index 4d22243..7f7db04 100644 --- a/src/scene/directional-light.hpp +++ b/src/scene/directional-light.hpp @@ -21,22 +21,44 @@ #define ANTKEEPER_SCENE_DIRECTIONAL_LIGHT_HPP #include "scene/light.hpp" +#include "gl/texture-2d.hpp" #include "utility/fundamental-types.hpp" namespace scene { +/** + * Light source with parallel rays and constant intensity. + */ class directional_light: public light { public: + /// Creates a directional light. directional_light(); - /// Returns light_type::directional + /** + * Sets the light texture, also known as a gobo, cucoloris, or cookie. + * + * @param texture Light texture. + */ + void set_light_texture(const gl::texture_2d* texture); + + void set_light_texture_opacity(float opacity); + void set_light_texture_translation(const float2& translation); + void set_light_texture_rotation(float rotation); + void set_light_texture_scale(const float2& scale); + + /// Returns light_type::directional. virtual light_type get_light_type() const; + /// Returns the normalized direction vector of the light. const float3& get_direction() const; - + + /// Returns the light texture for this light, or `nullptr` if no light texture is set. + const gl::texture_2d* get_light_texture() const; + const tween& get_direction_tween() const; + /// @copydoc object_base::update_tweens(); virtual void update_tweens(); @@ -44,6 +66,11 @@ private: virtual void transformed(); tween direction; + const gl::texture_2d* light_texture; + tween light_texture_opacity; + tween light_texture_translation; + tween light_texture_rotation; + tween light_texture_scale; }; inline light_type directional_light::get_light_type() const @@ -61,6 +88,11 @@ inline const tween& directional_light::get_direction_tween() const return direction; } +inline const gl::texture_2d* directional_light::get_light_texture() const +{ + return light_texture; +} + } // namespace scene #endif // ANTKEEPER_SCENE_DIRECTIONAL_LIGHT_HPP diff --git a/src/scene/light.cpp b/src/scene/light.cpp index 2f50fef..d28bac7 100644 --- a/src/scene/light.cpp +++ b/src/scene/light.cpp @@ -18,7 +18,6 @@ */ #include "scene/light.hpp" -#include "animation/ease.hpp" #include "math/interpolation.hpp" namespace scene { diff --git a/src/scene/light.hpp b/src/scene/light.hpp index 89af207..d81786e 100644 --- a/src/scene/light.hpp +++ b/src/scene/light.hpp @@ -26,30 +26,60 @@ namespace scene { +/// Light object type enumerations. enum class light_type { + /// Denotes an ambient light. ambient, + + /// Denotes a directional light. directional, + + /// Denotes a point light. point, + + /// Denotes a spot light. spot }; +/** + * Abstract base class for light objects. + */ class light: public object { public: typedef geom::sphere sphere_type; + /// Creates a light. light(); + /// Returns an enumeration denoting the light object type. virtual light_type get_light_type() const = 0; - + + /** + * Sets the color of the light. + * + * @param color Scene-linear light color. + */ void set_color(const float3& color); + + /** + * Sets the intensity of the light. + * + * @param intensity Light intensity. + */ void set_intensity(float intensity); + /// Returns the bounding volume of the light. virtual const bounding_volume_type& get_bounds() const; - + + /// Returns the light color. const float3& get_color() const; + + /// Returns the light intensity. float get_intensity() const; + + /// Returns the intensity-scaled light color. const float3& get_scaled_color() const; const tween& get_color_tween() const; diff --git a/src/scene/point-light.hpp b/src/scene/point-light.hpp index f78745d..485925f 100644 --- a/src/scene/point-light.hpp +++ b/src/scene/point-light.hpp @@ -25,6 +25,9 @@ namespace scene { +/** + * Light source that radiates outward from a point. + */ class point_light: public light { public: diff --git a/src/scene/spotlight.hpp b/src/scene/spotlight.hpp index 7033812..7b06673 100644 --- a/src/scene/spotlight.hpp +++ b/src/scene/spotlight.hpp @@ -25,9 +25,13 @@ namespace scene { +/** + * Directional cone light source. + */ class spotlight: public light { public: + /// Creates a spotlight. spotlight(); /// Returns light_type::spot