1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_Workspace.hxx>
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_ShaderManager.hxx>
31 #include <OpenGl_Texture.hxx>
32 #include <OpenGl_View.hxx>
33 #include <OpenGl_Window.hxx>
35 #include <Graphic3d_TextureParams.hxx>
36 #include <Graphic3d_TransformUtils.hxx>
37 #include <NCollection_AlignedAllocator.hxx>
39 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient)
43 static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f);
44 static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
46 static const OpenGl_Matrix myDefaultMatrix =
48 {{ 1.0F, 0.0F, 0.0F, 0.0F },
49 { 0.0F, 1.0F, 0.0F, 0.0F },
50 { 0.0F, 0.0F, 1.0F, 0.0F },
51 { 0.0F, 0.0F, 0.0F, 1.0F }}
56 // =======================================================================
59 // =======================================================================
60 void OpenGl_Material::Init (const Graphic3d_MaterialAspect& theMat,
61 const Quantity_Color& theInteriorColor)
63 const bool isPhysic = theMat.MaterialType (Graphic3d_MATERIAL_PHYSIC);
64 ChangeShine() = 128.0f * theMat.Shininess();
65 ChangeTransparency() = theMat.Alpha();
68 if (theMat.ReflectionMode (Graphic3d_TOR_AMBIENT))
70 const OpenGl_Vec3& aSrcAmb = isPhysic ? theMat.AmbientColor() : theInteriorColor;
71 Ambient = OpenGl_Vec4 (aSrcAmb * theMat.Ambient(), 1.0f);
75 Ambient = THE_BLACK_COLOR;
78 // diffusion component
79 if (theMat.ReflectionMode (Graphic3d_TOR_DIFFUSE))
81 const OpenGl_Vec3& aSrcDif = isPhysic ? theMat.DiffuseColor() : theInteriorColor;
82 Diffuse = OpenGl_Vec4 (aSrcDif * theMat.Diffuse(), 1.0f);
86 Diffuse = THE_BLACK_COLOR;
90 if (theMat.ReflectionMode (Graphic3d_TOR_SPECULAR))
92 const OpenGl_Vec3& aSrcSpe = isPhysic ? (const OpenGl_Vec3& )theMat.SpecularColor() : THE_WHITE_COLOR.rgb();
93 Specular = OpenGl_Vec4 (aSrcSpe * theMat.Specular(), 1.0f);
97 Specular = THE_BLACK_COLOR;
100 // emission component
101 if (theMat.ReflectionMode (Graphic3d_TOR_EMISSION))
103 const OpenGl_Vec3& aSrcEms = isPhysic ? theMat.EmissiveColor() : theInteriorColor;
104 Emission = OpenGl_Vec4 (aSrcEms * theMat.Emissive(), 1.0f);
108 Emission = THE_BLACK_COLOR;
112 // =======================================================================
113 // function : OpenGl_Workspace
115 // =======================================================================
116 OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow)
118 myWindow (theWindow),
119 myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL),
120 myUseZBuffer (Standard_True),
121 myUseDepthWrite (Standard_True),
123 myNbSkippedTranspElems (0),
124 myRenderFilter (OpenGl_RenderFilter_Empty),
126 myAspectLineSet (&myDefaultAspectLine),
127 myAspectFaceSet (&myDefaultAspectFace),
128 myAspectMarkerSet (&myDefaultAspectMarker),
129 myAspectTextSet (&myDefaultAspectText),
131 ViewMatrix_applied (&myDefaultMatrix),
132 StructureMatrix_applied (&myDefaultMatrix),
133 myToAllowFaceCulling (false),
134 myModelViewMatrix (myDefaultMatrix)
136 if (!myGlContext.IsNull() && myGlContext->MakeCurrent())
138 myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
140 // General initialization of the context
141 #if !defined(GL_ES_VERSION_2_0)
142 if (myGlContext->core11 != NULL)
144 // enable two-side lighting by default
145 glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
146 glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST);
147 if (myGlContext->caps->ffpEnable)
149 glHint (GL_FOG_HINT, GL_FASTEST);
153 glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST);
154 glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
158 myFontFaceAspect.Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Mask, 0.285f);
159 myFontFaceAspect.Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
161 myNoneCulling .Aspect()->SetSuppressBackFaces (false);
162 myNoneCulling .Aspect()->SetDrawEdges (false);
163 myNoneCulling .Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Opaque);
165 myFrontCulling.Aspect()->SetSuppressBackFaces (true);
166 myFrontCulling.Aspect()->SetDrawEdges (false);
167 myFrontCulling.Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Opaque);
170 // =======================================================================
171 // function : Activate
173 // =======================================================================
174 Standard_Boolean OpenGl_Workspace::Activate()
176 if (myWindow.IsNull() || !myWindow->Activate())
178 return Standard_False;
181 ViewMatrix_applied = &myDefaultMatrix;
182 StructureMatrix_applied = &myDefaultMatrix;
184 ResetAppliedAspect();
186 // reset state for safety
187 myGlContext->BindProgram (Handle(OpenGl_ShaderProgram)());
188 if (myGlContext->core20fwd != NULL)
190 myGlContext->core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM);
192 if (myGlContext->caps->ffpEnable)
194 myGlContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
196 return Standard_True;
199 //=======================================================================
200 //function : ResetAppliedAspect
201 //purpose : Sets default values of GL parameters in accordance with default aspects
202 //=======================================================================
203 void OpenGl_Workspace::ResetAppliedAspect()
205 myGlContext->BindDefaultVao();
207 myHighlightStyle.Nullify();
208 myToAllowFaceCulling = false;
209 myAspectLineSet = &myDefaultAspectLine;
210 myAspectFaceSet = &myDefaultAspectFace;
211 myAspectFaceApplied.Nullify();
212 myAspectMarkerSet = &myDefaultAspectMarker;
213 myAspectMarkerApplied.Nullify();
214 myAspectTextSet = &myDefaultAspectText;
215 myGlContext->SetPolygonOffset (Graphic3d_PolygonOffset());
222 myGlContext->SetTypeOfLine (myDefaultAspectLine.Aspect()->Type());
223 myGlContext->SetLineWidth (myDefaultAspectLine.Aspect()->Width());
226 // =======================================================================
227 // function : SetDefaultPolygonOffset
229 // =======================================================================
230 Graphic3d_PolygonOffset OpenGl_Workspace::SetDefaultPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
232 Graphic3d_PolygonOffset aPrev = myDefaultAspectFace.Aspect()->PolygonOffset();
233 myDefaultAspectFace.Aspect()->SetPolygonOffset (theOffset);
234 if (myAspectFaceApplied == myDefaultAspectFace.Aspect()
235 || myAspectFaceApplied.IsNull()
236 || (myAspectFaceApplied->PolygonOffset().Mode & Aspect_POM_None) == Aspect_POM_None)
238 myGlContext->SetPolygonOffset (theOffset);
243 // =======================================================================
244 // function : SetAspectLine
246 // =======================================================================
247 const OpenGl_AspectLine* OpenGl_Workspace::SetAspectLine (const OpenGl_AspectLine* theAspect)
249 const OpenGl_AspectLine* aPrevAspectLine = myAspectLineSet;
250 myAspectLineSet = theAspect;
251 return aPrevAspectLine;
254 // =======================================================================
255 // function : SetAspectFace
257 // =======================================================================
258 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace (const OpenGl_AspectFace* theAspect)
260 const OpenGl_AspectFace* aPrevAspectFace = myAspectFaceSet;
261 myAspectFaceSet = theAspect;
262 return aPrevAspectFace;
265 // =======================================================================
266 // function : SetAspectMarker
268 // =======================================================================
269 const OpenGl_AspectMarker* OpenGl_Workspace::SetAspectMarker (const OpenGl_AspectMarker* theAspect)
271 const OpenGl_AspectMarker* aPrevAspectMarker = myAspectMarkerSet;
272 myAspectMarkerSet = theAspect;
273 return aPrevAspectMarker;
276 // =======================================================================
277 // function : SetAspectText
279 // =======================================================================
280 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText (const OpenGl_AspectText* theAspect)
282 const OpenGl_AspectText* aPrevAspectText = myAspectTextSet;
283 myAspectTextSet = theAspect;
284 return aPrevAspectText;
287 // =======================================================================
288 // function : ApplyAspectFace
290 // =======================================================================
291 const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
293 if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
295 bool toSuppressBackFaces = myToAllowFaceCulling
296 && myAspectFaceSet->Aspect()->ToSuppressBackFaces();
297 if (toSuppressBackFaces)
299 if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH
300 || myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend
301 || myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask
302 || (myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto
303 && myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f))
305 // disable culling in case of translucent shading aspect
306 toSuppressBackFaces = false;
309 myGlContext->SetCullBackFaces (toSuppressBackFaces);
312 if (myAspectFaceSet->Aspect() == myAspectFaceApplied
313 && myHighlightStyle == myAspectFaceAppliedWithHL)
315 return myAspectFaceSet;
317 myAspectFaceAppliedWithHL = myHighlightStyle;
319 #if !defined(GL_ES_VERSION_2_0)
320 const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle();
321 if (myAspectFaceApplied.IsNull()
322 || myAspectFaceApplied->InteriorStyle() != anIntstyle)
326 case Aspect_IS_EMPTY:
327 case Aspect_IS_HOLLOW:
329 myGlContext->SetPolygonMode (GL_LINE);
332 case Aspect_IS_HATCH:
334 myGlContext->SetPolygonMode (GL_FILL);
335 myGlContext->SetPolygonHatchEnabled (true);
338 case Aspect_IS_SOLID:
339 case Aspect_IS_HIDDENLINE:
341 myGlContext->SetPolygonMode (GL_FILL);
342 myGlContext->SetPolygonHatchEnabled (false);
345 case Aspect_IS_POINT:
347 myGlContext->SetPolygonMode (GL_POINT);
353 if (anIntstyle == Aspect_IS_HATCH)
355 myGlContext->SetPolygonHatchStyle (myAspectFaceSet->Aspect()->HatchStyle());
359 // Aspect_POM_None means: do not change current settings
360 if ((myAspectFaceSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None)
362 myGlContext->SetPolygonOffset (myAspectFaceSet->Aspect()->PolygonOffset());
365 // Case of hidden line
366 if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
368 // copy all values including line edge aspect
369 *myAspectFaceHl.Aspect() = *myAspectFaceSet->Aspect();
370 myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge());
371 myAspectFaceHl.Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
372 myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB());
373 myAspectFaceHl.SetNoLighting();
374 myAspectFaceSet = &myAspectFaceHl;
378 myGlContext->SetShadingMaterial (myAspectFaceSet, myHighlightStyle);
381 if (myAspectFaceSet->Aspect()->ToMapTexture())
383 myGlContext->BindTextures (myAspectFaceSet->TextureSet (myGlContext));
387 myGlContext->BindTextures (myEnvironmentTexture);
390 myAspectFaceApplied = myAspectFaceSet->Aspect();
391 return myAspectFaceSet;
394 // =======================================================================
395 // function : ApplyAspectMarker
397 // =======================================================================
398 const OpenGl_AspectMarker* OpenGl_Workspace::ApplyAspectMarker()
400 if (myAspectMarkerSet->Aspect() != myAspectMarkerApplied)
402 if (myAspectMarkerApplied.IsNull()
403 || (myAspectMarkerSet->Aspect()->Scale() != myAspectMarkerApplied->Scale()))
405 #if !defined(GL_ES_VERSION_2_0)
406 glPointSize (myAspectMarkerSet->Aspect()->Scale());
409 myAspectMarkerApplied = myAspectMarkerSet->Aspect();
411 return myAspectMarkerSet;
414 // =======================================================================
417 // =======================================================================
418 Standard_Integer OpenGl_Workspace::Width() const
420 return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0;
423 // =======================================================================
426 // =======================================================================
427 Standard_Integer OpenGl_Workspace::Height() const
429 return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0;
432 // =======================================================================
433 // function : FBOCreate
435 // =======================================================================
436 Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
437 const Standard_Integer theHeight)
439 // activate OpenGL context
441 return Handle(OpenGl_FrameBuffer)();
444 const Handle(OpenGl_Context)& aCtx = GetGlContext();
445 aCtx->BindTextures (Handle(OpenGl_TextureSet)());
446 Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer();
447 if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0))
449 aFrameBuffer->Release (aCtx.operator->());
450 return Handle(OpenGl_FrameBuffer)();
455 // =======================================================================
456 // function : FBORelease
458 // =======================================================================
459 void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo)
461 // activate OpenGL context
468 theFbo->Release (GetGlContext().operator->());
472 // =======================================================================
473 // function : BufferDump
475 // =======================================================================
476 Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo,
477 Image_PixMap& theImage,
478 const Graphic3d_BufferType& theBufferType)
480 return !theImage.IsEmpty()
482 && OpenGl_FrameBuffer::BufferDump (GetGlContext(), theFbo, theImage, theBufferType);
485 // =======================================================================
486 // function : ShouldRender
488 // =======================================================================
489 bool OpenGl_Workspace::ShouldRender (const OpenGl_Element* theElement)
491 // render only non-raytracable elements when RayTracing is enabled
492 if ((myRenderFilter & OpenGl_RenderFilter_NonRaytraceableOnly) != 0)
494 if (OpenGl_Raytrace::IsRaytracedElement (theElement))
499 else if ((myRenderFilter & OpenGl_RenderFilter_FillModeOnly) != 0)
501 if (!theElement->IsFillDrawMode())
507 // handle opaque/transparency render passes
508 if ((myRenderFilter & OpenGl_RenderFilter_OpaqueOnly) != 0)
510 if (!theElement->IsFillDrawMode())
515 if (OpenGl_Context::CheckIsTransparent (myAspectFaceSet, myHighlightStyle))
517 ++myNbSkippedTranspElems;
521 else if ((myRenderFilter & OpenGl_RenderFilter_TransparentOnly) != 0)
523 if (!theElement->IsFillDrawMode())
525 if (dynamic_cast<const OpenGl_AspectFace*> (theElement) == NULL)
530 else if (!OpenGl_Context::CheckIsTransparent (myAspectFaceSet, myHighlightStyle))