0029516: Visualization - eliminate redundant property Graphic3d_MaterialAspect::Refle...
[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_Aspects.hxx>
20 #include <OpenGl_Context.hxx>
21 #include <OpenGl_Element.hxx>
22 #include <OpenGl_FrameBuffer.hxx>
23 #include <OpenGl_GlCore15.hxx>
24 #include <OpenGl_SceneGeometry.hxx>
25 #include <OpenGl_Structure.hxx>
26 #include <OpenGl_Sampler.hxx>
27 #include <OpenGl_ShaderManager.hxx>
28 #include <OpenGl_Texture.hxx>
29 #include <OpenGl_View.hxx>
30 #include <OpenGl_Window.hxx>
31
32 #include <Graphic3d_TextureParams.hxx>
33 #include <Graphic3d_TransformUtils.hxx>
34 #include <NCollection_AlignedAllocator.hxx>
35
36 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient)
37
38 namespace
39 {
40   static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f);
41   static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
42
43   static const OpenGl_Matrix myDefaultMatrix =
44   {
45     {{ 1.0F, 0.0F, 0.0F, 0.0F },
46      { 0.0F, 1.0F, 0.0F, 0.0F },
47      { 0.0F, 0.0F, 1.0F, 0.0F },
48      { 0.0F, 0.0F, 0.0F, 1.0F }}
49   };
50
51 }
52
53 // =======================================================================
54 // function : Init
55 // purpose  :
56 // =======================================================================
57 void OpenGl_Material::Init (const Graphic3d_MaterialAspect& theMat,
58                             const Quantity_Color&           theInteriorColor)
59 {
60   ChangeShine()        = 128.0f * theMat.Shininess();
61   ChangeTransparency() = theMat.Alpha();
62
63   const OpenGl_Vec3& aSrcAmb = theMat.AmbientColor();
64   const OpenGl_Vec3& aSrcDif = theMat.DiffuseColor();
65   const OpenGl_Vec3& aSrcSpe = theMat.SpecularColor();
66   const OpenGl_Vec3& aSrcEms = theMat.EmissiveColor();
67   Specular.SetValues (aSrcSpe, 1.0f); // interior color is ignored for Specular
68   switch (theMat.MaterialType())
69   {
70     case Graphic3d_MATERIAL_ASPECT:
71     {
72       Ambient .SetValues (aSrcAmb * theInteriorColor, 1.0f);
73       Diffuse .SetValues (aSrcDif * theInteriorColor, 1.0f);
74       Emission.SetValues (aSrcEms * theInteriorColor, 1.0f);
75       break;
76     }
77     case Graphic3d_MATERIAL_PHYSIC:
78     {
79       Ambient .SetValues (aSrcAmb, 1.0f);
80       Diffuse .SetValues (aSrcDif, 1.0f);
81       Emission.SetValues (aSrcEms, 1.0f);
82       break;
83     }
84   }
85 }
86
87 // =======================================================================
88 // function : OpenGl_Workspace
89 // purpose  :
90 // =======================================================================
91 OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow)
92 : myView (theView),
93   myWindow (theWindow),
94   myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL),
95   myUseZBuffer    (Standard_True),
96   myUseDepthWrite (Standard_True),
97   //
98   myNbSkippedTranspElems (0),
99   myRenderFilter (OpenGl_RenderFilter_Empty),
100   //
101   myAspectsSet (&myDefaultAspects),
102   //
103   ViewMatrix_applied (&myDefaultMatrix),
104   StructureMatrix_applied (&myDefaultMatrix),
105   myToAllowFaceCulling (false),
106   myModelViewMatrix (myDefaultMatrix)
107 {
108   if (!myGlContext.IsNull() && myGlContext->MakeCurrent())
109   {
110     myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
111
112     // General initialization of the context
113   #if !defined(GL_ES_VERSION_2_0)
114     if (myGlContext->core11 != NULL)
115     {
116       // enable two-side lighting by default
117       glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
118       glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST);
119       if (myGlContext->caps->ffpEnable)
120       {
121         glHint (GL_FOG_HINT, GL_FASTEST);
122       }
123     }
124
125     glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
126     glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
127     if (myGlContext->Vendor() == "microsoft corporation"
128     && !myGlContext->IsGlGreaterEqual (1, 2))
129     {
130       // this software implementation causes too slow rendering into GL_FRONT on modern Windows
131       theView->SetImmediateModeDrawToFront (false);
132     }
133   #endif
134   }
135
136   myNoneCulling .Aspect()->SetSuppressBackFaces (false);
137   myNoneCulling .Aspect()->SetDrawEdges (false);
138   myNoneCulling .Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Opaque);
139
140   myFrontCulling.Aspect()->SetSuppressBackFaces (true);
141   myFrontCulling.Aspect()->SetDrawEdges (false);
142   myFrontCulling.Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Opaque);
143 }
144
145 // =======================================================================
146 // function : Activate
147 // purpose  :
148 // =======================================================================
149 Standard_Boolean OpenGl_Workspace::Activate()
150 {
151   if (myWindow.IsNull() || !myWindow->Activate())
152   {
153     return Standard_False;
154   }
155
156   ViewMatrix_applied      = &myDefaultMatrix;
157   StructureMatrix_applied = &myDefaultMatrix;
158
159   ResetAppliedAspect();
160
161   // reset state for safety
162   myGlContext->BindProgram (Handle(OpenGl_ShaderProgram)());
163   if (myGlContext->core20fwd != NULL)
164   {
165     myGlContext->core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM);
166   }
167   if (myGlContext->caps->ffpEnable)
168   {
169     myGlContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
170   }
171   return Standard_True;
172 }
173
174 //=======================================================================
175 //function : ResetAppliedAspect
176 //purpose  : Sets default values of GL parameters in accordance with default aspects
177 //=======================================================================
178 void OpenGl_Workspace::ResetAppliedAspect()
179 {
180   myGlContext->BindDefaultVao();
181
182   myHighlightStyle.Nullify();
183   myToAllowFaceCulling  = false;
184   myAspectsSet = &myDefaultAspects;
185   myAspectsApplied.Nullify();
186   myGlContext->SetPolygonOffset (Graphic3d_PolygonOffset());
187
188   ApplyAspects();
189   myGlContext->SetTypeOfLine (myDefaultAspects.Aspect()->LineType());
190   myGlContext->SetLineWidth  (myDefaultAspects.Aspect()->LineWidth());
191   if (myGlContext->core15fwd != NULL)
192   {
193     myGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
194   }
195 }
196
197 // =======================================================================
198 // function : SetDefaultPolygonOffset
199 // purpose  :
200 // =======================================================================
201 Graphic3d_PolygonOffset OpenGl_Workspace::SetDefaultPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
202 {
203   Graphic3d_PolygonOffset aPrev = myDefaultAspects.Aspect()->PolygonOffset();
204   myDefaultAspects.Aspect()->SetPolygonOffset (theOffset);
205   if (myAspectsApplied == myDefaultAspects.Aspect()
206    || myAspectsApplied.IsNull()
207    || (myAspectsApplied->PolygonOffset().Mode & Aspect_POM_None) == Aspect_POM_None)
208   {
209     myGlContext->SetPolygonOffset (theOffset);
210   }
211   return aPrev;
212 }
213
214 // =======================================================================
215 // function : SetAspects
216 // purpose  :
217 // =======================================================================
218 const OpenGl_Aspects* OpenGl_Workspace::SetAspects (const OpenGl_Aspects* theAspect)
219 {
220   const OpenGl_Aspects* aPrevAspects = myAspectsSet;
221   myAspectsSet = theAspect;
222   return aPrevAspects;
223 }
224
225 // =======================================================================
226 // function : ApplyAspects
227 // purpose  :
228 // =======================================================================
229 const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects()
230 {
231   if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
232   {
233     bool toSuppressBackFaces = myToAllowFaceCulling
234                             && myAspectsSet->Aspect()->ToSuppressBackFaces();
235     if (toSuppressBackFaces)
236     {
237       if (myAspectsSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH
238        || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend
239        || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask
240        || (myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto
241         && myAspectsSet->Aspect()->FrontMaterial().Transparency() != 0.0f))
242       {
243         // disable culling in case of translucent shading aspect
244         toSuppressBackFaces = false;
245       }
246     }
247     myGlContext->SetCullBackFaces (toSuppressBackFaces);
248   }
249
250   if (myAspectsSet->Aspect() == myAspectsApplied
251    && myHighlightStyle == myAspectFaceAppliedWithHL)
252   {
253     return myAspectsSet;
254   }
255   myAspectFaceAppliedWithHL = myHighlightStyle;
256
257   // Aspect_POM_None means: do not change current settings
258   if ((myAspectsSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None)
259   {
260     myGlContext->SetPolygonOffset (myAspectsSet->Aspect()->PolygonOffset());
261   }
262
263   const Aspect_InteriorStyle anIntstyle = myAspectsSet->Aspect()->InteriorStyle();
264   if (myAspectsApplied.IsNull()
265    || myAspectsApplied->InteriorStyle() != anIntstyle)
266   {
267   #if !defined(GL_ES_VERSION_2_0)
268     myGlContext->SetPolygonMode (anIntstyle == Aspect_IS_POINT ? GL_POINT : GL_FILL);
269     myGlContext->SetPolygonHatchEnabled (anIntstyle == Aspect_IS_HATCH);
270   #endif
271   }
272
273 #if !defined(GL_ES_VERSION_2_0)
274   if (anIntstyle == Aspect_IS_HATCH)
275   {
276     myGlContext->SetPolygonHatchStyle (myAspectsSet->Aspect()->HatchStyle());
277   }
278 #endif
279
280   // Case of hidden line
281   if (anIntstyle == Aspect_IS_HIDDENLINE)
282   {
283     // copy all values including line edge aspect
284     *myAspectFaceHl.Aspect() = *myAspectsSet->Aspect();
285     myAspectFaceHl.Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
286     myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB());
287     myAspectFaceHl.Aspect()->SetDistinguish (false);
288     myAspectFaceHl.SetNoLighting();
289     myAspectsSet = &myAspectFaceHl;
290   }
291   else
292   {
293     myGlContext->SetShadingMaterial (myAspectsSet, myHighlightStyle);
294   }
295
296   const Handle(OpenGl_TextureSet)& aTextureSet = myAspectsSet->TextureSet (myGlContext, ToHighlight());
297   if (!aTextureSet.IsNull()
298    || myAspectsSet->Aspect()->ToMapTexture())
299   {
300     myGlContext->BindTextures (aTextureSet);
301   }
302   else
303   {
304     myGlContext->BindTextures (myEnvironmentTexture);
305   }
306
307   myAspectsApplied = myAspectsSet->Aspect();
308   return myAspectsSet;
309 }
310
311 // =======================================================================
312 // function : Width
313 // purpose  :
314 // =======================================================================
315 Standard_Integer OpenGl_Workspace::Width()  const
316 {
317   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0;
318 }
319
320 // =======================================================================
321 // function : Height
322 // purpose  :
323 // =======================================================================
324 Standard_Integer OpenGl_Workspace::Height() const
325 {
326   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0;
327 }
328
329 // =======================================================================
330 // function : FBOCreate
331 // purpose  :
332 // =======================================================================
333 Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
334                                                         const Standard_Integer theHeight)
335 {
336   // activate OpenGL context
337   if (!Activate())
338     return Handle(OpenGl_FrameBuffer)();
339
340   // create the FBO
341   const Handle(OpenGl_Context)& aCtx = GetGlContext();
342   aCtx->BindTextures (Handle(OpenGl_TextureSet)());
343   Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer();
344   if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0))
345   {
346     aFrameBuffer->Release (aCtx.operator->());
347     return Handle(OpenGl_FrameBuffer)();
348   }
349   return aFrameBuffer;
350 }
351
352 // =======================================================================
353 // function : FBORelease
354 // purpose  :
355 // =======================================================================
356 void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo)
357 {
358   // activate OpenGL context
359   if (!Activate()
360    || theFbo.IsNull())
361   {
362     return;
363   }
364
365   theFbo->Release (GetGlContext().operator->());
366   theFbo.Nullify();
367 }
368
369 // =======================================================================
370 // function : BufferDump
371 // purpose  :
372 // =======================================================================
373 Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo,
374                                                Image_PixMap&                     theImage,
375                                                const Graphic3d_BufferType&       theBufferType)
376 {
377   return !theImage.IsEmpty()
378       && Activate()
379       && OpenGl_FrameBuffer::BufferDump (GetGlContext(), theFbo, theImage, theBufferType);
380 }
381
382 // =======================================================================
383 // function : ShouldRender
384 // purpose  :
385 // =======================================================================
386 bool OpenGl_Workspace::ShouldRender (const OpenGl_Element* theElement)
387 {
388   // render only non-raytracable elements when RayTracing is enabled
389   if ((myRenderFilter & OpenGl_RenderFilter_NonRaytraceableOnly) != 0)
390   {
391     if (OpenGl_Raytrace::IsRaytracedElement (theElement))
392     {
393       return false;
394     }
395   }
396   else if ((myRenderFilter & OpenGl_RenderFilter_FillModeOnly) != 0)
397   {
398     if (!theElement->IsFillDrawMode())
399     {
400       return false;
401     }
402   }
403
404   // handle opaque/transparency render passes
405   if ((myRenderFilter & OpenGl_RenderFilter_OpaqueOnly) != 0)
406   {
407     if (!theElement->IsFillDrawMode())
408     {
409       return true;
410     }
411
412     if (OpenGl_Context::CheckIsTransparent (myAspectsSet, myHighlightStyle))
413     {
414       ++myNbSkippedTranspElems;
415       return false;
416     }
417   }
418   else if ((myRenderFilter & OpenGl_RenderFilter_TransparentOnly) != 0)
419   {
420     if (!theElement->IsFillDrawMode())
421     {
422       if (dynamic_cast<const OpenGl_Aspects*> (theElement) == NULL)
423       {
424         return false;
425       }
426     }
427     else if (!OpenGl_Context::CheckIsTransparent (myAspectsSet, myHighlightStyle))
428     {
429       return false;
430     }
431   }
432   return true;
433 }