diff --git a/src/game/biome.hpp b/src/game/biome.hpp index 4d09ef8..89d06a1 100644 --- a/src/game/biome.hpp +++ b/src/game/biome.hpp @@ -28,7 +28,9 @@ class image; struct biome { std::string name; - float2 coordinates; // Latitude and longitude, in radians + + /// Latitude (radians), longitude (radians), altitude (meters) + float3 location; // Terrain material* terrain_material; diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index a480774..6b2ea6c 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -91,7 +91,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")); - ctx->weather_system->set_coordinates(ctx->biome->coordinates); + ctx->weather_system->set_location(ctx->biome->location[0], ctx->biome->location[1], ctx->biome->location[2]); ctx->weather_system->set_time(2020, 6, 1, 5, 0, 0, -7.0); ctx->weather_system->set_sky_palette(ctx->biome->sky_palette); ctx->weather_system->set_sun_palette(ctx->biome->sun_palette); diff --git a/src/game/systems/weather-system.cpp b/src/game/systems/weather-system.cpp index 36be504..6945e72 100644 --- a/src/game/systems/weather-system.cpp +++ b/src/game/systems/weather-system.cpp @@ -178,7 +178,7 @@ weather_system::weather_system(entt::registry& registry): sky_palette(nullptr), shadow_palette(nullptr), sun_direction{0.0f, -1.0f, 0.0f}, - coordinates{0.0f, 0.0f}, + location{0.0f, 0.0f, 0.0f}, jd(0.0) {} @@ -186,8 +186,8 @@ void weather_system::update(double t, double dt) { jd += (dt * time_scale) / seconds_per_day; - const float latitude = coordinates[0]; - const float longitude = coordinates[1]; + const float latitude = location[0]; + const float longitude = location[1]; // Time correction double tc = longitude / (math::two_pi / 24.0); @@ -323,7 +323,7 @@ void weather_system::update(double t, double dt) sky_pass->set_sky_gradient(sky_gradient); sky_pass->set_time_of_day(static_cast(hour * 60.0 * 60.0)); - sky_pass->set_observer_coordinates(coordinates); + sky_pass->set_observer_location(location[0], location[1], location[2]); sky_pass->set_sun_coordinates(sun_position, sun_az_el); sky_pass->set_moon_coordinates(moon_position, moon_az_el); sky_pass->set_julian_day(static_cast(jd)); @@ -349,14 +349,14 @@ void weather_system::update(double t, double dt) } } -void weather_system::set_coordinates(const float2& coordinates) +void weather_system::set_location(float latitude, float longitude, float altitude) { - this->coordinates = coordinates; + location = {latitude, longitude, altitude}; } void weather_system::set_ambient_light(::ambient_light* light) { - this->ambient_light = light; + ambient_light = light; } void weather_system::set_sun_light(directional_light* light) @@ -372,6 +372,12 @@ void weather_system::set_moon_light(directional_light* light) void weather_system::set_sky_pass(::sky_pass* pass) { sky_pass = pass; + + if (sky_pass) + { + sky_pass->set_moon_angular_radius(math::radians(1.0f)); + sky_pass->set_sun_angular_radius(math::radians(1.1f)); + } } void weather_system::set_shadow_map_pass(::shadow_map_pass* pass) diff --git a/src/game/systems/weather-system.hpp b/src/game/systems/weather-system.hpp index 134f40d..39698e3 100644 --- a/src/game/systems/weather-system.hpp +++ b/src/game/systems/weather-system.hpp @@ -37,7 +37,13 @@ public: weather_system(entt::registry& registry); virtual void update(double t, double dt); - void set_coordinates(const float2& coordinates); + /** + * + * @param latitude Latitude, in radians. + * @param longitude Longitude, in radians. + * @param altitude Altitude, in radians. + */ + void set_location(float latitude, float longitude, float altitude); void set_ambient_light(ambient_light* light); void set_sun_light(directional_light* light); @@ -61,7 +67,7 @@ private: static T interpolate_gradient(const std::vector& gradient, float position); double jd; - float2 coordinates; + float3 location; float time_scale; float3 sun_direction; ambient_light* ambient_light; diff --git a/src/renderer/passes/sky-pass.cpp b/src/renderer/passes/sky-pass.cpp index b2594ed..bdc353f 100644 --- a/src/renderer/passes/sky-pass.cpp +++ b/src/renderer/passes/sky-pass.cpp @@ -46,12 +46,14 @@ sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, r render_pass(rasterizer, framebuffer), mouse_position({0.0f, 0.0f}), sky_model(nullptr), + sky_material(nullptr), sky_model_vao(nullptr), moon_model(nullptr), + moon_material(nullptr), moon_model_vao(nullptr), moon_shader_program(nullptr), blue_noise_map(nullptr), - observer_coordinates{0.0f, 0.0f} + observer_location{0.0f, 0.0f, 0.0f} { shader_program = resource_manager->load<::shader_program>("sky.glsl"); model_view_projection_input = shader_program->get_input("model_view_projection"); @@ -61,12 +63,14 @@ sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, r time_input = shader_program->get_input("time"); time_of_day_input = shader_program->get_input("time_of_day"); blue_noise_map_input = shader_program->get_input("blue_noise_map"); - observer_coordinates_input = shader_program->get_input("observer_coordinates"); + observer_location_input = shader_program->get_input("observer_location"); sun_position_input = shader_program->get_input("sun_position"); sun_az_el_input = shader_program->get_input("sun_az_el"); moon_position_input = shader_program->get_input("moon_position"); moon_az_el_input = shader_program->get_input("moon_az_el"); julian_day_input = shader_program->get_input("julian_day"); + cos_moon_angular_radius_input = shader_program->get_input("cos_moon_angular_radius"); + cos_sun_angular_radius_input = shader_program->get_input("cos_sun_angular_radius"); sky_gradient[0] = {1.0, 0.0f, 0.0f, 0.0f}; sky_gradient[1] = {0.0, 1.0f, 0.0f, 0.333f}; @@ -106,7 +110,6 @@ void sky_pass::render(render_context* context) const float4x4 projection = camera.get_projection_tween().interpolate(context->alpha); float4x4 model_view_projection = projection * model_view; - float time_of_day = time_of_day_tween.interpolate(context->alpha); float julian_day = julian_day_tween.interpolate(context->alpha); float3 sun_position = sun_position_tween.interpolate(context->alpha); @@ -133,9 +136,8 @@ 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 (observer_coordinates_input) - observer_coordinates_input->upload(observer_coordinates); - + if (observer_location_input) + observer_location_input->upload(observer_location); if (sun_position_input) sun_position_input->upload(sun_position); if (sun_az_el_input) @@ -146,16 +148,22 @@ void sky_pass::render(render_context* context) const moon_az_el_input->upload(moon_az_el); if (julian_day_input) julian_day_input->upload(julian_day); + if (cos_moon_angular_radius_input) + 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); + sky_material->upload(context->alpha); + rasterizer->draw_arrays(*sky_model_vao, sky_model_drawing_mode, sky_model_start_index, sky_model_index_count); } // Draw moon model + if (moon_az_el[1] >= -moon_angular_radius) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); - float moon_angular_radius = math::radians(1.0f); float moon_distance = (clip_near + clip_far) * 0.5f; float moon_radius = moon_angular_radius * moon_distance; @@ -189,6 +197,7 @@ void sky_pass::set_sky_model(const model* model) const std::vector& groups = *model->get_groups(); for (model_group* group: groups) { + sky_material = group->get_material(); sky_model_drawing_mode = group->get_drawing_mode(); sky_model_start_index = group->get_start_index(); sky_model_index_count = group->get_index_count(); @@ -271,9 +280,9 @@ void sky_pass::set_julian_day(float jd) julian_day_tween[1] = jd; } -void sky_pass::set_observer_coordinates(const float2& coordinates) +void sky_pass::set_observer_location(float latitude, float longitude, float altitude) { - observer_coordinates = coordinates; + observer_location = {latitude, longitude, altitude}; } void sky_pass::set_sun_coordinates(const float3& position, const float2& az_el) @@ -288,6 +297,18 @@ void sky_pass::set_moon_coordinates(const float3& position, const float2& az_el) moon_az_el_tween[1] = az_el; } +void sky_pass::set_moon_angular_radius(float radius) +{ + moon_angular_radius = radius; + cos_moon_angular_radius = std::cos(moon_angular_radius); +} + +void sky_pass::set_sun_angular_radius(float radius) +{ + sun_angular_radius = radius; + cos_sun_angular_radius = std::cos(sun_angular_radius); +} + void sky_pass::handle_event(const mouse_moved_event& event) { mouse_position = {static_cast(event.x), static_cast(event.y)}; diff --git a/src/renderer/passes/sky-pass.hpp b/src/renderer/passes/sky-pass.hpp index b8c494a..8b7aac8 100644 --- a/src/renderer/passes/sky-pass.hpp +++ b/src/renderer/passes/sky-pass.hpp @@ -57,9 +57,12 @@ public: void set_moon_model(const model* model); void set_julian_day(float jd); - void set_observer_coordinates(const float2& coordinates); + void set_observer_location(float latitude, float longitude, float altitude); 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_angular_radius(float radius); + void set_sun_angular_radius(float radius); private: virtual void handle_event(const mouse_moved_event& event); @@ -71,13 +74,15 @@ private: const shader_input* resolution_input; const shader_input* time_input; const shader_input* time_of_day_input; - const shader_input* observer_coordinates_input; + const shader_input* observer_location_input; const shader_input* sun_position_input; const shader_input* sun_az_el_input; const shader_input* moon_position_input; const shader_input* moon_az_el_input; const shader_input* blue_noise_map_input; const shader_input* julian_day_input; + const shader_input* cos_sun_angular_radius_input; + const shader_input* cos_moon_angular_radius_input; ::shader_program* moon_shader_program; const shader_input* moon_model_view_projection_input; @@ -86,6 +91,7 @@ private: const shader_input* moon_sun_position_input; const model* sky_model; + const material* sky_material; const vertex_array* sky_model_vao; drawing_mode sky_model_drawing_mode; std::size_t sky_model_start_index; @@ -102,7 +108,7 @@ private: float2 mouse_position; std::array sky_gradient; const tween* time_tween; - float2 observer_coordinates; + float3 observer_location; tween time_of_day_tween; tween julian_day_tween; @@ -110,6 +116,10 @@ private: tween sun_az_el_tween; tween moon_position_tween; tween moon_az_el_tween; + float moon_angular_radius; + float cos_moon_angular_radius; + float sun_angular_radius; + float cos_sun_angular_radius; }; #endif // ANTKEEPER_SKY_PASS_HPP diff --git a/src/resources/biome-loader.cpp b/src/resources/biome-loader.cpp index 2f32421..b83f9d2 100644 --- a/src/resources/biome-loader.cpp +++ b/src/resources/biome-loader.cpp @@ -70,10 +70,10 @@ biome* resource_loader::load(resource_manager* resource_manager, PHYSFS_F load_value(&biome->name, json, "name"); - float2 coordinates; - if (load_array(&coordinates.x, 2, json, "coordinates")) + float3 location; + if (load_array(&location.x, 3, json, "location")) { - biome->coordinates = {math::radians(coordinates.x), math::radians(coordinates.y)}; + biome->location = {math::radians(location.x), math::radians(location.y), location.z}; } if (auto terrain = json.find("terrain"); terrain != json.end())