]> git.tdb.fi Git - libs/gl.git/commitdiff
Support fog in lighting and shaders
authorMikko Rasa <tdb@tdb.fi>
Wed, 18 Nov 2015 18:53:43 +0000 (20:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Wed, 18 Nov 2015 18:53:43 +0000 (20:53 +0200)
source/lighting.cpp
source/lighting.h
source/programbuilder.cpp
source/programbuilder.h

index a927d622fade9b0c81a916f51ef31bce079bf825..5cda4f4c6a4e005a5ad71c22427ddc0c5d0d69c7 100644 (file)
@@ -1,4 +1,5 @@
 #include <stdexcept>
+#include <cmath>
 #include <msp/gl/extensions/msp_legacy_features.h>
 #include "error.h"
 #include "light.h"
@@ -15,7 +16,9 @@ namespace GL {
 Lighting::Lighting():
        ambient(0.2),
        sky_direction(0, 0, 1),
-       horizon_angle(Geometry::Angle<float>::zero())
+       horizon_angle(Geometry::Angle<float>::zero()),
+       fog_color(0.0f, 0.0f, 0.0f, 0.0f),
+       fog_density(0.0f)
 { }
 
 void Lighting::set_ambient(const Color &a)
@@ -38,6 +41,24 @@ void Lighting::set_horizon_angle(const Geometry::Angle<float> &a)
        horizon_angle = a;
 }
 
+void Lighting::set_fog_color(const Color &c)
+{
+       fog_color = c;
+}
+
+void Lighting::set_fog_density(float d)
+{
+       if(d<0)
+               throw invalid_argument("Lighting::set_fog_density");
+
+       fog_density = d;
+}
+
+void Lighting::set_fog_half_distance(float d)
+{
+       set_fog_density(-log(pow(0.5, 1.0/d)));
+}
+
 void Lighting::attach(unsigned i, const Light &l)
 {
        if(i>=lights.size())
@@ -69,6 +90,8 @@ void Lighting::update_shader_data(ProgramData &shdata, const Matrix &view_matrix
        shdata.uniform("sky_color", sky_color);
        shdata.uniform("eye_sky_dir", view_matrix.block<3, 3>(0, 0)*sky_direction);
        shdata.uniform("horizon_limit", horizon_angle.radians());
+       shdata.uniform("fog_color", fog_color);
+       shdata.uniform("fog_density", fog_density);
 
        for(unsigned i=0; i<lights.size(); ++i)
                if(lights[i])
@@ -89,6 +112,14 @@ void Lighting::bind() const
        for(unsigned i=0; i<lights.size(); ++i)
                if(lights[i])
                        lights[i]->bind_to(i);
+
+       if(fog_density)
+       {
+               enable(GL_FOG);
+               glFogi(GL_FOG_MODE, GL_EXP);
+               glFogf(GL_FOG_DENSITY, fog_density);
+               glFogfv(GL_FOG_COLOR, &fog_color.r);
+       }
 }
 
 void Lighting::unbind()
@@ -102,6 +133,8 @@ void Lighting::unbind()
                        Light::unbind_from(i);
 
        disable(GL_LIGHTING);
+       if(old->fog_density)
+               disable(GL_FOG);
 }
 
 } // namespace GL
index 8b3feb5f343af74622aa26b8b9689697a8da09a3..931d06d3daf8d2e72aede2af04452b0d0a2e740a 100644 (file)
@@ -24,6 +24,8 @@ private:
        Color sky_color;
        Vector3 sky_direction;
        Geometry::Angle<float> horizon_angle;
+       Color fog_color;
+       float fog_density;
        std::vector<const Light *> lights;
 
 public:
@@ -45,6 +47,16 @@ public:
        Has no effect without shaders. */
        void set_horizon_angle(const Geometry::Angle<float> &);
 
+       /** Sets the fog color, which is blended into distant surfaces. */
+       void set_fog_color(const Color &);
+
+       /** Sets the density of the fog.  Zero means no fog. */
+       void set_fog_density(float);
+
+       /** Sets the density of the fog so that the blending factor at the given
+       distance is 50%. */
+       void set_fog_half_distance(float);
+
        /** Attaches a light source.  If the attachment index is greater than
        LightUnit::get_n_units, the Lighting can't be bound for legacy mode. */
        void attach(unsigned, const Light &);
