1 // Copyright (C) 2007-2022 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 // to compile, otherwise we get:
24 // #error gl.h included before glew.h
25 #include <vtkglew/include/GL/glew.h>
27 #include "VTKViewer_OpenGLRenderer.h"
28 #include "VTKViewer_Texture.h"
30 #include <vtkCuller.h>
31 #include <vtkLightCollection.h>
32 #include <vtkObjectFactory.h>
33 #include <vtkOpenGLCamera.h>
34 #include <vtkOpenGLLight.h>
35 #include <vtkOpenGLProperty.h>
36 #include <vtkRenderWindow.h>
38 #include <vtkOpenGLExtensionManager.h>
39 #include <vtkgl.h> // vtkgl namespace
41 #include <vtkImageImport.h>
42 #include <vtkPNGWriter.h>
43 #include <vtkOpenGLTexture.h>
44 #include <vtkTimerLog.h>
46 #include <vtkObjectFactory.h>
48 #include <Basics_Utils.hxx>
50 vtkStandardNewMacro(VTKViewer_OpenGLRenderer)
52 VTKViewer_OpenGLRenderer::VTKViewer_OpenGLRenderer()
54 this->GradientType = HorizontalGradient;
57 this->BackgroundProgram = 0;
58 this->BackgroundVertexShader = 0;
59 this->BackgroundFragmentShader = 0;
60 this->VertexArrayObject = 0;
62 this->OpenGLHelper.Init();
66 VTKViewer_OpenGLRenderer::~VTKViewer_OpenGLRenderer()
70 void VTKViewer_OpenGLRenderer::SetGradientType( const int theGradientType )
72 this->GradientType = theGradientType;
75 void VTKViewer_OpenGLRenderer::GetCornersColor(Vec2D& cornersColor)
77 if( this->GradientBackground )
86 switch( this->GradientType )
88 case HorizontalGradient:
89 corner1 = this->Background;
90 corner2 = this->Background;
91 corner3 = this->Background2;
92 corner4 = this->Background2;
94 case VerticalGradient:
95 corner1 = this->Background;
96 corner2 = this->Background2;
97 corner3 = this->Background2;
98 corner4 = this->Background;
100 case FirstDiagonalGradient:
101 corner1 = this->Background;
102 corner3 = this->Background2;
103 dcorner1[0] = dcorner2[0] = 0.5F * ( corner1[0] + corner3[0] );
104 dcorner1[1] = dcorner2[1] = 0.5F * ( corner1[1] + corner3[1] );
105 dcorner1[2] = dcorner2[2] = 0.5F * ( corner1[2] + corner3[2] );
109 case SecondDiagonalGradient:
110 corner2 = this->Background2;
111 corner4 = this->Background;
112 dcorner1[0] = dcorner2[0] = 0.5F * ( corner2[0] + corner4[0] );
113 dcorner1[1] = dcorner2[1] = 0.5F * ( corner2[1] + corner4[1] );
114 dcorner1[2] = dcorner2[2] = 0.5F * ( corner2[2] + corner4[2] );
118 case FirstCornerGradient:
119 corner1 = this->Background2;
120 corner2 = this->Background2;
121 corner3 = this->Background;
122 corner4 = this->Background2;
124 case SecondCornerGradient:
125 corner1 = this->Background2;
126 corner2 = this->Background2;
127 corner3 = this->Background2;
128 corner4 = this->Background;
130 case ThirdCornerGradient:
131 corner1 = this->Background;
132 corner2 = this->Background2;
133 corner3 = this->Background2;
134 corner4 = this->Background2;
136 case FourthCornerGradient:
137 corner1 = this->Background2;
138 corner2 = this->Background;
139 corner3 = this->Background2;
140 corner4 = this->Background2;
142 default: // just in case
143 corner1 = this->Background;
144 corner2 = this->Background;
145 corner3 = this->Background;
146 corner4 = this->Background;
149 cornersColor[0][0] = corner1[0]; cornersColor[0][1] = corner1[1]; cornersColor[0][2] = corner1[2];
150 cornersColor[1][0] = corner2[0]; cornersColor[1][1] = corner2[1]; cornersColor[1][2] = corner2[2];
151 cornersColor[2][0] = corner3[0]; cornersColor[2][1] = corner3[1]; cornersColor[2][2] = corner3[2];
152 cornersColor[3][0] = corner4[0]; cornersColor[3][1] = corner4[1]; cornersColor[3][2] = corner4[2];
156 for (int i = 0; i < 4; i++)
157 for(int j = 0; j < 3; j++)
158 cornersColor[i][j] = this->Background[j];
162 void VTKViewer_OpenGLRenderer::Clear(void)
164 vtkOpenGLRenderer::Clear();
166 if (this->OpenGLHelper.IsInitialized())
168 if (this->BackgroundProgram == 0)
170 #if defined(WIN32) && defined(UNICODE)
171 std::wstring wFilePath = std::wstring( _wgetenv(L"GUI_ROOT_DIR") ) + L"/share/salome/resources/gui/Background";
172 std::string filePath = Kernel_Utils::utf8_encode_s( wFilePath );
174 std::string filePath = std::string(getenv("GUI_ROOT_DIR")) + "/share/salome/resources/gui/Background";
177 if (!this->OpenGLHelper.CreateShaderProgram (filePath,
178 this->BackgroundProgram,
179 this->BackgroundVertexShader,
180 this->BackgroundFragmentShader))
184 // Get uniform locations.
185 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
187 this->myLocations.UseTexture = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uUseTexture");
188 this->myLocations.BackgroundTexture = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uBackgroundTexture");
190 this->OpenGLHelper.vglUseProgramObjectARB (0);
195 GLbitfield clear_mask = 0;
197 if( !this->Transparent() )
199 glClearColor( static_cast<GLclampf>(this->Background[0]),
200 static_cast<GLclampf>(this->Background[1]),
201 static_cast<GLclampf>(this->Background[2]),
202 static_cast<GLclampf>(this->BackgroundAlpha));
203 clear_mask |= GL_COLOR_BUFFER_BIT;
206 if( !this->GetPreserveDepthBuffer() )
208 glClearDepth(static_cast<GLclampf>(1.0));
209 clear_mask |= GL_DEPTH_BUFFER_BIT;
212 vtkDebugMacro(<< "glClear\n");
215 // If gradient background is turned on, draw it now.
216 if( !this->Transparent() &&
217 ( this->GradientBackground || this->TexturedBackground ) )
219 double aTileViewport[4];
220 this->GetRenderWindow()->GetTileViewport( aTileViewport );
221 glPushAttrib( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_TEXTURE_BIT );
222 glDisable( GL_ALPHA_TEST );
223 glDisable( GL_DEPTH_TEST );
224 glDisable( GL_LIGHTING );
225 glDisable( GL_TEXTURE_1D );
226 glDisable( GL_TEXTURE_2D );
227 glDisable( GL_BLEND );
230 glGetIntegerv(GL_SHADE_MODEL, &oldShadeModel);
231 glShadeModel( GL_SMOOTH ); // color interpolation
233 glMatrixMode( GL_PROJECTION );
236 glMatrixMode( GL_MODELVIEW );
240 glOrtho( aTileViewport[0], aTileViewport[2], aTileViewport[1], aTileViewport[3], -1.0, 1.0 );
242 if( this->GradientBackground )
244 Vec2D corners = {{0.0f,0.0f,0.0f},
248 GetCornersColor(corners);
251 if (this->OpenGLHelper.IsInitialized())
253 if (this->VertexArrayObject == 0)
255 this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
258 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
259 this->OpenGLHelper.vglBindVertexArrayARB (this->VertexArrayObject);
261 GLfloat data[10 * 4];
262 if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
264 const float tmpData[] = { (float)corners[0][0], (float)corners[0][1], (float)corners[0][2], 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
265 (float)corners[1][0], (float)corners[1][1], (float)corners[1][2], 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
266 (float)corners[2][0], (float)corners[2][1], (float)corners[2][2], 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
267 (float)corners[3][0], (float)corners[3][1], (float)corners[3][2], 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
268 memcpy (data, tmpData, sizeof(float) * 10 * 4);
270 else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
272 const float tmpData[] = { (float)corners[1][0], (float)corners[1][1], (float)corners[1][2], 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
273 (float)corners[2][0], (float)corners[2][1], (float)corners[2][2], 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
274 (float)corners[3][0], (float)corners[3][1], (float)corners[3][2], 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
275 (float)corners[0][0], (float)corners[0][1], (float)corners[0][2], 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
276 memcpy (data, tmpData, sizeof(float) * 10 * 4);
280 this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
281 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
282 this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
284 GLint colorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
285 GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
286 GLint bgColorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "ColorBG");
287 GLsizei vertexSize = sizeof(GLfloat) * 10;
289 this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
290 this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
292 this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
293 this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
295 this->OpenGLHelper.vglVertexAttribPointerARB (bgColorAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 7));
296 this->OpenGLHelper.vglEnableVertexAttribArrayARB (bgColorAttrib);
298 this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 0);
300 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
302 this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
303 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
304 this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
305 this->OpenGLHelper.vglBindVertexArrayARB (0);
306 this->OpenGLHelper.vglUseProgramObjectARB (0);
310 glBegin( GL_TRIANGLE_FAN );
311 if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
313 glColor3f( corners[0][0], corners[0][1], corners[0][2] ); glVertex2f( 0.F, 0.F );
314 glColor3f( corners[1][0], corners[1][1], corners[1][2] ); glVertex2f( 1.F, 0.F );
315 glColor3f( corners[2][0], corners[2][1], corners[2][2] ); glVertex2f( 1.F, 1.F );
316 glColor3f( corners[3][0], corners[3][1], corners[3][2] ); glVertex2f( 0.F, 1.F );
318 else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
320 glColor3f( corners[1][0], corners[1][1], corners[1][2] ); glVertex2f( 1.F, 0.F );
321 glColor3f( corners[2][0], corners[2][1], corners[2][2] ); glVertex2f( 1.F, 1.F );
322 glColor3f( corners[3][0], corners[3][1], corners[3][2] ); glVertex2f( 0.F, 1.F );
323 glColor3f( corners[0][0], corners[0][1], corners[0][2] ); glVertex2f( 0.F, 0.F );
329 if( this->TexturedBackground && this->BackgroundTexture )
331 if( VTKViewer_Texture* aTexture = VTKViewer_Texture::SafeDownCast( this->BackgroundTexture ) )
333 glEnable( GL_TEXTURE_2D );
335 aTexture->Render( this );
337 // NOTE: By default the mode is GL_MODULATE. Since the user
338 // cannot set the mode, the default is set to replace.
339 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
340 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
341 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
343 // NOTE: vtkTexture Render enables the alpha test
344 // so that no buffer is affected if alpha of incoming fragment is
345 // below the threshold. Here we have to enable it so that it won't
346 // rejects the fragments of the quad as the alpha is set to 0 on it.
347 glDisable( GL_ALPHA_TEST );
349 GLfloat texX = 1.F; // texture <s> coordinate
350 GLfloat texY = 1.F; // texture <t> coordinate
352 int aPosition = aTexture->GetPosition();
353 int aWidth = aTexture->GetWidth();
354 int aHeight = aTexture->GetHeight();
355 int aViewWidth = this->RenderWindow->GetSize()[0];
356 int aViewHeight = this->RenderWindow->GetSize()[1];
358 if( aPosition == VTKViewer_Texture::Tiled )
360 texX = (GLfloat)aViewWidth / (GLfloat)aWidth;
361 texY = (GLfloat)aViewHeight / (GLfloat)aHeight; texY *= -1;
364 if (this->OpenGLHelper.IsInitialized())
366 if (this->VertexArrayObject == 0)
368 this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
371 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
372 this->OpenGLHelper.vglBindVertexArrayARB (this->VertexArrayObject);
374 GLfloat dx = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aWidth / (GLfloat)aViewWidth )) : 1.0f;
375 GLfloat dy = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aHeight / (GLfloat)aViewHeight )) : (aPosition == VTKViewer_Texture::Stretched) ? 1.0f : -1.0f;
377 // call to get backcolor
378 Vec2D bgColor = {{0.0f,0.0f,0.0f},
382 GetCornersColor(bgColor);
383 // First 4 components of Vertex is TexCoords now.
384 GLfloat data[10 * 4];
385 if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
387 const float tmpData[] = { 0.0f, texY, 0.0f, 1.0f, -dx, dy, 0.0f, (float)bgColor[0][0], (float)bgColor[0][1], (float)bgColor[0][2],
388 0.0f, 0.0f, 0.0f, 1.0f, -dx, -dy, 0.0f, (float)bgColor[1][0], (float)bgColor[1][1], (float)bgColor[1][2],
389 texX, 0.0f, 0.0f, 1.0f, dx, -dy, 0.0f, (float)bgColor[2][0], (float)bgColor[2][1], (float)bgColor[2][2],
390 texX, texY, 0.0f, 1.0f, dx, dy, 0.0f, (float)bgColor[3][0], (float)bgColor[3][1], (float)bgColor[3][2] };
391 memcpy (data, tmpData, sizeof(float) * 10 * 4);
393 else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
395 const float tmpData[] = { 0.0f, texY, 0.0f, 1.0f, -dx, dy, 0.0f, (float)bgColor[2][0], (float)bgColor[2][1], (float)bgColor[2][2],
396 0.0f, 0.0f, 0.0f, 1.0f, -dx, -dy, 0.0f, (float)bgColor[1][0], (float)bgColor[1][1], (float)bgColor[1][2],
397 texX, 0.0f, 0.0f, 1.0f, dx, -dy, 0.0f, (float)bgColor[0][0], (float)bgColor[0][1], (float)bgColor[0][2],
398 texX, texY, 0.0f, 1.0f, dx, dy, 0.0f, (float)bgColor[3][0], (float)bgColor[3][1], (float)bgColor[3][2] };
399 memcpy (data, tmpData, sizeof(float) * 10 * 4);
403 this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
404 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
405 this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
407 GLint colorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
408 GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
409 GLint bgColorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "ColorBG");
410 GLsizei vertexSize = sizeof(GLfloat) * 10;
412 this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
413 this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
415 this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
416 this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
418 this->OpenGLHelper.vglVertexAttribPointerARB (bgColorAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 7));
419 this->OpenGLHelper.vglEnableVertexAttribArrayARB (bgColorAttrib);
421 this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 1);
422 this->OpenGLHelper.vglUniform1iARB (this->myLocations.BackgroundTexture, GL_TEXTURE0);
424 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
426 this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
427 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
428 this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
429 this->OpenGLHelper.vglBindVertexArrayARB (0);
430 this->OpenGLHelper.vglUseProgramObjectARB (0);
433 GLfloat x_offset = 0.5f, y_offset = 0.5f;
434 GLfloat coeff = 0.5f;
435 if( aPosition == VTKViewer_Texture::Centered )
437 x_offset = ( (GLfloat)aWidth / (GLfloat)aViewWidth ) / 2.;
438 y_offset = ( (GLfloat)aHeight / (GLfloat)aViewHeight ) / 2.;
441 // OCCT issue 0023102: Change the algorithm of rendering the
442 // 3d viewer background using tiled texture
443 // Setting this coefficient to -1.F allows to tile textures relatively
444 // to the top-left corner of the view (value 1.F corresponds to the
445 // initial behaviour - tiling from the bottom-left corner)
446 GLfloat aCoef = -1.F;
448 // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
449 // is simply ignored, and negative multiplier is here for convenience only
450 // and does not result e.g. in texture mirroring
452 glTexCoord2f( 0.F, 0.F ); glVertex2f( -x_offset + coeff, -aCoef * y_offset + coeff );
453 glTexCoord2f( texX, 0.F ); glVertex2f( x_offset + coeff, -aCoef * y_offset + coeff );
454 glTexCoord2f( texX, aCoef * texY ); glVertex2f( x_offset + coeff, aCoef * y_offset + coeff );
455 glTexCoord2f( 0.F, aCoef * texY ); glVertex2f( -x_offset + coeff, aCoef * y_offset + coeff );
463 glEnable( GL_ALPHA_TEST );
464 glEnable( GL_DEPTH_TEST );
465 glEnable( GL_LIGHTING );
466 glEnable( GL_TEXTURE_1D );
467 glEnable( GL_TEXTURE_2D );
468 glEnable( GL_BLEND );
470 glShadeModel( oldShadeModel ); // color interpolation
474 glMatrixMode( GL_PROJECTION );
476 glMatrixMode( GL_MODELVIEW );