Browse Source

Load sky gradient from sky palette texture, make sun position more physically accurate, revise linear<->srgb functions

master
C. J. Howard 4 years ago
parent
commit
3172042ac5
8 changed files with 107 additions and 64 deletions
  1. +3
    -0
      src/game/biome.hpp
  2. +2
    -7
      src/game/states/play-state.cpp
  3. +58
    -3
      src/game/systems/weather-system.cpp
  4. +7
    -0
      src/game/systems/weather-system.hpp
  5. +10
    -22
      src/renderer/passes/sky-pass.cpp
  6. +5
    -8
      src/renderer/passes/sky-pass.hpp
  7. +12
    -0
      src/resources/biome-loader.cpp
  8. +10
    -24
      src/utility/gamma.hpp

+ 3
- 0
src/game/biome.hpp View File

@ -23,6 +23,7 @@
#include <string> #include <string>
#include "utility/fundamental-types.hpp" #include "utility/fundamental-types.hpp"
class material; class material;
class image;
struct biome struct biome
{ {
@ -43,6 +44,8 @@ struct biome
float3 zenith_color; float3 zenith_color;
float wind_speed; float wind_speed;
float wind_direction; float wind_direction;
image* sky_palette;
image* shadow_palette;
// Traits // Traits
}; };

+ 2
- 7
src/game/states/play-state.cpp View File

@ -90,14 +90,9 @@ void play_state_enter(game_context* ctx)
sky_pass->set_enabled(true); sky_pass->set_enabled(true);
sky_pass->set_sun_angular_radius(ctx->biome->sun_angular_radius); sky_pass->set_sun_angular_radius(ctx->biome->sun_angular_radius);
sky_pass->set_sun_color(ctx->biome->sun_color * ctx->biome->sun_intensity); sky_pass->set_sun_color(ctx->biome->sun_color * ctx->biome->sun_intensity);
sky_pass->set_horizon_color(ctx->biome->horizon_color);
sky_pass->set_zenith_color(ctx->biome->zenith_color);
texture_2d* sky_palette = ctx->resource_manager->load<texture_2d>("sky-palette.png");
sky_palette->set_wrapping(texture_wrapping::clamp, texture_wrapping::clamp);
sky_palette->set_filters(texture_min_filter::nearest, texture_mag_filter::nearest);
sky_pass->set_sky_palette(sky_palette);
ctx->weather_system->set_sky_palette(ctx->biome->sky_palette);
ctx->weather_system->set_shadow_palette(ctx->biome->shadow_palette);
ctx->weather_system->set_time_of_day(6.0f * 60.0f * 60.0f); ctx->weather_system->set_time_of_day(6.0f * 60.0f * 60.0f);
resource_manager* resource_manager = ctx->resource_manager; resource_manager* resource_manager = ctx->resource_manager;

+ 58
- 3
src/game/systems/weather-system.cpp View File

