/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkLightKit.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkLightKit - a simple but quality lighting kit // .SECTION Description // vtkLightKit is designed to make general purpose lighting of vtk // scenes simple, flexible, and attractive (or at least not horribly // ugly without significant effort). Use a LightKit when you want // more control over your lighting than you can get with the default // vtk light, which is a headlight located at the camera. (HeadLights // are very simple to use, but they don't show the shape of objects very // well, don't give a good sense of "up" and "down", and don't evenly // light the object.) // // A LightKit consists of three lights, a key light, a fill light, and // a headlight. The main light is the key light. It is usually // positioned so that it appears like an overhead light (like the sun, // or a ceiling light). It is generally positioned to shine down on the // scene from about a 45 degree angle vertically and at least a little // offset side to side. The key light usually at least about twice as // bright as the total of all other lights in the scene to provide good // modeling of object features. // // The other lights in the kit (the fill light, headlight, and a pair of // back lights) are weaker sources that provide extra // illumination to fill in the spots that the key light misses. The // fill light is usually positioned across from or opposite from the // key light (though still on the same side of the object as the // camera) in order to simulate diffuse reflections from other objects // in the scene. The headlight, always located at the position of the // camera, reduces the contrast between areas lit by the key and fill // light. The two back lights, one on the left of the object as seen // from the observer and one on the right, fill on the high-contrast // areas behind the object. To enforce the relationship between the // different lights, the intensity of the fill, back and headlights // are set as a ratio to the key light brightness. Thus, the // brightness of all the lights in the scene can be changed by // changing the key light intensity. // // All lights are directional lights (infinitely far away with no // falloff). Lights move with the camera. // // For simplicity, the position of lights in the LightKit can only be // specified using angles: the elevation (latitude) and azimuth // (longitude) of each light with respect to the camera, expressed in // degrees. (Lights always shine on the camera's lookat point.) For // example, a light at (elevation=0, azimuth=0) is located at the // camera (a headlight). A light at (elevation=90, azimuth=0) is // above the lookat point, shining down. Negative azimuth values move // the lights clockwise as seen above, positive values // counter-clockwise. So, a light at (elevation=45, azimuth=-20) is // above and in front of the object and shining slightly from the left // side. // // vtkLightKit limits the colors that can be assigned to any light to // those of incandescent sources such as light bulbs and sunlight. It // defines a special color spectrum called "warmth" from which light // colors can be chosen, where 0 is cold blue, 0.5 is neutral white, // and 1 is deep sunset red. Colors close to 0.5 are "cool whites" and // "warm whites," respectively. // // Since colors far from white on the warmth scale appear less bright, // key-to-fill and key-to-headlight ratios are skewed by // key, fill, and headlight colors. If the flag MaintainLuminance // is set, vtkLightKit will attempt to compensate for these perceptual // differences by increasing the brightness of more saturated colors. // // A LightKit is not explicitly part of the vtk pipeline. Rather, it // is a composite object that controls the behavior of lights using a // unified user interface. Every time a parameter of vtkLightKit is // adjusted, the properties of its lights are modified. // // .SECTION Credits // vtkLightKit was originally written and contributed to vtk by // Michael Halle (mhalle@bwh.harvard.edu) at the Surgical Planning // Lab, Brigham and Women's Hospital. #ifndef __vtkLightKit_h #define __vtkLightKit_h #include "vtkObject.h" class vtkLight; class vtkPiecewiseFunction; class vtkRenderer; class VTK_RENDERING_EXPORT vtkLightKit : public vtkObject { public: static vtkLightKit *New(); vtkTypeRevisionMacro(vtkLightKit, vtkObject); void PrintSelf(ostream& os, vtkIndent indent); //BTX enum LightKitType { TKeyLight, TFillLight, TBackLight, THeadLight }; enum LightKitSubType { Warmth, Intensity, Elevation, Azimuth, KFRatio, KBRatio, KHRatio }; //ETX // Description: // Set/Get the intensity of the key light. The key light is the // brightest light in the scene. The intensities of the other two // lights are ratios of the key light's intensity. vtkSetMacro(KeyLightIntensity, double); vtkGetMacro(KeyLightIntensity, double); // Description: // Set/Get the key-to-fill ratio. This ratio controls // how bright the fill light is compared to the key light: larger // values correspond to a dimmer fill light. The purpose of the // fill light is to light parts of the object not lit by the key // light, while still maintaining constrast. This type of lighting // may correspond to indirect illumination from the key light, bounced // off a wall, floor, or other object. The fill light should never // be brighter than the key light: a good range for the key-to-fill // ratio is between 2 and 10. vtkSetClampMacro(KeyToFillRatio, double, 0.5, VTK_FLOAT_MAX); vtkGetMacro(KeyToFillRatio, double); // Description: // Set/Get the key-to-headlight ratio. Similar to the key-to-fill // ratio, this ratio controls how bright the headlight light is // compared to the key light: larger values correspond to a dimmer // headlight light. The headlight is special kind of fill light, // lighting only the parts of the object that the camera can see. // As such, a headlight tends to reduce the contrast of a scene. It // can be used to fill in "shadows" of the object missed by the key // and fill lights. The headlight should always be significantly // dimmer than the key light: ratios of 2 to 15 are typical. vtkSetClampMacro(KeyToHeadRatio, double, 0.5, VTK_FLOAT_MAX); vtkGetMacro(KeyToHeadRatio, double); // Description: // Set/Get the key-to-back light ratio. This ratio controls // how bright the back lights are compared to the key light: larger // values correspond to dimmer back lights. The back lights fill // in the remaining high-contrast regions behind the object. // Values between 2 and 10 are good. vtkSetClampMacro(KeyToBackRatio, double, 0.5, VTK_FLOAT_MAX); vtkGetMacro(KeyToBackRatio, double); // Description: // Set the warmth of each the lights. Warmth is a parameter that // varies from 0 to 1, where 0 is "cold" (looks icy or lit by a very // blue sky), 1 is "warm" (the red of a very red sunset, or the // embers of a campfire), and 0.5 is a neutral white. The warmth // scale is non-linear. Warmth values close to 0.5 are subtly // "warmer" or "cooler," much like a warmer tungsten incandescent // bulb, a cooler halogen, or daylight (cooler still). Moving // further away from 0.5, colors become more quickly varying towards // blues and reds. With regards to aesthetics, extremes of warmth // should be used sparingly. vtkSetMacro(KeyLightWarmth, double); vtkGetMacro(KeyLightWarmth, double); vtkSetMacro(FillLightWarmth, double); vtkGetMacro(FillLightWarmth, double); vtkSetMacro(HeadLightWarmth, double); vtkGetMacro(HeadLightWarmth, double); vtkSetMacro(BackLightWarmth, double); vtkGetMacro(BackLightWarmth, double); // Description: // Returns the floating-point RGB values of each of the light's color. vtkGetVectorMacro(KeyLightColor, double, 3); vtkGetVectorMacro(FillLightColor, double, 3); vtkGetVectorMacro(HeadLightColor, double, 3); vtkGetVectorMacro(BackLightColor, double, 3); // Description: // To maintain a deprecation API: VTK_LEGACY(void SetHeadlightWarmth(double v)); VTK_LEGACY(double GetHeadlightWarmth()); VTK_LEGACY(void GetHeadlightColor(double *color)); // Description: // If MaintainLuminance is set, the LightKit will attempt to maintain // the apparent intensity of lights based on their perceptual brightnesses. // By default, MaintainLuminance is off. vtkBooleanMacro(MaintainLuminance, int); vtkGetMacro(MaintainLuminance, int); vtkSetMacro(MaintainLuminance, int); // Description: // Get/Set the position of the key, fill, and back lights // using angular methods. Elevation corresponds to latitude, // azimuth to longitude. It is recommended that the key light // always be on the viewer's side of the object and above the // object, while the fill light generally lights the part of the object // not lit by the fill light. The headlight, which is always located // at the viewer, can then be used to reduce the contrast in the image. // There are a pair of back lights. They are located at the same // elevation and at opposing azimuths (ie, one to the left, and one to // the right). They are generally set at the equator (elevation = 0), // and at approximately 120 degrees (lighting from each side and behind). void SetKeyLightAngle(double elevation, double azimuth); void SetKeyLightAngle(double angle[2]) { this->SetKeyLightAngle(angle[0], angle[1]); }; void SetKeyLightElevation(double x) { this->SetKeyLightAngle(x, this->KeyLightAngle[1]); }; void SetKeyLightAzimuth(double x) { this->SetKeyLightAngle(this->KeyLightAngle[0], x); }; vtkGetVectorMacro(KeyLightAngle, double, 2); double GetKeyLightElevation() { double ang[2]; this->GetKeyLightAngle(ang); return ang[0]; }; double GetKeyLightAzimuth() { double ang[2]; this->GetKeyLightAngle(ang); return ang[1]; }; void SetFillLightAngle(double elevation, double azimuth); void SetFillLightAngle(double angle[2]) { this->SetFillLightAngle(angle[0], angle[1]); }; void SetFillLightElevation(double x) { this->SetFillLightAngle(x, this->FillLightAngle[1]); }; void SetFillLightAzimuth(double x) { this->SetFillLightAngle(this->FillLightAngle[0], x); }; vtkGetVectorMacro(FillLightAngle, double, 2); double GetFillLightElevation() { double ang[2]; this->GetFillLightAngle(ang); return ang[0]; }; double GetFillLightAzimuth() { double ang[2]; this->GetFillLightAngle(ang); return ang[1]; }; void SetBackLightAngle(double elevation, double azimuth); void SetBackLightAngle(double angle[2]) { this->SetBackLightAngle(angle[0], angle[1]); }; void SetBackLightElevation(double x) { this->SetBackLightAngle(x, this->BackLightAngle[1]); }; void SetBackLightAzimuth(double x) { this->SetBackLightAngle(this->BackLightAngle[0], x); }; vtkGetVectorMacro(BackLightAngle, double, 2); double GetBackLightElevation() { double ang[2]; this->GetBackLightAngle(ang); return ang[0]; }; double GetBackLightAzimuth() { double ang[2]; this->GetBackLightAngle(ang); return ang[1]; }; // Description: // Add lights to, or remove lights from, a renderer. // Lights may be added to more than one renderer, if desired. void AddLightsToRenderer(vtkRenderer *renderer); void RemoveLightsFromRenderer(vtkRenderer *renderer); void DeepCopy(vtkLightKit *kit); void Modified(); void Update(); // Description: // Helper method to go from a enum type to a string type static const char *GetStringFromType(int type); // Description: // Helper method to go from a enum subtype to a string subtype static const char *GetStringFromSubType(int type); // Description: // Helper method to go from a enum subtype to a string subtype // The difference from GetStringFromSubType is that it returns // a shorter strings (usefull for GUI with minimun space) static const char *GetShortStringFromSubType(int subtype); // Description: // Return the possible subtype from a given type. You have to pass // in a number i [0,3] no check is done. static LightKitSubType GetSubType(LightKitType type, int i); protected: vtkLightKit(); ~vtkLightKit(); void WarmthToRGBI(double w, double rgb[3], double& i); void WarmthToRGB(double w, double rgb[3]); void InitializeWarmthFunctions(); double WarmthToIntensity(double w); double KeyLightIntensity; double KeyToFillRatio; double KeyToHeadRatio; double KeyToBackRatio; vtkLight *KeyLight; double KeyLightWarmth; double KeyLightAngle[2]; double KeyLightColor[3]; vtkLight *FillLight; double FillLightWarmth; double FillLightAngle[2]; double FillLightColor[3]; double BackLightWarmth; double BackLightColor[3]; vtkLight *BackLight0; vtkLight *BackLight1; double BackLightAngle[2]; vtkLight *HeadLight; double HeadLightWarmth; double HeadLightColor[3]; int MaintainLuminance; vtkPiecewiseFunction *WarmthFunction[4]; // r, g, b, perceptual length private: vtkLightKit(const vtkLightKit&); // Not implemented. void operator=(const vtkLightKit&); // Not implemented. }; #endif