From f7ec9dacc521668c920c421ec92a26d6612062ec Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Fri, 25 Sep 2020 03:40:35 -0700 Subject: [PATCH] Switch sky pass from using fullscreen quad to sky dome model --- src/configuration.hpp.in | 2 +- src/game/biome.hpp | 1 + src/game/bootloader.cpp | 8 +++- src/game/game-context.hpp | 1 + src/game/states/play-state.cpp | 4 +- src/game/systems/weather-system.cpp | 54 ++++++++++++++++++++- src/game/systems/weather-system.hpp | 3 ++ src/renderer/passes/sky-pass.cpp | 74 ++++++++++++++++++++++++----- src/renderer/passes/sky-pass.hpp | 17 ++++++- src/resources/biome-loader.cpp | 6 +++ 10 files changed, 150 insertions(+), 20 deletions(-) diff --git a/src/configuration.hpp.in b/src/configuration.hpp.in index f1dda17..a9217c6 100644 --- a/src/configuration.hpp.in +++ b/src/configuration.hpp.in @@ -33,7 +33,7 @@ constexpr math::vector global_right = {1.0f, 0.0f, 0.0f}; #define MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT 1 #define MATERIAL_PASS_MAX_POINT_LIGHT_COUNT 1 -#define MATERIAL_PASS_MAX_DIRECTIONAL_LIGHT_COUNT 1 +#define MATERIAL_PASS_MAX_DIRECTIONAL_LIGHT_COUNT 2 #define MATERIAL_PASS_MAX_SPOTLIGHT_COUNT 1 #define TERRAIN_PATCH_SIZE 200.0f #define TERRAIN_PATCH_RESOLUTION 4 diff --git a/src/game/biome.hpp b/src/game/biome.hpp index 0ceb063..b6604e4 100644 --- a/src/game/biome.hpp +++ b/src/game/biome.hpp @@ -46,6 +46,7 @@ struct biome float wind_direction; image* sky_palette; image* sun_palette; + image* moon_palette; image* ambient_palette; image* shadow_palette; diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index aec9e97..803c793 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -491,7 +491,7 @@ void setup_rendering(game_context* ctx) ctx->overworld_shadow_map_pass = new shadow_map_pass(ctx->rasterizer, ctx->shadow_map_framebuffer, ctx->resource_manager); ctx->overworld_shadow_map_pass->set_split_scheme_weight(0.75f); ctx->overworld_clear_pass = new clear_pass(ctx->rasterizer, ctx->framebuffer_hdr); - ctx->overworld_clear_pass->set_cleared_buffers(false, true, true); + ctx->overworld_clear_pass->set_cleared_buffers(true, true, true); ctx->overworld_sky_pass = new sky_pass(ctx->rasterizer, ctx->framebuffer_hdr, ctx->resource_manager); ctx->app->get_event_dispatcher()->subscribe(ctx->overworld_sky_pass); ctx->overworld_sky_pass->set_enabled(false); @@ -635,6 +635,10 @@ void setup_scenes(game_context* ctx) ctx->sun_direct->set_intensity(0.0f); ctx->sun_direct->update_tweens(); + ctx->moon_light = new directional_light(); + ctx->moon_light->set_intensity(0.0f); + ctx->moon_light->update_tweens(); + ctx->subterrain_light = new point_light(); ctx->subterrain_light->set_color({1, 1, 1}); ctx->subterrain_light->set_intensity(1.0f); @@ -693,6 +697,7 @@ void setup_scenes(game_context* ctx) ctx->overworld_scene->add_object(ctx->overworld_camera); ctx->overworld_scene->add_object(ctx->sun_indirect); ctx->overworld_scene->add_object(ctx->sun_direct); + ctx->overworld_scene->add_object(ctx->moon_light); //ctx->overworld_scene->add_object(ctx->spotlight); // Setup underworld scene @@ -861,6 +866,7 @@ void setup_systems(game_context* ctx) ctx->weather_system = new weather_system(*ctx->ecs_registry); ctx->weather_system->set_ambient_light(ctx->sun_indirect); ctx->weather_system->set_sun_light(ctx->sun_direct); + ctx->weather_system->set_moon_light(ctx->moon_light); ctx->weather_system->set_sky_pass(ctx->overworld_sky_pass); ctx->weather_system->set_shadow_map_pass(ctx->overworld_shadow_map_pass); ctx->weather_system->set_material_pass(ctx->overworld_material_pass); diff --git a/src/game/game-context.hpp b/src/game/game-context.hpp index a91a757..8b8b232 100644 --- a/src/game/game-context.hpp +++ b/src/game/game-context.hpp @@ -180,6 +180,7 @@ struct game_context camera* ui_camera; ambient_light* sun_indirect; directional_light* sun_direct; + directional_light* moon_light; point_light* subterrain_light; ambient_light* underworld_ambient_light; billboard* splash_billboard; diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 801e16e..569199c 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -85,15 +85,17 @@ void play_state_enter(game_context* ctx) ctx->sun_direct->set_rotation(sun_rotation); ctx->sun_direct->set_color(ctx->biome->sun_color); ctx->sun_direct->set_intensity(ctx->biome->sun_intensity); - + sky_pass* sky_pass = ctx->overworld_sky_pass; sky_pass->set_enabled(true); + sky_pass->set_sky_model(ctx->resource_manager->load("sky-dome.mdl")); sky_pass->set_sun_angular_radius(ctx->biome->sun_angular_radius); sky_pass->set_sun_color(ctx->biome->sun_color * ctx->biome->sun_intensity); ctx->weather_system->set_sky_palette(ctx->biome->sky_palette); ctx->weather_system->set_sun_palette(ctx->biome->sun_palette); ctx->weather_system->set_ambient_palette(ctx->biome->ambient_palette); + ctx->weather_system->set_moon_palette(ctx->biome->moon_palette); ctx->weather_system->set_shadow_palette(ctx->biome->shadow_palette); ctx->weather_system->set_time_of_day(6.0f * 60.0f * 60.0f); diff --git a/src/game/systems/weather-system.cpp b/src/game/systems/weather-system.cpp index e580a48..30564a2 100644 --- a/src/game/systems/weather-system.cpp +++ b/src/game/systems/weather-system.cpp @@ -69,6 +69,11 @@ void weather_system::set_sun_light(directional_light* light) void weather_system::set_moon_light(directional_light* light) { moon_light = light; + + if (sky_pass) + { + sky_pass->set_moon_light(moon_light); + } } void weather_system::set_sky_pass(::sky_pass* pass) @@ -78,6 +83,7 @@ void weather_system::set_sky_pass(::sky_pass* pass) if (sky_pass) { sky_pass->set_sun_light(sun_light); + sky_pass->set_moon_light(moon_light); } } @@ -102,8 +108,8 @@ void weather_system::set_material_pass(::material_pass* pass) } void weather_system::set_time_of_day(float t) -{ - time_of_day = std::fmod(t, seconds_per_day); +{ + time_of_day = std::fmod(seconds_per_day + fmod(t, seconds_per_day), seconds_per_day); //sun_azimuth = 0.0f; //sun_elevation = (time_of_day / seconds_per_day) * math::two_pi - math::half_pi; @@ -132,6 +138,14 @@ void weather_system::set_time_of_day(float t) sun_light->set_rotation(sun_rotation); } + if (moon_light) + { + math::quaternion moon_azimuth_rotation = math::angle_axis(sun_azimuth, float3{0, 1, 0}); + math::quaternion moon_elevation_rotation = math::angle_axis(sun_elevation, float3{1, 0, 0}); + math::quaternion moon_rotation = math::normalize(moon_azimuth_rotation * moon_elevation_rotation); + moon_light->set_rotation(moon_rotation); + } + if (sky_pass) { float hour = time_of_day / (60.0f * 60.0f); @@ -151,11 +165,19 @@ void weather_system::set_time_of_day(float t) float3 sun_color1 = sun_colors[(hour_index + 1) % sun_colors.size()]; float3 sun_color = math::lerp(sun_color0, sun_color1, t); + float3 moon_color0 = moon_colors[hour_index]; + float3 moon_color1 = moon_colors[(hour_index + 1) % moon_colors.size()]; + float3 moon_color = math::lerp(moon_color0, moon_color1, t); + float3 ambient_color0 = ambient_colors[hour_index]; float3 ambient_color1 = ambient_colors[(hour_index + 1) % sun_colors.size()]; float3 ambient_color = math::lerp(ambient_color0, ambient_color1, t); sun_light->set_color(sun_color); + + moon_light->set_color(moon_color); + moon_light->set_intensity(1.0f); + ambient_light->set_color(ambient_color); sky_pass->set_sky_gradient(gradient); @@ -231,6 +253,34 @@ void weather_system::set_sun_palette(const ::image* image) } } +void weather_system::set_moon_palette(const ::image* image) +{ + moon_palette = image; + if (moon_palette) + { + unsigned int w = image->get_width(); + unsigned int h = image->get_height(); + unsigned int c = image->get_channels(); + const unsigned char* pixels = static_cast(image->get_pixels()); + + for (unsigned int x = 0; x < w; ++x) + { + float3 color; + + unsigned int y = 0; + + unsigned int i = y * w * c + x * c; + float r = srgb_to_linear(static_cast(pixels[i]) / 255.0f); + float g = srgb_to_linear(static_cast(pixels[i + 1]) / 255.0f); + float b = srgb_to_linear(static_cast(pixels[i + 2]) / 255.0f); + + color = {r, g, b}; + + moon_colors.push_back(color); + } + } +} + void weather_system::set_ambient_palette(const ::image* image) { ambient_palette = image; diff --git a/src/game/systems/weather-system.hpp b/src/game/systems/weather-system.hpp index 644fb3a..3eafce6 100644 --- a/src/game/systems/weather-system.hpp +++ b/src/game/systems/weather-system.hpp @@ -49,6 +49,7 @@ public: void set_sky_palette(const ::image* image); void set_sun_palette(const ::image* image); + void set_moon_palette(const ::image* image); void set_ambient_palette(const ::image* image); void set_shadow_palette(const ::image* image); @@ -67,9 +68,11 @@ private: material_pass* material_pass; const image* sky_palette; const image* sun_palette; + const image* moon_palette; const image* ambient_palette; const image* shadow_palette; std::vector sun_colors; + std::vector moon_colors; std::vector ambient_colors; std::vector> sky_gradients; }; diff --git a/src/renderer/passes/sky-pass.cpp b/src/renderer/passes/sky-pass.cpp index 04e8857..934c341 100644 --- a/src/renderer/passes/sky-pass.cpp +++ b/src/renderer/passes/sky-pass.cpp @@ -32,6 +32,7 @@ #include "rasterizer/texture-filter.hpp" #include "renderer/vertex-attributes.hpp" #include "renderer/render-context.hpp" +#include "renderer/model.hpp" #include "scene/camera.hpp" #include "scene/scene.hpp" #include "scene/ambient-light.hpp" @@ -45,11 +46,15 @@ sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, r render_pass(rasterizer, framebuffer), mouse_position({0.0f, 0.0f}), sun_light(nullptr), - time_of_day(0.0f) + moon_light(nullptr), + time_of_day(0.0f), + sky_model(nullptr), + sky_model_vao(nullptr) { shader_program = resource_manager->load<::shader_program>("sky.glsl"); - matrix_input = shader_program->get_input("matrix"); + model_view_projection_input = shader_program->get_input("model_view_projection"); sun_direction_input = shader_program->get_input("sun_direction"); + moon_direction_input = shader_program->get_input("moon_direction"); sun_angular_radius_input = shader_program->get_input("sun_angular_radius"); sun_angular_radius_input = shader_program->get_input("sun_angular_radius"); sun_color_input = shader_program->get_input("sun_color"); @@ -91,38 +96,54 @@ sky_pass::~sky_pass() void sky_pass::render(render_context* context) const { + if (!sky_model_vao) + return; + rasterizer->use_framebuffer(*framebuffer); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - glDisable(GL_CULL_FACE); + 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)); float time = (time_tween) ? time_tween->interpolate(context->alpha) : 0.0f; float2 resolution = {static_cast(std::get<0>(viewport)), static_cast(std::get<1>(viewport))}; - float3 sun_direction = {0, -1, 0}; + float3 sun_direction = {0, -1, 0}; if (sun_light) { sun_direction = sun_light->get_direction_tween().interpolate(context->alpha); } - // Calculate matrix - float4x4 model_view = math::resize<4, 4>(math::resize<3, 3>(context->camera->get_view_tween().interpolate(context->alpha))); - float4x4 inverse_projection = math::inverse(context->camera->get_projection_tween().interpolate(context->alpha)); - float4x4 matrix = math::inverse(model_view) * inverse_projection; - + float3 moon_direction = {0, -1, 0}; + if (moon_light) + { + moon_direction = moon_light->get_direction_tween().interpolate(context->alpha); + } + + const ::camera& camera = *context->camera; + float clip_near = camera.get_clip_near_tween().interpolate(context->alpha); + float clip_far = camera.get_clip_far_tween().interpolate(context->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 model_view = math::resize<4, 4>(math::resize<3, 3>(camera.get_view_tween().interpolate(context->alpha))) * model; + float4x4 projection = camera.get_projection_tween().interpolate(context->alpha); + float4x4 model_view_projection = projection * model_view; + // Change shader program rasterizer->use_program(*shader_program); // Upload shader parameters - if (matrix_input) - matrix_input->upload(matrix); + if (model_view_projection_input) + model_view_projection_input->upload(model_view_projection); if (sun_direction_input) sun_direction_input->upload(sun_direction); + if (moon_direction_input) + moon_direction_input->upload(moon_direction); if (sun_angular_radius_input) sun_angular_radius_input->upload(sun_angular_radius); if (sun_color_input) @@ -138,8 +159,30 @@ void sky_pass::render(render_context* context) const if (time_of_day_input) time_of_day_input->upload(time_of_day); - // Draw quad - rasterizer->draw_arrays(*quad_vao, drawing_mode::triangles, 0, 6); + // Draw sky model + rasterizer->draw_arrays(*sky_model_vao, sky_model_drawing_mode, sky_model_start_index, sky_model_index_count); +} + +void sky_pass::set_sky_model(const model* model) +{ + sky_model = model; + + if (sky_model) + { + sky_model_vao = model->get_vertex_array(); + + const std::vector& groups = *model->get_groups(); + for (model_group* group: groups) + { + sky_model_drawing_mode = group->get_drawing_mode(); + sky_model_start_index = group->get_start_index(); + sky_model_index_count = group->get_index_count(); + } + } + else + { + sky_model_vao = nullptr; + } } void sky_pass::set_sun_angular_radius(float angle) @@ -157,6 +200,11 @@ void sky_pass::set_sun_light(const directional_light* light) sun_light = light; } +void sky_pass::set_moon_light(const directional_light* light) +{ + moon_light = light; +} + void sky_pass::set_sky_gradient(const std::array& gradient) { sky_gradient = gradient; diff --git a/src/renderer/passes/sky-pass.hpp b/src/renderer/passes/sky-pass.hpp index 0296565..f49539a 100644 --- a/src/renderer/passes/sky-pass.hpp +++ b/src/renderer/passes/sky-pass.hpp @@ -33,6 +33,8 @@ class vertex_array; class texture_2d; class resource_manager; class directional_light; +class model; +enum class drawing_mode; /** * @@ -45,21 +47,25 @@ public: virtual ~sky_pass(); virtual void render(render_context* context) const final; + void set_sky_model(const model* model); void set_sun_angular_radius(float angle); void set_sun_color(const float3& color); - void set_sun_light(const directional_light* direction); + void set_sun_light(const directional_light* light); + void set_moon_light(const directional_light* light); void set_sky_gradient(const std::array& gradient); void set_time_of_day(float time); + void set_time_tween(const tween* time); private: virtual void handle_event(const mouse_moved_event& event); shader_program* shader_program; - const shader_input* matrix_input; + const shader_input* model_view_projection_input; const shader_input* sun_direction_input; + const shader_input* moon_direction_input; const shader_input* sun_angular_radius_input; const shader_input* sun_color_input; const shader_input* sky_gradient_input; @@ -70,10 +76,17 @@ private: vertex_buffer* quad_vbo; vertex_array* quad_vao; + + const model* sky_model; + const vertex_array* sky_model_vao; + drawing_mode sky_model_drawing_mode; + std::size_t sky_model_start_index; + std::size_t sky_model_index_count; float sun_angular_radius; float3 sun_color; const directional_light* sun_light; + const directional_light* moon_light; const texture_2d* sky_palette; float2 mouse_position; std::array sky_gradient; diff --git a/src/resources/biome-loader.cpp b/src/resources/biome-loader.cpp index 0ff8cad..5df2baf 100644 --- a/src/resources/biome-loader.cpp +++ b/src/resources/biome-loader.cpp @@ -113,6 +113,12 @@ biome* resource_loader::load(resource_manager* resource_manager, PHYSFS_F biome->sun_palette = resource_manager->load(sun_palette_filename); } + std::string moon_palette_filename; + if (load_value(&moon_palette_filename, weather.value(), "moon_palette")) + { + biome->moon_palette = resource_manager->load(moon_palette_filename); + } + std::string ambient_palette_filename; if (load_value(&ambient_palette_filename, weather.value(), "ambient_palette")) {