1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkOpenGLScalarsToColorsPainter.cxx
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 #include "vtkOpenGLScalarsToColorsPainter.h"
17 
18 #include "vtkActor.h"
19 #include "vtkCellData.h"
20 #include "vtkDataArray.h"
21 #include "vtkImageData.h"
22 #include "vtkMapper.h" //for VTK_MATERIALMODE_*
23 #include "vtkObjectFactory.h"
24 #include "vtkOpenGLRenderer.h"
25 #include "vtkOpenGLRenderWindow.h"
26 #include "vtkOpenGLTexture.h"
27 #include "vtkPointData.h"
28 #include "vtkPolyData.h"
29 #include "vtkProperty.h"
30 #include "vtkRenderer.h"
31 #include "vtkRenderWindow.h"
32 
33 #include "vtkOpenGL.h"
34 #include "vtkOpenGLError.h"
35 #include "vtkOpenGLExtensionManager.h"
36 
37 #include "vtkgl.h" // vtkgl namespace
38 
39 vtkStandardNewMacro(vtkOpenGLScalarsToColorsPainter);
40 
41 //-----------------------------------------------------------------------------
vtkOpenGLScalarsToColorsPainter()42 vtkOpenGLScalarsToColorsPainter::vtkOpenGLScalarsToColorsPainter()
43 {
44   this->InternalColorTexture = 0;
45   this->AlphaBitPlanes = -1;
46   this->AcquiredGraphicsResources = false;
47   this->SupportsSeparateSpecularColor = false;
48 }
49 
50 //-----------------------------------------------------------------------------
~vtkOpenGLScalarsToColorsPainter()51 vtkOpenGLScalarsToColorsPainter::~vtkOpenGLScalarsToColorsPainter()
52 {
53   if (this->InternalColorTexture)
54     {
55     this->InternalColorTexture->Delete();
56     this->InternalColorTexture = 0;
57     }
58 }
59 
60 //-----------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * win)61 void vtkOpenGLScalarsToColorsPainter::ReleaseGraphicsResources(vtkWindow* win)
62 {
63   if (this->InternalColorTexture)
64     {
65     this->InternalColorTexture->ReleaseGraphicsResources(win);
66     }
67   this->AcquiredGraphicsResources = false;
68   this->Superclass::ReleaseGraphicsResources(win);
69 }
70 
71 //-----------------------------------------------------------------------------
GetPremultiplyColorsWithAlpha(vtkActor * actor)72 int vtkOpenGLScalarsToColorsPainter::GetPremultiplyColorsWithAlpha(
73   vtkActor* actor)
74 {
75   // Use the AlphaBitPlanes member, which should already be initialized. If
76   // not, initialize it.
77   GLint alphaBits;
78   if (this->AlphaBitPlanes < 0)
79     {
80     glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
81     this->AlphaBitPlanes = (int)alphaBits;
82     }
83   alphaBits = (GLint)this->AlphaBitPlanes;
84 
85   // Dealing with having a correct alpha (none square) in the framebuffer
86   // is only required if there is an alpha component in the framebuffer
87   // (doh...) and if we cannot deal directly with BlendFuncSeparate.
88 
89   return vtkgl::BlendFuncSeparate==0 && alphaBits>0 &&
90     this->Superclass::GetPremultiplyColorsWithAlpha(actor);
91 }
92 
93 //-----------------------------------------------------------------------------
GetTextureSizeLimit()94 vtkIdType vtkOpenGLScalarsToColorsPainter::GetTextureSizeLimit()
95 {
96   GLint textureSize = 0;
97   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &textureSize);
98   return static_cast<vtkIdType>(textureSize);
99 }
100 
101 //-----------------------------------------------------------------------------
RenderInternal(vtkRenderer * renderer,vtkActor * actor,unsigned long typeflags,bool forceCompileOnly)102 void vtkOpenGLScalarsToColorsPainter::RenderInternal(vtkRenderer *renderer,
103                                                      vtkActor *actor,
104                                                      unsigned long typeflags,
105                                                      bool forceCompileOnly)
106 {
107   vtkOpenGLClearErrorMacro();
108 
109   // If we have not yet set the alpha bit planes, do it based on the
110   // render window so we're not querying GL in the middle of render.
111   if (this->AlphaBitPlanes < 0)
112     {
113     vtkOpenGLRenderer* oglRenderer = vtkOpenGLRenderer::SafeDownCast(renderer);
114     if (oglRenderer)
115       {
116       vtkOpenGLRenderWindow* context = vtkOpenGLRenderWindow::SafeDownCast(
117         oglRenderer->GetRenderWindow());
118       if (context)
119         {
120         this->AlphaBitPlanes = context->GetAlphaBitPlanes();
121         }
122       }
123     }
124 
125   // check for separate specular color support
126   if (!this->AcquiredGraphicsResources)
127     {
128     vtkOpenGLRenderer *oglRenderer = vtkOpenGLRenderer::SafeDownCast(renderer);
129     if (oglRenderer)
130       {
131       vtkOpenGLRenderWindow *oglRenderWindow =
132         vtkOpenGLRenderWindow::SafeDownCast(oglRenderer->GetRenderWindow());
133       if (oglRenderWindow)
134         {
135         vtkOpenGLExtensionManager *oglExtensionManager =
136           oglRenderWindow->GetExtensionManager();
137 
138         if (oglExtensionManager)
139           {
140           this->SupportsSeparateSpecularColor =
141             (oglExtensionManager->ExtensionSupported("GL_EXT_separate_specular_color") != 0);
142           }
143         }
144       }
145 
146     this->AcquiredGraphicsResources = true;
147     }
148 
149   // If we are coloring by texture, then load the texture map.
150   if (this->ColorTextureMap)
151     {
152     if (this->InternalColorTexture == 0)
153       {
154       this->InternalColorTexture = vtkOpenGLTexture::New();
155       this->InternalColorTexture->RepeatOff();
156       this->InternalColorTexture->EdgeClampOn();
157       }
158     this->InternalColorTexture->SetInputData(this->ColorTextureMap);
159 
160 
161     this->LastWindow = renderer->GetRenderWindow();
162     }
163   else if (this->LastWindow)
164     {
165     // release the texture.
166     this->ReleaseGraphicsResources(this->LastWindow);
167     this->LastWindow = 0;
168     }
169 
170   vtkProperty* prop = actor->GetProperty();
171   // if we are doing vertex colors then set lmcolor to adjust
172   // the current materials ambient and diffuse values using
173   // vertex color commands otherwise tell it not to.
174   glDisable(GL_COLOR_MATERIAL);
175 
176   if (this->UsingScalarColoring)
177     {
178     GLenum lmcolorMode;
179     if (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT)
180       {
181       lmcolorMode = (prop->GetAmbient() > prop->GetDiffuse()) ?
182         GL_AMBIENT : GL_DIFFUSE;
183       }
184     else if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE)
185       {
186       lmcolorMode = GL_AMBIENT_AND_DIFFUSE;
187       }
188     else if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT)
189       {
190       lmcolorMode = GL_AMBIENT;
191       }
192     else // if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE)
193       {
194       lmcolorMode = GL_DIFFUSE;
195       }
196 
197     glColorMaterial(GL_FRONT_AND_BACK, lmcolorMode);
198     glEnable(GL_COLOR_MATERIAL);
199 
200     if (this->ColorTextureMap)
201       {
202       this->InternalColorTexture->Load(renderer);
203       // Keep the surface color from interacting with color loaded from texture.
204       // We don't simple use (GL_TEXTURE_ENV_MODE, GL_REPLACE) since that
205       // implies all the lighting colors are lost too i.e. no diffuse
206       // highlights.
207       glColor3f(1.0, 1.0, 1.0);
208       }
209     }
210 
211   int pre_multiplied_by_alpha =  this->GetPremultiplyColorsWithAlpha(actor);
212 
213   if (pre_multiplied_by_alpha || this->InterpolateScalarsBeforeMapping)
214     {
215     // save the blend function.
216     glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LIGHTING_BIT);
217     }
218 
219   // We colors were premultiplied by alpha then we change the blending
220   // function to one that will compute correct blended destination alpha
221   // value, otherwise we stick with the default.
222   if (pre_multiplied_by_alpha)
223     {
224     // the following function is not correct with textures because there are
225     // not premultiplied by alpha.
226     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
227     }
228 
229   if (this->InterpolateScalarsBeforeMapping && this->SupportsSeparateSpecularColor)
230     {
231     // Turn on color sum and separate specular color so specular works
232     // with texturing.
233     glEnable(vtkgl::COLOR_SUM);
234     glLightModeli(vtkgl::LIGHT_MODEL_COLOR_CONTROL, vtkgl::SEPARATE_SPECULAR_COLOR);
235     }
236 
237   this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly);
238 
239   if (this->InterpolateScalarsBeforeMapping && this->SupportsSeparateSpecularColor)
240     {
241     glLightModeli(vtkgl::LIGHT_MODEL_COLOR_CONTROL, vtkgl::SINGLE_COLOR);
242     glDisable(vtkgl::COLOR_SUM);
243     }
244 
245   if (pre_multiplied_by_alpha || this->InterpolateScalarsBeforeMapping)
246     {
247     // restore the blend function & lights
248     glPopAttrib();
249     }
250   vtkOpenGLCheckErrorMacro("failed after RenderInternal");
251 }
252 
253 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)254 void vtkOpenGLScalarsToColorsPainter::PrintSelf(ostream& os, vtkIndent indent)
255 {
256   this->Superclass::PrintSelf(os, indent);
257   os << indent << "AlphaBitPlanes: " << this->AlphaBitPlanes << endl;
258 }
259