#include <stdexcept>
+#include <cmath>
#include <msp/gl/extensions/msp_legacy_features.h>
#include "error.h"
#include "light.h"
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)
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())
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])
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()
Light::unbind_from(i);
disable(GL_LIGHTING);
+ if(old->fog_density)
+ disable(GL_FOG);
}
} // namespace GL
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 },
{ 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 },
{ 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 },
if(normalmap)
flags += 'n';
}
+ if(fog)
+ flags += 'f';
if(shadow)
flags += 's';
if(reflection)
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);