1 // Copyright (C) 2007-2016 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
23 #include "VTKViewer_OpenGLRenderer.h"
24 #include "VTKViewer_Texture.h"
26 #include <vtkCuller.h>
27 #include <vtkLightCollection.h>
28 #include <vtkObjectFactory.h>
29 #include <vtkOpenGLCamera.h>
30 #include <vtkOpenGLLight.h>
31 #include <vtkOpenGLProperty.h>
32 #include <vtkRenderWindow.h>
34 #include <vtkOpenGLExtensionManager.h>
35 #include <vtkgl.h> // vtkgl namespace
37 #include <vtkImageImport.h>
38 #include <vtkPNGWriter.h>
39 #include <vtkOpenGLTexture.h>
40 #include <vtkTimerLog.h>
41 #include <vtkOpenGL.h>
42 #include <vtkObjectFactory.h>
44 vtkStandardNewMacro(VTKViewer_OpenGLRenderer);
46 VTKViewer_OpenGLRenderer::VTKViewer_OpenGLRenderer()
48 this->GradientType = HorizontalGradient;
51 this->BackgroundProgram = 0;
52 this->BackgroundVertexShader = 0;
53 this->BackgroundFragmentShader = 0;
54 this->VertexArrayObject = 0;
56 this->OpenGLHelper.Init();
60 VTKViewer_OpenGLRenderer::~VTKViewer_OpenGLRenderer()
64 void VTKViewer_OpenGLRenderer::SetGradientType( const int theGradientType )
66 this->GradientType = theGradientType;
69 void VTKViewer_OpenGLRenderer::Clear(void)
72 if (this->OpenGLHelper.IsInitialized())
74 if (this->BackgroundProgram == 0)
76 std::string filePath = std::string( getenv( "GUI_ROOT_DIR") ) + "/share/salome/resources/gui/Background";
77 if (!this->OpenGLHelper.CreateShaderProgram (filePath,
78 this->BackgroundProgram,
79 this->BackgroundVertexShader,
80 this->BackgroundFragmentShader))
84 // Get uniform locations.
85 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
87 this->myLocations.UseTexture = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uUseTexture");
88 this->myLocations.BackgroundTexture = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uBackgroundTexture");
90 this->OpenGLHelper.vglUseProgramObjectARB (0);
95 GLbitfield clear_mask = 0;
97 if( !this->Transparent() )
99 glClearColor( static_cast<GLclampf>(this->Background[0]),
100 static_cast<GLclampf>(this->Background[1]),
101 static_cast<GLclampf>(this->Background[2]),
102 static_cast<GLclampf>(0.0));
103 clear_mask |= GL_COLOR_BUFFER_BIT;
106 if( !this->GetPreserveDepthBuffer() )
108 glClearDepth(static_cast<GLclampf>(1.0));
109 clear_mask |= GL_DEPTH_BUFFER_BIT;
112 vtkDebugMacro(<< "glClear\n");
115 // If gradient background is turned on, draw it now.
116 if( !this->Transparent() &&
117 ( this->GradientBackground || this->TexturedBackground ) )
119 double aTileViewport[4];
120 this->GetRenderWindow()->GetTileViewport( aTileViewport );
121 glPushAttrib( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_TEXTURE_BIT );
122 glDisable( GL_ALPHA_TEST );
123 glDisable( GL_DEPTH_TEST );
124 glDisable( GL_LIGHTING );
125 glDisable( GL_TEXTURE_1D );
126 glDisable( GL_TEXTURE_2D );
127 glDisable( GL_BLEND );
130 glGetIntegerv(GL_SHADE_MODEL, &oldShadeModel);
131 glShadeModel( GL_SMOOTH ); // color interpolation
133 glMatrixMode( GL_PROJECTION );
136 glMatrixMode( GL_MODELVIEW );
140 glOrtho( aTileViewport[0], aTileViewport[2], aTileViewport[1], aTileViewport[3], -1.0, 1.0 );
142 if( this->GradientBackground )
151 switch( this->GradientType )
153 case HorizontalGradient:
154 corner1 = this->Background;
155 corner2 = this->Background2;
156 corner3 = this->Background2;
157 corner4 = this->Background;
159 case VerticalGradient:
160 corner1 = this->Background2;
161 corner2 = this->Background2;
162 corner3 = this->Background;
163 corner4 = this->Background;
165 case FirstDiagonalGradient:
166 corner2 = this->Background2;
167 corner4 = this->Background;
168 dcorner1[0] = dcorner2[0] = 0.5F * ( corner2[0] + corner4[0] );
169 dcorner1[1] = dcorner2[1] = 0.5F * ( corner2[1] + corner4[1] );
170 dcorner1[2] = dcorner2[2] = 0.5F * ( corner2[2] + corner4[2] );
174 case SecondDiagonalGradient:
175 corner1 = this->Background2;
176 corner3 = this->Background;
177 dcorner1[0] = dcorner2[0] = 0.5F * ( corner1[0] + corner3[0] );
178 dcorner1[1] = dcorner2[1] = 0.5F * ( corner1[1] + corner3[1] );
179 dcorner1[2] = dcorner2[2] = 0.5F * ( corner1[2] + corner3[2] );
183 case FirstCornerGradient:
184 corner1 = this->Background2;
185 corner2 = this->Background2;
186 corner3 = this->Background2;
187 corner4 = this->Background;
189 case SecondCornerGradient:
190 corner1 = this->Background2;
191 corner2 = this->Background2;
192 corner3 = this->Background;
193 corner4 = this->Background2;
195 case ThirdCornerGradient:
196 corner1 = this->Background2;
197 corner2 = this->Background;
198 corner3 = this->Background2;
199 corner4 = this->Background2;
201 case FourthCornerGradient:
202 corner1 = this->Background;
203 corner2 = this->Background2;
204 corner3 = this->Background2;
205 corner4 = this->Background2;
207 default: // just in case
208 corner1 = this->Background;
209 corner2 = this->Background;
210 corner3 = this->Background;
211 corner4 = this->Background;
216 if (this->OpenGLHelper.IsInitialized())
218 if (this->VertexArrayObject == 0)
220 this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
223 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
224 this->OpenGLHelper.vglBindVertexArrayARB (this->VertexArrayObject);
227 if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
229 const float tmpData[] = { (float)corner1[0], (float)corner1[1], (float)corner1[2], 1.0f, -1.0f, 1.0f, 0.0f,
230 (float)corner2[0], (float)corner2[1], (float)corner2[2], 1.0f, -1.0f, -1.0f, 0.0f,
231 (float)corner3[0], (float)corner3[1], (float)corner3[2], 1.0f, 1.0f, -1.0f, 0.0f,
232 (float)corner4[0], (float)corner4[1], (float)corner4[2], 1.0f, 1.0f, 1.0f, 0.0f };
233 memcpy (data, tmpData, sizeof(float) * 7 * 4);
235 else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
237 const float tmpData[] = { (float)corner2[0], (float)corner2[1], (float)corner2[2], 1.0f, -1.0f, -1.0f, 0.0f,
238 (float)corner3[0], (float)corner3[1], (float)corner3[2], 1.0f, -1.0f, 1.0f, 0.0f,
239 (float)corner4[0], (float)corner4[1], (float)corner4[2], 1.0f, 1.0f, 1.0f, 0.0f,
240 (float)corner1[0], (float)corner1[1], (float)corner1[2], 1.0f, 1.0f, -1.0f, 0.0f };
241 memcpy (data, tmpData, sizeof(float) * 7 * 4);
245 this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
246 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
247 this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
249 GLint colorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
250 GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
251 GLsizei vertexSize = sizeof(GLfloat) * 7;
253 this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
254 this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
256 this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
257 this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
259 this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 0);
261 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
263 this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
264 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
265 this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
266 this->OpenGLHelper.vglBindVertexArrayARB (0);
267 this->OpenGLHelper.vglUseProgramObjectARB (0);
271 glBegin( GL_TRIANGLE_FAN );
272 if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
274 glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
275 glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
276 glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
277 glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
279 else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
281 glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
282 glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
283 glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
284 glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
290 if( this->TexturedBackground && this->BackgroundTexture )
292 if( VTKViewer_Texture* aTexture = VTKViewer_Texture::SafeDownCast( this->BackgroundTexture ) )
294 glEnable( GL_TEXTURE_2D );
296 aTexture->Render( this );
298 // NOTE: By default the mode is GL_MODULATE. Since the user
299 // cannot set the mode, the default is set to replace.
300 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
301 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
302 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
304 // NOTE: vtkTexture Render enables the alpha test
305 // so that no buffer is affected if alpha of incoming fragment is
306 // below the threshold. Here we have to enable it so that it won't
307 // rejects the fragments of the quad as the alpha is set to 0 on it.
308 glDisable( GL_ALPHA_TEST );
310 GLfloat texX = 1.F; // texture <s> coordinate
311 GLfloat texY = 1.F; // texture <t> coordinate
313 int aPosition = aTexture->GetPosition();
314 int aWidth = aTexture->GetWidth();
315 int aHeight = aTexture->GetHeight();
316 int aViewWidth = this->RenderWindow->GetSize()[0];
317 int aViewHeight = this->RenderWindow->GetSize()[1];
319 if( aPosition == VTKViewer_Texture::Tiled )
321 texX = (GLfloat)aViewWidth / (GLfloat)aWidth;
322 texY = (GLfloat)aViewHeight / (GLfloat)aHeight;
325 if (this->OpenGLHelper.IsInitialized())
327 if (this->VertexArrayObject == 0)
329 this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
332 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
333 this->OpenGLHelper.vglBindVertexArrayARB (this->VertexArrayObject);
335 GLfloat dx = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aWidth / (GLfloat)aViewWidth )) : 1.0f;
336 GLfloat dy = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aHeight / (GLfloat)aViewHeight )) : 1.0f;
339 // First 4 components of Vertex is TexCoords now.
340 GLfloat data[7 * 4] = { 0.0f, texY, 0.0f, 1.0f, -dx, dy, 0.0f,
341 0.0f, 0.0f, 0.0f, 1.0f, -dx, -dy, 0.0f,
342 texX, 0.0f, 0.0f, 1.0f, dx, -dy, 0.0f,
343 texX, texY, 0.0f, 1.0f, dx, dy, 0.0f };
346 this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
347 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
348 this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
350 GLint colorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
351 GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
352 GLsizei vertexSize = sizeof(GLfloat) * 7;
354 this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
355 this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
357 this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
358 this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
360 this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 1);
361 this->OpenGLHelper.vglUniform1iARB (this->myLocations.BackgroundTexture, GL_TEXTURE0);
363 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
365 this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
366 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
367 this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
368 this->OpenGLHelper.vglBindVertexArrayARB (0);
369 this->OpenGLHelper.vglUseProgramObjectARB (0);
372 GLfloat x_offset = 0.5f, y_offset = 0.5f;
373 GLfloat coeff = 0.5f;
374 if( aPosition == VTKViewer_Texture::Centered )
376 x_offset = ( (GLfloat)aWidth / (GLfloat)aViewWidth ) / 2.;
377 y_offset = ( (GLfloat)aHeight / (GLfloat)aViewHeight ) / 2.;
380 // OCCT issue 0023102: Change the algorithm of rendering the
381 // 3d viewer background using tiled texture
382 // Setting this coefficient to -1.F allows to tile textures relatively
383 // to the top-left corner of the view (value 1.F corresponds to the
384 // initial behaviour - tiling from the bottom-left corner)
385 GLfloat aCoef = -1.F;
387 // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
388 // is simply ignored, and negative multiplier is here for convenience only
389 // and does not result e.g. in texture mirroring
391 glTexCoord2f( 0.F, 0.F ); glVertex2f( -x_offset + coeff, -aCoef * y_offset + coeff );
392 glTexCoord2f( texX, 0.F ); glVertex2f( x_offset + coeff, -aCoef * y_offset + coeff );
393 glTexCoord2f( texX, aCoef * texY ); glVertex2f( x_offset + coeff, aCoef * y_offset + coeff );
394 glTexCoord2f( 0.F, aCoef * texY ); glVertex2f( -x_offset + coeff, aCoef * y_offset + coeff );
402 glEnable( GL_ALPHA_TEST );
403 glEnable( GL_DEPTH_TEST );
404 glEnable( GL_LIGHTING );
405 glEnable( GL_TEXTURE_1D );
406 glEnable( GL_TEXTURE_2D );
407 glEnable( GL_BLEND );
409 glShadeModel( oldShadeModel ); // color interpolation
413 glMatrixMode( GL_PROJECTION );
415 glMatrixMode( GL_MODELVIEW );