1 // Copyright (C) 2007-2020 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>
45 #include <vtkOpenGL.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::Clear(void)
77 vtkOpenGLRenderer::Clear();
79 if (this->OpenGLHelper.IsInitialized())
81 if (this->BackgroundProgram == 0)
83 #if defined(WIN32) && defined(UNICODE)
84 std::wstring wFilePath = std::wstring( _wgetenv(L"GUI_ROOT_DIR") ) + L"/share/salome/resources/gui/Background";
85 std::string filePath = Kernel_Utils::utf8_encode_s( wFilePath );
87 std::string filePath = std::string(getenv("GUI_ROOT_DIR")) + "/share/salome/resources/gui/Background";
90 if (!this->OpenGLHelper.CreateShaderProgram (filePath,
91 this->BackgroundProgram,
92 this->BackgroundVertexShader,
93 this->BackgroundFragmentShader))
97 // Get uniform locations.
98 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
100 this->myLocations.UseTexture = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uUseTexture");
101 this->myLocations.BackgroundTexture = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uBackgroundTexture");
103 this->OpenGLHelper.vglUseProgramObjectARB (0);
108 GLbitfield clear_mask = 0;
110 if( !this->Transparent() )
112 glClearColor( static_cast<GLclampf>(this->Background[0]),
113 static_cast<GLclampf>(this->Background[1]),
114 static_cast<GLclampf>(this->Background[2]),
115 static_cast<GLclampf>(0.0));
116 clear_mask |= GL_COLOR_BUFFER_BIT;
119 if( !this->GetPreserveDepthBuffer() )
121 glClearDepth(static_cast<GLclampf>(1.0));
122 clear_mask |= GL_DEPTH_BUFFER_BIT;
125 vtkDebugMacro(<< "glClear\n");
128 // If gradient background is turned on, draw it now.
129 if( !this->Transparent() &&
130 ( this->GradientBackground || this->TexturedBackground ) )
132 double aTileViewport[4];
133 this->GetRenderWindow()->GetTileViewport( aTileViewport );
134 glPushAttrib( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_TEXTURE_BIT );
135 glDisable( GL_ALPHA_TEST );
136 glDisable( GL_DEPTH_TEST );
137 glDisable( GL_LIGHTING );
138 glDisable( GL_TEXTURE_1D );
139 glDisable( GL_TEXTURE_2D );
140 glDisable( GL_BLEND );
143 glGetIntegerv(GL_SHADE_MODEL, &oldShadeModel);
144 glShadeModel( GL_SMOOTH ); // color interpolation
146 glMatrixMode( GL_PROJECTION );
149 glMatrixMode( GL_MODELVIEW );
153 glOrtho( aTileViewport[0], aTileViewport[2], aTileViewport[1], aTileViewport[3], -1.0, 1.0 );
155 if( this->GradientBackground )
164 switch( this->GradientType )
166 case HorizontalGradient:
167 corner1 = this->Background;
168 corner2 = this->Background;
169 corner3 = this->Background2;
170 corner4 = this->Background2;
172 case VerticalGradient:
173 corner1 = this->Background;
174 corner2 = this->Background2;
175 corner3 = this->Background2;
176 corner4 = this->Background;
178 case FirstDiagonalGradient:
179 corner1 = this->Background;
180 corner3 = this->Background2;
181 dcorner1[0] = dcorner2[0] = 0.5F * ( corner1[0] + corner3[0] );
182 dcorner1[1] = dcorner2[1] = 0.5F * ( corner1[1] + corner3[1] );
183 dcorner1[2] = dcorner2[2] = 0.5F * ( corner1[2] + corner3[2] );
187 case SecondDiagonalGradient:
188 corner2 = this->Background2;
189 corner4 = this->Background;
190 dcorner1[0] = dcorner2[0] = 0.5F * ( corner2[0] + corner4[0] );
191 dcorner1[1] = dcorner2[1] = 0.5F * ( corner2[1] + corner4[1] );
192 dcorner1[2] = dcorner2[2] = 0.5F * ( corner2[2] + corner4[2] );
196 case FirstCornerGradient:
197 corner1 = this->Background2;
198 corner2 = this->Background2;
199 corner3 = this->Background;
200 corner4 = this->Background2;
202 case SecondCornerGradient:
203 corner1 = this->Background2;
204 corner2 = this->Background2;
205 corner3 = this->Background2;
206 corner4 = this->Background;
208 case ThirdCornerGradient:
209 corner1 = this->Background;
210 corner2 = this->Background2;
211 corner3 = this->Background2;
212 corner4 = this->Background2;
214 case FourthCornerGradient:
215 corner1 = this->Background2;
216 corner2 = this->Background;
217 corner3 = this->Background2;
218 corner4 = this->Background2;
220 default: // just in case
221 corner1 = this->Background;
222 corner2 = this->Background;
223 corner3 = this->Background;
224 corner4 = this->Background;
229 if (this->OpenGLHelper.IsInitialized())
231 if (this->VertexArrayObject == 0)
233 this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
236 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
237 this->OpenGLHelper.vglBindVertexArrayARB (this->VertexArrayObject);
240 if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
242 const float tmpData[] = { (float)corner1[0], (float)corner1[1], (float)corner1[2], 1.0f, -1.0f, 1.0f, 0.0f,
243 (float)corner2[0], (float)corner2[1], (float)corner2[2], 1.0f, -1.0f, -1.0f, 0.0f,
244 (float)corner3[0], (float)corner3[1], (float)corner3[2], 1.0f, 1.0f, -1.0f, 0.0f,
245 (float)corner4[0], (float)corner4[1], (float)corner4[2], 1.0f, 1.0f, 1.0f, 0.0f };
246 memcpy (data, tmpData, sizeof(float) * 7 * 4);
248 else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
250 const float tmpData[] = { (float)corner2[0], (float)corner2[1], (float)corner2[2], 1.0f, -1.0f, -1.0f, 0.0f,
251 (float)corner3[0], (float)corner3[1], (float)corner3[2], 1.0f, -1.0f, 1.0f, 0.0f,
252 (float)corner4[0], (float)corner4[1], (float)corner4[2], 1.0f, 1.0f, 1.0f, 0.0f,
253 (float)corner1[0], (float)corner1[1], (float)corner1[2], 1.0f, 1.0f, -1.0f, 0.0f };
254 memcpy (data, tmpData, sizeof(float) * 7 * 4);
258 this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
259 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
260 this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
262 GLint colorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
263 GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
264 GLsizei vertexSize = sizeof(GLfloat) * 7;
266 this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
267 this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
269 this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
270 this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
272 this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 0);
274 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
276 this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
277 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
278 this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
279 this->OpenGLHelper.vglBindVertexArrayARB (0);
280 this->OpenGLHelper.vglUseProgramObjectARB (0);
284 glBegin( GL_TRIANGLE_FAN );
285 if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
287 glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
288 glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
289 glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
290 glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
292 else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
294 glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
295 glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
296 glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
297 glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
303 if( this->TexturedBackground && this->BackgroundTexture )
305 if( VTKViewer_Texture* aTexture = VTKViewer_Texture::SafeDownCast( this->BackgroundTexture ) )
307 glEnable( GL_TEXTURE_2D );
309 aTexture->Render( this );
311 // NOTE: By default the mode is GL_MODULATE. Since the user
312 // cannot set the mode, the default is set to replace.
313 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
314 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
315 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
317 // NOTE: vtkTexture Render enables the alpha test
318 // so that no buffer is affected if alpha of incoming fragment is
319 // below the threshold. Here we have to enable it so that it won't
320 // rejects the fragments of the quad as the alpha is set to 0 on it.
321 glDisable( GL_ALPHA_TEST );
323 GLfloat texX = 1.F; // texture <s> coordinate
324 GLfloat texY = 1.F; // texture <t> coordinate
326 int aPosition = aTexture->GetPosition();
327 int aWidth = aTexture->GetWidth();
328 int aHeight = aTexture->GetHeight();
329 int aViewWidth = this->RenderWindow->GetSize()[0];
330 int aViewHeight = this->RenderWindow->GetSize()[1];
332 if( aPosition == VTKViewer_Texture::Tiled )
334 texX = (GLfloat)aViewWidth / (GLfloat)aWidth;
335 texY = (GLfloat)aViewHeight / (GLfloat)aHeight; texY *= -1;
338 if (this->OpenGLHelper.IsInitialized())
340 if (this->VertexArrayObject == 0)
342 this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
345 this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
346 this->OpenGLHelper.vglBindVertexArrayARB (this->VertexArrayObject);
348 GLfloat dx = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aWidth / (GLfloat)aViewWidth )) : 1.0f;
349 GLfloat dy = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aHeight / (GLfloat)aViewHeight )) : (aPosition == VTKViewer_Texture::Stretched) ? 1.0f : -1.0f;
352 // First 4 components of Vertex is TexCoords now.
353 GLfloat data[7 * 4] = { 0.0f, texY, 0.0f, 1.0f, -dx, dy, 0.0f,
354 0.0f, 0.0f, 0.0f, 1.0f, -dx, -dy, 0.0f,
355 texX, 0.0f, 0.0f, 1.0f, dx, -dy, 0.0f,
356 texX, texY, 0.0f, 1.0f, dx, dy, 0.0f };
359 this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
360 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
361 this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
363 GLint colorAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
364 GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
365 GLsizei vertexSize = sizeof(GLfloat) * 7;
367 this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
368 this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
370 this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
371 this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
373 this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 1);
374 this->OpenGLHelper.vglUniform1iARB (this->myLocations.BackgroundTexture, GL_TEXTURE0);
376 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
378 this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
379 this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
380 this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
381 this->OpenGLHelper.vglBindVertexArrayARB (0);
382 this->OpenGLHelper.vglUseProgramObjectARB (0);
385 GLfloat x_offset = 0.5f, y_offset = 0.5f;
386 GLfloat coeff = 0.5f;
387 if( aPosition == VTKViewer_Texture::Centered )
389 x_offset = ( (GLfloat)aWidth / (GLfloat)aViewWidth ) / 2.;
390 y_offset = ( (GLfloat)aHeight / (GLfloat)aViewHeight ) / 2.;
393 // OCCT issue 0023102: Change the algorithm of rendering the
394 // 3d viewer background using tiled texture
395 // Setting this coefficient to -1.F allows to tile textures relatively
396 // to the top-left corner of the view (value 1.F corresponds to the
397 // initial behaviour - tiling from the bottom-left corner)
398 GLfloat aCoef = -1.F;
400 // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
401 // is simply ignored, and negative multiplier is here for convenience only
402 // and does not result e.g. in texture mirroring
404 glTexCoord2f( 0.F, 0.F ); glVertex2f( -x_offset + coeff, -aCoef * y_offset + coeff );
405 glTexCoord2f( texX, 0.F ); glVertex2f( x_offset + coeff, -aCoef * y_offset + coeff );
406 glTexCoord2f( texX, aCoef * texY ); glVertex2f( x_offset + coeff, aCoef * y_offset + coeff );
407 glTexCoord2f( 0.F, aCoef * texY ); glVertex2f( -x_offset + coeff, aCoef * y_offset + coeff );
415 glEnable( GL_ALPHA_TEST );
416 glEnable( GL_DEPTH_TEST );
417 glEnable( GL_LIGHTING );
418 glEnable( GL_TEXTURE_1D );
419 glEnable( GL_TEXTURE_2D );
420 glEnable( GL_BLEND );
422 glShadeModel( oldShadeModel ); // color interpolation
426 glMatrixMode( GL_PROJECTION );
428 glMatrixMode( GL_MODELVIEW );