@ -22,7 +22,12 @@
#include "renderer/passes/sky-pass.hpp" #include "renderer/passes/sky-pass.hpp"
#include "renderer/passes/shadow-map-pass.hpp" #include "renderer/passes/shadow-map-pass.hpp"
#include "renderer/passes/material-pass.hpp" #include "renderer/passes/material-pass.hpp"
#include "utility/gamma.hpp"
#include "resources/image.hpp"
#include <cmath> #include <cmath>
#include <iostream>
static constexpr float seconds_per_day = 24.0f * 60.0f * 60.0f;
weather_system::weather_system(entt::registry& registry): weather_system::weather_system(entt::registry& registry):
entity_system(registry), entity_system(registry),
@ -35,6 +40,8 @@ weather_system::weather_system(entt::registry& registry):
material_pass(nullptr), material_pass(nullptr),
time_of_day(0.0f), time_of_day(0.0f),
time_scale(1.0f), time_scale(1.0f),
sky_palette(nullptr),
shadow_palette(nullptr),
sun_direction{0.0f, -1.0f, 0.0f} sun_direction{0.0f, -1.0f, 0.0f}
{} {}
@ -95,11 +102,24 @@ void weather_system::set_material_pass(::material_pass* pass)
void weather_system::set_time_of_day(float t) void weather_system::set_time_of_day(float t)
{ {
static constexpr float seconds_per_day = 24.0f * 60.0f * 60.0f;
time_of_day = std::fmod(t, seconds_per_day); time_of_day = std::fmod(t, seconds_per_day);
sun_azimuth = 0.0f;
sun_elevation = (time_of_day / seconds_per_day) * math::two_pi<float> - math::half_pi<float>;
//sun_azimuth = 0.0f;
//sun_elevation = (time_of_day / seconds_per_day) * math::two_pi<float> - math::half_pi<float>;
float hour_angle = math::wrap_radians(time_of_day * (math::two_pi<float> / seconds_per_day) - math::pi<float>);
float declination = math::radians(0.0f);
float latitude = math::radians(0.0f);
sun_elevation = std::asin(std::sin(declination) * std::sin(latitude) + std::cos(declination) * std::cos(hour_angle) * std::cos(latitude));
sun_azimuth = std::acos((std::sin(declination) * std::cos(latitude) - std::cos(declination) * std::cos(hour_angle) * std::sin(latitude)) / std::cos(sun_elevation));
if (hour_angle < 0.0f)
sun_azimuth = math::two_pi<float> - sun_azimuth;
//std::cout << "hour angle: " << math::degrees(hour_angle) << std::endl;
//std::cout << "azimuth: " << math::degrees(sun_azimuth) << std::endl;
//std::cout << "time: " << (time_of_day / 60.0f / 60.0f) << std::endl;
math::quaternion<float> sun_azimuth_rotation = math::angle_axis(sun_azimuth, float3{0, 1, 0}); math::quaternion<float> sun_azimuth_rotation = math::angle_axis(sun_azimuth, float3{0, 1, 0});
math::quaternion<float> sun_elevation_rotation = math::angle_axis(sun_elevation, float3{-1, 0, 0}); math::quaternion<float> sun_elevation_rotation = math::angle_axis(sun_elevation, float3{-1, 0, 0});
@ -111,6 +131,11 @@ void weather_system::set_time_of_day(float t)
sun_light->set_rotation(sun_rotation); sun_light->set_rotation(sun_rotation);
} }
if (sky_pass)
{
sky_pass->set_sky_gradient(sky_gradient);
}
shadow_light = sun_light; shadow_light = sun_light;
if (shadow_map_pass) if (shadow_map_pass)
{ {
@ -122,3 +147,33 @@ void weather_system::set_time_scale(float scale)
{ {
time_scale = scale; time_scale = scale;
} }
void weather_system::set_sky_palette(const ::image* image)
{
sky_palette = image;
if (sky_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<const unsigned char*>(image->get_pixels());
for (unsigned int x = 0; x < w; ++x)
{
for (unsigned int y = 0; y < std::min<unsigned int>(4, h); ++y)
{
unsigned int i = y * w * c + x * c;
float r = srgb_to_linear(static_cast<float>(pixels[i]) / 255.0f);
float g = srgb_to_linear(static_cast<float>(pixels[i + 1]) / 255.0f);
float b = srgb_to_linear(static_cast<float>(pixels[i + 2]) / 255.0f);
sky_gradient[y] = {r, g, b, static_cast<float>(y) * (1.0f / 3.0f)};
}
}
}
}
void weather_system::set_shadow_palette(const ::image* image)
{
shadow_palette = image;
}

+ 7
- 0
src/game/systems/weather-system.hpp View File

@ -28,6 +28,7 @@ class shadow_map_pass;
class material_pass; class material_pass;
class ambient_light; class ambient_light;
class directional_light; class directional_light;
class image;
class weather_system: class weather_system:
public entity_system public entity_system
@ -46,6 +47,9 @@ public:
void set_time_of_day(float t); void set_time_of_day(float t);
void set_time_scale(float scale); void set_time_scale(float scale);
void set_sky_palette(const ::image* image);
void set_shadow_palette(const ::image* image);
private: private:
float time_of_day; float time_of_day;
float time_scale; float time_scale;
@ -59,6 +63,9 @@ private:
sky_pass* sky_pass; sky_pass* sky_pass;
shadow_map_pass* shadow_map_pass; shadow_map_pass* shadow_map_pass;
material_pass* material_pass; material_pass* material_pass;
const image* sky_palette;
const image* shadow_palette;
std::array<float4, 4> sky_gradient;
}; };
#endif // ANTKEEPER_WEATHER_SYSTEM_HPP #endif // ANTKEEPER_WEATHER_SYSTEM_HPP

