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