/*========================================================================= Program: Visualization Toolkit Module: vtkLightKit.h 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. =========================================================================*/ /** * @class vtkLightKit * @brief a simple but quality lighting kit * * 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. * * @par 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" #include "vtkRenderingCoreModule.h" // For export macro class vtkLight; class vtkPiecewiseFunction; class vtkRenderer; class VTKRENDERINGCORE_EXPORT vtkLightKit : public vtkObject { public: static vtkLightKit* New(); vtkTypeMacro(vtkLightKit, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; enum LightKitType { TKeyLight, TFillLight, TBackLight, THeadLight }; enum LightKitSubType { Warmth, Intensity, Elevation, Azimuth, KFRatio, KBRatio, KHRatio }; //@{ /** * 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); //@} //@{ /** * 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 contrast. 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_DOUBLE_MAX); vtkGetMacro(KeyToFillRatio, double); //@} //@{ /** * 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_DOUBLE_MAX); vtkGetMacro(KeyToHeadRatio, double); //@} //@{ /** * 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_DOUBLE_MAX); vtkGetMacro(KeyToBackRatio, double); //@} //@{ /** * 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); //@{ /** * 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); //@} //@{ /** * 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, vtkTypeBool); vtkGetMacro(MaintainLuminance, vtkTypeBool); vtkSetMacro(MaintainLuminance, vtkTypeBool); //@} /** * 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]; } //@{ /** * 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() override; void Update(); /** * Helper method to go from a enum type to a string type */ static const char* GetStringFromType(int type); /** * Helper method to go from a enum subtype to a string subtype */ static const char* GetStringFromSubType(int type); /** * Helper method to go from a enum subtype to a string subtype * The difference from GetStringFromSubType is that it returns * a shorter strings (useful for GUI with minimum space) */ static const char* GetShortStringFromSubType(int subtype); /** * 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() override; 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]; vtkTypeBool MaintainLuminance; vtkPiecewiseFunction* WarmthFunction[4]; // r, g, b, perceptual length private: vtkLightKit(const vtkLightKit&) = delete; void operator=(const vtkLightKit&) = delete; }; #endif