+ 10
- 22
src/renderer/passes/sky-pass.cpp View File

@ -43,7 +43,6 @@
sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager):
render_pass(rasterizer, framebuffer), render_pass(rasterizer, framebuffer),
sky_palette(nullptr),
mouse_position({0.0f, 0.0f}), mouse_position({0.0f, 0.0f}),
sun_light(nullptr) sun_light(nullptr)
{ {
@ -51,11 +50,9 @@ sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, r
matrix_input = shader_program->get_input("matrix"); matrix_input = shader_program->get_input("matrix");
sun_direction_input = shader_program->get_input("sun_direction"); sun_direction_input = shader_program->get_input("sun_direction");
sun_angular_radius_input = shader_program->get_input("sun_angular_radius"); sun_angular_radius_input = shader_program->get_input("sun_angular_radius");
horizon_color_input = shader_program->get_input("horizon_color");
zenith_color_input = shader_program->get_input("zenith_color");
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"); sun_color_input = shader_program->get_input("sun_color");
sky_palette_input = shader_program->get_input("sky_palette");
sky_gradient_input = shader_program->get_input("sky_gradient");
mouse_input = shader_program->get_input("mouse"); mouse_input = shader_program->get_input("mouse");
resolution_input = shader_program->get_input("resolution"); resolution_input = shader_program->get_input("resolution");
time_input = shader_program->get_input("time"); time_input = shader_program->get_input("time");
@ -77,6 +74,11 @@ sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, r
quad_vbo = new vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data); quad_vbo = new vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data);
quad_vao = new vertex_array(); quad_vao = new vertex_array();
quad_vao->bind_attribute(VERTEX_POSITION_LOCATION, *quad_vbo, 3, vertex_attribute_type::float_32, vertex_stride, 0); quad_vao->bind_attribute(VERTEX_POSITION_LOCATION, *quad_vbo, 3, vertex_attribute_type::float_32, vertex_stride, 0);
sky_gradient[0] = {1.0, 0.0f, 0.0f, 0.0f};
sky_gradient[1] = {0.0, 1.0f, 0.0f, 0.333f};
sky_gradient[2] = {0.0, 0.0f, 1.0f, 0.667f};
sky_gradient[3] = {1.0, 1.0f, 0.0f, 1.0f};
} }
sky_pass::~sky_pass() sky_pass::~sky_pass()
@ -123,12 +125,8 @@ void sky_pass::render(render_context* context) const
sun_angular_radius_input->upload(sun_angular_radius); sun_angular_radius_input->upload(sun_angular_radius);
if (sun_color_input) if (sun_color_input)
sun_color_input->upload(sun_color); sun_color_input->upload(sun_color);
if (horizon_color_input)
horizon_color_input->upload(horizon_color);
if (zenith_color_input)
zenith_color_input->upload(zenith_color);
if (sky_palette_input && sky_palette)
sky_palette_input->upload(sky_palette);
if (sky_gradient_input)
sky_gradient_input->upload(0, &sky_gradient[0], 4);
if (mouse_input) if (mouse_input)
mouse_input->upload(mouse_position); mouse_input->upload(mouse_position);
if (resolution_input) if (resolution_input)
@ -150,24 +148,14 @@ void sky_pass::set_sun_color(const float3& color)
sun_color = color; sun_color = color;
} }
void sky_pass::set_horizon_color(const float3& color)
{
horizon_color = color;
}
void sky_pass::set_zenith_color(const float3& color)
{
zenith_color = color;
}
void sky_pass::set_sun_light(const directional_light* light) void sky_pass::set_sun_light(const directional_light* light)
{ {
sun_light = light; sun_light = light;
} }
void sky_pass::set_sky_palette(const texture_2d* texture)
void sky_pass::set_sky_gradient(const std::array<float4, 4>& gradient)
{ {
sky_palette = texture;
sky_gradient = gradient;
} }
void sky_pass::set_time_tween(const tween<double>* time) void sky_pass::set_time_tween(const tween<double>* time)

+ 5
- 8
src/renderer/passes/sky-pass.hpp View File

