position(0, 0, 1, 0),
spot_dir(0, 0, -1),
spot_exp(0),
- spot_cutoff(180)
+ spot_cutoff(Geometry::Angle<float>::straight())
{
attenuation[0] = 1;
attenuation[1] = 0;
if(mask&SPOT_EXP)
glLightf(l, GL_SPOT_EXPONENT, spot_exp);
if(mask&SPOT_CUTOFF)
- glLightf(l, GL_SPOT_CUTOFF, spot_cutoff);
+ glLightf(l, GL_SPOT_CUTOFF, spot_cutoff.degrees());
if(mask&ATTENUATION)
{
glLightf(l, GL_CONSTANT_ATTENUATION, attenuation[0]);
void Light::set_spot_direction(const Vector3 &d)
{
- spot_dir = d;
+ spot_dir = normalize(d);
update_parameter(SPOT_DIR);
}
void Light::set_spot_exponent(float e)
{
+ if(e<0)
+ throw invalid_argument("Light::set_spot_exponent");
+
spot_exp = e;
update_parameter(SPOT_EXP);
}
void Light::set_spot_cutoff(float c)
{
+ set_spot_cutoff(Geometry::Angle<float>::from_degrees(c));
+}
+
+void Light::set_spot_cutoff(const Geometry::Angle<float> &c)
+{
+ if(c<Geometry::Angle<float>::zero() || (c>Geometry::Angle<float>::right() && c!=Geometry::Angle<float>::straight()))
+ throw invalid_argument("Light::set_spot_cutoff");
+
spot_cutoff = c;
update_parameter(SPOT_CUTOFF);
}
+void Light::disable_spot_cutoff()
+{
+ set_spot_cutoff(Geometry::Angle<float>::straight());
+}
+
void Light::set_attenuation(float c, float l, float q)
{
attenuation[0] = c;
class ProgramData;
/**
-Stores properties of a single light source.
+Stores properties of a single light source. Lights can be directional, point
+lights or spotlights. No explicit type parameter is provided; rather the
+other parameters determine what kind of light it is. If the fourth component
+of position is zero, it's a directional light. Otherwise, if the spot cutoff
+is not 180 degrees, it's a spotlight. Otherwise it's an omnidirectional point
+light.
+
+Lights are usually grouped with a Lighting object, which can be used in a
+Pipeline::Pass.
Lights do not cast shadows by themselves. See ShadowMap for that.
*/
Vector4 position;
Vector3 spot_dir;
float spot_exp;
- float spot_cutoff;
+ Geometry::Angle<float> spot_cutoff;
float attenuation[3];
public:
void set_diffuse(const Color &c);
/** Sets the specular (direction-dependent) color of the Light. Provided to
- shaders with the name light_sources[i].diffuse. */
+ shaders with the name light_sources[i].specular. */
void set_specular(const Color &c);
const Color &get_diffuse() const { return diffuse; }
const Vector4 &get_position() const { return position; }
+ /** Sets the direction of a spotlight. Has no effect if spotlight cutoff is
+ not set. */
void set_spot_direction(const Vector3 &);
+
+ /** Sets the angular falloff exponent of the spotlight. Must be >= 0. */
void set_spot_exponent(float);
+
+ /// Deprecated.
void set_spot_cutoff(float);
+
+ /** Sets the cutoff angle of a spotlight. Beyond this angle from its axis
+ the spotlight provides no illumination. Must be between 0 and 90 degrees,
+ or exactly 180 degrees to indicate a non-spotlight. */
+ void set_spot_cutoff(const Geometry::Angle<float> &);
+
+ /** Disables spotlight, reverting to an omnidirectional point light.
+ Equivalent to setting the spot cutoff to 180 degrees. */
+ void disable_spot_cutoff();
+
const Vector3 &get_spot_direction() const { return spot_dir; }
float get_spot_exponent() const { return spot_exp; }
- float get_spot_cutoff() const { return spot_cutoff; }
+ const Geometry::Angle<float> &get_spot_cutoff() const { return spot_cutoff; }
void set_attenuation(float, float, float);
const float *get_attenuation() const { return attenuation; }