0025475: Visualization, TKOpenGl - draw background using primitive arrays
[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 <Graphic3d_TextureParams.hxx>
23 #include <Graphic3d_Texture2Dmanual.hxx>
24 #include <Image_AlienPixMap.hxx>
25 #include <Visual3d_Layer.hxx>
26
27 #include <NCollection_Mat4.hxx>
28
29 #include <OpenGl_AspectLine.hxx>
30 #include <OpenGl_Context.hxx>
31 #include <OpenGl_Matrix.hxx>
32 #include <OpenGl_Workspace.hxx>
33 #include <OpenGl_View.hxx>
34 #include <OpenGl_Trihedron.hxx>
35 #include <OpenGl_GraduatedTrihedron.hxx>
36 #include <OpenGl_PrimitiveArray.hxx>
37 #include <OpenGl_PrinterContext.hxx>
38 #include <OpenGl_ShaderManager.hxx>
39 #include <OpenGl_ShaderProgram.hxx>
40 #include <OpenGl_Structure.hxx>
41
42 #define EPSI 0.0001
43
44 namespace
45 {
46
47   static const GLfloat THE_DEFAULT_AMBIENT[4]    = { 0.0f, 0.0f, 0.0f, 1.0f };
48   static const GLfloat THE_DEFAULT_SPOT_DIR[3]   = { 0.0f, 0.0f, -1.0f };
49   static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
50   static const GLfloat THE_DEFAULT_SPOT_CUTOFF   = 180.0f;
51
52 };
53
54 extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx
55
56 /*----------------------------------------------------------------------*/
57
58 struct OPENGL_CLIP_PLANE
59 {
60   GLboolean isEnabled;
61   GLdouble Equation[4];
62   DEFINE_STANDARD_ALLOC
63 };
64
65 /*----------------------------------------------------------------------*/
66 /*
67 * Fonctions privees
68 */
69
70 #if !defined(GL_ES_VERSION_2_0)
71 /*-----------------------------------------------------------------*/
72 /*
73 *  Set des lumieres
74 */
75 static void bindLight (const OpenGl_Light&             theLight,
76                        GLenum&                         theLightGlId,
77                        Graphic3d_Vec4&                 theAmbientColor,
78                        const Handle(OpenGl_Workspace)& theWorkspace)
79 {
80   // Only 8 lights in OpenGL...
81   if (theLightGlId > GL_LIGHT7)
82   {
83     return;
84   }
85
86   if (theLight.Type == Visual3d_TOLS_AMBIENT)
87   {
88     // add RGBA intensity of the ambient light
89     theAmbientColor += theLight.Color;
90     return;
91   }
92
93   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
94
95   // the light is a headlight?
96   if (theLight.IsHeadlight)
97   {
98
99     aContext->WorldViewState.Push();
100     aContext->WorldViewState.SetIdentity();
101
102     aContext->ApplyWorldViewMatrix();
103   }
104
105   // setup light type
106   switch (theLight.Type)
107   {
108     case Visual3d_TOLS_DIRECTIONAL:
109     {
110       // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
111       const OpenGl_Vec4 anInfDir = -theLight.Direction;
112
113       // to create a realistic effect,  set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
114       glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
115       glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
116       glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
117       glLightfv (theLightGlId, GL_POSITION,              anInfDir.GetData());
118       glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
119       glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
120       glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
121       break;
122     }
123     case Visual3d_TOLS_POSITIONAL:
124     {
125       // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
126       glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
127       glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
128       glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
129       glLightfv (theLightGlId, GL_POSITION,              theLight.Position.GetData());
130       glLightfv (theLightGlId, GL_SPOT_DIRECTION,        THE_DEFAULT_SPOT_DIR);
131       glLightf  (theLightGlId, GL_SPOT_EXPONENT,         THE_DEFAULT_SPOT_EXPONENT);
132       glLightf  (theLightGlId, GL_SPOT_CUTOFF,           THE_DEFAULT_SPOT_CUTOFF);
133       glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
134       glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
135       glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
136       break;
137     }
138     case Visual3d_TOLS_SPOT:
139     {
140       glLightfv (theLightGlId, GL_AMBIENT,               THE_DEFAULT_AMBIENT);
141       glLightfv (theLightGlId, GL_DIFFUSE,               theLight.Color.GetData());
142       glLightfv (theLightGlId, GL_SPECULAR,              theLight.Color.GetData());
143       glLightfv (theLightGlId, GL_POSITION,              theLight.Position.GetData());
144       glLightfv (theLightGlId, GL_SPOT_DIRECTION,        theLight.Direction.GetData());
145       glLightf  (theLightGlId, GL_SPOT_EXPONENT,         theLight.Concentration() * 128.0f);
146       glLightf  (theLightGlId, GL_SPOT_CUTOFF,          (theLight.Angle() * 180.0f) / GLfloat(M_PI));
147       glLightf  (theLightGlId, GL_CONSTANT_ATTENUATION,  theLight.ConstAttenuation());
148       glLightf  (theLightGlId, GL_LINEAR_ATTENUATION,    theLight.LinearAttenuation());
149       glLightf  (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
150       break;
151     }
152   }
153
154   // restore matrix in case of headlight
155   if (theLight.IsHeadlight)
156   {
157     aContext->WorldViewState.Pop();
158   }
159
160   glEnable (theLightGlId++);
161 }
162 #endif
163
164 /*----------------------------------------------------------------------*/
165
166 void OpenGl_View::DrawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
167 {
168   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
169
170   if ((theWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) != 0 // no background
171     || (!myBgTextureArray->IsDefined()                       // no texture
172      && !myBgGradientArray->IsDefined()))                    // no gradient
173   {
174     return;
175   }
176
177   aCtx->core11fwd->glDisable (GL_DEPTH_TEST);
178
179   aCtx->WorldViewState.Push();
180   aCtx->ProjectionState.Push();
181   aCtx->WorldViewState.SetIdentity();
182   aCtx->ProjectionState.SetIdentity();
183   aCtx->ApplyProjectionMatrix();
184   aCtx->ApplyWorldViewMatrix();
185
186   // Drawing background gradient if:
187   // - gradient fill type is not Aspect_GFM_NONE and
188   // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
189   if (myBgGradientArray->IsDefined()
190     && (!myBgTextureArray->IsDefined()
191       || myBgTextureArray->TextureFillMethod() == Aspect_FM_CENTERED
192       || myBgTextureArray->TextureFillMethod() == Aspect_FM_NONE))
193   {
194   #if !defined(GL_ES_VERSION_2_0)
195     GLint aShadingModelOld = GL_SMOOTH;
196     if (aCtx->core11 != NULL)
197     {
198       aCtx->core11fwd->glDisable (GL_LIGHTING);
199       aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld);
200       aCtx->core11->glShadeModel (GL_SMOOTH);
201     }
202   #endif
203
204     if (myBgGradientArray->IsDataChanged())
205     {
206       myBgGradientArray->Init (theWorkspace);
207     }
208
209     myBgGradientArray->Render (theWorkspace);
210
211   #if !defined(GL_ES_VERSION_2_0)
212     if (aCtx->core11 != NULL)
213     {
214       aCtx->core11->glShadeModel (aShadingModelOld);
215     }
216   #endif
217   }
218
219   // Drawing background image if it is defined
220   // (texture is defined and fill type is not Aspect_FM_NONE)
221   if (myBgTextureArray->IsDefined()
222    && myTextureParams->DoTextureMap())
223   {
224     aCtx->core11fwd->glDisable (GL_BLEND);
225
226     const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams);
227
228     if (myBgTextureArray->IsDataChanged()
229      || myBgTextureArray->IsViewSizeChanged (theWorkspace))
230     {
231       myBgTextureArray->Init (theWorkspace);
232     }
233
234     myBgTextureArray->Render (theWorkspace);
235
236     // restore aspects
237     theWorkspace->SetAspectFace (anOldAspectFace);
238   }
239
240   aCtx->WorldViewState.Pop();
241   aCtx->ProjectionState.Pop();
242   aCtx->ApplyProjectionMatrix();
243
244   if (theWorkspace->UseZBuffer())
245   {
246     aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
247   }
248 }
249
250 /*----------------------------------------------------------------------*/
251
252 //call_func_redraw_all_structs_proc
253 void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
254                           const Handle(OpenGl_Workspace)&      theWorkspace,
255                           const Graphic3d_CView&               theCView,
256                           const Aspect_CLayer2d&               theCUnderLayer,
257                           const Aspect_CLayer2d&               theCOverLayer,
258                           const Standard_Boolean               theToDrawImmediate)
259 {
260   // ==================================
261   //      Step 1: Prepare for redraw
262   // ==================================
263
264   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
265
266 #if !defined(GL_ES_VERSION_2_0)
267   // store and disable current clipping planes
268   const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
269   NCollection_Array1<OPENGL_CLIP_PLANE> aOldPlanes (GL_CLIP_PLANE0, GL_CLIP_PLANE0 + aMaxPlanes - 1);
270   if (aContext->core11 != NULL)
271   {
272     for (Standard_Integer aClipPlaneId = aOldPlanes.Lower(); aClipPlaneId <= aOldPlanes.Upper(); ++aClipPlaneId)
273     {
274       OPENGL_CLIP_PLANE& aPlane = aOldPlanes.ChangeValue (aClipPlaneId);
275       aContext->core11->glGetClipPlane (aClipPlaneId, aPlane.Equation);
276       if (aPlane.isEnabled)
277       {
278         aContext->core11fwd->glDisable (aClipPlaneId);
279         aPlane.isEnabled = GL_TRUE;
280       }
281       else
282       {
283         aPlane.isEnabled = GL_FALSE;
284       }
285     }
286   }
287 #endif
288
289   // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm).
290   Standard_Boolean isProjectionMatUpdateNeeded  = Standard_False;
291   Standard_Boolean isOrientationMatUpdateNeeded = Standard_False;
292   if (myBVHSelector.ProjectionState() != myCamera->ProjectionState())
293   {
294     isProjectionMatUpdateNeeded = Standard_True;
295     myBVHSelector.ChangeProjectionState() = myCamera->ProjectionState();
296   }
297   if (myBVHSelector.ModelViewState() != myCamera->ModelViewState())
298   {
299     isOrientationMatUpdateNeeded = Standard_True;
300     myBVHSelector.ChangeModelViewState() = myCamera->ModelViewState();
301   }
302
303   if (isProjectionMatUpdateNeeded
304    || isOrientationMatUpdateNeeded)
305   {
306     myBVHSelector.SetViewVolume (myCamera);
307   }
308
309   const Handle(OpenGl_ShaderManager) aManager   = aContext->ShaderManager();
310   const Standard_Boolean             isSameView = aManager->IsSameView (this); // force camera state update when needed
311   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
312   {
313     aManager->UpdateLightSourceStateTo (&myLights);
314     myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
315   }
316
317   if (myProjectionState != myCamera->ProjectionState()
318   || !isSameView)
319   {
320     myProjectionState = myCamera->ProjectionState();
321     aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF());
322     aContext->ApplyProjectionMatrix();
323   }
324
325   if (myModelViewState != myCamera->ModelViewState()
326   || !isSameView)
327   {
328     myModelViewState = myCamera->ModelViewState();
329     aContext->WorldViewState.SetCurrent (myCamera->OrientationMatrixF());
330     aContext->ApplyWorldViewMatrix();
331   }
332
333   if (aManager->ModelWorldState().Index() == 0)
334   {
335     aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
336   }
337
338   // ====================================
339   //      Step 2: Redraw background
340   // ====================================
341
342   // Render background
343   if (theWorkspace->ToRedrawGL()
344   && !theToDrawImmediate)
345   {
346     DrawBackground (theWorkspace);
347   }
348
349 #if !defined(GL_ES_VERSION_2_0)
350   // Switch off lighting by default
351   glDisable(GL_LIGHTING);
352 #endif
353
354   // =================================
355   //      Step 3: Draw underlayer
356   // =================================
357   if (!theToDrawImmediate)
358   {
359     RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCUnderLayer);
360   }
361
362   // =================================
363   //      Step 4: Redraw main plane
364   // =================================
365
366   // Setup face culling
367   GLboolean isCullFace = GL_FALSE;
368   if ( myBackfacing )
369   {
370     isCullFace = glIsEnabled( GL_CULL_FACE );
371     if ( myBackfacing < 0 )
372     {
373       glEnable( GL_CULL_FACE );
374       glCullFace( GL_BACK );
375     }
376     else
377       glDisable( GL_CULL_FACE );
378   }
379
380 #if !defined(GL_ES_VERSION_2_0)
381   // if the view is scaled normal vectors are scaled to unit
382   // length for correct displaying of shaded objects
383   const gp_Pnt anAxialScale = myCamera->AxialScale();
384   if (anAxialScale.X() != 1.F ||
385       anAxialScale.Y() != 1.F ||
386       anAxialScale.Z() != 1.F)
387   {
388     aContext->SetGlNormalizeEnabled (Standard_True);
389   }
390   else
391   {
392     aContext->SetGlNormalizeEnabled (Standard_False);
393   }
394
395   // Apply Fog
396   if ( myFog.IsOn )
397   {
398     Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance();
399     if (myCamera->ZFar() < aFogFrontConverted)
400     {
401       aFogFrontConverted = myCamera->ZFar();
402       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
403     }
404
405     Standard_Real aFogBackConverted = (Standard_Real )myFog.Back + myCamera->Distance();
406     if (myCamera->ZFar() < aFogFrontConverted)
407     {
408       aFogBackConverted = myCamera->ZFar();
409       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
410     }
411
412     if (aFogFrontConverted > aFogBackConverted)
413     {
414       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
415       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
416     }
417
418     glFogi(GL_FOG_MODE, GL_LINEAR);
419     glFogf(GL_FOG_START, (Standard_ShortReal )aFogFrontConverted);
420     glFogf(GL_FOG_END, (Standard_ShortReal )aFogBackConverted);
421     glFogfv(GL_FOG_COLOR, myFog.Color.rgb);
422     glEnable(GL_FOG);
423   }
424   else
425     glDisable(GL_FOG);
426
427   // Apply InteriorShadingMethod
428   aContext->core11->glShadeModel (myShadingModel == Visual3d_TOM_FACET
429                                || myShadingModel == Visual3d_TOM_NONE ? GL_FLAT : GL_SMOOTH);
430 #endif
431
432   aManager->SetShadingModel (myShadingModel);
433
434   // Apply AntiAliasing
435   if (myAntiAliasing)
436     theWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
437   else
438     theWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
439
440   if (!aManager->IsEmpty())
441   {
442     aManager->UpdateClippingState();
443   }
444
445   // Redraw 3d scene
446   if (!myCamera->IsStereo() || !aContext->HasStereoBuffers())
447   {
448     // single-pass monographic rendering
449     // redraw scene with normal orientation and projection
450     RedrawScene (thePrintContext, theWorkspace, theToDrawImmediate);
451   }
452   else
453   {
454     // two stereographic passes
455
456     // safely switch to left Eye buffer
457     aContext->SetDrawBufferLeft();
458
459     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
460     aContext->ApplyProjectionMatrix();
461
462     // redraw left Eye
463     RedrawScene (thePrintContext, theWorkspace, theToDrawImmediate);
464
465     // reset depth buffer of first rendering pass
466     if (theWorkspace->UseDepthTest())
467     {
468       glClear (GL_DEPTH_BUFFER_BIT);
469     }
470     // safely switch to right Eye buffer
471     aContext->SetDrawBufferRight();
472
473     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
474     aContext->ApplyProjectionMatrix();
475
476     // redraw right Eye
477     RedrawScene (thePrintContext, theWorkspace, theToDrawImmediate);
478
479     // switch back to monographic rendering
480     aContext->SetDrawBufferMono();
481   }
482
483   // ===============================
484   //      Step 5: Trihedron
485   // ===============================
486
487   // Resetting GL parameters according to the default aspects
488   // in order to synchronize GL state with the graphic driver state
489   // before drawing auxiliary stuff (trihedrons, overlayer)
490   // and invoking optional callbacks
491   theWorkspace->ResetAppliedAspect();
492
493   aContext->ChangeClipping().RemoveAll();
494
495   if (!aManager->IsEmpty())
496   {
497     aManager->ResetMaterialStates();
498     aManager->RevertClippingState();
499
500     // We need to disable (unbind) all shaders programs to ensure
501     // that all objects without specified aspect will be drawn
502     // correctly (such as background)
503     aContext->BindProgram (NULL);
504   }
505
506   // Render trihedron
507   if (theWorkspace->ToRedrawGL()
508   && !theToDrawImmediate)
509   {
510     RedrawTrihedron (theWorkspace);
511
512     // Restore face culling
513     if ( myBackfacing )
514     {
515       if ( isCullFace )
516       {
517         glEnable   ( GL_CULL_FACE );
518         glCullFace ( GL_BACK      );
519       }
520       else
521         glDisable ( GL_CULL_FACE );
522     }
523   }
524
525   // ===============================
526   //      Step 6: Redraw overlay
527   // ===============================
528   if (!theToDrawImmediate)
529   {
530     const int aMode = 0;
531     theWorkspace->DisplayCallback (theCView, (aMode | OCC_PRE_OVERLAY));
532
533     RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCOverLayer);
534
535     theWorkspace->DisplayCallback (theCView, aMode);
536   }
537
538   // ===============================
539   //      Step 7: Finalize
540   // ===============================
541
542 #if !defined(GL_ES_VERSION_2_0)
543   // restore clipping planes
544   if (aContext->core11 != NULL)
545   {
546     for (Standard_Integer aClipPlaneId = aOldPlanes.Lower(); aClipPlaneId <= aOldPlanes.Upper(); ++aClipPlaneId)
547     {
548       const OPENGL_CLIP_PLANE& aPlane = aOldPlanes.ChangeValue (aClipPlaneId);
549       aContext->core11->glClipPlane (aClipPlaneId, aPlane.Equation);
550       if (aPlane.isEnabled)
551         aContext->core11fwd->glEnable (aClipPlaneId);
552       else
553         aContext->core11fwd->glDisable (aClipPlaneId);
554     }
555   }
556 #endif
557
558   // ==============================================================
559   //      Step 8: Keep shader manager informed about last View
560   // ==============================================================
561
562   if (!aManager.IsNull())
563   {
564     aManager->SetLastView (this);
565   }
566 }
567
568 // =======================================================================
569 // function : InvalidateBVHData
570 // purpose  :
571 // =======================================================================
572 void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
573 {
574   myZLayers.InvalidateBVHData (theLayerId);
575 }
576
577 /*----------------------------------------------------------------------*/
578
579 //ExecuteViewDisplay
580 void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace)& AWorkspace,
581                                  const Standard_Boolean          theToDrawImmediate)
582 {
583   if ( myZLayers.NbStructures() <= 0 )
584     return;
585
586 #if !defined(GL_ES_VERSION_2_0)
587   glPushAttrib ( GL_DEPTH_BUFFER_BIT );
588 #endif
589
590   //TsmPushAttri(); /* save previous graphics context */
591
592   if ( (AWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
593   {
594   #if !defined(GL_ES_VERSION_2_0)
595     const int antiAliasingMode = AWorkspace->AntiAliasingMode();
596   #endif
597
598     if ( !myAntiAliasing )
599     {
600     #if !defined(GL_ES_VERSION_2_0)
601       glDisable(GL_POINT_SMOOTH);
602       glDisable(GL_LINE_SMOOTH);
603       if( antiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
604     #endif
605       glBlendFunc (GL_ONE, GL_ZERO);
606       glDisable (GL_BLEND);
607     }
608     else
609     {
610     #if !defined(GL_ES_VERSION_2_0)
611       glEnable(GL_POINT_SMOOTH);
612       glEnable(GL_LINE_SMOOTH);
613       if( antiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
614     #endif
615       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
616       glEnable (GL_BLEND);
617     }
618   }
619
620   myZLayers.Render (AWorkspace, theToDrawImmediate);
621
622 #if !defined(GL_ES_VERSION_2_0)
623   //TsmPopAttri(); /* restore previous graphics context; before update lights */
624   glPopAttrib();
625 #endif
626 }
627
628 /*----------------------------------------------------------------------*/
629
630 //call_togl_redraw_layer2d
631 void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintContext,
632                                  const Handle(OpenGl_Workspace)&      theWorkspace,
633                                  const Graphic3d_CView&               /*ACView*/,
634                                  const Aspect_CLayer2d&               ACLayer)
635 {
636 #if !defined(GL_ES_VERSION_2_0)
637   if (&ACLayer == NULL
638    || ACLayer.ptrLayer == NULL
639    || ACLayer.ptrLayer->listIndex == 0) return;
640
641   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
642
643   GLsizei dispWidth  = (GLsizei )ACLayer.viewport[0];
644   GLsizei dispHeight = (GLsizei )ACLayer.viewport[1];
645
646   aContext->WorldViewState.Push();
647   aContext->ProjectionState.Push();
648
649   aContext->WorldViewState.SetIdentity();
650   aContext->ProjectionState.SetIdentity();
651
652   aContext->ApplyWorldViewMatrix();
653   aContext->ApplyProjectionMatrix();
654
655   if (!ACLayer.sizeDependent)
656     aContext->core11fwd->glViewport (0, 0, dispWidth, dispHeight);
657
658   float left = ACLayer.ortho[0];
659   float right = ACLayer.ortho[1];
660   float bottom = ACLayer.ortho[2];
661   float top = ACLayer.ortho[3];
662
663   int attach = ACLayer.attach;
664
665   const float ratio = !ACLayer.sizeDependent
666                     ? float(dispWidth) / float(dispHeight)
667                     : float(theWorkspace->Width()) / float(theWorkspace->Height());
668
669   float delta;
670   if (ratio >= 1.0) {
671     delta = (float )((top - bottom)/2.0);
672     switch (attach) {
673       case 0: /* Aspect_TOC_BOTTOM_LEFT */
674         top = bottom + 2*delta/ratio;
675         break;
676       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
677         top = bottom + 2*delta/ratio;
678         break;
679       case 2: /* Aspect_TOC_TOP_LEFT */
680         bottom = top - 2*delta/ratio;
681         break;
682       case 3: /* Aspect_TOC_TOP_RIGHT */
683         bottom = top - 2*delta/ratio;
684         break;
685     }
686   }
687   else {
688     delta = (float )((right - left)/2.0);
689     switch (attach) {
690       case 0: /* Aspect_TOC_BOTTOM_LEFT */
691         right = left + 2*delta*ratio;
692         break;
693       case 1: /* Aspect_TOC_BOTTOM_RIGHT */
694         left = right - 2*delta*ratio;
695         break;
696       case 2: /* Aspect_TOC_TOP_LEFT */
697         right = left + 2*delta*ratio;
698         break;
699       case 3: /* Aspect_TOC_TOP_RIGHT */
700         left = right - 2*delta*ratio;
701         break;
702     }
703   }
704
705 #ifdef _WIN32
706   // Check printer context that exists only for print operation
707   if (!thePrintContext.IsNull())
708   {
709     // additional transformation matrix could be applied to
710     // render only those parts of viewport that will be
711     // passed to a printer as a current "frame" to provide
712     // tiling; scaling of graphics by matrix helps render a
713     // part of a view (frame) in same viewport, but with higher
714     // resolution
715
716     // set printing scale/tiling transformation
717     aContext->ProjectionState.SetCurrent (thePrintContext->ProjTransformation());
718     aContext->ApplyProjectionMatrix();
719
720     // printing operation also assumes other viewport dimension
721     // to comply with transformation matrix or graphics scaling
722     // factors for tiling for layer redraw
723     GLsizei anViewportX = 0;
724     GLsizei anViewportY = 0;
725     thePrintContext->GetLayerViewport (anViewportX, anViewportY);
726     if (anViewportX != 0 && anViewportY != 0)
727       aContext->core11fwd->glViewport (0, 0, anViewportX, anViewportY);
728   }
729 #endif
730
731   glOrtho (left, right, bottom, top, -1.0, 1.0);
732
733   glPushAttrib (
734     GL_LIGHTING_BIT | GL_LINE_BIT | GL_POLYGON_BIT |
735     GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT );
736
737   glDisable (GL_DEPTH_TEST);
738   glDisable (GL_TEXTURE_1D);
739   glDisable (GL_TEXTURE_2D);
740   glDisable (GL_LIGHTING);
741
742   // TODO: Obsolete code, the display list is always empty now, to be removed
743   glCallList (ACLayer.ptrLayer->listIndex);
744
745   //calling dynamic render of LayerItems
746   if ( ACLayer.ptrLayer->layerData )
747   {
748     InitLayerProp (ACLayer.ptrLayer->listIndex);
749     ((Visual3d_Layer*)ACLayer.ptrLayer->layerData)->RenderLayerItems();
750     InitLayerProp (0);
751   }
752
753   glPopAttrib ();
754
755   aContext->WorldViewState.Pop();
756   aContext->ProjectionState.Pop();
757
758   aContext->ApplyProjectionMatrix();
759   aContext->ApplyWorldViewMatrix();
760
761   if (!ACLayer.sizeDependent)
762     aContext->core11fwd->glViewport (0, 0, theWorkspace->Width(), theWorkspace->Height());
763
764   glFlush ();
765 #endif
766 }
767
768 /*----------------------------------------------------------------------*/
769
770 void OpenGl_View::RedrawTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
771 {
772   // display global trihedron
773   if (myTrihedron != NULL)
774   {
775     myTrihedron->Render (theWorkspace);
776   }
777   if (myGraduatedTrihedron != NULL)
778   {
779     myGraduatedTrihedron->Render (theWorkspace);
780   }
781 }
782
783 /*----------------------------------------------------------------------*/
784
785 //call_togl_create_bg_texture
786 void OpenGl_View::CreateBackgroundTexture (const Standard_CString  theFilePath,
787                                            const Aspect_FillMethod theFillStyle)
788 {
789   // Prepare aspect for texture storage
790   Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
791   Handle(Graphic3d_Texture2Dmanual) aTextureMap = new Graphic3d_Texture2Dmanual (TCollection_AsciiString (theFilePath));
792   aTextureMap->EnableRepeat();
793   aTextureMap->DisableModulate();
794   aTextureMap->GetParams()->SetGenMode (Graphic3d_TOTM_MANUAL,
795                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
796                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
797   anAspect->SetTextureMap (aTextureMap);
798   anAspect->SetInteriorStyle (Aspect_IS_SOLID);
799   // Enable texture mapping
800   if (aTextureMap->IsDone())
801   {
802     anAspect->SetTextureMapOn();
803   }
804   else
805   {
806     anAspect->SetTextureMapOff();
807     return;
808
809   }
810
811   // Set texture parameters
812   myTextureParams->SetAspect (anAspect);
813
814   myBgTextureArray->SetTextureParameters (theFillStyle);
815 }
816
817 /*----------------------------------------------------------------------*/
818
819 //call_togl_set_bg_texture_style
820 void OpenGl_View::SetBackgroundTextureStyle (const Aspect_FillMethod theFillStyle)
821 {
822   myBgTextureArray->SetTextureFillMethod (theFillStyle);
823 }
824
825 /*----------------------------------------------------------------------*/
826
827 //call_togl_gradient_background
828 void OpenGl_View::SetBackgroundGradient (const Quantity_Color& theColor1,
829                                         const Quantity_Color& theColor2,
830                                         const Aspect_GradientFillMethod theType)
831 {
832   myBgGradientArray->SetGradientParameters (theColor1, theColor2, theType);
833 }
834
835 /*----------------------------------------------------------------------*/
836
837 //call_togl_set_gradient_type
838 void OpenGl_View::SetBackgroundGradientType (const Aspect_GradientFillMethod theType)
839 {
840   myBgGradientArray->SetGradientFillMethod (theType);
841 }
842
843 //=======================================================================
844 //function : AddZLayer
845 //purpose  :
846 //=======================================================================
847
848 void OpenGl_View::AddZLayer (const Graphic3d_ZLayerId theLayerId)
849 {
850   myZLayers.AddLayer (theLayerId);
851 }
852
853 //=======================================================================
854 //function : RemoveZLayer
855 //purpose  :
856 //=======================================================================
857
858 void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
859 {
860   myZLayers.RemoveLayer (theLayerId);
861 }
862
863 //=======================================================================
864 //function : DisplayStructure
865 //purpose  :
866 //=======================================================================
867
868 void OpenGl_View::DisplayStructure (const Handle(Graphic3d_Structure)& theStructure,
869                                     const Standard_Integer             thePriority)
870 {
871   const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure->CStructure().operator->());
872   const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
873   myZLayers.AddStructure (aStruct, aZLayer, thePriority);
874 }
875
876 //=======================================================================
877 //function : DisplayImmediateStructure
878 //purpose  :
879 //=======================================================================
880
881 void OpenGl_View::DisplayImmediateStructure (const Handle(Graphic3d_Structure)& theStructure)
882 {
883   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure->CStructure().operator->());
884   for (OpenGl_SequenceOfStructure::Iterator anIter (myImmediateList);
885        anIter.More(); anIter.Next())
886   {
887     if (anIter.Value() == aStruct)
888     {
889       return;
890     }
891   }
892
893   myImmediateList.Append (aStruct);
894 }
895
896 //=======================================================================
897 //function : EraseStructure
898 //purpose  :
899 //=======================================================================
900
901 void OpenGl_View::EraseStructure (const Handle(Graphic3d_Structure)& theStructure)
902 {
903   myZLayers.RemoveStructure (theStructure);
904 }
905
906 //=======================================================================
907 //function : EraseImmediateStructure
908 //purpose  :
909 //=======================================================================
910
911 void OpenGl_View::EraseImmediateStructure (const OpenGl_Structure* theStructure)
912 {
913   for (OpenGl_SequenceOfStructure::Iterator anIter (myImmediateList);
914        anIter.More(); anIter.Next())
915   {
916     if (anIter.Value() == theStructure)
917     {
918       myImmediateList.Remove (anIter);
919       return;
920     }
921   }
922 }
923
924 //=======================================================================
925 //function : ChangeZLayer
926 //purpose  :
927 //=======================================================================
928
929 void OpenGl_View::ChangeZLayer (const OpenGl_Structure*  theStructure,
930                                 const Graphic3d_ZLayerId theNewLayerId)
931 {
932   const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer();
933   myZLayers.ChangeLayer (theStructure, anOldLayer, theNewLayerId);
934 }
935
936 //=======================================================================
937 //function : SetZLayerSettings
938 //purpose  :
939 //=======================================================================
940 void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
941                                      const Graphic3d_ZLayerSettings& theSettings)
942 {
943   myZLayers.SetLayerSettings (theLayerId, theSettings);
944 }
945
946 //=======================================================================
947 //function : ChangePriority
948 //purpose  :
949 //=======================================================================
950 void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure,
951                                   const Standard_Integer theNewPriority)
952 {
953   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
954   myZLayers.ChangePriority (theStructure, aLayerId, theNewPriority);
955 }
956
957 //=======================================================================
958 //function : RedrawScene
959 //purpose  :
960 //=======================================================================
961
962 void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintContext,
963                                const Handle(OpenGl_Workspace)&      theWorkspace,
964                                const Standard_Boolean               theToDrawImmediate)
965 {
966   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
967
968   if (myZClip.Back.IsOn || myZClip.Front.IsOn)
969   {
970     Handle(Graphic3d_ClipPlane) aPlaneBack;
971     Handle(Graphic3d_ClipPlane) aPlaneFront;
972
973     if (myZClip.Back.IsOn)
974     {
975       Standard_Real aClipBackConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
976       if (myCamera->ZFar() < aClipBackConverted)
977       {
978         aClipBackConverted = myCamera->ZFar();
979         myZClip.Back.Limit = (Standard_ShortReal )(aClipBackConverted - myCamera->Distance());
980       }
981       const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, (Standard_ShortReal )aClipBackConverted);
982       aPlaneBack = new Graphic3d_ClipPlane (aBackEquation);
983     }
984
985     if (myZClip.Front.IsOn)
986     {
987       Standard_Real aClipFrontConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
988       if (myCamera->ZNear() > aClipFrontConverted)
989       {
990         aClipFrontConverted = myCamera->ZNear();
991         myZClip.Front.Limit = (Standard_ShortReal )(aClipFrontConverted - myCamera->Distance());
992       }
993       const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, (Standard_ShortReal )-aClipFrontConverted);
994       aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation);
995     }
996
997     // Specify slicing planes with identity transformation
998     if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull())
999     {
1000       Graphic3d_SequenceOfHClipPlane aSlicingPlanes;
1001       if (!aPlaneBack.IsNull())
1002       {
1003         aSlicingPlanes.Append (aPlaneBack);
1004       }
1005
1006       if (!aPlaneFront.IsNull())
1007       {
1008         aSlicingPlanes.Append (aPlaneFront);
1009       }
1010
1011       // add planes at loaded view matrix state
1012       aContext->ChangeClipping().AddView (aSlicingPlanes, theWorkspace);
1013     }
1014   }
1015
1016 #ifdef _WIN32
1017   // set printing scale/tiling transformation
1018   if (!thePrintContext.IsNull())
1019   {
1020     aContext->ProjectionState.Push();
1021     aContext->ProjectionState.SetCurrent (thePrintContext->ProjTransformation() * aContext->ProjectionState.Current());
1022     aContext->ApplyProjectionMatrix();
1023   }
1024 #endif
1025
1026   // Specify clipping planes in view transformation space
1027   if (!myClipPlanes.IsEmpty())
1028   {
1029     Graphic3d_SequenceOfHClipPlane aUserPlanes;
1030     Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes);
1031     for (; aClippingIt.More(); aClippingIt.Next())
1032     {
1033       const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
1034       if (aClipPlane->IsOn())
1035       {
1036         aUserPlanes.Append (aClipPlane);
1037       }
1038     }
1039
1040     if (!aUserPlanes.IsEmpty())
1041     {
1042       aContext->ChangeClipping().AddWorld (aUserPlanes);
1043     }
1044
1045     if (!aContext->ShaderManager()->IsEmpty())
1046     {
1047       aContext->ShaderManager()->UpdateClippingState();
1048     }
1049   }
1050
1051 #if !defined(GL_ES_VERSION_2_0)
1052   // Apply Lights
1053   {
1054     // setup lights
1055     Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0],
1056                                    THE_DEFAULT_AMBIENT[1],
1057                                    THE_DEFAULT_AMBIENT[2],
1058                                    THE_DEFAULT_AMBIENT[3]);
1059     GLenum aLightGlId = GL_LIGHT0;
1060     for (OpenGl_ListOfLight::Iterator aLightIt (myLights);
1061          aLightIt.More(); aLightIt.Next())
1062     {
1063       bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, theWorkspace);
1064     }
1065
1066     // apply accumulated ambient color
1067     anAmbientColor.a() = 1.0f;
1068     glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData());
1069
1070     if (aLightGlId != GL_LIGHT0)
1071     {
1072       glEnable (GL_LIGHTING);
1073     }
1074     // switch off unused lights
1075     for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
1076     {
1077       glDisable (aLightGlId);
1078     }
1079   }
1080 #endif
1081
1082   // Clear status bitfields
1083   theWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
1084
1085   // Added PCT for handling of textures
1086   switch (mySurfaceDetail)
1087   {
1088     case Visual3d_TOD_NONE:
1089       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1090       theWorkspace->DisableTexture();
1091       // Render the view
1092       RenderStructs (theWorkspace, theToDrawImmediate);
1093       break;
1094
1095     case Visual3d_TOD_ENVIRONMENT:
1096       theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1097       theWorkspace->EnableTexture (myTextureEnv);
1098       // Render the view
1099       RenderStructs (theWorkspace, theToDrawImmediate);
1100       theWorkspace->DisableTexture();
1101       break;
1102
1103     case Visual3d_TOD_ALL:
1104       // First pass
1105       theWorkspace->NamedStatus &= ~OPENGL_NS_FORBIDSETTEX;
1106       // Render the view
1107       RenderStructs (theWorkspace, theToDrawImmediate);
1108       theWorkspace->DisableTexture();
1109
1110       // Second pass
1111       if (theWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
1112       {
1113         theWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
1114         theWorkspace->EnableTexture (myTextureEnv);
1115
1116         // Remember OpenGl properties
1117         GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA;
1118         GLint aSaveZbuffFunc;
1119         GLboolean aSaveZbuffWrite;
1120         glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite);
1121         glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc);
1122       #if !defined(GL_ES_VERSION_2_0)
1123         glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst);
1124         glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc);
1125       #endif
1126         GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST);
1127         GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND);
1128
1129         // Change the properties for second rendering pass
1130         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1131         glEnable (GL_BLEND);
1132
1133         glDepthFunc (GL_EQUAL);
1134         glDepthMask (GL_FALSE);
1135         glEnable (GL_DEPTH_TEST);
1136
1137         theWorkspace->NamedStatus |= OPENGL_NS_FORBIDSETTEX;
1138
1139         // Render the view
1140         RenderStructs (theWorkspace, theToDrawImmediate);
1141         theWorkspace->DisableTexture();
1142
1143         // Restore properties back
1144         glBlendFunc (aSaveBlendSrc, aSaveBlendDst);
1145         if (!wasBlendEnabled)
1146           glDisable (GL_BLEND);
1147
1148         glDepthFunc (aSaveZbuffFunc);
1149         glDepthMask (aSaveZbuffWrite);
1150         if (!wasZbuffEnabled)
1151           glDisable (GL_DEPTH_FUNC);
1152       }
1153       break;
1154   }
1155
1156   // Apply restored view matrix.
1157   aContext->ApplyWorldViewMatrix();
1158
1159 #ifdef _WIN32
1160   // set printing scale/tiling transformation
1161   if (!thePrintContext.IsNull())
1162   {
1163     aContext->ProjectionState.Pop();
1164     aContext->ApplyProjectionMatrix();
1165   }
1166 #endif
1167
1168 }