@ -47,10 +47,10 @@ public:
void set_sun_angular_radius(float angle); void set_sun_angular_radius(float angle);
void set_sun_color(const float3& color); void set_sun_color(const float3& color);
void set_horizon_color(const float3& color);
void set_zenith_color(const float3& color);
void set_sun_light(const directional_light* direction); void set_sun_light(const directional_light* direction);
void set_sky_palette(const texture_2d* texture);
void set_sky_gradient(const std::array<float4, 4>& gradient);
void set_time_tween(const tween<double>* time); void set_time_tween(const tween<double>* time);
private: private:
@ -61,9 +61,7 @@ private:
const shader_input* sun_direction_input; const shader_input* sun_direction_input;
const shader_input* sun_angular_radius_input; const shader_input* sun_angular_radius_input;
const shader_input* sun_color_input; const shader_input* sun_color_input;
const shader_input* horizon_color_input;
const shader_input* zenith_color_input;
const shader_input* sky_palette_input;
const shader_input* sky_gradient_input;
const shader_input* mouse_input; const shader_input* mouse_input;
const shader_input* resolution_input; const shader_input* resolution_input;
const shader_input* time_input; const shader_input* time_input;
@ -73,11 +71,10 @@ private:
float sun_angular_radius; float sun_angular_radius;
float3 sun_color; float3 sun_color;
float3 horizon_color;
float3 zenith_color;
const directional_light* sun_light; const directional_light* sun_light;
const texture_2d* sky_palette; const texture_2d* sky_palette;
float2 mouse_position; float2 mouse_position;
std::array<float4, 4> sky_gradient;
const tween<double>* time_tween; const tween<double>* time_tween;
}; };

+ 12
- 0
src/resources/biome-loader.cpp View File

@ -100,6 +100,18 @@ biome* resource_loader::load(resource_manager* resource_manager, PHYSFS_F
load_value(&biome->wind_speed, weather.value(), "wind_speed"); load_value(&biome->wind_speed, weather.value(), "wind_speed");
load_value(&biome->wind_direction, weather.value(), "wind_direction"); load_value(&biome->wind_direction, weather.value(), "wind_direction");
biome->wind_direction = math::radians(biome->wind_direction); biome->wind_direction = math::radians(biome->wind_direction);
std::string sky_palette_filename;
if (load_value(&sky_palette_filename, weather.value(), "sky_palette"))
{
biome->sky_palette = resource_manager->load<image>(sky_palette_filename);
}
std::string shadow_palette_filename;
if (load_value(&shadow_palette_filename, weather.value(), "shadow_palette"))
{
biome->shadow_palette = resource_manager->load<image>(shadow_palette_filename);
}
} }
return biome; return biome;

+ 10
- 24
src/utility/gamma.hpp View File

@ -23,40 +23,26 @@
#include "math/vector-type.hpp" #include "math/vector-type.hpp"
#include <cmath> #include <cmath>
template <typename T, std::size_t N>
math::vector<T, N> to_linear(math::vector<T, N> v)
template <typename T>
T srgb_to_linear(const T& x)
{ {
for (std::size_t i = 0; i < N; ++i)
if (x <= T(0.04045))
{ {
if (v[i] <= T(0.04045))
{
v[i] /= T(12.92);
}
else
{
v[i] = std::pow((v[i] + T(0.055)) / T(1.055), T(2.4));
}
return x / T(12.92);
} }
return v;
return std::pow((x + T(0.055)) / T(1.055), T(2.4));
} }
template <typename T, std::size_t N>
math::vector<T, N> to_srgb(math::vector<T, N> v)
template <typename T>
T linear_to_srgb(const T& x)
{ {
for (std::size_t i = 0; i < N; ++i)
if (x <= T(0.0031308))
{ {
if (v[i] <= T(0.0031308))
{
v[i] *= T(12.92);
}
else
{
v[i] = std::pow(v[i], T(1.0 / 2.4)) * T(1.055) - T(0.055);
}
return x * T(12.92);
} }
return v;
return std::pow(x, T(1.0 / 2.4)) * T(1.055) - T(0.055);
} }
#endif // ANTKEEPER_GAMMA_HPP #endif // ANTKEEPER_GAMMA_HPP

Loading…
Cancel
Save