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