a0e76563af24887329482627b437a5c33fc5eb7e
[occt.git] / src / OpenGl / OpenGl_Workspace.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 <OpenGl_Workspace.hxx>
17
18 #include <OpenGl_ArbFBO.hxx>
19 #include <OpenGl_AspectLine.hxx>
20 #include <OpenGl_AspectFace.hxx>
21 #include <OpenGl_AspectMarker.hxx>
22 #include <OpenGl_AspectText.hxx>
23 #include <OpenGl_Context.hxx>
24 #include <OpenGl_Element.hxx>
25 #include <OpenGl_FrameBuffer.hxx>
26 #include <OpenGl_GlCore15.hxx>
27 #include <OpenGl_SceneGeometry.hxx>
28 #include <OpenGl_Structure.hxx>
29 #include <OpenGl_Sampler.hxx>
30 #include <OpenGl_Texture.hxx>
31 #include <OpenGl_View.hxx>
32 #include <OpenGl_Window.hxx>
33
34 #include <Graphic3d_TextureParams.hxx>
35 #include <Graphic3d_TransformUtils.hxx>
36
37 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient)
38 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter,OpenGl_RenderFilter)
39
40 #ifdef HAVE_GL2PS
41   #include <gl2ps.h>
42   /* OCC22216 NOTE: linker dependency can be switched off by undefining macro.
43      Pragma comment for gl2ps.lib is defined only here. */
44   #ifdef _MSC_VER
45   #pragma comment( lib, "gl2ps.lib" )
46   #endif
47 #endif
48
49 namespace
50 {
51   static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f);
52   static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
53
54   static const OpenGl_AspectLine myDefaultAspectLine;
55   static const OpenGl_AspectFace myDefaultAspectFace;
56   static const OpenGl_AspectMarker myDefaultAspectMarker;
57   static const OpenGl_AspectText myDefaultAspectText;
58
59   static const OpenGl_Matrix myDefaultMatrix =
60   {
61     {{ 1.0F, 0.0F, 0.0F, 0.0F },
62      { 0.0F, 1.0F, 0.0F, 0.0F },
63      { 0.0F, 0.0F, 1.0F, 0.0F },
64      { 0.0F, 0.0F, 0.0F, 1.0F }}
65   };
66
67 }
68
69 // =======================================================================
70 // function : Init
71 // purpose  :
72 // =======================================================================
73 void OpenGl_Material::Init (const Graphic3d_MaterialAspect& theMat,
74                             const Quantity_Color&           theInteriorColor)
75 {
76   const bool isPhysic = theMat.MaterialType (Graphic3d_MATERIAL_PHYSIC) == Standard_True;
77
78   // ambient component
79   if (theMat.ReflectionMode (Graphic3d_TOR_AMBIENT))
80   {
81     const OpenGl_Vec3& aSrcAmb = isPhysic ? theMat.AmbientColor() : theInteriorColor;
82     Ambient = OpenGl_Vec4 (aSrcAmb * (float )theMat.Ambient(), 1.0f);
83   }
84   else
85   {
86     Ambient = THE_BLACK_COLOR;
87   }
88
89   // diffusion component
90   if (theMat.ReflectionMode (Graphic3d_TOR_DIFFUSE))
91   {
92     const OpenGl_Vec3& aSrcDif = isPhysic ? theMat.DiffuseColor() : theInteriorColor;
93     Diffuse = OpenGl_Vec4 (aSrcDif * (float )theMat.Diffuse(), 1.0f);
94   }
95   else
96   {
97     Diffuse = THE_BLACK_COLOR;
98   }
99
100   // specular component
101   if (theMat.ReflectionMode (Graphic3d_TOR_SPECULAR))
102   {
103     const OpenGl_Vec3& aSrcSpe = isPhysic ? (const OpenGl_Vec3& )theMat.SpecularColor() : THE_WHITE_COLOR.rgb();
104     Specular = OpenGl_Vec4 (aSrcSpe * (float )theMat.Specular(), 1.0f);
105   }
106   else
107   {
108     Specular = THE_BLACK_COLOR;
109   }
110
111   // emission component
112   if (theMat.ReflectionMode (Graphic3d_TOR_EMISSION))
113   {
114     const OpenGl_Vec3& aSrcEms = isPhysic ? theMat.EmissiveColor() : theInteriorColor;
115     Emission = OpenGl_Vec4 (aSrcEms * (float )theMat.Emissive(), 1.0f);
116   }
117   else
118   {
119     Emission = THE_BLACK_COLOR;
120   }
121
122   ChangeShine()        = 128.0f * float(theMat.Shininess());
123   ChangeTransparency() = 1.0f - (float )theMat.Transparency();
124 }
125
126 // =======================================================================
127 // function : OpenGl_Workspace
128 // purpose  :
129 // =======================================================================
130 OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow)
131 : NamedStatus (0),
132   HighlightColor (&THE_WHITE_COLOR),
133   myView (theView),
134   myWindow (theWindow),
135   myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL),
136   myUseZBuffer    (Standard_True),
137   myUseDepthWrite (Standard_True),
138   myUseGLLight (Standard_True),
139   //
140   myAspectLineSet (&myDefaultAspectLine),
141   myAspectFaceSet (&myDefaultAspectFace),
142   myAspectMarkerSet (&myDefaultAspectMarker),
143   myAspectTextSet (&myDefaultAspectText),
144   myAspectFaceAppliedWithHL (false),
145   //
146   ViewMatrix_applied (&myDefaultMatrix),
147   StructureMatrix_applied (&myDefaultMatrix),
148   myToAllowFaceCulling (false),
149   myToHighlight (false),
150   myModelViewMatrix (myDefaultMatrix)
151 {
152   if (!myGlContext.IsNull() && myGlContext->MakeCurrent())
153   {
154     myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
155
156     // General initialization of the context
157   #if !defined(GL_ES_VERSION_2_0)
158     if (myGlContext->core11 != NULL)
159     {
160       // Eviter d'avoir les faces mal orientees en noir.
161       // Pourrait etre utiliser pour detecter les problemes d'orientation
162       glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
163
164       // Optimisation pour le Fog et l'antialiasing
165       glHint (GL_FOG_HINT,            GL_FASTEST);
166       glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
167     }
168
169     glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
170     glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
171   #endif
172   }
173
174   myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter();
175
176   myNoneCulling .Aspect()->SetSuppressBackFaces (false);
177   myNoneCulling .Aspect()->SetDrawEdges (false);
178   myFrontCulling.Aspect()->SetSuppressBackFaces (true);
179   myFrontCulling.Aspect()->SetDrawEdges (false);
180 }
181
182 // =======================================================================
183 // function : Activate
184 // purpose  :
185 // =======================================================================
186 Standard_Boolean OpenGl_Workspace::Activate()
187 {
188   if (myWindow.IsNull() || !myWindow->Activate())
189   {
190     return Standard_False;
191   }
192
193   ViewMatrix_applied      = &myDefaultMatrix;
194   StructureMatrix_applied = &myDefaultMatrix;
195
196   ResetAppliedAspect();
197
198   return Standard_True;
199 }
200
201 //=======================================================================
202 //function : ResetAppliedAspect
203 //purpose  : Sets default values of GL parameters in accordance with default aspects
204 //=======================================================================
205 void OpenGl_Workspace::ResetAppliedAspect()
206 {
207   myGlContext->BindDefaultVao();
208
209   NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
210   HighlightColor        = &THE_WHITE_COLOR;
211   myToAllowFaceCulling  = false;
212   myAspectLineSet       = &myDefaultAspectLine;
213   myAspectFaceSet       = &myDefaultAspectFace;
214   myAspectFaceApplied.Nullify();
215   myAspectMarkerSet     = &myDefaultAspectMarker;
216   myAspectMarkerApplied.Nullify();
217   myAspectTextSet       = &myDefaultAspectText;
218   myPolygonOffsetApplied= Graphic3d_PolygonOffset();
219
220   ApplyAspectLine();
221   ApplyAspectFace();
222   ApplyAspectMarker();
223   ApplyAspectText();
224
225   myGlContext->SetTypeOfLine (myDefaultAspectLine.Aspect()->Type());
226   myGlContext->SetLineWidth  (myDefaultAspectLine.Aspect()->Width());
227 }
228
229 // =======================================================================
230 // function : DisableTexture
231 // purpose  :
232 // =======================================================================
233 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
234 {
235   if (myTextureBound.IsNull())
236   {
237     return myTextureBound;
238   }
239
240   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
241   if (!aSampler.IsNull())
242   {
243     aSampler->Unbind (*myGlContext);
244   }
245
246 #if !defined(GL_ES_VERSION_2_0)
247   // reset texture matrix because some code may expect it is identity
248   if (myGlContext->core11 != NULL)
249   {
250     GLint aMatrixMode = GL_TEXTURE;
251     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
252     glMatrixMode (GL_TEXTURE);
253     glLoadIdentity();
254     glMatrixMode (aMatrixMode);
255   }
256 #endif
257
258   myTextureBound->Unbind (myGlContext);
259   switch (myTextureBound->GetTarget())
260   {
261   #if !defined(GL_ES_VERSION_2_0)
262     case GL_TEXTURE_1D:
263     {
264       if (myGlContext->core11 != NULL)
265       {
266         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
267         {
268           glDisable (GL_TEXTURE_GEN_S);
269         }
270         glDisable (GL_TEXTURE_1D);
271       }
272       break;
273     }
274   #endif
275     case GL_TEXTURE_2D:
276     {
277     #if !defined(GL_ES_VERSION_2_0)
278       if (myGlContext->core11 != NULL)
279       {
280         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
281         {
282           glDisable (GL_TEXTURE_GEN_S);
283           glDisable (GL_TEXTURE_GEN_T);
284           if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
285           {
286             glDisable (GL_POINT_SPRITE);
287           }
288         }
289         glDisable (GL_TEXTURE_2D);
290       }
291     #endif
292       break;
293     }
294     default: break;
295   }
296
297   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
298   myTextureBound.Nullify();
299   return aPrevTexture;
300 }
301
302 // =======================================================================
303 // function : setTextureParams
304 // purpose  :
305 // =======================================================================
306 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
307                                          const Handle(Graphic3d_TextureParams)& theParams)
308 {
309   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
310   if (aParams.IsNull())
311   {
312     return;
313   }
314
315 #if !defined(GL_ES_VERSION_2_0)
316   if (myGlContext->core11 != NULL)
317   {
318     GLint anEnvMode = GL_MODULATE; // lighting mode
319     if (!aParams->IsModulate())
320     {
321       anEnvMode = GL_DECAL;
322       if (theTexture->GetFormat() == GL_ALPHA
323        || theTexture->GetFormat() == GL_LUMINANCE)
324       {
325         anEnvMode = GL_REPLACE;
326       }
327     }
328
329     // setup generation of texture coordinates
330     switch (aParams->GenMode())
331     {
332       case Graphic3d_TOTM_OBJECT:
333       {
334         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
335         glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
336         if (theTexture->GetTarget() != GL_TEXTURE_1D)
337         {
338           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
339           glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
340         }
341         break;
342       }
343       case Graphic3d_TOTM_SPHERE:
344       {
345         glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
346         if (theTexture->GetTarget() != GL_TEXTURE_1D)
347         {
348           glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
349         }
350         break;
351       }
352       case Graphic3d_TOTM_EYE:
353       {
354         myGlContext->WorldViewState.Push();
355
356         myGlContext->WorldViewState.SetIdentity();
357         myGlContext->ApplyWorldViewMatrix();
358
359         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
360         glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
361
362         if (theTexture->GetTarget() != GL_TEXTURE_1D)
363         {
364           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
365           glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
366         }
367
368         myGlContext->WorldViewState.Pop();
369
370         break;
371       }
372       case Graphic3d_TOTM_SPRITE:
373       {
374         if (myGlContext->core20fwd != NULL)
375         {
376           glEnable  (GL_POINT_SPRITE);
377           glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
378           anEnvMode = GL_REPLACE;
379         }
380         break;
381       }
382       case Graphic3d_TOTM_MANUAL:
383       default: break;
384     }
385
386     // setup lighting
387     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
388   }
389 #endif
390
391   // get active sampler object to override default texture parameters
392   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
393
394   // setup texture filtering and wrapping
395   //if (theTexture->GetParams() != theParams)
396   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
397   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
398   switch (theTexture->GetTarget())
399   {
400   #if !defined(GL_ES_VERSION_2_0)
401     case GL_TEXTURE_1D:
402     {
403       if (aSampler.IsNull() || !aSampler->IsValid())
404       {
405         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
406         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
407         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
408       }
409       else
410       {
411         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
412         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
413         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
414       }
415
416       break;
417     }
418   #endif
419     case GL_TEXTURE_2D:
420     {
421       GLenum aFilterMin = aFilter;
422       if (theTexture->HasMipmaps())
423       {
424         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
425         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
426         {
427           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
428         }
429         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
430         {
431           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
432         }
433
434         if (myGlContext->extAnis)
435         {
436           // setup degree of anisotropy filter
437           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
438           GLint aDegree;
439           switch (aParams->AnisoFilter())
440           {
441             case Graphic3d_LOTA_QUALITY:
442             {
443               aDegree = aMaxDegree;
444               break;
445             }
446             case Graphic3d_LOTA_MIDDLE:
447             {
448               aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
449               break;
450             }
451             case Graphic3d_LOTA_FAST:
452             {
453               aDegree = 2;
454               break;
455             }
456             case Graphic3d_LOTA_OFF:
457             default:
458             {
459               aDegree = 1;
460               break;
461             }
462           }
463
464           if (aSampler.IsNull() || !aSampler->IsValid())
465           {
466             glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
467           }
468           else
469           {
470             aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
471           }
472         }
473       }
474
475       if (aSampler.IsNull() || !aSampler->IsValid())
476       {
477         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
478         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
479         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
480         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
481       }
482       else
483       {
484         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
485         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
486         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
487         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
488       }
489
490       break;
491     }
492     default: break;
493   }
494
495   switch (theTexture->GetTarget())
496   {
497   #if !defined(GL_ES_VERSION_2_0)
498     case GL_TEXTURE_1D:
499     {
500       if (myGlContext->core11 != NULL)
501       {
502         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
503         {
504           glEnable (GL_TEXTURE_GEN_S);
505         }
506         glEnable (GL_TEXTURE_1D);
507       }
508       break;
509     }
510   #endif
511     case GL_TEXTURE_2D:
512     {
513     #if !defined(GL_ES_VERSION_2_0)
514       if (myGlContext->core11 != NULL)
515       {
516         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
517         {
518           glEnable (GL_TEXTURE_GEN_S);
519           glEnable (GL_TEXTURE_GEN_T);
520         }
521         glEnable (GL_TEXTURE_2D);
522       }
523     #endif
524       break;
525     }
526     default: break;
527   }
528
529   theTexture->SetParams (aParams);
530 }
531
532 // =======================================================================
533 // function : EnableTexture
534 // purpose  :
535 // =======================================================================
536 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
537                                                         const Handle(Graphic3d_TextureParams)& theParams)
538 {
539   if (theTexture.IsNull() || !theTexture->IsValid())
540   {
541     return DisableTexture();
542   }
543
544   if (myTextureBound == theTexture
545    && (theParams.IsNull() || theParams == theTexture->GetParams()))
546   {
547     // already bound
548     return myTextureBound;
549   }
550
551   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
552   myTextureBound = theTexture;
553   myTextureBound->Bind (myGlContext);
554   setTextureParams (myTextureBound, theParams);
555
556   // If custom sampler object is available it will be
557   // used for overriding default texture parameters
558   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
559
560   if (!aSampler.IsNull() && aSampler->IsValid())
561   {
562     aSampler->Bind (*myGlContext);
563   }
564
565   return aPrevTexture;
566 }
567
568 // =======================================================================
569 // function : updateMaterial
570 // purpose  :
571 // =======================================================================
572 void OpenGl_Workspace::updateMaterial (const int theFlag)
573 {
574   // Case of hidden line
575   if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
576   {
577     // copy all values including line edge aspect
578     *myAspectFaceHl.Aspect().operator->() = *myAspectFaceSet->Aspect();
579     myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge());
580     myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB());
581     myAspectFaceHl.SetNoLighting (true);
582     myAspectFaceSet = &myAspectFaceHl;
583     return;
584   }
585
586   const Graphic3d_MaterialAspect* aSrcMat      = &myAspectFaceSet->Aspect()->FrontMaterial();
587   const Quantity_Color*           aSrcIntColor = &myAspectFaceSet->Aspect()->InteriorColor();
588   GLenum aFace = GL_FRONT_AND_BACK;
589   if (theFlag == TEL_BACK_MATERIAL)
590   {
591     aFace        = GL_BACK;
592     aSrcMat      = &myAspectFaceSet->Aspect()->BackMaterial();
593     aSrcIntColor = &myAspectFaceSet->Aspect()->BackInteriorColor();
594   }
595   else if (myAspectFaceSet->Aspect()->Distinguish()
596         && !(NamedStatus & OPENGL_NS_RESMAT))
597   {
598     aFace = GL_FRONT;
599   }
600
601   myMatTmp.Init (*aSrcMat, *aSrcIntColor);
602   if (myToHighlight)
603   {
604     myMatTmp.SetColor (*HighlightColor);
605   }
606
607   // handling transparency
608   if (NamedStatus & OPENGL_NS_2NDPASSDO)
609   {
610     // second pass
611     myMatTmp.Diffuse.a() = aSrcMat->EnvReflexion();
612   }
613   else
614   {
615     if (aSrcMat->EnvReflexion() != 0.0f)
616     {
617       // if the material reflects the environment scene, the second pass is needed
618       NamedStatus |= OPENGL_NS_2NDPASSNEED;
619     }
620
621     const float aTransp = (float )aSrcMat->Transparency();
622     if (aTransp != 0.0f)
623     {
624       // render transparent
625       myMatTmp.Diffuse.a() = 1.0f - aTransp;
626       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
627       glEnable    (GL_BLEND);
628       if (myUseDepthWrite)
629       {
630         glDepthMask (GL_FALSE);
631       }
632     }
633     else
634     {
635       // render opaque
636       glBlendFunc (GL_ONE, GL_ZERO);
637       glDisable   (GL_BLEND);
638       if (myUseDepthWrite)
639       {
640         glDepthMask (GL_TRUE);
641       }
642     }
643   }
644
645   // do not update material properties in case of zero reflection mode,
646   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
647   if (myAspectFaceSet->IsNoLighting())
648   {
649     return;
650   }
651
652   // reset material
653   if (NamedStatus & OPENGL_NS_RESMAT)
654   {
655   #if !defined(GL_ES_VERSION_2_0)
656     if (myGlContext->core11 != NULL)
657     {
658       myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT,   myMatTmp.Ambient.GetData());
659       myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE,   myMatTmp.Diffuse.GetData());
660       myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR,  myMatTmp.Specular.GetData());
661       myGlContext->core11->glMaterialfv (aFace, GL_EMISSION,  myMatTmp.Emission.GetData());
662       myGlContext->core11->glMaterialf  (aFace, GL_SHININESS, myMatTmp.Shine());
663     }
664   #endif
665
666     if (theFlag == TEL_FRONT_MATERIAL)
667     {
668       myMatFront = myMatTmp;
669       myMatBack  = myMatTmp;
670     }
671     else
672     {
673       myMatBack = myMatTmp;
674     }
675
676     NamedStatus &= ~OPENGL_NS_RESMAT;
677     return;
678   }
679
680   // reduce updates
681   OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL)
682                          ? myMatFront
683                          : myMatBack;
684 #if !defined(GL_ES_VERSION_2_0)
685   if (myGlContext->core11 != NULL)
686   {
687     if (myMatTmp.Ambient.r() != anOld.Ambient.r()
688      || myMatTmp.Ambient.g() != anOld.Ambient.g()
689      || myMatTmp.Ambient.b() != anOld.Ambient.b())
690     {
691       myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData());
692     }
693     if (myMatTmp.Diffuse.r() != anOld.Diffuse.r()
694      || myMatTmp.Diffuse.g() != anOld.Diffuse.g()
695      || myMatTmp.Diffuse.b() != anOld.Diffuse.b()
696      || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f)
697     {
698       myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData());
699     }
700     if (myMatTmp.Specular.r() != anOld.Specular.r()
701      || myMatTmp.Specular.g() != anOld.Specular.g()
702      || myMatTmp.Specular.b() != anOld.Specular.b())
703     {
704       myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData());
705     }
706     if (myMatTmp.Emission.r() != anOld.Emission.r()
707      || myMatTmp.Emission.g() != anOld.Emission.g()
708      || myMatTmp.Emission.b() != anOld.Emission.b())
709     {
710       myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData());
711     }
712     if (myMatTmp.Shine() != anOld.Shine())
713     {
714       myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine());
715     }
716   }
717 #endif
718   anOld = myMatTmp;
719   if (aFace == GL_FRONT_AND_BACK)
720   {
721     myMatBack = myMatTmp;
722   }
723 }
724
725 // =======================================================================
726 // function : SetAspectLine
727 // purpose  :
728 // =======================================================================
729 const OpenGl_AspectLine* OpenGl_Workspace::SetAspectLine (const OpenGl_AspectLine* theAspect)
730 {
731   const OpenGl_AspectLine* aPrevAspectLine = myAspectLineSet;
732   myAspectLineSet = theAspect;
733   return aPrevAspectLine;
734 }
735
736 // =======================================================================
737 // function : SetAspectFace
738 // purpose  :
739 // =======================================================================
740 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace (const OpenGl_AspectFace* theAspect)
741 {
742   const OpenGl_AspectFace* aPrevAspectFace = myAspectFaceSet;
743   myAspectFaceSet = theAspect;
744   return aPrevAspectFace;
745 }
746
747 // =======================================================================
748 // function : SetAspectMarker
749 // purpose  :
750 // =======================================================================
751 const OpenGl_AspectMarker* OpenGl_Workspace::SetAspectMarker (const OpenGl_AspectMarker* theAspect)
752 {
753   const OpenGl_AspectMarker* aPrevAspectMarker = myAspectMarkerSet;
754   myAspectMarkerSet = theAspect;
755   return aPrevAspectMarker;
756 }
757
758 // =======================================================================
759 // function : SetAspectText
760 // purpose  :
761 // =======================================================================
762 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText (const OpenGl_AspectText* theAspect)
763 {
764   const OpenGl_AspectText* aPrevAspectText = myAspectTextSet;
765   myAspectTextSet = theAspect;
766   return aPrevAspectText;
767 }
768
769 // =======================================================================
770 // function : ApplyAspectFace
771 // purpose  :
772 // =======================================================================
773 const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
774 {
775   if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
776   {
777     // manage back face culling mode, disable culling when clipping is enabled
778     bool toSuppressBackFaces = myToAllowFaceCulling
779                             && myAspectFaceSet->Aspect()->ToSuppressBackFaces();
780     if (toSuppressBackFaces)
781     {
782       if (myGlContext->Clipping().IsClippingOrCappingOn()
783        || myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH)
784       {
785         toSuppressBackFaces = false;
786       }
787     }
788     if (toSuppressBackFaces)
789     {
790       if (!(NamedStatus & OPENGL_NS_2NDPASSDO)
791        && (float )myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f)
792       {
793         // disable culling in case of translucent shading aspect
794         toSuppressBackFaces = false;
795       }
796     }
797     myGlContext->SetCullBackFaces (toSuppressBackFaces);
798   }
799
800   if (myAspectFaceSet->Aspect() == myAspectFaceApplied
801    && myToHighlight == myAspectFaceAppliedWithHL)
802   {
803     return myAspectFaceSet;
804   }
805   myAspectFaceAppliedWithHL = myToHighlight;
806
807 #if !defined(GL_ES_VERSION_2_0)
808   const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle();
809   if (myAspectFaceApplied.IsNull()
810    || myAspectFaceApplied->InteriorStyle() != anIntstyle)
811   {
812     switch (anIntstyle)
813     {
814       case Aspect_IS_EMPTY:
815       case Aspect_IS_HOLLOW:
816       {
817         myGlContext->SetPolygonMode (GL_LINE);
818         break;
819       }
820       case Aspect_IS_HATCH:
821       {
822         myGlContext->SetPolygonMode (GL_FILL);
823         myGlContext->SetPolygonHatchEnabled (true);
824         break;
825       }
826       case Aspect_IS_SOLID:
827       case Aspect_IS_HIDDENLINE:
828       {
829         myGlContext->SetPolygonMode (GL_FILL);
830         myGlContext->SetPolygonHatchEnabled (false);
831         break;
832       }
833       case Aspect_IS_POINT:
834       {
835         myGlContext->SetPolygonMode (GL_POINT);
836         break;
837       }
838     }
839   }
840
841   if (anIntstyle == Aspect_IS_HATCH)
842   {
843     myGlContext->SetPolygonHatchStyle (myAspectFaceSet->Aspect()->HatchStyle());
844   }
845 #endif
846
847   // Aspect_POM_None means: do not change current settings
848   if ((myAspectFaceSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None)
849   {
850     if (myPolygonOffsetApplied.Mode   != myAspectFaceSet->Aspect()->PolygonOffset().Mode
851      || myPolygonOffsetApplied.Factor != myAspectFaceSet->Aspect()->PolygonOffset().Factor
852      || myPolygonOffsetApplied.Units  != myAspectFaceSet->Aspect()->PolygonOffset().Units)
853     {
854       SetPolygonOffset (myAspectFaceSet->Aspect()->PolygonOffset());
855     }
856   }
857
858   updateMaterial (TEL_FRONT_MATERIAL);
859   if (myAspectFaceSet->Aspect()->Distinguish())
860   {
861     updateMaterial (TEL_BACK_MATERIAL);
862   }
863
864   if (myAspectFaceSet->Aspect()->ToMapTexture())
865   {
866     EnableTexture (myAspectFaceSet->TextureRes (myGlContext),
867                    myAspectFaceSet->TextureParams());
868   }
869   else
870   {
871     if (!myEnvironmentTexture.IsNull())
872     {
873       EnableTexture (myEnvironmentTexture,
874                      myEnvironmentTexture->GetParams());
875     }
876     else
877     {
878       DisableTexture();
879     }
880   }
881
882   myAspectFaceApplied = myAspectFaceSet->Aspect();
883   return myAspectFaceSet;
884 }
885
886 //=======================================================================
887 //function : SetPolygonOffset
888 //purpose  :
889 //=======================================================================
890 void OpenGl_Workspace::SetPolygonOffset (const Graphic3d_PolygonOffset& theParams)
891 {
892   myPolygonOffsetApplied = theParams;
893
894   if ((theParams.Mode & Aspect_POM_Fill) == Aspect_POM_Fill)
895   {
896     glEnable (GL_POLYGON_OFFSET_FILL);
897   }
898   else
899   {
900     glDisable (GL_POLYGON_OFFSET_FILL);
901   }
902
903 #if !defined(GL_ES_VERSION_2_0)
904   if ((theParams.Mode & Aspect_POM_Line) == Aspect_POM_Line)
905   {
906     glEnable (GL_POLYGON_OFFSET_LINE);
907   }
908   else
909   {
910     glDisable (GL_POLYGON_OFFSET_LINE);
911   }
912
913   if ((theParams.Mode & Aspect_POM_Point) == Aspect_POM_Point)
914   {
915     glEnable (GL_POLYGON_OFFSET_POINT);
916   }
917   else
918   {
919     glDisable (GL_POLYGON_OFFSET_POINT);
920   }
921 #endif
922   glPolygonOffset (theParams.Factor, theParams.Units);
923 }
924
925 // =======================================================================
926 // function : ApplyAspectMarker
927 // purpose  :
928 // =======================================================================
929 const OpenGl_AspectMarker* OpenGl_Workspace::ApplyAspectMarker()
930 {
931   if (myAspectMarkerSet->Aspect() != myAspectMarkerApplied)
932   {
933     if (myAspectMarkerApplied.IsNull()
934     || (myAspectMarkerSet->Aspect()->Scale() != myAspectMarkerApplied->Scale()))
935     {
936     #if !defined(GL_ES_VERSION_2_0)
937       glPointSize (myAspectMarkerSet->Aspect()->Scale());
938     #ifdef HAVE_GL2PS
939       gl2psPointSize (myAspectMarkerSet->Aspect()->Scale());
940     #endif
941     #endif
942     }
943     myAspectMarkerApplied = myAspectMarkerSet->Aspect();
944   }
945   return myAspectMarkerSet;
946 }
947
948 // =======================================================================
949 // function : Width
950 // purpose  :
951 // =======================================================================
952 Standard_Integer OpenGl_Workspace::Width()  const
953 {
954   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0;
955 }
956
957 // =======================================================================
958 // function : Height
959 // purpose  :
960 // =======================================================================
961 Standard_Integer OpenGl_Workspace::Height() const
962 {
963   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0;
964 }
965
966 // =======================================================================
967 // function : UseGLLight
968 // purpose  :
969 // =======================================================================
970 Standard_Boolean OpenGl_Workspace::UseGLLight() const
971 {
972   return myView->IsGLLightEnabled();
973 }
974
975 // =======================================================================
976 // function : IsCullingEnabled
977 // purpose  :
978 // =======================================================================
979 Standard_Boolean OpenGl_Workspace::IsCullingEnabled() const
980 {
981   return myView->IsCullingEnabled();
982 }
983
984 // =======================================================================
985 // function : FBOCreate
986 // purpose  :
987 // =======================================================================
988 Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
989                                                         const Standard_Integer theHeight)
990 {
991   // activate OpenGL context
992   if (!Activate())
993     return Handle(OpenGl_FrameBuffer)();
994
995   DisableTexture();
996
997   // create the FBO
998   const Handle(OpenGl_Context)& aCtx = GetGlContext();
999   Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer();
1000   if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0))
1001   {
1002     aFrameBuffer->Release (aCtx.operator->());
1003     return Handle(OpenGl_FrameBuffer)();
1004   }
1005   return aFrameBuffer;
1006 }
1007
1008 // =======================================================================
1009 // function : FBORelease
1010 // purpose  :
1011 // =======================================================================
1012 void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo)
1013 {
1014   // activate OpenGL context
1015   if (!Activate()
1016    || theFbo.IsNull())
1017   {
1018     return;
1019   }
1020
1021   theFbo->Release (GetGlContext().operator->());
1022   theFbo.Nullify();
1023 }
1024
1025 inline bool getDataFormat (const Image_PixMap& theData,
1026                            GLenum&             thePixelFormat,
1027                            GLenum&             theDataType)
1028 {
1029   thePixelFormat = GL_RGB;
1030   theDataType    = GL_UNSIGNED_BYTE;
1031   switch (theData.Format())
1032   {
1033   #if !defined(GL_ES_VERSION_2_0)
1034     case Image_PixMap::ImgGray:
1035       thePixelFormat = GL_DEPTH_COMPONENT;
1036       theDataType    = GL_UNSIGNED_BYTE;
1037       return true;
1038     case Image_PixMap::ImgGrayF:
1039       thePixelFormat = GL_DEPTH_COMPONENT;
1040       theDataType    = GL_FLOAT;
1041       return true;
1042     case Image_PixMap::ImgBGR:
1043       thePixelFormat = GL_BGR;
1044       theDataType    = GL_UNSIGNED_BYTE;
1045       return true;
1046     case Image_PixMap::ImgBGRA:
1047     case Image_PixMap::ImgBGR32:
1048       thePixelFormat = GL_BGRA;
1049       theDataType    = GL_UNSIGNED_BYTE;
1050       return true;
1051     case Image_PixMap::ImgBGRF:
1052       thePixelFormat = GL_BGR;
1053       theDataType    = GL_FLOAT;
1054       return true;
1055     case Image_PixMap::ImgBGRAF:
1056       thePixelFormat = GL_BGRA;
1057       theDataType    = GL_FLOAT;
1058       return true;
1059   #else
1060     case Image_PixMap::ImgGray:
1061     case Image_PixMap::ImgGrayF:
1062     case Image_PixMap::ImgBGR:
1063     case Image_PixMap::ImgBGRA:
1064     case Image_PixMap::ImgBGR32:
1065     case Image_PixMap::ImgBGRF:
1066     case Image_PixMap::ImgBGRAF:
1067       return false;
1068   #endif
1069     case Image_PixMap::ImgRGB:
1070       thePixelFormat = GL_RGB;
1071       theDataType    = GL_UNSIGNED_BYTE;
1072       return true;
1073     case Image_PixMap::ImgRGBA:
1074     case Image_PixMap::ImgRGB32:
1075       thePixelFormat = GL_RGBA;
1076       theDataType    = GL_UNSIGNED_BYTE;
1077       return true;
1078     case Image_PixMap::ImgRGBF:
1079       thePixelFormat = GL_RGB;
1080       theDataType    = GL_FLOAT;
1081       return true;
1082     case Image_PixMap::ImgRGBAF:
1083       thePixelFormat = GL_RGBA;
1084       theDataType    = GL_FLOAT;
1085       return true;
1086     case Image_PixMap::ImgAlpha:
1087     case Image_PixMap::ImgAlphaF:
1088       return false; // GL_ALPHA is no more supported in core context
1089     case Image_PixMap::ImgUNKNOWN:
1090       return false;
1091   }
1092   return false;
1093 }
1094
1095 // =======================================================================
1096 // function : getAligned
1097 // purpose  :
1098 // =======================================================================
1099 inline Standard_Size getAligned (const Standard_Size theNumber,
1100                                  const Standard_Size theAlignment)
1101 {
1102   return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
1103 }
1104
1105 // =======================================================================
1106 // function : BufferDump
1107 // purpose  :
1108 // =======================================================================
1109 Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo,
1110                                                Image_PixMap&                     theImage,
1111                                                const Graphic3d_BufferType&       theBufferType)
1112 {
1113   GLenum aFormat, aType;
1114   if (theImage.IsEmpty()
1115    || !getDataFormat (theImage, aFormat, aType)
1116    || !Activate())
1117   {
1118     return Standard_False;
1119   }
1120 #if !defined(GL_ES_VERSION_2_0)
1121   GLint aReadBufferPrev = GL_BACK;
1122   if (theBufferType == Graphic3d_BT_Depth
1123    && aFormat != GL_DEPTH_COMPONENT)
1124   {
1125     return Standard_False;
1126   }
1127 #else
1128   (void )theBufferType;
1129 #endif
1130
1131   // bind FBO if used
1132   if (!theFbo.IsNull() && theFbo->IsValid())
1133   {
1134     theFbo->BindBuffer (GetGlContext());
1135   }
1136   else
1137   {
1138   #if !defined(GL_ES_VERSION_2_0)
1139     glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
1140     GLint aDrawBufferPrev = GL_BACK;
1141     glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
1142     glReadBuffer (aDrawBufferPrev);
1143   #endif
1144   }
1145
1146   // setup alignment
1147   const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
1148   glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
1149   bool isBatchCopy = !theImage.IsTopDown();
1150
1151   const GLint   anExtraBytes       = GLint(theImage.RowExtraBytes());
1152   GLint         aPixelsWidth       = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
1153   Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
1154   if (anExtraBytes < anAligment)
1155   {
1156     aPixelsWidth = 0;
1157   }
1158   else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
1159   {
1160     aPixelsWidth = 0;
1161     isBatchCopy  = false;
1162   }
1163 #if !defined(GL_ES_VERSION_2_0)
1164   glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
1165 #else
1166   if (aPixelsWidth != 0)
1167   {
1168     isBatchCopy = false;
1169   }
1170 #endif
1171
1172   if (!isBatchCopy)
1173   {
1174     // copy row by row
1175     for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
1176     {
1177       // Image_PixMap rows indexation always starts from the upper corner
1178       // while order in memory depends on the flag and processed by ChangeRow() method
1179       glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
1180     }
1181   }
1182   else
1183   {
1184     glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
1185   }
1186
1187   glPixelStorei (GL_PACK_ALIGNMENT,  1);
1188 #if !defined(GL_ES_VERSION_2_0)
1189   glPixelStorei (GL_PACK_ROW_LENGTH, 0);
1190 #endif
1191
1192   if (!theFbo.IsNull() && theFbo->IsValid())
1193   {
1194     theFbo->UnbindBuffer (GetGlContext());
1195   }
1196   else
1197   {
1198   #if !defined(GL_ES_VERSION_2_0)
1199     glReadBuffer (aReadBufferPrev);
1200   #endif
1201   }
1202   return Standard_True;
1203 }
1204
1205 // =======================================================================
1206 // function : CanRender
1207 // purpose  :
1208 // =======================================================================
1209 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1210 {
1211   Standard_Boolean aPrevFilterResult = Standard_True;
1212   if (!myPrevRenderFilter.IsNull())
1213   {
1214     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1215   }
1216   return aPrevFilterResult &&
1217     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1218 }