diff --git a/src/game/state/nuptial-flight.cpp b/src/game/state/nuptial-flight.cpp index 57713f4..3e1cd4d 100644 --- a/src/game/state/nuptial-flight.cpp +++ b/src/game/state/nuptial-flight.cpp @@ -323,7 +323,7 @@ void nuptial_flight::setup_camera() ctx.entity_registry->assign(camera_eid, constraint_stack); } - ctx.surface_camera->set_exposure(15.0f); + ctx.surface_camera->set_exposure(15.5f); ctx.astronomy_system->set_camera(ctx.surface_camera); } diff --git a/src/render/passes/sky-pass.cpp b/src/render/passes/sky-pass.cpp index f6a9c3a..f040914 100644 --- a/src/render/passes/sky-pass.cpp +++ b/src/render/passes/sky-pass.cpp @@ -68,7 +68,7 @@ sky_pass::sky_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffe clouds_model_vao(nullptr), cloud_material(nullptr), cloud_shader_program(nullptr), - observer_elevation_tween(0.0f, math::lerp), + observer_position_tween({0, 0, 0}, math::lerp), sun_position_tween(float3{1.0f, 0.0f, 0.0f}, math::lerp), sun_luminance_tween(float3{0.0f, 0.0f, 0.0f}, math::lerp), sun_illuminance_tween(float3{0.0f, 0.0f, 0.0f}, math::lerp), @@ -82,24 +82,84 @@ sky_pass::sky_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffe moon_planetlight_direction_tween(float3{0, 0, 0}, math::lerp), moon_planetlight_illuminance_tween(float3{0, 0, 0}, math::lerp), magnification(1.0f) -{} +{ + // Build quad VBO and VAO + const float quad_vertex_data[] = + { + -1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f + }; + std::size_t quad_vertex_size = 3; + std::size_t quad_vertex_stride = sizeof(float) * quad_vertex_size; + std::size_t quad_vertex_count = 6; + quad_vbo = new gl::vertex_buffer(sizeof(float) * quad_vertex_size * quad_vertex_count, quad_vertex_data); + quad_vao = new gl::vertex_array(); + gl::vertex_attribute quad_position_attribute; + quad_position_attribute.buffer = quad_vbo; + quad_position_attribute.offset = 0; + quad_position_attribute.stride = quad_vertex_stride; + quad_position_attribute.type = gl::vertex_attribute_type::float_32; + quad_position_attribute.components = 3; + quad_vao->bind(render::vertex_attribute::position, quad_position_attribute); + + // Create transmittance LUT texture and framebuffer (32F color, no depth) + int transmittance_width = 256; + int transmittance_height = 64; + transmittance_inverse_lut_resolution = {1.0f / static_cast(transmittance_width), 1.0f / static_cast(transmittance_height)}; + transmittance_texture = new gl::texture_2d(transmittance_width, transmittance_height, gl::pixel_type::float_32, gl::pixel_format::rgb); + transmittance_texture->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend); + transmittance_texture->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear); + transmittance_texture->set_max_anisotropy(0.0f); + transmittance_framebuffer = new gl::framebuffer(transmittance_width, transmittance_height); + transmittance_framebuffer->attach(gl::framebuffer_attachment_type::color, transmittance_texture); + + // Load transmittance LUT shader + transmittance_shader_program = resource_manager->load("transmittance-lut.glsl"); + transmittance_atmosphere_radii_input = transmittance_shader_program->get_input("atmosphere_radii"); + transmittance_rayleigh_parameters_input = transmittance_shader_program->get_input("rayleigh_parameters"); + transmittance_mie_parameters_input = transmittance_shader_program->get_input("mie_parameters"); + transmittance_ozone_distribution_input = transmittance_shader_program->get_input("ozone_distribution"); + transmittance_ozone_absorption_input = transmittance_shader_program->get_input("ozone_absorption"); + transmittance_inverse_lut_resolution_input = transmittance_shader_program->get_input("inverse_lut_resolution"); +} sky_pass::~sky_pass() -{} +{ + delete transmittance_framebuffer; + delete transmittance_texture; + delete quad_vao; + delete quad_vbo; +} void sky_pass::render(const render::context& ctx, render::queue& queue) const { - rasterizer->use_framebuffer(*framebuffer); - glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); - + + // Render transmittance LUT + auto transmittance_viewport = transmittance_framebuffer->get_dimensions(); + rasterizer->set_viewport(0, 0, std::get<0>(transmittance_viewport), std::get<1>(transmittance_viewport)); + rasterizer->use_framebuffer(*transmittance_framebuffer); + rasterizer->use_program(*transmittance_shader_program); + transmittance_atmosphere_radii_input->upload(atmosphere_radii); + transmittance_rayleigh_parameters_input->upload(rayleigh_parameters); + transmittance_mie_parameters_input->upload(mie_parameters); + transmittance_ozone_distribution_input->upload(ozone_distribution); + transmittance_ozone_absorption_input->upload(ozone_absorption); + if (transmittance_inverse_lut_resolution_input) + transmittance_inverse_lut_resolution_input->upload(transmittance_inverse_lut_resolution); + rasterizer->draw_arrays(*quad_vao, gl::drawing_mode::triangles, 0, 6); + + rasterizer->use_framebuffer(*framebuffer); 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; @@ -113,8 +173,8 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const float4x4 view_projection = projection * view; float4x4 model_view_projection = projection * model_view; - // Interpolate observer elevation - float observer_elevation = observer_elevation_tween.interpolate(ctx.alpha); + // Interpolate observer position + float3 observer_position = observer_position_tween.interpolate(ctx.alpha); // Construct tweened ICRF to EUS transformation math::transformation::se3 icrf_to_eus = @@ -157,8 +217,8 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const sun_angular_radius_input->upload(sun_angular_radius * magnification); if (atmosphere_radii_input) atmosphere_radii_input->upload(atmosphere_radii); - if (observer_elevation_input) - observer_elevation_input->upload(observer_elevation); + if (observer_position_input) + observer_position_input->upload(observer_position); if (rayleigh_parameters_input) rayleigh_parameters_input->upload(rayleigh_parameters); if (mie_parameters_input) @@ -167,6 +227,10 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const ozone_distribution_input->upload(ozone_distribution); if (ozone_absorption_input) ozone_absorption_input->upload(ozone_absorption); + if (transmittance_lut_input) + transmittance_lut_input->upload(transmittance_texture); + if (inverse_transmittance_lut_resolution_input) + inverse_transmittance_lut_resolution_input->upload(transmittance_inverse_lut_resolution); sky_material->upload(ctx.alpha); @@ -295,11 +359,13 @@ void sky_pass::set_sky_model(const model* model) sun_illuminance_input = sky_shader_program->get_input("sun_illuminance"); sun_angular_radius_input = sky_shader_program->get_input("sun_angular_radius"); atmosphere_radii_input = sky_shader_program->get_input("atmosphere_radii"); - observer_elevation_input = sky_shader_program->get_input("observer_elevation"); + observer_position_input = sky_shader_program->get_input("observer_position"); rayleigh_parameters_input = sky_shader_program->get_input("rayleigh_parameters"); mie_parameters_input = sky_shader_program->get_input("mie_parameters"); ozone_distribution_input = sky_shader_program->get_input("ozone_distribution"); ozone_absorption_input = sky_shader_program->get_input("ozone_absorption"); + transmittance_lut_input = sky_shader_program->get_input("transmittance_lut"); + inverse_transmittance_lut_resolution_input = sky_shader_program->get_input("inverse_transmittance_lut_resolution"); } } } @@ -424,7 +490,7 @@ void sky_pass::set_clouds_model(const model* model) void sky_pass::update_tweens() { - observer_elevation_tween.update(); + observer_position_tween.update(); sun_position_tween.update(); sun_luminance_tween.update(); sun_illuminance_tween.update(); @@ -476,6 +542,7 @@ void sky_pass::set_planet_radius(float radius) atmosphere_radii.x = radius; atmosphere_radii.y = atmosphere_radii.x + atmosphere_upper_limit; atmosphere_radii.z = atmosphere_radii.y * atmosphere_radii.y; + observer_position_tween[1] = {0.0f, atmosphere_radii.x + observer_elevation, 0.0f}; } void sky_pass::set_atmosphere_upper_limit(float limit) @@ -487,7 +554,8 @@ void sky_pass::set_atmosphere_upper_limit(float limit) void sky_pass::set_observer_elevation(float elevation) { - observer_elevation_tween[1] = elevation; + observer_elevation = elevation; + observer_position_tween[1] = {0.0f, atmosphere_radii.x + observer_elevation, 0.0f}; } void sky_pass::set_rayleigh_parameters(float scale_height, const float3& scattering) diff --git a/src/render/passes/sky-pass.hpp b/src/render/passes/sky-pass.hpp index 19ea3d2..9216fb7 100644 --- a/src/render/passes/sky-pass.hpp +++ b/src/render/passes/sky-pass.hpp @@ -85,6 +85,20 @@ public: private: virtual void handle_event(const mouse_moved_event& event); + + gl::vertex_buffer* quad_vbo; + gl::vertex_array* quad_vao; + gl::texture_2d* transmittance_texture; + gl::framebuffer* transmittance_framebuffer; + float2 transmittance_inverse_lut_resolution; + + gl::shader_program* transmittance_shader_program; + const gl::shader_input* transmittance_atmosphere_radii_input; + const gl::shader_input* transmittance_rayleigh_parameters_input; + const gl::shader_input* transmittance_mie_parameters_input; + const gl::shader_input* transmittance_ozone_distribution_input; + const gl::shader_input* transmittance_ozone_absorption_input; + const gl::shader_input* transmittance_inverse_lut_resolution_input; gl::shader_program* sky_shader_program; const gl::shader_input* model_view_projection_input; @@ -97,11 +111,13 @@ private: const gl::shader_input* sun_illuminance_input; const gl::shader_input* sun_angular_radius_input; const gl::shader_input* atmosphere_radii_input; - const gl::shader_input* observer_elevation_input; + const gl::shader_input* observer_position_input; const gl::shader_input* rayleigh_parameters_input; const gl::shader_input* mie_parameters_input; const gl::shader_input* ozone_distribution_input; const gl::shader_input* ozone_absorption_input; + const gl::shader_input* transmittance_lut_input; + const gl::shader_input* inverse_transmittance_lut_resolution_input; gl::shader_program* moon_shader_program; const gl::shader_input* moon_model_input; @@ -158,7 +174,6 @@ private: const gl::texture_2d* sky_gradient2; float2 mouse_position; - tween observer_elevation_tween; tween sun_position_tween; tween sun_luminance_tween; tween sun_illuminance_tween; @@ -177,6 +192,7 @@ private: float atmosphere_upper_limit; float3 atmosphere_radii; float observer_elevation; + tween observer_position_tween; float4 rayleigh_parameters; float4 mie_parameters; float3 ozone_distribution;