]> git.tdb.fi Git - libs/gl.git/commitdiff
Modify sunlight color based on transmittance of the atmosphere
authorMikko Rasa <tdb@tdb.fi>
Wed, 5 May 2021 15:35:34 +0000 (18:35 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 5 May 2021 15:35:34 +0000 (18:35 +0300)
demos/desertpillars/source/desertpillars.cpp
source/effects/sky.cpp
source/effects/sky.h
source/materials/light.cpp
source/materials/light.h

index 5f3b29b1375fdfd6c99283fbd60779e9724bb655..bdbc069e3e153d31bc69747c5a4f4a203c0dce2d 100644 (file)
@@ -34,7 +34,7 @@ DesertPillars::DesertPillars(int, char **):
        window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &DesertPillars::exit), 0));
        keyboard.signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &DesertPillars::key_press), false));
 
-       const GL::Light &sun = resources.get<GL::Light>("Sun.light");
+       GL::Light &sun = resources.get<GL::Light>("Sun.light");
        sky = make_unique<GL::Sky>(content, sun);
 
        unsigned shadow_size = 8192;
index baf4864ad02256b1b83a332541369241c5e8f019..9a5f73bc73f8d1b6405c810935721b220b53804d 100644 (file)
@@ -1,3 +1,5 @@
+#include <msp/geometry/hypersphere.h>
+#include <msp/geometry/ray.h>
 #include "light.h"
 #include "mesh.h"
 #include "renderer.h"
@@ -9,7 +11,7 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-Sky::Sky(Renderable &r, const Light &s):
+Sky::Sky(Renderable &r, Light &s):
        Effect(r),
        sun(s),
        transmittance_lookup(128, 64, (RENDER_COLOR, RGB16F)),
@@ -29,8 +31,9 @@ Sky::Sky(Renderable &r, const Light &s):
        set_view_height(5.0f);
 }
 
