Salome HOME
Merge modifications for HYDRO project (origin/hydro/imps_2017_salome_83 branch)
[modules/gui.git] / src / VTKViewer / VTKViewer_OpenGLRenderer.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "VTKViewer_OpenGLRenderer.h"
24 #include "VTKViewer_Texture.h"
25
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>
33 #ifndef VTK_OPENGL2
34 #include <vtkOpenGLExtensionManager.h>
35 #include <vtkgl.h> // vtkgl namespace
36 #endif
37 #include <vtkImageImport.h>
38 #include <vtkPNGWriter.h>
39 #include <vtkOpenGLTexture.h>
40 #include <vtkTimerLog.h>
41 #include <vtkOpenGL.h>
42 #include <vtkObjectFactory.h>
43
44 vtkStandardNewMacro(VTKViewer_OpenGLRenderer);
45
46 VTKViewer_OpenGLRenderer::VTKViewer_OpenGLRenderer()
47 {
48   this->GradientType = HorizontalGradient;
49
50 #ifdef VTK_OPENGL2
51   this->BackgroundProgram        = 0;
52   this->BackgroundVertexShader   = 0;
53   this->BackgroundFragmentShader = 0;
54   this->VertexArrayObject        = 0;
55
56   this->OpenGLHelper.Init();
57 #endif
58 }
59
60 VTKViewer_OpenGLRenderer::~VTKViewer_OpenGLRenderer()
61 {
62 }
63
64 void VTKViewer_OpenGLRenderer::SetGradientType( const int theGradientType )
65 {
66   this->GradientType = theGradientType;
67 }
68
69 void VTKViewer_OpenGLRenderer::Clear(void)
70 {
71   vtkOpenGLRenderer::Clear();
72 #ifdef VTK_OPENGL2
73   if (this->OpenGLHelper.IsInitialized())
74   {
75     if (this->BackgroundProgram == 0)
76     {
77       std::string filePath = std::string( getenv( "GUI_ROOT_DIR") ) + "/share/salome/resources/gui/Background";
78       if (!this->OpenGLHelper.CreateShaderProgram (filePath,
79                                                    this->BackgroundProgram,
80                                                    this->BackgroundVertexShader,
81                                                    this->BackgroundFragmentShader))
82       {
83         return;
84       }
85       // Get uniform locations.
86       this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
87
88       this->myLocations.UseTexture        = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uUseTexture");
89       this->myLocations.BackgroundTexture = this->OpenGLHelper.vglGetUniformLocationARB (this->BackgroundProgram, "uBackgroundTexture");
90
91       this->OpenGLHelper.vglUseProgramObjectARB (0);
92     }
93   }
94 #endif
95
96   GLbitfield clear_mask = 0;
97
98   if( !this->Transparent() )
99   {
100     glClearColor( static_cast<GLclampf>(this->Background[0]),
101                   static_cast<GLclampf>(this->Background[1]),
102                   static_cast<GLclampf>(this->Background[2]),
103                   static_cast<GLclampf>(0.0));
104     clear_mask |= GL_COLOR_BUFFER_BIT;
105   }
106
107   if( !this->GetPreserveDepthBuffer() )
108   {
109     glClearDepth(static_cast<GLclampf>(1.0));
110     clear_mask |= GL_DEPTH_BUFFER_BIT;
111   }
112
113   vtkDebugMacro(<< "glClear\n");
114   glClear(clear_mask);
115
116   // If gradient background is turned on, draw it now.
117   if( !this->Transparent() &&
118       ( this->GradientBackground || this->TexturedBackground ) )
119   {
120     double aTileViewport[4];
121     this->GetRenderWindow()->GetTileViewport( aTileViewport );
122     glPushAttrib( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_TEXTURE_BIT );
123     glDisable( GL_ALPHA_TEST );
124     glDisable( GL_DEPTH_TEST );
125     glDisable( GL_LIGHTING );
126     glDisable( GL_TEXTURE_1D );
127     glDisable( GL_TEXTURE_2D );
128     glDisable( GL_BLEND );
129
130     GLint oldShadeModel;
131     glGetIntegerv(GL_SHADE_MODEL, &oldShadeModel);
132     glShadeModel( GL_SMOOTH ); // color interpolation
133
134     glMatrixMode( GL_PROJECTION );
135     glPushMatrix();
136     glLoadIdentity();
137     glMatrixMode( GL_MODELVIEW );
138     glPushMatrix();
139     glLoadIdentity();
140
141     glOrtho( aTileViewport[0], aTileViewport[2], aTileViewport[1], aTileViewport[3], -1.0, 1.0 );
142
143     if( this->GradientBackground )
144     {
145       double* corner1 = 0;
146       double* corner2 = 0;
147       double* corner3 = 0;
148       double* corner4 = 0;
149       double dcorner1[3];
150       double dcorner2[3];
151
152       switch( this->GradientType )
153       {
154         case HorizontalGradient:
155           corner1 = this->Background;
156           corner2 = this->Background2;
157           corner3 = this->Background2;
158           corner4 = this->Background;
159           break;
160         case VerticalGradient:
161           corner1 = this->Background2;
162           corner2 = this->Background2;
163           corner3 = this->Background;
164           corner4 = this->Background;
165           break;
166         case FirstDiagonalGradient:
167           corner2 = this->Background2;
168           corner4 = this->Background;
169           dcorner1[0] = dcorner2[0] = 0.5F * ( corner2[0] + corner4[0] );
170           dcorner1[1] = dcorner2[1] = 0.5F * ( corner2[1] + corner4[1] );
171           dcorner1[2] = dcorner2[2] = 0.5F * ( corner2[2] + corner4[2] );
172           corner1 = dcorner1;
173           corner3 = dcorner2;
174           break;
175         case SecondDiagonalGradient:
176           corner1 = this->Background2;  
177           corner3 = this->Background;
178           dcorner1[0] = dcorner2[0] = 0.5F * ( corner1[0] + corner3[0] );
179           dcorner1[1] = dcorner2[1] = 0.5F * ( corner1[1] + corner3[1] );
180           dcorner1[2] = dcorner2[2] = 0.5F * ( corner1[2] + corner3[2] );
181           corner2 = dcorner1;
182           corner4 = dcorner2;
183           break;
184         case FirstCornerGradient:
185           corner1 = this->Background2;
186           corner2 = this->Background2;
187           corner3 = this->Background2;
188           corner4 = this->Background;
189           break;
190         case SecondCornerGradient:
191           corner1 = this->Background2;
192           corner2 = this->Background2;
193           corner3 = this->Background;
194           corner4 = this->Background2;
195           break;
196         case ThirdCornerGradient:
197           corner1 = this->Background2;
198           corner2 = this->Background;
199           corner3 = this->Background2;
200           corner4 = this->Background2;
201           break;
202         case FourthCornerGradient:
203           corner1 = this->Background;
204           corner2 = this->Background2;
205           corner3 = this->Background2;
206           corner4 = this->Background2;
207           break;
208         default: // just in case
209           corner1 = this->Background;
210           corner2 = this->Background;
211           corner3 = this->Background;
212           corner4 = this->Background;
213           break;
214       }
215
216 #ifdef VTK_OPENGL2
217   if (this->OpenGLHelper.IsInitialized())
218   {
219     if (this->VertexArrayObject == 0)
220     {
221       this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
222     }
223
224     this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
225     this->OpenGLHelper.vglBindVertexArrayARB  (this->VertexArrayObject);
226
227     GLfloat data[7 * 4];
228     if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
229     {
230       const float tmpData[] = { (float)corner1[0], (float)corner1[1], (float)corner1[2], 1.0f,       -1.0f,  1.0f, 0.0f,
231                                 (float)corner2[0], (float)corner2[1], (float)corner2[2], 1.0f,       -1.0f, -1.0f, 0.0f,
232                                 (float)corner3[0], (float)corner3[1], (float)corner3[2], 1.0f,        1.0f, -1.0f, 0.0f,
233                                 (float)corner4[0], (float)corner4[1], (float)corner4[2], 1.0f,        1.0f,  1.0f, 0.0f };
234       memcpy (data, tmpData, sizeof(float) * 7 * 4);
235     }
236     else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
237     {
238       const float tmpData[] = { (float)corner2[0], (float)corner2[1], (float)corner2[2], 1.0f,       -1.0f, -1.0f, 0.0f,
239                                 (float)corner3[0], (float)corner3[1], (float)corner3[2], 1.0f,       -1.0f,  1.0f, 0.0f,
240                                 (float)corner4[0], (float)corner4[1], (float)corner4[2], 1.0f,        1.0f,  1.0f, 0.0f,
241                                 (float)corner1[0], (float)corner1[1], (float)corner1[2], 1.0f,        1.0f, -1.0f, 0.0f };
242       memcpy (data, tmpData, sizeof(float) * 7 * 4);
243     }
244
245     GLuint vertexBuffer;
246     this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
247     this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
248     this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
249
250     GLint colorAttrib  = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
251     GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
252     GLsizei vertexSize = sizeof(GLfloat) * 7;
253
254     this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
255     this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
256
257     this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
258     this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
259
260     this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 0);
261
262     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
263
264     this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
265     this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
266     this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
267     this->OpenGLHelper.vglBindVertexArrayARB (0);
268     this->OpenGLHelper.vglUseProgramObjectARB (0);
269   }
270 #else
271
272       glBegin( GL_TRIANGLE_FAN );
273       if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
274       {
275         glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
276         glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
277         glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
278         glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
279       }
280       else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
281       {
282         glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
283         glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
284         glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
285         glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
286       }
287       glEnd();
288 #endif
289     }
290
291     if( this->TexturedBackground && this->BackgroundTexture )
292     {
293       if( VTKViewer_Texture* aTexture = VTKViewer_Texture::SafeDownCast( this->BackgroundTexture ) )
294       {
295         glEnable( GL_TEXTURE_2D );
296
297         aTexture->Render( this );
298
299         // NOTE: By default the mode is GL_MODULATE. Since the user
300         // cannot set the mode, the default is set to replace.
301         glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
302         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
303         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
304
305         // NOTE: vtkTexture Render enables the alpha test
306         // so that no buffer is affected if alpha of incoming fragment is
307         // below the threshold. Here we have to enable it so that it won't
308         // rejects the fragments of the quad as the alpha is set to 0 on it.
309         glDisable( GL_ALPHA_TEST );
310
311         GLfloat texX = 1.F; // texture <s> coordinate
312         GLfloat texY = 1.F; // texture <t> coordinate
313
314         int aPosition = aTexture->GetPosition();
315         int aWidth = aTexture->GetWidth();
316         int aHeight = aTexture->GetHeight();
317         int aViewWidth = this->RenderWindow->GetSize()[0];
318         int aViewHeight = this->RenderWindow->GetSize()[1];
319
320         if( aPosition == VTKViewer_Texture::Tiled )
321         {
322           texX = (GLfloat)aViewWidth / (GLfloat)aWidth;
323           texY = (GLfloat)aViewHeight / (GLfloat)aHeight;
324         }
325 #ifdef VTK_OPENGL2
326         if (this->OpenGLHelper.IsInitialized())
327         {
328           if (this->VertexArrayObject == 0)
329           {
330             this->OpenGLHelper.vglGenVertexArraysARB (1, &this->VertexArrayObject);
331           }
332
333           this->OpenGLHelper.vglUseProgramObjectARB (this->BackgroundProgram);
334           this->OpenGLHelper.vglBindVertexArrayARB  (this->VertexArrayObject);
335
336           GLfloat dx = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aWidth / (GLfloat)aViewWidth )) : 1.0f;
337           GLfloat dy = (aPosition == VTKViewer_Texture::Centered) ? (( (GLfloat)aHeight / (GLfloat)aViewHeight )) : 1.0f;
338
339
340           // First 4 components of Vertex is TexCoords now.
341           GLfloat data[7 * 4] = { 0.0f, texY, 0.0f, 1.0f,       -dx,  dy, 0.0f,
342                                   0.0f, 0.0f, 0.0f, 1.0f,       -dx, -dy, 0.0f,
343                                   texX, 0.0f, 0.0f, 1.0f,        dx, -dy, 0.0f,
344                                   texX, texY, 0.0f, 1.0f,        dx,  dy, 0.0f };
345
346           GLuint vertexBuffer;
347           this->OpenGLHelper.vglGenBuffersARB (1, &vertexBuffer);
348           this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, vertexBuffer);
349           this->OpenGLHelper.vglBufferDataARB (GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB);
350
351           GLint colorAttrib  = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Color");
352           GLint vertexAttrib = this->OpenGLHelper.vglGetAttribLocationARB (this->BackgroundProgram, "Vertex");
353           GLsizei vertexSize = sizeof(GLfloat) * 7;
354
355           this->OpenGLHelper.vglVertexAttribPointerARB (colorAttrib, 4, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
356           this->OpenGLHelper.vglEnableVertexAttribArrayARB (colorAttrib);
357
358           this->OpenGLHelper.vglVertexAttribPointerARB (vertexAttrib, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 4));
359           this->OpenGLHelper.vglEnableVertexAttribArrayARB (vertexAttrib);
360
361           this->OpenGLHelper.vglUniform1iARB (this->myLocations.UseTexture, 1);
362           this->OpenGLHelper.vglUniform1iARB (this->myLocations.BackgroundTexture, GL_TEXTURE0);
363
364           glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
365
366           this->OpenGLHelper.vglDisableVertexAttribArrayARB (0);
367           this->OpenGLHelper.vglBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
368           this->OpenGLHelper.vglDeleteBuffersARB (1, &vertexBuffer);
369           this->OpenGLHelper.vglBindVertexArrayARB (0);
370           this->OpenGLHelper.vglUseProgramObjectARB (0);
371         }
372 #else
373         GLfloat x_offset = 0.5f, y_offset = 0.5f;
374         GLfloat coeff = 0.5f;
375         if( aPosition == VTKViewer_Texture::Centered )
376         {
377           x_offset = ( (GLfloat)aWidth / (GLfloat)aViewWidth ) / 2.;
378           y_offset = ( (GLfloat)aHeight / (GLfloat)aViewHeight ) / 2.;
379         }
380
381         // OCCT issue 0023102: Change the algorithm of rendering the
382         // 3d viewer background using tiled texture
383         // Setting this coefficient to -1.F allows to tile textures relatively
384         // to the top-left corner of the view (value 1.F corresponds to the
385         // initial behaviour - tiling from the bottom-left corner)
386         GLfloat aCoef = -1.F;
387
388         // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
389         // is simply ignored, and negative multiplier is here for convenience only
390         // and does not result e.g. in texture mirroring
391         glBegin( GL_QUADS );
392         glTexCoord2f(  0.F,          0.F ); glVertex2f( -x_offset + coeff, -aCoef * y_offset + coeff );
393         glTexCoord2f( texX,          0.F ); glVertex2f(  x_offset + coeff, -aCoef * y_offset + coeff );
394         glTexCoord2f( texX, aCoef * texY ); glVertex2f(  x_offset + coeff,  aCoef * y_offset + coeff );
395         glTexCoord2f(  0.F, aCoef * texY ); glVertex2f( -x_offset + coeff,  aCoef * y_offset + coeff );
396         glEnd();
397 #endif
398       }
399     }
400
401     // Restore settings.
402     {
403       glEnable( GL_ALPHA_TEST );
404       glEnable( GL_DEPTH_TEST );
405       glEnable( GL_LIGHTING );
406       glEnable( GL_TEXTURE_1D );
407       glEnable( GL_TEXTURE_2D );
408       glEnable( GL_BLEND );
409
410       glShadeModel( oldShadeModel ); // color interpolation
411     }
412
413     glPopMatrix();
414     glMatrixMode( GL_PROJECTION );
415     glPopMatrix();
416     glMatrixMode( GL_MODELVIEW );
417
418     glPopAttrib();
419   }
420 }