index de1fb1604db2ea5dcd77c20a2fbf036f18fe3894..18255b95839e99180a6c3905c51ad76e63f1c5b5 100644 (file)
@@ -45,9 +45,13 @@ anything that might need them. */
 const ProgramBuilder::VariableDefinition ProgramBuilder::standard_variables[] =
 {
        { FRAGMENT, "gl_FragColor", "vec4", "frag_color", 0 },
-       { FRAGMENT, "frag_color", "vec4", "basic_color", "!e!l" },
-       { FRAGMENT, "frag_color", "vec4", "vec4(rgb_surface, surface_alpha)", "!el" },
-       { FRAGMENT, "frag_color", "vec4", "vec4(rgb_surface+rgb_reflection, surface_alpha)", "e" },
+       { FRAGMENT, "frag_color", "vec4", "incoming_color", "!f" },
+       { FRAGMENT, "frag_color", "vec4", "vec4(mix(fog_color.rgb, incoming_color.rgb, fog_value), incoming_color.a)", "f" },
+       { FRAGMENT, "fog_value", "float", "exp(-fog_coord*fog_density)", 0 },
+
+       { FRAGMENT, "incoming_color", "vec4", "basic_color", "!e!l" },
+       { FRAGMENT, "incoming_color", "vec4", "vec4(rgb_surface, surface_alpha)", "!el" },
+       { FRAGMENT, "incoming_color", "vec4", "vec4(rgb_surface+rgb_reflection, surface_alpha)", "e" },
 
        { FRAGMENT, "rgb_reflection", "vec3", "reflect_sample.rgb*reflectivity", 0 },
        { FRAGMENT, "reflect_sample", "vec4", "textureCube(environment, env_reflect_dir)", 0 },
@@ -106,6 +110,7 @@ const ProgramBuilder::VariableDefinition ProgramBuilder::standard_variables[] =
        { FRAGMENT, "diffuse_sample", "vec4", "texture2D(diffusemap, texture_coord)", 0 },
 
        { VERTEX, "gl_Position", "vec4", "projection_matrix*eye_vertex", 0 },
+       { VERTEX, "fog_coord", "float", "-eye_vertex.z", 0 },
        { VERTEX, "shd_vertex", "vec3", "(shd_eye_matrix*eye_vertex).xyz", 0 },
        { VERTEX, "tbn_sky_dir", "vec3", "eye_sky_dir*eye_tbn_matrix", "n" },
        { VERTEX, "tbn_light_dir[i]", "vec3", "eye_light_dir[i]*eye_tbn_matrix", 0 },
@@ -143,6 +148,8 @@ const ProgramBuilder::VariableDefinition ProgramBuilder::standard_variables[] =
        { UNIFORM, "Lighting::sky_color", "vec4", 0, 0 },
        { UNIFORM, "Lighting::eye_sky_dir", "vec3", 0, 0 },
        { UNIFORM, "Lighting::horizon_limit", "float", 0, 0 },
+       { UNIFORM, "Lighting::fog_color", "vec4", "gl_Fog.color", 0 },
+       { UNIFORM, "Lighting::fog_density", "float", "gl_Fog.density", 0 },
        { UNIFORM, "Material::material", "MaterialParameters", "gl_FrontMaterial", 0 },
 
        { TYPE, "LightSourceParameters", "struct { vec4 position; vec4 diffuse; vec4 specular; }", "gl_LightSourceParameters", 0 },
@@ -748,6 +755,8 @@ string ProgramBuilder::StandardFeatures::create_flags() const
                if(normalmap)
                        flags += 'n';
        }
+       if(fog)
+               flags += 'f';
        if(shadow)
                flags += 's';
        if(reflection)
@@ -1078,6 +1087,7 @@ ProgramBuilder::StandardFeatures::Loader::Loader(StandardFeatures &f):
        DataFile::ObjectLoader<StandardFeatures>(f)
 {
        add("custom",    &StandardFeatures::custom);
+       add("fog",       &StandardFeatures::fog);
        add("lighting",  &StandardFeatures::lighting);
        add("material",  &StandardFeatures::material);
        add("max_lights", &StandardFeatures::max_lights);
index 56fd5e80e59d45ae7de271bcc744eb5d17587e45..ecd006d552709eec6656a3409efe47b5bb6afa51 100644 (file)
@@ -82,6 +82,8 @@ public:
                /** Use a skylight component for ambient lighting. */
                bool skylight;
 
+               bool fog;
+
                /** Use a specular lighting component. */
                bool specular;