-void Sky::set_planet(const Planet &planet)
+void Sky::set_planet(const Planet &p)
 {
+       planet = p;
        shdata.uniform("events.rayleigh_scatter", planet.rayleigh_scatter.r, planet.rayleigh_scatter.g, planet.rayleigh_scatter.b);
        shdata.uniform("events.mie_scatter", planet.mie_scatter.r, planet.mie_scatter.g, planet.mie_scatter.b);
        shdata.uniform("events.mie_absorb", planet.mie_absorb.r, planet.mie_absorb.g, planet.mie_absorb.b);
@@ -46,9 +49,45 @@ void Sky::set_planet(const Planet &planet)
 
 void Sky::set_view_height(float h)
 {
+       view_height = h;
        shdata.uniform("view_height", h);
 }
 
+Color Sky::get_transmittance(const Vector3 &look_dir)
+{
+       Vector3 pos(0.0f, 0.0f, view_height);
+       Vector3 planet_center(0.0f, 0.0f, -planet.planet_radius);
+
+       Geometry::Ray<float, 3> ray(pos-planet_center, look_dir);
+       Geometry::HyperSphere<float, 3> surface(planet.planet_radius);
+       Geometry::SurfacePoint<float, 3> intersection;
+       if(surface.get_intersections(ray, &intersection, 1))
+               return Color(0.0f);
+
+       Geometry::HyperSphere<float, 3> space(planet.planet_radius+planet.atmosphere_thickness);
+       if(!space.get_intersections(ray, &intersection, 1))
+               return Color(1.0f);
+
+       float step_size = intersection.distance/50;
+
+       Color path_extinction(0.0f);
+       for(unsigned i=0; i<50; ++i)
+       {
+               Vector3 from_center = pos-planet_center;
+               float height = from_center.norm()-planet.planet_radius;
+
+               Color rayleigh_scatter = planet.rayleigh_scatter*exp(height/planet.rayleigh_density_decay);
+               Color mie_scatter = planet.mie_scatter*exp(height/planet.mie_density_decay);
+               Color mie_absorb = planet.mie_absorb*exp(height/planet.mie_density_decay);
+               Color ozone_absorb = planet.ozone_absorb*max(1.0f-abs(height-planet.ozone_band_center)/planet.ozone_band_extent, 0.0f);
+
+               path_extinction = path_extinction+(rayleigh_scatter+mie_scatter+mie_absorb+ozone_absorb)*step_size;
+               pos += look_dir*step_size;
+       }
+
+       return Color(exp(-path_extinction.r), exp(-path_extinction.g), exp(-path_extinction.b));
+}
+
 void Sky::setup_frame(Renderer &renderer)
 {
        if(rendered)
@@ -58,6 +97,7 @@ void Sky::setup_frame(Renderer &renderer)
 
        shdata.uniform("light_color", sun.get_color());
        shdata.uniform("light_dir", sun.get_position().slice<3>(0));
+       sun.set_transmittance(get_transmittance(normalize(sun.get_position().slice<3>(0))));
 
        Renderer::Push push(renderer);
 
index faa3eb033d594bc73f8eb7cff6eae6b664d6be96..5f84c861689249bc0533d1772be61f2e401473b0 100644 (file)
@@ -41,7 +41,8 @@ public:
        };
 
 private:
-       const Light &sun;
+       Planet planet;
+       Light &sun;
        RenderTarget transmittance_lookup;
        const Program &transmittance_shprog;
        bool transmittance_lookup_dirty;
@@ -52,14 +53,17 @@ private:
        const Sampler &sampler;
        const Sampler &wrap_sampler;
        mutable ProgramData shdata;
+       float view_height;
        bool rendered;
 
 public:
-       Sky(Renderable &, const Light &);
+       Sky(Renderable &, Light &);
 
        void set_planet(const Planet &);
        void set_view_height(float);
 
+       Color get_transmittance(const Vector3 &);
+
        virtual void setup_frame(Renderer &);
        virtual void finish_frame();
        virtual void render(Renderer &, Tag = Tag()) const;
index d84be2ac8dcc1a8542212df87c6f8063aebbaed2..2825b81eaa745f70b9d5aa4ed6009e499c4dce5c 100644 (file)
@@ -12,6 +12,7 @@ namespace GL {
 
 Light::Light():
        color(1),
+       transmittance(1),
        position(0, 0, 1, 0),
        spot_dir(0, 0, -1),
        spot_exp(0),
@@ -44,6 +45,11 @@ void Light::set_color(const Color &c)
        color = c;
 }
 
+void Light::set_transmittance(const Color &t)
+{
+       transmittance = t;
+}
+
 void Light::set_matrix(const Matrix &m)
 {
        Placeable::set_matrix(m);
@@ -101,7 +107,7 @@ void Light::update_shader_data(ProgramData &shdata, const Matrix &view_matrix, u
 {
        string base = format("light_sources[%d]", i);
        shdata.uniform(base+".position", view_matrix*position);
-       shdata.uniform(base+".color", color.r, color.g, color.b);
+       shdata.uniform(base+".color", color.r*transmittance.r, color.g*transmittance.g, color.b*transmittance.b);
 }
 
 
index d097d04ae435157ebb1c4ddd18cc2bd5857d37d0..d4b66077928188076b44974d6eaf6c36d4e2ccc2 100644 (file)
@@ -44,6 +44,7 @@ public:
 
 private:
        Color color;
+       Color transmittance;
        Vector4 position;
        Vector3 spot_dir;
        Vector3 direction;
@@ -62,7 +63,12 @@ public:
        to shaders as light_sources[i].color. */
        void set_color(const Color &);
 
+       /** Sets a multiplier on how much light actually reaches the target.  Used
+       when modeling an atmosphere. */
+       void set_transmittance(const Color &);
+
        const Color &get_color() const { return color; }
+       const Color &get_transmittance() const { return transmittance; }
 
        DEPRECATED void set_diffuse(const Color &c) { set_color(c); }
        DEPRECATED void set_specular(const Color &) { }