0025511: Visualization - drop redundant viewer option V3d_View::Transparency()
[occt.git] / src / OpenGl / OpenGl_Workspace_5.cxx
1 // Created on: 2011-08-05
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_GlCore11.hxx>
17
18 #include <OpenGl_Workspace.hxx>
19
20 #include <OpenGl_AspectLine.hxx>
21 #include <OpenGl_AspectFace.hxx>
22 #include <OpenGl_AspectMarker.hxx>
23 #include <OpenGl_AspectText.hxx>
24 #include <OpenGl_Context.hxx>
25 #include <OpenGl_ShaderManager.hxx>
26 #include <OpenGl_telem_util.hxx>
27
28 /* OCC22218 NOTE: project dependency on gl2ps is specified by macro */
29 #ifdef HAVE_GL2PS
30   #include <gl2ps.h>
31   /* OCC22216 NOTE: linker dependency can be switched off by undefining macro.
32      Pragma comment for gl2ps.lib is defined only here. */
33   #ifdef _MSC_VER
34   #pragma comment( lib, "gl2ps.lib" )
35   #endif
36 #endif
37
38 #include <Aspect_PolygonOffsetMode.hxx>
39 #include <OpenGl_View.hxx>
40
41 /*----------------------------------------------------------------------*/
42
43 static void TelUpdatePolygonOffsets (const TEL_POFFSET_PARAM& theOffsetData)
44 {
45   if ((theOffsetData.mode & Aspect_POM_Fill) == Aspect_POM_Fill)
46   {
47     glEnable (GL_POLYGON_OFFSET_FILL);
48   }
49   else
50   {
51     glDisable (GL_POLYGON_OFFSET_FILL);
52   }
53
54 #if !defined(GL_ES_VERSION_2_0)
55   if ((theOffsetData.mode & Aspect_POM_Line) == Aspect_POM_Line)
56   {
57     glEnable (GL_POLYGON_OFFSET_LINE);
58   }
59   else
60   {
61     glDisable (GL_POLYGON_OFFSET_LINE);
62   }
63
64   if ((theOffsetData.mode & Aspect_POM_Point) == Aspect_POM_Point)
65   {
66     glEnable (GL_POLYGON_OFFSET_POINT);
67   }
68   else
69   {
70     glDisable (GL_POLYGON_OFFSET_POINT);
71   }
72 #endif
73
74   glPolygonOffset (theOffsetData.factor, theOffsetData.units);
75 }
76
77 /*----------------------------------------------------------------------*/
78
79 void OpenGl_Workspace::updateMaterial (const int theFlag)
80 {
81   // Case of hidden line
82   if (AspectFace_set->InteriorStyle() == Aspect_IS_HIDDENLINE)
83   {
84     myAspectFaceHl = *AspectFace_set; // copy all values including line edge aspect
85     myAspectFaceHl.ChangeIntFront().matcol     = BackgroundColor();
86     myAspectFaceHl.ChangeIntFront().color_mask = 0;
87     myAspectFaceHl.ChangeIntFront().color_mask = 0;
88
89     AspectFace_set = &myAspectFaceHl;
90     return;
91   }
92
93   const OPENGL_SURF_PROP* aProps = &AspectFace_set->IntFront();
94   GLenum aFace = GL_FRONT_AND_BACK;
95   if (theFlag == TEL_BACK_MATERIAL)
96   {
97     aFace  = GL_BACK;
98     aProps = &AspectFace_set->IntBack();
99   }
100   else if (AspectFace_set->DistinguishingMode() == TOn
101         && !(NamedStatus & OPENGL_NS_RESMAT))
102   {
103     aFace = GL_FRONT;
104   }
105
106   myMatTmp.Init (*aProps);
107
108   // handling transparency
109   if (NamedStatus & OPENGL_NS_2NDPASSDO)
110   {
111     // second pass
112     myMatTmp.Diffuse.a() = aProps->env_reflexion;
113   }
114   else
115   {
116     if (aProps->env_reflexion != 0.0f)
117     {
118       // if the material reflects the environment scene, the second pass is needed
119       NamedStatus |= OPENGL_NS_2NDPASSNEED;
120     }
121
122     if (aProps->trans != 1.0f)
123     {
124       // render transparent
125       myMatTmp.Diffuse.a() = aProps->trans;
126       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
127       glEnable    (GL_BLEND);
128       glDepthMask (GL_FALSE);
129     }
130     else
131     {
132       // render opaque
133       if ((NamedStatus & OPENGL_NS_ANTIALIASING) == 0)
134       {
135         glBlendFunc (GL_ONE, GL_ZERO);
136         glDisable   (GL_BLEND);
137       }
138       glDepthMask (GL_TRUE);
139     }
140   }
141
142   // do not update material properties in case of zero reflection mode,
143   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
144   if (aProps->color_mask == 0)
145   {
146     return;
147   }
148
149   // reset material
150   if (NamedStatus & OPENGL_NS_RESMAT)
151   {
152   #if !defined(GL_ES_VERSION_2_0)
153     glMaterialfv (aFace, GL_AMBIENT,   myMatTmp.Ambient.GetData());
154     glMaterialfv (aFace, GL_DIFFUSE,   myMatTmp.Diffuse.GetData());
155     glMaterialfv (aFace, GL_SPECULAR,  myMatTmp.Specular.GetData());
156     glMaterialfv (aFace, GL_EMISSION,  myMatTmp.Emission.GetData());
157     glMaterialf  (aFace, GL_SHININESS, myMatTmp.Shine());
158   #endif
159
160     if (theFlag == TEL_FRONT_MATERIAL)
161     {
162       myMatFront = myMatTmp;
163       myMatBack  = myMatTmp;
164     }
165     else
166     {
167       myMatBack = myMatTmp;
168     }
169
170     NamedStatus &= ~OPENGL_NS_RESMAT;
171     return;
172   }
173
174   // reduce updates
175   OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL)
176                          ? myMatFront
177                          : myMatBack;
178 #if !defined(GL_ES_VERSION_2_0)
179   if (myMatTmp.Ambient.r() != anOld.Ambient.r()
180    || myMatTmp.Ambient.g() != anOld.Ambient.g()
181    || myMatTmp.Ambient.b() != anOld.Ambient.b())
182   {
183     glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData());
184   }
185   if (myMatTmp.Diffuse.r() != anOld.Diffuse.r()
186    || myMatTmp.Diffuse.g() != anOld.Diffuse.g()
187    || myMatTmp.Diffuse.b() != anOld.Diffuse.b()
188    || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f)
189   {
190     glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData());
191   }
192   if (myMatTmp.Specular.r() != anOld.Specular.r()
193    || myMatTmp.Specular.g() != anOld.Specular.g()
194    || myMatTmp.Specular.b() != anOld.Specular.b())
195   {
196     glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData());
197   }
198   if (myMatTmp.Emission.r() != anOld.Emission.r()
199    || myMatTmp.Emission.g() != anOld.Emission.g()
200    || myMatTmp.Emission.b() != anOld.Emission.b())
201   {
202     glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData());
203   }
204   if (myMatTmp.Shine() != anOld.Shine())
205   {
206     glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine());
207   }
208 #endif
209   anOld = myMatTmp;
210   if (aFace == GL_FRONT_AND_BACK)
211   {
212     myMatBack = myMatTmp;
213   }
214 }
215
216 /*----------------------------------------------------------------------*/
217
218 const OpenGl_AspectLine * OpenGl_Workspace::SetAspectLine(const OpenGl_AspectLine *AnAspect)
219 {
220   const OpenGl_AspectLine *AspectLine_old = AspectLine_set;
221   AspectLine_set = AnAspect;
222   return AspectLine_old;
223 }
224
225 /*----------------------------------------------------------------------*/
226
227 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace(const OpenGl_AspectFace *AnAspect)
228 {
229   const OpenGl_AspectFace *AspectFace_old = AspectFace_set;
230   AspectFace_set = AnAspect;
231   return AspectFace_old;
232 }
233
234 /*----------------------------------------------------------------------*/
235
236 const OpenGl_AspectMarker * OpenGl_Workspace::SetAspectMarker(const OpenGl_AspectMarker *AnAspect)
237 {
238   const OpenGl_AspectMarker *AspectMarker_old = AspectMarker_set;
239   AspectMarker_set = AnAspect;
240   return AspectMarker_old;
241 }
242
243 /*----------------------------------------------------------------------*/
244
245 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText(const OpenGl_AspectText *AnAspect)
246 {
247   const OpenGl_AspectText *AspectText_old = AspectText_set;
248   AspectText_set = AnAspect;
249   return AspectText_old;
250 }
251
252 /*----------------------------------------------------------------------*/
253
254 const OpenGl_AspectLine * OpenGl_Workspace::AspectLine(const Standard_Boolean WithApply)
255 {
256   if ( WithApply && (AspectLine_set != AspectLine_applied) )
257   {
258     const GLfloat* anRgb = AspectLine_set->Color().rgb;
259   #if !defined(GL_ES_VERSION_2_0)
260     glColor3fv(anRgb);
261   #endif
262
263     if ( !AspectLine_applied || (AspectLine_set->Type() != AspectLine_applied->Type() ) )
264     {
265       myLineAttribs->SetTypeOfLine (AspectLine_set->Type());
266     }
267
268     if ( !AspectLine_applied || ( AspectLine_set->Width() != AspectLine_applied->Width() ) )
269     {
270       glLineWidth( (GLfloat)AspectLine_set->Width() );
271 #ifdef HAVE_GL2PS
272       gl2psLineWidth( (GLfloat)AspectLine_set->Width() );
273 #endif
274     }
275
276     AspectLine_applied = AspectLine_set;
277   }
278   return AspectLine_set;
279 }
280
281 /*----------------------------------------------------------------------*/
282
283 const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply)
284 {
285   if (!theToApply)
286   {
287     return AspectFace_set;
288   }
289
290   if (!ActiveView()->Backfacing())
291   {
292     // manage back face culling mode, disable culling when clipping is enabled
293     TelCullMode aCullingMode = (myGlContext->Clipping().IsClippingOrCappingOn()
294                              || AspectFace_set->InteriorStyle() == Aspect_IS_HATCH)
295                              ? TelCullNone
296                              : (TelCullMode )AspectFace_set->CullingMode();
297     if (aCullingMode != TelCullNone
298      && !(NamedStatus & OPENGL_NS_2NDPASSDO))
299     {
300       // disable culling in case of translucent shading aspect
301       if (AspectFace_set->IntFront().trans != 1.0f)
302       {
303         aCullingMode = TelCullNone;
304       }
305     }
306     if (myCullingMode != aCullingMode)
307     {
308       myCullingMode = aCullingMode;
309       switch (myCullingMode)
310       {
311         case TelCullNone:
312         case TelCullUndefined:
313         {
314           glDisable (GL_CULL_FACE);
315           break;
316         }
317         case TelCullFront:
318         {
319           glCullFace (GL_FRONT);
320           glEnable (GL_CULL_FACE);
321           break;
322         }
323         case TelCullBack:
324         {
325           glCullFace (GL_BACK);
326           glEnable (GL_CULL_FACE);
327           break;
328         }
329       }
330     }
331   }
332
333   if (AspectFace_set == AspectFace_applied)
334   {
335     return AspectFace_set;
336   }
337
338 #if !defined(GL_ES_VERSION_2_0)
339   const Aspect_InteriorStyle anIntstyle = AspectFace_set->InteriorStyle();
340   if (AspectFace_applied == NULL || AspectFace_applied->InteriorStyle() != anIntstyle)
341   {
342     switch (anIntstyle)
343     {
344       case Aspect_IS_EMPTY:
345       case Aspect_IS_HOLLOW:
346       {
347         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
348         break;
349       }
350       case Aspect_IS_HATCH:
351       {
352         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
353         myLineAttribs->SetTypeOfHatch (AspectFace_applied != NULL ? AspectFace_applied->Hatch() : TEL_HS_SOLID);
354         break;
355       }
356       case Aspect_IS_SOLID:
357       case Aspect_IS_HIDDENLINE:
358       {
359         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
360         glDisable (GL_POLYGON_STIPPLE);
361         break;
362       }
363       case Aspect_IS_POINT:
364       {
365         glPolygonMode (GL_FRONT_AND_BACK, GL_POINT);
366         break;
367       }
368     }
369   }
370
371   if (anIntstyle == Aspect_IS_HATCH)
372   {
373     const Tint hatchstyle = AspectFace_set->Hatch();
374     if (AspectFace_applied == NULL || AspectFace_applied->Hatch() != hatchstyle)
375     {
376       myLineAttribs->SetTypeOfHatch (hatchstyle);
377     }
378   }
379 #endif
380
381   // Aspect_POM_None means: do not change current settings
382   if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
383   {
384     if (PolygonOffset_applied.mode   != AspectFace_set->PolygonOffset().mode
385      || PolygonOffset_applied.factor != AspectFace_set->PolygonOffset().factor
386      || PolygonOffset_applied.units  != AspectFace_set->PolygonOffset().units)
387     {
388       SetPolygonOffset (AspectFace_set->PolygonOffset().mode,
389                         AspectFace_set->PolygonOffset().factor,
390                         AspectFace_set->PolygonOffset().units);
391     }
392   }
393
394   updateMaterial (TEL_FRONT_MATERIAL);
395   if (AspectFace_set->DistinguishingMode() == TOn)
396   {
397     updateMaterial (TEL_BACK_MATERIAL);
398   }
399
400   if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
401   {
402     if (AspectFace_set->DoTextureMap())
403     {
404       EnableTexture (AspectFace_set->TextureRes (myGlContext),
405                      AspectFace_set->TextureParams());
406     }
407     else
408     {
409       DisableTexture();
410     }
411   }
412
413   AspectFace_applied = AspectFace_set;
414   return AspectFace_set;
415 }
416
417 //=======================================================================
418 //function : SetPolygonOffset
419 //purpose  :
420 //=======================================================================
421 void OpenGl_Workspace::SetPolygonOffset (int theMode,
422                                          Standard_ShortReal theFactor,
423                                          Standard_ShortReal theUnits)
424 {
425   PolygonOffset_applied.mode   = theMode;
426   PolygonOffset_applied.factor = theFactor;
427   PolygonOffset_applied.units  = theUnits;
428
429   TelUpdatePolygonOffsets (PolygonOffset_applied);
430 }
431
432 /*----------------------------------------------------------------------*/
433
434 const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
435 {
436   if (theToApply && (AspectMarker_set != AspectMarker_applied))
437   {
438     if (!AspectMarker_applied || (AspectMarker_set->Scale() != AspectMarker_applied->Scale()))
439     {
440     #if !defined(GL_ES_VERSION_2_0)
441       glPointSize (AspectMarker_set->Scale());
442     #ifdef HAVE_GL2PS
443       gl2psPointSize (AspectMarker_set->Scale());
444     #endif
445     #endif
446     }
447     AspectMarker_applied = AspectMarker_set;
448   }
449   return AspectMarker_set;
450 }
451
452 /*----------------------------------------------------------------------*/
453
454 const OpenGl_AspectText* OpenGl_Workspace::AspectText (const Standard_Boolean theWithApply)
455 {
456   if (theWithApply)
457   {
458     AspectText_applied = AspectText_set;
459     TextParam_applied  = TextParam_set;
460   }
461
462   return AspectText_set;
463 }