1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkEncodedGradientShader.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 /**
17  * @class   vtkEncodedGradientShader
18  * @brief   Compute shading tables for encoded normals.
19  *
20  *
21  * vtkEncodedGradientShader computes shading tables for encoded normals
22  * that indicates the amount of diffuse and specular illumination that is
23  * received from all light sources at a surface location with that normal.
24  * For diffuse illumination this is accurate, but for specular illumination
25  * it is approximate for perspective projections since the center view
26  * direction is always used as the view direction. Since the shading table is
27  * dependent on the volume (for the transformation that must be applied to
28  * the normals to put them into world coordinates) there is a shading table
29  * per volume. This is necessary because multiple volumes can share a
30  * volume mapper.
31  */
32 
33 #ifndef vtkEncodedGradientShader_h
34 #define vtkEncodedGradientShader_h
35 
36 #include "vtkObject.h"
37 #include "vtkRenderingVolumeModule.h" // For export macro
38 
39 class vtkVolume;
40 class vtkRenderer;
41 class vtkEncodedGradientEstimator;
42 
43 #define VTK_MAX_SHADING_TABLES 100
44 
45 class VTKRENDERINGVOLUME_EXPORT vtkEncodedGradientShader : public vtkObject
46 {
47 public:
48   static vtkEncodedGradientShader* New();
49   vtkTypeMacro(vtkEncodedGradientShader, vtkObject);
50 
51   /**
52    * Print the vtkEncodedGradientShader
53    */
54   void PrintSelf(ostream& os, vtkIndent indent) override;
55 
56   ///@{
57   /**
58    * Set / Get the intensity diffuse / specular light used for the
59    * zero normals.
60    */
61   vtkSetClampMacro(ZeroNormalDiffuseIntensity, float, 0.0f, 1.0f);
62   vtkGetMacro(ZeroNormalDiffuseIntensity, float);
63   vtkSetClampMacro(ZeroNormalSpecularIntensity, float, 0.0f, 1.0f);
64   vtkGetMacro(ZeroNormalSpecularIntensity, float);
65   ///@}
66 
67   /**
68    * Cause the shading table to be updated
69    */
70   void UpdateShadingTable(vtkRenderer* ren, vtkVolume* vol, vtkEncodedGradientEstimator* gradest);
71 
72   ///@{
73   /**
74    * Get the red/green/blue shading table.
75    */
76   float* GetRedDiffuseShadingTable(vtkVolume* vol);
77   float* GetGreenDiffuseShadingTable(vtkVolume* vol);
78   float* GetBlueDiffuseShadingTable(vtkVolume* vol);
79   float* GetRedSpecularShadingTable(vtkVolume* vol);
80   float* GetGreenSpecularShadingTable(vtkVolume* vol);
81   float* GetBlueSpecularShadingTable(vtkVolume* vol);
82   ///@}
83 
84   ///@{
85   /**
86    * Set the active component for shading. This component's
87    * ambient / diffuse / specular / specular power values will
88    * be used to create the shading table. The default is 1.0
89    */
90   vtkSetClampMacro(ActiveComponent, int, 0, 3);
91   vtkGetMacro(ActiveComponent, int);
92   ///@}
93 
94 protected:
95   vtkEncodedGradientShader();
96   ~vtkEncodedGradientShader() override;
97 
98   /**
99    * Build a shading table for a light with the specified direction,
100    * and color for an object of the specified material properties.
101    * material[0] = ambient, material[1] = diffuse, material[2] = specular
102    * and material[3] = specular exponent.  If the ambient flag is 1,
103    * then ambient illumination is added. If not, then this means we
104    * are calculating the "other side" of two sided lighting, so no
105    * ambient intensity is added in. If the update flag is 0,
106    * the shading table is overwritten with these new shading values.
107    * If the updateFlag is 1, then the computed light contribution is
108    * added to the current shading table values. There is one shading
109    * table per volume, and the index value indicated which index table
110    * should be used. It is computed in the UpdateShadingTable method.
111    */
112   void BuildShadingTable(int index, double lightDirection[3], double lightAmbientColor[3],
113     double lightDiffuseColor[3], double lightSpecularColor[3], double lightIntensity,
114     double viewDirection[3], double material[4], int twoSided, vtkEncodedGradientEstimator* gradest,
115     int updateFlag);
116 
117   // The six shading tables (r diffuse ,g diffuse ,b diffuse,
118   // r specular, g specular, b specular ) - with an entry for each
119   // encoded normal plus one entry at the end for the zero normal
120   // There is one shading table per volume listed in the ShadingTableVolume
121   // array. A null entry indicates an available slot.
122   float* ShadingTable[VTK_MAX_SHADING_TABLES][6];
123   vtkVolume* ShadingTableVolume[VTK_MAX_SHADING_TABLES];
124   int ShadingTableSize[VTK_MAX_SHADING_TABLES];
125 
126   int ActiveComponent;
127 
128   // The intensity of light used for the zero normals, since it
129   // can not be computed from the normal angles. Defaults to 0.0.
130   float ZeroNormalDiffuseIntensity;
131   float ZeroNormalSpecularIntensity;
132 
133 private:
134   vtkEncodedGradientShader(const vtkEncodedGradientShader&) = delete;
135   void operator=(const vtkEncodedGradientShader&) = delete;
136 };
137 
138 #endif
139