]> git.tdb.fi Git - libs/gl.git/blobdiff - source/effects/sky.cpp
Add debug name capability to more classes
[libs/gl.git] / source / effects / sky.cpp
index 8fa00cfbd4d44e884cdfadfd6268226705e039d2..19fb526b1bdaa83b911954ef6f26b7c37c241c4b 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,32 +11,29 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-Sky::Sky(Resources &resources, Renderable &r, const Light &s):
+Sky::Sky(Renderable &r, Light &s):
        Effect(r),
        sun(s),
-       transmittance_shprog(resources.get<Program>("_sky_transmittance.glsl.shader")),
+       transmittance_lookup(128, 64, (RENDER_COLOR, RGB16F)),
+       transmittance_shprog(Resources::get_global().get<Program>("_sky_transmittance.glsl.shader")),
        transmittance_lookup_dirty(true),
-       distant_shprog(resources.get<Program>("_sky_distant.glsl.shader")),
-       fullscreen_mesh(resources.get<Mesh>("_fullscreen_quad.mesh")),
-       backdrop_shprog(resources.get<Program>("_sky_backdrop.glsl.shader")),
-       sampler(resources.get<Sampler>("_linear_clamp.samp")),
-       wrap_sampler(resources.get<Sampler>("_linear_clamp_v.samp")),
+       distant(256, 128, (RENDER_COLOR, RGB16F)),
+       distant_shprog(Resources::get_global().get<Program>("_sky_distant.glsl.shader")),
+       fullscreen_mesh(Resources::get_global().get<Mesh>("_fullscreen_quad.mesh")),
+       backdrop_shprog(Resources::get_global().get<Program>("_sky_backdrop.glsl.shader")),
+       sampler(Resources::get_global().get<Sampler>("_linear_clamp.samp")),
+       wrap_sampler(Resources::get_global().get<Sampler>("_linear_clamp_v.samp")),
        rendered(false)
 {
-       transmittance_lookup.storage(RGB16F, 128, 64, 1);
-       transmittance_fbo.attach(COLOR_ATTACHMENT0, transmittance_lookup);
-
-       distant.storage(RGB16F, 256, 128, 1);
-       distant_fbo.attach(COLOR_ATTACHMENT0, distant);
-
        shdata.uniform("n_steps", 50);
 
        set_planet(Planet::earth());
        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);
@@ -50,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)
@@ -62,20 +97,21 @@ 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);
 
        if(transmittance_lookup_dirty)
        {
                transmittance_lookup_dirty = false;
-               Bind bind_fbo(transmittance_fbo);
+               Bind bind_fbo(transmittance_lookup.get_framebuffer());
                renderer.set_shader_program(&transmittance_shprog, &shdata);
                fullscreen_mesh.draw(renderer);
        }
 
-       Bind bind_fbo(distant_fbo);
+       Bind bind_fbo(distant.get_framebuffer());
        renderer.set_shader_program(&distant_shprog, &shdata);
-       renderer.set_texture("transmittance_lookup", &transmittance_lookup, &sampler);
+       renderer.set_texture("transmittance_lookup", &transmittance_lookup.get_target_texture(0), &sampler);
        fullscreen_mesh.draw(renderer);
 
        renderable.setup_frame(renderer);
@@ -97,10 +133,21 @@ void Sky::render(Renderer &renderer, Tag tag) const
        Renderer::Push push(renderer);
 
        renderer.set_shader_program(&backdrop_shprog, &shdata);
-       renderer.set_texture("distant", &distant, &wrap_sampler);
+       renderer.set_texture("distant", &distant.get_target_texture(0), &wrap_sampler);
        fullscreen_mesh.draw(renderer);
 }
 
+void Sky::set_debug_name(const string &name)
+{
+#ifdef DEBUG
+       transmittance_lookup.set_debug_name(name+" [RT:transmittance]");
+       distant.set_debug_name(name+" [RT:distant]");
+       shdata.set_debug_name(name+" [UBO]");
+#else
+       (void)name;
+#endif
+}
+
 
 Sky::Planet::Planet():
        rayleigh_scatter(0.0f),