0025213: Visualization, TKOpenGl - do not use deprecated built-ins in GLSL shaders
[occt.git] / src / OpenGl / OpenGl_View_2.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <stdio.h>
17 #include <stdlib.h>
18
19 #include <OpenGl_GlCore11.hxx>
20 #include <OpenGl_tgl_funcs.hxx>
21
22 #include <Image_AlienPixMap.hxx>
23 #include <Visual3d_Layer.hxx>
24
25 #include <NCollection_Mat4.hxx>
26
27 #include <OpenGl_AspectLine.hxx>
28 #include <OpenGl_Context.hxx>
29 #include <OpenGl_Matrix.hxx>
30 #include <OpenGl_Workspace.hxx>
31 #include <OpenGl_View.hxx>
32 #include <OpenGl_Trihedron.hxx>
33 #include <OpenGl_GraduatedTrihedron.hxx>
34 #include <OpenGl_PrinterContext.hxx>
35 #include <OpenGl_ShaderManager.hxx>
36 #include <OpenGl_ShaderProgram.hxx>
37 #include <OpenGl_Structure.hxx>
38
39 #define EPSI 0.0001
40
41 namespace
42 {
43
44   static const GLfloat THE_DEFAULT_AMBIENT[4]    = { 0.0f, 0.0f, 0.0f, 1.0f };
45   static const GLfloat THE_DEFAULT_SPOT_DIR[3]   = { 0.0f, 0.0f, -1.0f };
46   static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
47   static const GLfloat THE_DEFAULT_SPOT_CUTOFF   = 180.0f;
48
49 };
50
51 extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx
52
53 /*----------------------------------------------------------------------*/
54
55 struct OPENGL_CLIP_PLANE
56 {
57   GLboolean isEnabled;
58   GLdouble Equation[4];
59   DEFINE_STANDARD_ALLOC
60 };
61
62 /*----------------------------------------------------------------------*/
63 /*
64 * Fonctions privees
65 */
66
67 /*-----------------------------------------------------------------*/
68 /*
69 *  Set des lumieres
70 */
71 static void bind_light (const OpenGl_Light& theLight,
72                         GLenum&             theLightGlId,
73                         Graphic3d_Vec4&     theAmbientColor)
74 {
75   // Only 8 lights in OpenGL...
76   if (theLightGlId > GL_LIGHT7)
77   {
78     return;
79   }
80
81   if (theLight.Type == Visual3d_TOLS_AMBIENT)
82   {
83     // add RGBA intensity of the ambient light
84     theAmbientColor += theLight.Color;
85     return;
86   }
87
88   // the light is a headlight?
89   GLint aMatrixModeOld = 0;
90   if (theLight.IsHeadlight)
91   {
92     glGetIntegerv (GL_MATRIX_MODE, &aMatrixModeOld);
93     glMatrixMode  (GL_MODELVIEW);
94     glPushMatrix();
95     glLoadIdentity();
96   }
97
98   // setup light type
99   switch (theLight.Type)
100   {
101     case Visual3d_TOLS_DIRECTIONAL:
102     {
103       // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
104       const OpenGl_Vec4 anInfDir = -theLight.Direction;
105
106       // to create a realistic effect,  set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
107       glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
108       glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
109       glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
110       glLightfv (theLightGlId, GL_POSITION,              anInfDir.GetData());
111       glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
112       glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
113       glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
114       break;
115     }
116     case Visual3d_TOLS_POSITIONAL:
117     {
118       // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
119       glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
120       glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
121       glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
122       glLightfv (theLightGlId, GL_POSITION,              theLight.Position.GetData());
123       glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
124       glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
125       glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
126       glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
127       glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
128       glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
129       break;
130     }
131     case Visual3d_TOLS_SPOT:
132     {
133       glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
134       glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
135       glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
136       glLightfv (theLightGlId, GL_POSITION,              theLight.Position.GetData());
137       glLightfv (theLightGlId, GL_SPOT_DIRECTION,        theLight.Direction.GetData());
138       glLightf  (theLightGlId, GL_SPOT_EXPONENT,         theLight.Concentration() * 128.0f);
139       glLightf  (theLightGlId, GL_SPOT_CUTOFF,          (theLight.Angle() * 180.0f) / GLfloat(M_PI));
140       glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
141       glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
142       glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
143       break;
144     }
145   }
146
147   // restore matrix in case of headlight
148   if (theLight.IsHeadlight)
149   {
150     glPopMatrix();
151     glMatrixMode (aMatrixModeOld);
152   }
153
154   glEnable (theLightGlId++);
155 }
156
157 /*----------------------------------------------------------------------*/
158
159 void OpenGl_View::DrawBackground (OpenGl_Workspace& theWorkspace)
160 {
161   if ( (theWorkspace.NamedStatus & OPENGL_NS_WHITEBACK) == 0 &&
162        ( myBgTexture.TexId != 0 || myBgGradient.type != Aspect_GFM_NONE ) )
163   {
164     const Standard_Integer aViewWidth = theWorkspace.Width();
165     const Standard_Integer aViewHeight = theWorkspace.Height();
166
167     glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
168
169     glMatrixMode( GL_PROJECTION );
170     glPushMatrix();
171     glLoadIdentity();
172     glMatrixMode( GL_MODELVIEW );
173     glPushMatrix();
174     glLoadIdentity();
175
176     if ( glIsEnabled( GL_DEPTH_TEST ) )
177       glDisable( GL_DEPTH_TEST ); //push GL_ENABLE_BIT
178
179     // drawing bg gradient if:
180     // - gradient fill type is not Aspect_GFM_NONE and
181     // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
182     if ( ( myBgGradient.type != Aspect_GFM_NONE ) &&
183       ( myBgTexture.TexId == 0 || myBgTexture.Style == Aspect_FM_CENTERED ||
184       myBgTexture.Style == Aspect_FM_NONE ) )
185     {
186       Tfloat* corner1 = 0;/* -1,-1*/
187       Tfloat* corner2 = 0;/*  1,-1*/
188       Tfloat* corner3 = 0;/*  1, 1*/
189       Tfloat* corner4 = 0;/* -1, 1*/
190       Tfloat dcorner1[3];
191       Tfloat dcorner2[3];
192
193       switch( myBgGradient.type )
194       {
195       case Aspect_GFM_HOR:
196         corner1 = myBgGradient.color1.rgb;
197         corner2 = myBgGradient.color2.rgb;
198         corner3 = myBgGradient.color2.rgb;
199         corner4 = myBgGradient.color1.rgb;
200         break;
201       case Aspect_GFM_VER:
202         corner1 = myBgGradient.color2.rgb;
203         corner2 = myBgGradient.color2.rgb;
204         corner3 = myBgGradient.color1.rgb;
205         corner4 = myBgGradient.color1.rgb;
206         break;
207       case Aspect_GFM_DIAG1:
208         corner2 = myBgGradient.color2.rgb;
209         corner4 = myBgGradient.color1.rgb;
210         dcorner1 [0] = dcorner2[0] = 0.5F * (corner2[0] + corner4[0]);
211         dcorner1 [1] = dcorner2[1] = 0.5F * (corner2[1] + corner4[1]);
212         dcorner1 [2] = dcorner2[2] = 0.5F * (corner2[2] + corner4[2]);
213         corner1 = dcorner1;
214         corner3 = dcorner2;
215         break;
216       case Aspect_GFM_DIAG2:
217         corner1 = myBgGradient.color2.rgb;
218         corner3 = myBgGradient.color1.rgb;
219         dcorner1 [0] = dcorner2[0] = 0.5F * (corner1[0] + corner3[0]);
220         dcorner1 [1] = dcorner2[1] = 0.5F * (corner1[1] + corner3[1]);
221         dcorner1 [2] = dcorner2[2] = 0.5F * (corner1[2] + corner3[2]);
222         corner2 = dcorner1;
223         corner4 = dcorner2;
224         break;
225       case Aspect_GFM_CORNER1:
226         corner1 = myBgGradient.color2.rgb;
227         corner2 = myBgGradient.color2.rgb;
228         corner3 = myBgGradient.color2.rgb;
229         corner4 = myBgGradient.color1.rgb;
230         break;
231       case Aspect_GFM_CORNER2:
232         corner1 = myBgGradient.color2.rgb;
233         corner2 = myBgGradient.color2.rgb;
234         corner3 = myBgGradient.color1.rgb;
235         corner4 = myBgGradient.color2.rgb;
236         break;
237       case Aspect_GFM_CORNER3:
238         corner1 = myBgGradient.color2.rgb;
239         corner2 = myBgGradient.color1.rgb;
240         corner3 = myBgGradient.color2.rgb;
241         corner4 = myBgGradient.color2.rgb;
242         break;
243       case Aspect_GFM_CORNER4:
244         corner1 = myBgGradient.color1.rgb;
245         corner2 = myBgGradient.color2.rgb;
246         corner3 = myBgGradient.color2.rgb;
247         corner4 = myBgGradient.color2.rgb;
248         break;
249       default:
250         //printf("gradient background type not right\n");
251         break;
252       }
253
254       // Save GL parameters
255       glDisable( GL_LIGHTING ); //push GL_ENABLE_BIT
256
257       GLint curSM;
258       glGetIntegerv( GL_SHADE_MODEL, &curSM );
259       if ( curSM != GL_SMOOTH )
260         glShadeModel( GL_SMOOTH ); //push GL_LIGHTING_BIT
261
262       glBegin(GL_TRIANGLE_FAN);
263       if( myBgGradient.type != Aspect_GFM_CORNER1 && myBgGradient.type != Aspect_GFM_CORNER3 )
264       {
265         glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
266         glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
267         glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
268         glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
269       }
270       else //if ( myBgGradient.type == Aspect_GFM_CORNER1 || myBgGradient.type == Aspect_GFM_CORNER3 )
271       {
272         glColor3f(corner2[0],corner2[1],corner2[2]); glVertex2f( 1.,-1.);
273         glColor3f(corner3[0],corner3[1],corner3[2]); glVertex2f( 1., 1.);
274         glColor3f(corner4[0],corner4[1],corner4[2]); glVertex2f(-1., 1.);
275         glColor3f(corner1[0],corner1[1],corner1[2]); glVertex2f(-1.,-1.);
276       }
277       glEnd();
278
279       // Restore GL parameters
280       if ( curSM != GL_SMOOTH )
281         glShadeModel( curSM );
282     }
283     // drawing bg image if:
284     // - it is defined and
285     // - fill type is not Aspect_FM_NONE
286     if ( myBgTexture.TexId != 0 && myBgTexture.Style != Aspect_FM_NONE )
287     {
288       GLfloat texX_range = 1.F; // texture <s> coordinate
289       GLfloat texY_range = 1.F; // texture <t> coordinate
290
291       // Set up for stretching or tiling
292       GLfloat x_offset, y_offset;
293       if ( myBgTexture.Style == Aspect_FM_CENTERED )
294       {
295         x_offset = (GLfloat)myBgTexture.Width / (GLfloat)aViewWidth;
296         y_offset = (GLfloat)myBgTexture.Height / (GLfloat)aViewHeight;
297       }
298       else
299       {
300         x_offset = 1.F;
301         y_offset = 1.F;
302         if ( myBgTexture.Style == Aspect_FM_TILED )
303         {
304           texX_range = (GLfloat)aViewWidth / (GLfloat)myBgTexture.Width;
305           texY_range = (GLfloat)aViewHeight / (GLfloat)myBgTexture.Height;
306         }
307       }
308
309       // OCCT issue 0023000: Improve the way the gradient and textured
310       // background is managed in 3d viewer (note 0020339)
311       // Setting this coefficient to -1.F allows to tile textures relatively
312       // to the top-left corner of the view (value 1.F corresponds to the
313       // initial behaviour - tiling from the bottom-left corner)
314       GLfloat aCoef = -1.F;
315
316       glEnable( GL_TEXTURE_2D ); //push GL_ENABLE_BIT
317       glBindTexture( GL_TEXTURE_2D, myBgTexture.TexId ); //push GL_TEXTURE_BIT
318
319       glDisable( GL_BLEND ); //push GL_ENABLE_BIT
320
321       glColor3fv (theWorkspace.BackgroundColor().rgb);
322       glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); //push GL_TEXTURE_BIT
323
324       // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
325       // is simply ignored, and negative multiplier is here for convenience only
326       // and does not result e.g. in texture mirroring
327       glBegin( GL_QUADS );
328       glTexCoord2f(0.F, 0.F); glVertex2f( -x_offset, -aCoef * y_offset );
329       glTexCoord2f(texX_range, 0.F); glVertex2f( x_offset, -aCoef * y_offset );
330       glTexCoord2f(texX_range, aCoef * texY_range); glVertex2f( x_offset, aCoef * y_offset );
331       glTexCoord2f(0.F, aCoef * texY_range); glVertex2f( -x_offset, aCoef * y_offset );
332       glEnd();
333     }
334
335     glPopMatrix();
336     glMatrixMode( GL_PROJECTION );
337     glPopMatrix();
338     glMatrixMode( GL_MODELVIEW );
339
340     glPopAttrib(); //GL_ENABLE_BIT | GL_TEXTURE_BIT
341
342     if (theWorkspace.UseZBuffer())
343     {
344       glEnable (GL_DEPTH_TEST);
345     }
346   }
347 }
348
349 /*----------------------------------------------------------------------*/
350
351 //call_func_redraw_all_structs_proc
352 void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
353                           const Handle(OpenGl_Workspace) &theWorkspace,
354                           const Graphic3d_CView& theCView,
355                           const Aspect_CLayer2d& theCUnderLayer,
356                           const Aspect_CLayer2d& theCOverLayer)
357 {
358   // ==================================
359   //      Step 1: Prepare for redraw
360   // ==================================
361
362   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
363
364   // Store and disable current clipping planes
365   Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
366
367   OPENGL_CLIP_PLANE *aOldPlanes = new OPENGL_CLIP_PLANE[aMaxPlanes];
368   OPENGL_CLIP_PLANE *aPtrPlane = aOldPlanes;
369
370   GLenum aClipPlaneId = GL_CLIP_PLANE0;
371   const GLenum aClipLastId = GL_CLIP_PLANE0 + aMaxPlanes;
372   for (; aClipPlaneId < aClipLastId; aClipPlaneId++, aPtrPlane++)
373   {
374     glGetClipPlane (aClipPlaneId, aPtrPlane->Equation);
375     if (aPtrPlane->isEnabled)
376     {
377       glDisable (aClipPlaneId);
378       aPtrPlane->isEnabled = GL_TRUE;
379     }
380     else
381     {
382       aPtrPlane->isEnabled = GL_FALSE;
383     }
384   }
385
386   Standard_Boolean isProjectionMatUpdateNeeded  = Standard_False;
387   Standard_Boolean isOrientationMatUpdateNeeded = Standard_False;
388   if (myBVHSelector.ProjectionState() != myCamera->ProjectionState())
389   {
390     isProjectionMatUpdateNeeded = Standard_True;
391     myBVHSelector.ChangeProjectionState() = myCamera->ProjectionState();
392   }
393   if (myBVHSelector.ModelViewState() != myCamera->ModelViewState())
394   {
395     isOrientationMatUpdateNeeded = Standard_True;
396     myBVHSelector.ChangeModelViewState() = myCamera->ModelViewState();
397   }
398
399   // Set OCCT state uniform variables
400   const Handle(OpenGl_ShaderManager) aManager = aContext->ShaderManager();
401   if (!aManager->IsEmpty())
402   {
403     if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
404     {
405       aManager->UpdateLightSourceStateTo (&myLights);
406       myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
407     }
408
409     if (myProjectionState != myCamera->ProjectionState())
410     {
411       myProjectionState = myCamera->ProjectionState();
412       aManager->UpdateProjectionStateTo ((const Tmatrix3*)myCamera->ProjectionMatrixF().GetData());
413     }
414
415     if (myModelViewState != myCamera->ModelViewState())
416     {
417       myModelViewState = myCamera->ModelViewState();
418       aManager->UpdateWorldViewStateTo ((const Tmatrix3*)myCamera->OrientationMatrixF().GetData());
419     }
420
421     if (aManager->ModelWorldState().Index() == 0)
422     {
423       Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f },
424                                     { 0.f, 1.f, 0.f, 0.f },
425                                     { 0.f, 0.f, 1.f, 0.f },
426                                     { 0.f, 0.f, 0.f, 1.f } };
427
428       aContext->ShaderManager()->UpdateModelWorldStateTo (&aModelWorldState);
429     }
430   }
431
432   if (!aManager.IsNull())
433   {
434     if (!aManager->IsSameView (this))
435     {
436       // Force update camera states
437       myProjectionState = myCamera->ProjectionState();
438       aManager->UpdateProjectionStateTo ((const Tmatrix3*)myCamera->ProjectionMatrixF().GetData());
439
440       myModelViewState = myCamera->ModelViewState();
441       aManager->UpdateWorldViewStateTo ((const Tmatrix3*)myCamera->OrientationMatrixF().GetData());
442     }
443   }
444
445   if (isProjectionMatUpdateNeeded
446    || isOrientationMatUpdateNeeded)
447   {
448     myBVHSelector.SetViewVolume (myCamera);
449   }
450
451   // ====================================
452   //      Step 2: Redraw background
453   // ====================================
454
455   // Render background
456   if (theWorkspace->ToRedrawGL())
457   {
458     DrawBackground (*theWorkspace);
459   }
460
461   // Switch off lighting by default
462   glDisable(GL_LIGHTING);
463
464   // =================================
465   //      Step 3: Draw underlayer
466   // =================================
467
468   RedrawLayer2d (thePrintContext, theCView, theCUnderLayer);
469
470   // =================================
471   //      Step 4: Redraw main plane
472   // =================================
473
474   // Setup face culling
475   GLboolean isCullFace = GL_FALSE;
476   if ( myBackfacing )
477   {
478     isCullFace = glIsEnabled( GL_CULL_FACE );
479     if ( myBackfacing < 0 )
480     {
481       glEnable( GL_CULL_FACE );
482       glCullFace( GL_BACK );
483     }
484     else
485       glDisable( GL_CULL_FACE );
486   }
487
488   // if the view is scaled normal vectors are scaled to unit
489   // length for correct displaying of shaded objects
490   const gp_Pnt anAxialScale = myCamera->AxialScale();
491   if(anAxialScale.X() != 1.F ||
492      anAxialScale.Y() != 1.F ||
493      anAxialScale.Z() != 1.F)
494     glEnable(GL_NORMALIZE);
495   else if(glIsEnabled(GL_NORMALIZE))
496     glDisable(GL_NORMALIZE);
497
498   // Apply Fog
499   if ( myFog.IsOn )
500   {
501     Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance();
502     if (myCamera->ZFar() < aFogFrontConverted)
503     {
504       aFogFrontConverted = myCamera->ZFar();
505       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
506     }
507
508     Standard_Real aFogBackConverted = (Standard_Real )myFog.Back + myCamera->Distance();
509     if (myCamera->ZFar() < aFogFrontConverted)
510     {
511       aFogBackConverted = myCamera->ZFar();
512       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
513     }
514
515     if (aFogFrontConverted > aFogBackConverted)
516     {
517       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
518       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
519     }    
520
521     glFogi(GL_FOG_MODE, GL_LINEAR);
522     glFogf(GL_FOG_START, (Standard_ShortReal )aFogFrontConverted);
523     glFogf(GL_FOG_END, (Standard_ShortReal )aFogBackConverted);
524     glFogfv(GL_FOG_COLOR, myFog.Color.rgb);
525     glEnable(GL_FOG);
526   }
527   else
528     glDisable(GL_FOG);
529
530   // Apply InteriorShadingMethod
531   glShadeModel( myIntShadingMethod == TEL_SM_FLAT ? GL_FLAT : GL_SMOOTH );
532
533   // Apply AntiAliasing
534   if (myAntiAliasing)
535     theWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
536   else
537     theWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
538
539   if (!aManager->IsEmpty())
540   {
541     aManager->UpdateClippingState();
542   }
543
544   // Redraw 3d scene
545   if (!myCamera->IsStereo() || !aContext->HasStereoBuffers())
546   {
547     // single-pass monographic rendering
548     const OpenGl_Matrix* aProj = (const OpenGl_Matrix*) &myCamera->ProjectionMatrixF();
549
550     const OpenGl_Matrix* aOrient = (const OpenGl_Matrix*) &myCamera->OrientationMatrixF();
551
552     // redraw scene with normal orientation and projection
553     RedrawScene (thePrintContext, theWorkspace, aProj, aOrient);
554   }
555   else
556   {
557     // two stereographic passes
558     const OpenGl_Matrix* aLProj  = (const OpenGl_Matrix*) &myCamera->ProjectionStereoLeftF();
559     const OpenGl_Matrix* aRProj  = (const OpenGl_Matrix*) &myCamera->ProjectionStereoRightF();
560     const OpenGl_Matrix* aOrient = (const OpenGl_Matrix*) &myCamera->OrientationMatrixF();
561
562     // safely switch to left Eye buffer
563     aContext->SetDrawBufferLeft();
564
565     // redraw left Eye
566     RedrawScene (thePrintContext, theWorkspace, aLProj, aOrient);
567
568     // reset depth buffer of first rendering pass
569     if (theWorkspace->UseDepthTest())
570     {
571       glClear (GL_DEPTH_BUFFER_BIT);
572     }
573     // safely switch to right Eye buffer
574     aContext->SetDrawBufferRight();
575     
576     // redraw right Eye
577     RedrawScene (thePrintContext, theWorkspace, aRProj, aOrient);
578
579     // switch back to monographic rendering
580     aContext->SetDrawBufferMono();
581   }
582
583   // ===============================
584   //      Step 5: Trihedron
585   // ===============================
586
587   // Resetting GL parameters according to the default aspects
588   // in order to synchronize GL state with the graphic driver state
589   // before drawing auxiliary stuff (trihedrons, overlayer)
590   // and invoking optional callbacks
591   theWorkspace->ResetAppliedAspect();
592
593   aContext->ChangeClipping().RemoveAll();
594
595   if (!aManager->IsEmpty())
596   {
597     aManager->ResetMaterialStates();
598     aManager->RevertClippingState();
599
600     // We need to disable (unbind) all shaders programs to ensure
601     // that all objects without specified aspect will be drawn
602     // correctly (such as background)
603     aContext->BindProgram (NULL);
604   }
605
606   // Render trihedron
607   if (theWorkspace->ToRedrawGL())
608   {
609     RedrawTrihedron (theWorkspace);
610
611     // Restore face culling
612     if ( myBackfacing )
613     {
614       if ( isCullFace )
615       {
616         glEnable   ( GL_CULL_FACE );
617         glCullFace ( GL_BACK      );
618       }
619       else
620         glDisable ( GL_CULL_FACE );
621     }
622   }
623
624   // ===============================
625   //      Step 6: Redraw overlay
626   // ===============================
627
628   const int aMode = 0;
629   theWorkspace->DisplayCallback (theCView, (aMode | OCC_PRE_OVERLAY));
630
631   RedrawLayer2d (thePrintContext, theCView, theCOverLayer);
632
633   theWorkspace->DisplayCallback (theCView, aMode);
634
635   // ===============================
636   //      Step 7: Finalize
637   // ===============================
638
639   // Restore clipping planes
640   aClipPlaneId = GL_CLIP_PLANE0;
641   aPtrPlane = aOldPlanes;
642
643   for (; aClipPlaneId < aClipLastId; aClipPlaneId++, aPtrPlane++)
644   {
645     glClipPlane (aClipPlaneId, aPtrPlane->Equation);
646     if (aPtrPlane->isEnabled)
647       glEnable (aClipPlaneId);
648     else
649       glDisable (aClipPlaneId);
650   }
651
652   delete[] aOldPlanes;
653
654   // ==============================================================
655   //      Step 8: Keep shader manager informed about last View
656   // ==============================================================
657
658   if (!aManager.IsNull())
659   {
660     aManager->SetLastView (this);
661   }
662 }
663
664 // =======================================================================
665 // function : InvalidateBVHData
666 // purpose  :
667 // =======================================================================
668 void OpenGl_View::InvalidateBVHData (const Standard_Integer theLayerId)
669 {
670   myZLayers.InvalidateBVHData (theLayerId);
671 }
672
673 /*----------------------------------------------------------------------*/
674
675 //ExecuteViewDisplay
676 void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace)
677 {
678   if ( myZLayers.NbStructures() <= 0 )
679     return;
680
681   glPushAttrib ( GL_DEPTH_BUFFER_BIT );
682
683   //TsmPushAttri(); /* save previous graphics context */
684
685   if ( (AWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
686   {
687     const int antiAliasingMode = AWorkspace->AntiAliasingMode();
688
689     if ( !myAntiAliasing )
690     {
691       glDisable(GL_POINT_SMOOTH);
692       glDisable(GL_LINE_SMOOTH);
693       if( antiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
694       glBlendFunc (GL_ONE, GL_ZERO);
695       glDisable (GL_BLEND);
696     }
697     else
698     {
699       glEnable(GL_POINT_SMOOTH);
700       glEnable(GL_LINE_SMOOTH);
701       if( antiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
702       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
703       glEnable (GL_BLEND);
704     }
705   }
706
707   myZLayers.Render (AWorkspace);
708
709   //TsmPopAttri(); /* restore previous graphics context; before update lights */
710   glPopAttrib();
711 }
712
713 /*----------------------------------------------------------------------*/
714
715 //call_togl_redraw_layer2d
716 void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintContext,
717                                  const Graphic3d_CView&               ACView,
718                                  const Aspect_CLayer2d&               ACLayer)
719 {
720   if (&ACLayer == NULL
721    || ACLayer.ptrLayer == NULL
722    || ACLayer.ptrLayer->listIndex == 0) return;
723
724   GLsizei dispWidth  = (GLsizei )ACLayer.viewport[0];
725   GLsizei dispHeight = (GLsizei )ACLayer.viewport[1];
726
727   glMatrixMode( GL_MODELVIEW );
728   glPushMatrix ();
729   glLoadIdentity ();
730
731   glMatrixMode (GL_PROJECTION);
732   glPushMatrix ();
733   glLoadIdentity ();
734
735   if (!ACLayer.sizeDependent)
736     glViewport (0, 0, dispWidth, dispHeight);
737
738   float left = ACLayer.ortho[0];
739   float right = ACLayer.ortho[1];
740   float bottom = ACLayer.ortho[2];
741   float top = ACLayer.ortho[3];
742
743   int attach = ACLayer.attach;
744
745   float ratio;
746   if (!ACLayer.sizeDependent)
747     ratio = (float) dispWidth/dispHeight;
748   else
749     ratio = ACView.DefWindow.dx/ACView.DefWindow.dy;
750
751   float delta;
752   if (ratio >= 1.0) {
753     delta = (float )((top - bottom)/2.0);
754     switch (attach) {
755       case 0: /* Aspect_TOC_BOTTOM_LEFT */
756         top = bottom + 2*delta/ratio;
757         break;
758       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
759         top = bottom + 2*delta/ratio;
760         break;
761       case 2: /* Aspect_TOC_TOP_LEFT */
762         bottom = top - 2*delta/ratio;
763         break;
764       case 3: /* Aspect_TOC_TOP_RIGHT */
765         bottom = top - 2*delta/ratio;
766         break;
767     }
768   }
769   else {
770     delta = (float )((right - left)/2.0);
771     switch (attach) {
772       case 0: /* Aspect_TOC_BOTTOM_LEFT */
773         right = left + 2*delta*ratio;
774         break;
775       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
776         left = right - 2*delta*ratio;
777         break;
778       case 2: /* Aspect_TOC_TOP_LEFT */
779         right = left + 2*delta*ratio;
780         break;
781       case 3: /* Aspect_TOC_TOP_RIGHT */
782         left = right - 2*delta*ratio;
783         break;
784     }
785   }
786
787 #ifdef _WIN32
788   // Check printer context that exists only for print operation
789   if (!thePrintContext.IsNull())
790   {
791     // additional transformation matrix could be applied to
792     // render only those parts of viewport that will be
793     // passed to a printer as a current "frame" to provide
794     // tiling; scaling of graphics by matrix helps render a
795     // part of a view (frame) in same viewport, but with higher
796     // resolution
797     thePrintContext->LoadProjTransformation();
798
799     // printing operation also assumes other viewport dimension
800     // to comply with transformation matrix or graphics scaling
801     // factors for tiling for layer redraw
802     GLsizei anViewportX = 0;
803     GLsizei anViewportY = 0;
804     thePrintContext->GetLayerViewport (anViewportX, anViewportY);
805     if (anViewportX != 0 && anViewportY != 0)
806       glViewport (0, 0, anViewportX, anViewportY);
807   }
808 #endif
809
810   glOrtho (left, right, bottom, top, -1.0, 1.0);
811
812   glPushAttrib (
813     GL_LIGHTING_BIT | GL_LINE_BIT | GL_POLYGON_BIT |
814     GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT );
815
816   glDisable (GL_DEPTH_TEST);
817   glDisable (GL_TEXTURE_1D);
818   glDisable (GL_TEXTURE_2D);
819   glDisable (GL_LIGHTING);
820
821   // TODO: Obsolete code, the display list is always empty now, to be removed
822   glCallList (ACLayer.ptrLayer->listIndex);
823
824   //calling dynamic render of LayerItems
825   if ( ACLayer.ptrLayer->layerData )
826   {
827     InitLayerProp (ACLayer.ptrLayer->listIndex);
828     ((Visual3d_Layer*)ACLayer.ptrLayer->layerData)->RenderLayerItems();
829     InitLayerProp (0);
830   }
831
832   glPopAttrib ();
833
834   glMatrixMode (GL_PROJECTION);
835   glPopMatrix ();
836
837   glMatrixMode( GL_MODELVIEW );
838   glPopMatrix ();
839
840   if (!ACLayer.sizeDependent)
841     glViewport (0, 0, (GLsizei) ACView.DefWindow.dx, (GLsizei) ACView.DefWindow.dy);
842
843   glFlush ();
844 }
845
846 /*----------------------------------------------------------------------*/
847
848 void OpenGl_View::RedrawTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
849 {
850   // display global trihedron
851   if (myTrihedron != NULL)
852   {
853     myTrihedron->Render (theWorkspace);
854   }
855   if (myGraduatedTrihedron != NULL)
856   {
857     myGraduatedTrihedron->Render (theWorkspace);
858   }
859 }
860
861 /*----------------------------------------------------------------------*/
862
863 //call_togl_create_bg_texture
864 void OpenGl_View::CreateBackgroundTexture (const Standard_CString  theFilePath,
865                                            const Aspect_FillMethod theFillStyle)
866 {
867   if (myBgTexture.TexId != 0)
868   {
869     // delete existing texture
870     glDeleteTextures (1, (GLuint* )&(myBgTexture.TexId));
871     myBgTexture.TexId = 0;
872   }
873
874   // load image from file
875   Image_AlienPixMap anImageLoaded;
876   if (!anImageLoaded.Load (theFilePath))
877   {
878     return;
879   }
880
881   Image_PixMap anImage;
882   if (anImageLoaded.RowExtraBytes() == 0 &&
883       (anImageLoaded.Format() == Image_PixMap::ImgRGB
884     || anImageLoaded.Format() == Image_PixMap::ImgRGB32
885     || anImageLoaded.Format() == Image_PixMap::ImgRGBA))
886   {
887     anImage.InitWrapper (anImageLoaded.Format(), anImageLoaded.ChangeData(),
888                          anImageLoaded.SizeX(), anImageLoaded.SizeY(), anImageLoaded.SizeRowBytes());
889   }
890   else
891   {
892     // convert image to RGB format
893     if (!anImage.InitTrash (Image_PixMap::ImgRGB, anImageLoaded.SizeX(), anImageLoaded.SizeY()))
894     {
895       return;
896     }
897
898     anImage.SetTopDown (false);
899     Quantity_Color aSrcColor;
900     for (Standard_Size aRow = 0; aRow < anImage.SizeY(); ++aRow)
901     {
902       for (Standard_Size aCol = 0; aCol < anImage.SizeX(); ++aCol)
903       {
904         aSrcColor = anImageLoaded.PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
905         Image_ColorRGB& aColor = anImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
906         aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
907         aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
908         aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
909       }
910     }
911     anImageLoaded.Clear();
912   }
913
914   // create MipMapped texture
915   glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
916
917   GLuint aTextureId = 0;
918   glGenTextures (1, &aTextureId);
919   glBindTexture (GL_TEXTURE_2D, aTextureId);
920
921   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_REPEAT);
922   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_REPEAT);
923   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
924   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
925
926   const GLenum aDataFormat = (anImage.Format() == Image_PixMap::ImgRGB) ? GL_RGB : GL_RGBA;
927   gluBuild2DMipmaps (GL_TEXTURE_2D, 3/*4*/,
928                      GLint(anImage.SizeX()), GLint(anImage.SizeY()),
929                      aDataFormat, GL_UNSIGNED_BYTE, anImage.Data());
930
931   myBgTexture.TexId  = aTextureId;
932   myBgTexture.Width  = (Standard_Integer )anImage.SizeX();
933   myBgTexture.Height = (Standard_Integer )anImage.SizeY();
934   myBgTexture.Style  = theFillStyle;
935 }
936
937 /*----------------------------------------------------------------------*/
938
939 //call_togl_set_bg_texture_style
940 void OpenGl_View::SetBackgroundTextureStyle (const Aspect_FillMethod AFillStyle)
941 {
942   myBgTexture.Style = AFillStyle;
943 }
944
945 /*----------------------------------------------------------------------*/
946
947 //call_togl_gradient_background
948 void OpenGl_View::SetBackgroundGradient (const Quantity_Color& AColor1,
949                                         const Quantity_Color& AColor2,
950                                         const Aspect_GradientFillMethod AType)
951 {
952   Standard_Real R,G,B;
953   AColor1.Values( R, G, B, Quantity_TOC_RGB );
954   myBgGradient.color1.rgb[0] = ( Tfloat )R;
955   myBgGradient.color1.rgb[1] = ( Tfloat )G;
956   myBgGradient.color1.rgb[2] = ( Tfloat )B;
957   myBgGradient.color1.rgb[3] = 0.F;
958
959   AColor2.Values( R, G, B, Quantity_TOC_RGB );
960   myBgGradient.color2.rgb[0] = ( Tfloat )R;
961   myBgGradient.color2.rgb[1] = ( Tfloat )G;
962   myBgGradient.color2.rgb[2] = ( Tfloat )B;
963   myBgGradient.color2.rgb[3] = 0.F;
964
965   myBgGradient.type = AType;
966 }
967
968 /*----------------------------------------------------------------------*/
969
970 //call_togl_set_gradient_type
971 void OpenGl_View::SetBackgroundGradientType (const Aspect_GradientFillMethod AType)
972 {
973   myBgGradient.type = AType;
974 }
975
976 //=======================================================================
977 //function : AddZLayer
978 //purpose  :
979 //=======================================================================
980
981 void OpenGl_View::AddZLayer (const Standard_Integer theLayerId)
982 {
983   myZLayers.AddLayer (theLayerId);
984 }
985
986 //=======================================================================
987 //function : RemoveZLayer
988 //purpose  :
989 //=======================================================================
990
991 void OpenGl_View::RemoveZLayer (const Standard_Integer theLayerId)
992 {
993   myZLayers.RemoveLayer (theLayerId);
994 }
995
996 //=======================================================================
997 //function : DisplayStructure
998 //purpose  :
999 //=======================================================================
1000
1001 void OpenGl_View::DisplayStructure (const OpenGl_Structure *theStructure,
1002                                     const Standard_Integer  thePriority)
1003 {
1004   Standard_Integer aZLayer = theStructure->GetZLayer ();
1005   myZLayers.AddStructure (theStructure, aZLayer, thePriority);
1006 }
1007
1008 //=======================================================================
1009 //function : DisplayImmediateStructure
1010 //purpose  :
1011 //=======================================================================
1012
1013 void OpenGl_View::DisplayImmediateStructure (const OpenGl_Structure* theStructure)
1014 {
1015   for (OpenGl_SequenceOfStructure::Iterator anIter (myImmediateList);
1016        anIter.More(); anIter.Next())
1017   {
1018     if (anIter.Value() == theStructure)
1019     {
1020       return;
1021     }
1022   }
1023
1024   myImmediateList.Append (theStructure);
1025 }
1026
1027 //=======================================================================
1028 //function : EraseStructure
1029 //purpose  :
1030 //=======================================================================
1031
1032 void OpenGl_View::EraseStructure (const OpenGl_Structure *theStructure)
1033 {
1034   Standard_Integer aZLayer = theStructure->GetZLayer ();
1035   myZLayers.RemoveStructure (theStructure, aZLayer);
1036 }
1037
1038 //=======================================================================
1039 //function : EraseImmediateStructure
1040 //purpose  :
1041 //=======================================================================
1042
1043 void OpenGl_View::EraseImmediateStructure (const OpenGl_Structure* theStructure)
1044 {
1045   for (OpenGl_SequenceOfStructure::Iterator anIter (myImmediateList);
1046        anIter.More(); anIter.Next())
1047   {
1048     if (anIter.Value() == theStructure)
1049     {
1050       myImmediateList.Remove (anIter);
1051       return;
1052     }
1053   }
1054 }
1055
1056 //=======================================================================
1057 //function : ChangeZLayer
1058 //purpose  :
1059 //=======================================================================
1060
1061 void OpenGl_View::ChangeZLayer (const OpenGl_Structure *theStructure,
1062                                 const Standard_Integer  theNewLayerId)
1063 {
1064   Standard_Integer anOldLayer = theStructure->GetZLayer ();
1065   myZLayers.ChangeLayer (theStructure, anOldLayer, theNewLayerId);
1066 }
1067
1068 //=======================================================================
1069 //function : SetZLayerSettings
1070 //purpose  :
1071 //=======================================================================
1072 void OpenGl_View::SetZLayerSettings (const Standard_Integer theLayerId,
1073                                      const Graphic3d_ZLayerSettings theSettings)
1074 {
1075   myZLayers.Layer (theLayerId).SetLayerSettings (theSettings);
1076 }
1077
1078 //=======================================================================
1079 //function : ChangePriority
1080 //purpose  :
1081 //=======================================================================
1082 void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure,
1083                                   const Standard_Integer theNewPriority)
1084 {
1085   Standard_Integer aLayerId = theStructure->GetZLayer();
1086   myZLayers.ChangePriority (theStructure, aLayerId, theNewPriority);
1087 }
1088
1089 //=======================================================================
1090 //function : RedrawScene
1091 //purpose  :
1092 //=======================================================================
1093
1094 void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintContext,
1095                                const Handle(OpenGl_Workspace)& theWorkspace,
1096                                const OpenGl_Matrix* theProjection,
1097                                const OpenGl_Matrix* theOrientation)
1098 {
1099   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
1100
1101   if (myZClip.Back.IsOn || myZClip.Front.IsOn)
1102   {
1103     Handle(Graphic3d_ClipPlane) aPlaneBack;
1104     Handle(Graphic3d_ClipPlane) aPlaneFront;
1105
1106     if (myZClip.Back.IsOn)
1107     {
1108       Standard_Real aClipBackConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1109       if (myCamera->ZFar() < aClipBackConverted)
1110       {
1111         aClipBackConverted = myCamera->ZFar();
1112         myZClip.Back.Limit = (Standard_ShortReal )(aClipBackConverted - myCamera->Distance());
1113       }
1114       const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, (Standard_ShortReal )aClipBackConverted);
1115       aPlaneBack = new Graphic3d_ClipPlane (aBackEquation);
1116     }
1117
1118     if (myZClip.Front.IsOn)
1119     {
1120       Standard_Real aClipFrontConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1121       if (myCamera->ZNear() > aClipFrontConverted)
1122       {
1123         aClipFrontConverted = myCamera->ZNear();
1124         myZClip.Front.Limit = (Standard_ShortReal )(aClipFrontConverted - myCamera->Distance());
1125       }
1126       const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, (Standard_ShortReal )-aClipFrontConverted);
1127       aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation);
1128     }
1129
1130     // do some "memory allocation"-wise optimization
1131     if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull())
1132     {
1133       Graphic3d_SequenceOfHClipPlane aSlicingPlanes;
1134       if (!aPlaneBack.IsNull())
1135       {
1136         aSlicingPlanes.Append (aPlaneBack);
1137       }
1138
1139       if (!aPlaneFront.IsNull())
1140       {
1141         aSlicingPlanes.Append (aPlaneFront);
1142       }
1143
1144       // add planes at loaded view matrix state
1145       aContext->ChangeClipping().AddView (aSlicingPlanes, theWorkspace);
1146     }
1147   }
1148
1149   // Apply user clipping planes
1150   if (!myClipPlanes.IsEmpty())
1151   {
1152     Graphic3d_SequenceOfHClipPlane aUserPlanes;
1153     Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes);
1154     for (; aClippingIt.More(); aClippingIt.Next())
1155     {
1156       const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
1157       if (aClipPlane->IsOn())
1158       {
1159         aUserPlanes.Append (aClipPlane);
1160       }
1161     }
1162
1163     if (!aUserPlanes.IsEmpty())
1164     {
1165       // add planes at actual matrix state.
1166       aContext->ChangeClipping().AddWorld (aUserPlanes);
1167     }
1168
1169     if (!aContext->ShaderManager()->IsEmpty())
1170     {
1171       aContext->ShaderManager()->UpdateClippingState();
1172     }
1173   }
1174
1175   // Setup view projection
1176   glMatrixMode (GL_PROJECTION);
1177
1178 #ifdef _WIN32
1179   // add printing scale/tiling transformation
1180   if (!thePrintContext.IsNull())
1181   {
1182     thePrintContext->LoadProjTransformation();
1183   }
1184   else
1185 #endif
1186     glLoadIdentity();
1187
1188   glMultMatrixf ((const GLfloat*)theProjection);
1189
1190   if (!thePrintContext.IsNull())
1191   {
1192     // update shader uniform projection matrix with new data
1193     Tmatrix3 aResultProjection;
1194     glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection);
1195     aContext->ShaderManager()->UpdateProjectionStateTo (&aResultProjection);
1196
1197     // force shader uniform restore on next frame
1198     myProjectionState = 0; 
1199   }
1200
1201   // Setup view orientation
1202   theWorkspace->SetViewMatrix (theOrientation);
1203
1204   // Apply Lights
1205   {
1206     // setup lights
1207     Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0],
1208                                    THE_DEFAULT_AMBIENT[1],
1209                                    THE_DEFAULT_AMBIENT[2],
1210                                    THE_DEFAULT_AMBIENT[3]);
1211     GLenum aLightGlId = GL_LIGHT0;
1212     for (OpenGl_ListOfLight::Iterator aLightIt (myLights);
1213          aLightIt.More(); aLightIt.Next())
1214     {
1215       bind_light (aLightIt.Value(), aLightGlId, anAmbientColor);
1216     }
1217
1218     // apply accumulated ambient color
1219     anAmbientColor.a() = 1.0f;
1220     glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData());
1221
1222     if (aLightGlId != GL_LIGHT0)
1223     {
1224       glEnable (GL_LIGHTING);
1225     }
1226     // switch off unused lights
1227     for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
1228     {
1229       glDisable (aLightGlId);
1230     }
1231   }
1232
1233   // Clear status bitfields
1234   theWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
1235
1236   // Added PCT for handling of textures
1237   switch (mySurfaceDetail)
1238   {
1239     case Visual3d_TOD_NONE:
1240       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1241       theWorkspace->DisableTexture();
1242       // Render the view
1243       RenderStructs (theWorkspace);
1244       break;
1245
1246     case Visual3d_TOD_ENVIRONMENT:
1247       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1248       theWorkspace->EnableTexture (myTextureEnv);
1249       // Render the view
1250       RenderStructs (theWorkspace);
1251       theWorkspace->DisableTexture();
1252       break;
1253
1254     case Visual3d_TOD_ALL:
1255       // First pass
1256       theWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
1257       // Render the view
1258       RenderStructs (theWorkspace);
1259       theWorkspace->DisableTexture();
1260
1261       // Second pass
1262       if (theWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
1263       {
1264         theWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
1265         theWorkspace->EnableTexture (myTextureEnv);
1266
1267         // Remember OpenGl properties
1268         GLint aSaveBlendDst, aSaveBlendSrc;
1269         GLint aSaveZbuffFunc;
1270         GLboolean aSaveZbuffWrite;
1271         glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite);
1272         glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc);
1273         glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst);
1274         glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc);
1275         GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST);
1276         GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND);
1277
1278         // Change the properties for second rendering pass
1279         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1280         glEnable (GL_BLEND);
1281
1282         glDepthFunc (GL_EQUAL);
1283         glDepthMask (GL_FALSE);
1284         glEnable (GL_DEPTH_TEST);
1285
1286         theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1287
1288         // Render the view
1289         RenderStructs (theWorkspace);
1290         theWorkspace->DisableTexture();
1291
1292         // Restore properties back
1293         glBlendFunc (aSaveBlendSrc, aSaveBlendDst);
1294         if (!wasBlendEnabled)
1295           glDisable (GL_BLEND);
1296
1297         glDepthFunc (aSaveZbuffFunc);
1298         glDepthMask (aSaveZbuffWrite);
1299         if (!wasZbuffEnabled)
1300           glDisable (GL_DEPTH_FUNC);
1301       }
1302       break;
1303   }
1304 }