1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "VTKViewer_Texture.h"
24 #include "vtkHomogeneousTransform.h"
25 #include "vtkImageData.h"
26 #include "vtkLookupTable.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkOpenGLRenderer.h"
29 #include "vtkPointData.h"
30 #include "vtkRenderWindow.h"
31 #include "vtkOpenGLExtensionManager.h"
32 #include "vtkOpenGLRenderWindow.h"
33 #include "vtkTransform.h"
34 #include "vtkPixelBufferObject.h"
35 #include "vtkOpenGL.h"
36 #include "vtkgl.h" // vtkgl namespace
37 #include <vtkObjectFactory.h>
39 vtkStandardNewMacro(VTKViewer_Texture);
42 // ----------------------------------------------------------------------------
43 VTKViewer_Texture::VTKViewer_Texture()
47 myPosition = VTKViewer_Texture::Centered;
50 // ----------------------------------------------------------------------------
51 VTKViewer_Texture::~VTKViewer_Texture()
55 // ----------------------------------------------------------------------------
56 // Implement base class method.
57 void VTKViewer_Texture::Load(vtkRenderer *ren)
59 GLenum format = GL_LUMINANCE;
60 vtkImageData *input = this->GetInput();
62 this->Initialize(ren);
64 // Need to reload the texture.
65 // There used to be a check on the render window's mtime, but
66 // this is too broad of a check (e.g. it would cause all textures
67 // to load when only the desired update rate changed).
68 // If a better check is required, check something more specific,
69 // like the graphics context.
70 vtkOpenGLRenderWindow* renWin =
71 static_cast<vtkOpenGLRenderWindow*>(ren->GetRenderWindow());
73 if(this->BlendingMode != VTK_TEXTURE_BLENDING_MODE_NONE
74 && vtkgl::ActiveTexture)
76 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, vtkgl::COMBINE);
78 switch(this->BlendingMode)
80 case VTK_TEXTURE_BLENDING_MODE_REPLACE:
82 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
83 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
86 case VTK_TEXTURE_BLENDING_MODE_MODULATE:
88 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_MODULATE);
89 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_MODULATE);
92 case VTK_TEXTURE_BLENDING_MODE_ADD:
94 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_ADD);
95 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_ADD);
98 case VTK_TEXTURE_BLENDING_MODE_ADD_SIGNED:
100 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::ADD_SIGNED);
101 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::ADD_SIGNED);
104 case VTK_TEXTURE_BLENDING_MODE_INTERPOLATE:
106 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::INTERPOLATE);
107 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::INTERPOLATE);
110 case VTK_TEXTURE_BLENDING_MODE_SUBTRACT:
112 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::SUBTRACT);
113 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::SUBTRACT);
118 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_ADD);
119 glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_ADD);
124 if (this->GetMTime() > this->LoadTime.GetMTime() ||
125 input->GetMTime() > this->LoadTime.GetMTime() ||
126 (this->GetLookupTable() && this->GetLookupTable()->GetMTime () >
127 this->LoadTime.GetMTime()) ||
128 renWin != this->RenderWindow.GetPointer() ||
129 renWin->GetContextCreationTime() > this->LoadTime)
133 vtkDataArray *scalars;
134 unsigned char *dataPtr;
135 unsigned char *resultData=NULL;
140 // Get the scalars the user choose to color with.
141 scalars = this->GetInputArrayToProcess(0, input);
143 // make sure scalars are non null
146 vtkErrorMacro(<< "No scalar values found for texture input!");
151 input->GetDimensions(size);
153 if (input->GetNumberOfCells() == scalars->GetNumberOfTuples())
155 // we are using cell scalars. Adjust image size for cells.
156 for (int kk=0; kk < 3; kk++)
165 bytesPerPixel = scalars->GetNumberOfComponents();
167 // make sure using unsigned char data of color scalars type
168 if (this->MapColorScalarsThroughLookupTable ||
169 scalars->GetDataType() != VTK_UNSIGNED_CHAR )
171 dataPtr = this->MapScalarsToColors (scalars);
176 dataPtr = static_cast<vtkUnsignedCharArray *>(scalars)->GetPointer(0);
179 // we only support 2d texture maps right now
180 // so one of the three sizes must be 1, but it
181 // could be any of them, so lets find it
184 xsize = size[1]; ysize = size[2];
198 vtkErrorMacro(<< "3D texture maps currently are not supported!");
205 if(!this->CheckedHardwareSupport)
207 vtkOpenGLExtensionManager *m=renWin->GetExtensionManager();
208 this->CheckedHardwareSupport=true;
209 this->SupportsNonPowerOfTwoTextures=
210 m->ExtensionSupported("GL_VERSION_2_0")
211 || m->ExtensionSupported("GL_ARB_texture_non_power_of_two");
212 this->SupportsPBO=vtkPixelBufferObject::IsSupported(renWin);
215 // -- decide whether the texture needs to be resampled --
218 glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxDimGL);
219 // if larger than permitted by the graphics library then must resample
220 bool resampleNeeded=xsize > maxDimGL || ysize > maxDimGL;
223 vtkDebugMacro( "Texture too big for gl, maximum is " << maxDimGL);
226 if(!resampleNeeded && !this->SupportsNonPowerOfTwoTextures)
228 // xsize and ysize must be a power of 2 in OpenGL
229 xs = static_cast<unsigned int>(xsize);
230 ys = static_cast<unsigned int>(ysize);
239 // if not a power of two then resampling is required
240 resampleNeeded= (xs>1) || (ys>1);
245 vtkDebugMacro(<< "Resampling texture to power of two for OpenGL");
246 resultData = this->ResampleToPowerOfTwo(xsize, ysize, dataPtr,
250 if ( resultData == NULL )
252 resultData = dataPtr;
255 // free any old display lists (from the old context)
256 if (this->RenderWindow)
258 this->ReleaseGraphicsResources(this->RenderWindow);
261 this->RenderWindow = ren->GetRenderWindow();
263 // make the new context current before we mess with opengl
264 this->RenderWindow->MakeCurrent();
266 // define a display list for this texture
267 // get a unique display list id
269 #ifdef GL_VERSION_1_1
270 glGenTextures(1, &tempIndex);
271 this->Index = static_cast<long>(tempIndex);
272 glBindTexture(GL_TEXTURE_2D, this->Index);
274 this->Index = glGenLists(1);
275 glDeleteLists (static_cast<GLuint>(this->Index), static_cast<GLsizei>(0));
276 glNewList (static_cast<GLuint>(this->Index), GL_COMPILE);
278 //seg fault protection for those wackos that don't use an
279 //opengl render window
280 if(this->RenderWindow->IsA("vtkOpenGLRenderWindow"))
282 static_cast<vtkOpenGLRenderWindow *>(ren->GetRenderWindow())->
283 RegisterTextureResource( this->Index );
286 if (this->Interpolate)
288 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
290 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
295 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
296 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
300 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
301 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
305 vtkOpenGLExtensionManager* manager = renWin->GetExtensionManager();
306 if (this->EdgeClamp &&
307 (manager->ExtensionSupported("GL_VERSION_1_2") ||
308 manager->ExtensionSupported("GL_EXT_texture_edge_clamp")))
310 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
311 vtkgl::CLAMP_TO_EDGE );
312 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
313 vtkgl::CLAMP_TO_EDGE );
317 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
318 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
321 int internalFormat = bytesPerPixel;
322 switch (bytesPerPixel)
324 case 1: format = GL_LUMINANCE; break;
325 case 2: format = GL_LUMINANCE_ALPHA; break;
326 case 3: format = GL_RGB; break;
327 case 4: format = GL_RGBA; break;
329 // if we are using OpenGL 1.1, you can force 32 or16 bit textures
330 #ifdef GL_VERSION_1_1
331 if (this->Quality == VTK_TEXTURE_QUALITY_32BIT)
333 switch (bytesPerPixel)
335 case 1: internalFormat = GL_LUMINANCE8; break;
336 case 2: internalFormat = GL_LUMINANCE8_ALPHA8; break;
337 case 3: internalFormat = GL_RGB8; break;
338 case 4: internalFormat = GL_RGBA8; break;
341 else if (this->Quality == VTK_TEXTURE_QUALITY_16BIT)
343 switch (bytesPerPixel)
345 case 1: internalFormat = GL_LUMINANCE4; break;
346 case 2: internalFormat = GL_LUMINANCE4_ALPHA4; break;
347 case 3: internalFormat = GL_RGB4; break;
348 case 4: internalFormat = GL_RGBA4; break;
352 if(this->SupportsPBO)
356 this->PBO=vtkPixelBufferObject::New();
357 this->PBO->SetContext(renWin);
359 unsigned int dims[2];
360 vtkIdType increments[2];
361 dims[0]=static_cast<unsigned int>(xsize);
362 dims[1]=static_cast<unsigned int>(ysize);
365 this->PBO->Upload2D(VTK_UNSIGNED_CHAR,resultData,dims,bytesPerPixel,
368 this->PBO->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
369 glTexImage2D( GL_TEXTURE_2D, 0 , internalFormat,
370 xsize, ysize, 0, format,
379 glTexImage2D( GL_TEXTURE_2D, 0 , internalFormat,
380 xsize, ysize, 0, format,
382 static_cast<const GLvoid *>(resultData) );
386 #ifndef GL_VERSION_1_1
389 // modify the load time to the current time
390 this->LoadTime.Modified();
393 if (resultData != dataPtr)
395 delete [] resultData;
399 // execute the display list that uses creates the texture
400 #ifdef GL_VERSION_1_1
401 glBindTexture(GL_TEXTURE_2D, this->Index);
403 glCallList(this->Index);
406 // don't accept fragments if they have zero opacity. this will stop the
407 // zbuffer from be blocked by totally transparent texture fragments.
408 glAlphaFunc (GL_GREATER, static_cast<GLclampf>(0));
409 glEnable (GL_ALPHA_TEST);
411 if (this->PremultipliedAlpha)
413 // save the blend function.
414 glPushAttrib(GL_COLOR_BUFFER_BIT);
416 // make the blend function correct for textures premultiplied by alpha.
417 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
421 glEnable(GL_TEXTURE_2D);
423 // clear any texture transform
424 glMatrixMode(GL_TEXTURE);
427 // build transformation
430 double *mat = this->Transform->GetMatrix()->Element[0];
449 // insert texture transformation
452 glMatrixMode(GL_MODELVIEW);
454 GLint uUseTexture=-1;
457 vtkOpenGLRenderer *oRenderer=static_cast<vtkOpenGLRenderer *>(ren);
459 /* if(oRenderer->GetDepthPeelingHigherLayer())
461 uUseTexture=oRenderer->GetUseTextureUniformVariable();
462 uTexture=oRenderer->GetTextureUniformVariable();
463 vtkgl::Uniform1i(uUseTexture,1);
464 vtkgl::Uniform1i(uTexture,0); // active texture 0
469 void VTKViewer_Texture::Initialize(vtkRenderer * vtkNotUsed(ren))
473 int VTKViewer_Texture::GetWidth() const
478 int VTKViewer_Texture::GetHeight() const
483 void VTKViewer_Texture::SetPosition(int pos)
488 int VTKViewer_Texture::GetPosition() const