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_Blend, 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)());
197 #if !defined(GL_ES_VERSION_2_0)
198 // font GLSL program has embedded discard, while FFP needs alpha test
199 myFontFaceAspect.Aspect()->SetAlphaMode ((!myGlContext->caps->ffpEnable && myGlContext->core11 != NULL)
200 ? Graphic3d_AlphaMode_Blend
201 : Graphic3d_AlphaMode_Mask,
204 return Standard_True;
207 //=======================================================================
208 //function : ResetAppliedAspect
209 //purpose : Sets default values of GL parameters in accordance with default aspects
210 //=======================================================================
211 void OpenGl_Workspace::ResetAppliedAspect()
213 myGlContext->BindDefaultVao();
215 myHighlightStyle.Nullify();
216 myToAllowFaceCulling = false;
217 myAspectLineSet = &myDefaultAspectLine;
218 myAspectFaceSet = &myDefaultAspectFace;
219 myAspectFaceApplied.Nullify();
220 myAspectMarkerSet = &myDefaultAspectMarker;
221 myAspectMarkerApplied.Nullify();
222 myAspectTextSet = &myDefaultAspectText;
223 myGlContext->SetPolygonOffset (Graphic3d_PolygonOffset());
230 myGlContext->SetTypeOfLine (myDefaultAspectLine.Aspect()->Type());
231 myGlContext->SetLineWidth (myDefaultAspectLine.Aspect()->Width());
234 // =======================================================================
235 // function : SetDefaultPolygonOffset
237 // =======================================================================
238 Graphic3d_PolygonOffset OpenGl_Workspace::SetDefaultPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
240 Graphic3d_PolygonOffset aPrev = myDefaultAspectFace.Aspect()->PolygonOffset();
241 myDefaultAspectFace.Aspect()->SetPolygonOffset (theOffset);
242 if (myAspectFaceApplied == myDefaultAspectFace.Aspect()
243 || myAspectFaceApplied.IsNull()
244 || (myAspectFaceApplied->PolygonOffset().Mode & Aspect_POM_None) == Aspect_POM_None)
246 myGlContext->SetPolygonOffset (theOffset);
251 // =======================================================================
252 // function : SetAspectLine
254 // =======================================================================
255 const OpenGl_AspectLine* OpenGl_Workspace::SetAspectLine (const OpenGl_AspectLine* theAspect)
257 const OpenGl_AspectLine* aPrevAspectLine = myAspectLineSet;
258 myAspectLineSet = theAspect;
259 return aPrevAspectLine;
262 // =======================================================================
263 // function : SetAspectFace
265 // =======================================================================
266 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace (const OpenGl_AspectFace* theAspect)
268 const OpenGl_AspectFace* aPrevAspectFace = myAspectFaceSet;
269 myAspectFaceSet = theAspect;
270 return aPrevAspectFace;
273 // =======================================================================
274 // function : SetAspectMarker
276 // =======================================================================
277 const OpenGl_AspectMarker* OpenGl_Workspace::SetAspectMarker (const OpenGl_AspectMarker* theAspect)
279 const OpenGl_AspectMarker* aPrevAspectMarker = myAspectMarkerSet;
280 myAspectMarkerSet = theAspect;
281 return aPrevAspectMarker;
284 // =======================================================================
285 // function : SetAspectText
287 // =======================================================================
288 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText (const OpenGl_AspectText* theAspect)
290 const OpenGl_AspectText* aPrevAspectText = myAspectTextSet;
291 myAspectTextSet = theAspect;
292 return aPrevAspectText;
295 // =======================================================================
296 // function : ApplyAspectFace
298 // =======================================================================
299 const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
301 if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
303 bool toSuppressBackFaces = myToAllowFaceCulling
304 && myAspectFaceSet->Aspect()->ToSuppressBackFaces();
305 if (toSuppressBackFaces)
307 if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH
308 || myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend
309 || myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask
310 || (myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto
311 && myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f))
313 // disable culling in case of translucent shading aspect
314 toSuppressBackFaces = false;
317 myGlContext->SetCullBackFaces (toSuppressBackFaces);
320 if (myAspectFaceSet->Aspect() == myAspectFaceApplied
321 && myHighlightStyle == myAspectFaceAppliedWithHL)
323 return myAspectFaceSet;
325 myAspectFaceAppliedWithHL = myHighlightStyle;
327 // Aspect_POM_None means: do not change current settings
328 if ((myAspectFaceSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None)
330 myGlContext->SetPolygonOffset (myAspectFaceSet->Aspect()->PolygonOffset());
333 const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle();
334 if (myAspectFaceApplied.IsNull()
335 || myAspectFaceApplied->InteriorStyle() != anIntstyle)
337 #if !defined(GL_ES_VERSION_2_0)
338 myGlContext->SetPolygonMode (anIntstyle == Aspect_IS_POINT ? GL_POINT : GL_FILL);
339 myGlContext->SetPolygonHatchEnabled (anIntstyle == Aspect_IS_HATCH);
343 #if !defined(GL_ES_VERSION_2_0)
344 if (anIntstyle == Aspect_IS_HATCH)
346 myGlContext->SetPolygonHatchStyle (myAspectFaceSet->Aspect()->HatchStyle());
350 // Case of hidden line
351 if (anIntstyle == Aspect_IS_HIDDENLINE)
353 // copy all values including line edge aspect
354 *myAspectFaceHl.Aspect() = *myAspectFaceSet->Aspect();
355 myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge());
356 myAspectFaceHl.Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT);
357 myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB());
358 myAspectFaceHl.Aspect()->SetDistinguish (false);
359 myAspectFaceHl.SetNoLighting();
360 myAspectFaceSet = &myAspectFaceHl;
364 myGlContext->SetShadingMaterial (myAspectFaceSet, myHighlightStyle);
367 if (myAspectFaceSet->Aspect()->ToMapTexture())
369 myGlContext->BindTextures (myAspectFaceSet->TextureSet (myGlContext));
373 myGlContext->BindTextures (myEnvironmentTexture);
376 myAspectFaceApplied = myAspectFaceSet->Aspect();
377 return myAspectFaceSet;
380 // =======================================================================
381 // function : ApplyAspectMarker
383 // =======================================================================
384 const OpenGl_AspectMarker* OpenGl_Workspace::ApplyAspectMarker()
386 if (myAspectMarkerSet->Aspect() != myAspectMarkerApplied)
388 if (myAspectMarkerApplied.IsNull()
389 || (myAspectMarkerSet->Aspect()->Scale() != myAspectMarkerApplied->Scale()))
391 #if !defined(GL_ES_VERSION_2_0)
392 glPointSize (myAspectMarkerSet->Aspect()->Scale());
395 myAspectMarkerApplied = myAspectMarkerSet->Aspect();
397 return myAspectMarkerSet;
400 // =======================================================================
403 // =======================================================================
404 Standard_Integer OpenGl_Workspace::Width() const
406 return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0;
409 // =======================================================================
412 // =======================================================================
413 Standard_Integer OpenGl_Workspace::Height() const
415 return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0;
418 // =======================================================================
419 // function : FBOCreate
421 // =======================================================================
422 Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
423 const Standard_Integer theHeight)
425 // activate OpenGL context
427 return Handle(OpenGl_FrameBuffer)();
430 const Handle(OpenGl_Context)& aCtx = GetGlContext();
431 aCtx->BindTextures (Handle(OpenGl_TextureSet)());
432 Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer();
433 if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0))
435 aFrameBuffer->Release (aCtx.operator->());
436 return Handle(OpenGl_FrameBuffer)();
441 // =======================================================================
442 // function : FBORelease
444 // =======================================================================
445 void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo)
447 // activate OpenGL context
454 theFbo->Release (GetGlContext().operator->());
458 // =======================================================================
459 // function : BufferDump
461 // =======================================================================
462 Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo,
463 Image_PixMap& theImage,
464 const Graphic3d_BufferType& theBufferType)
466 return !theImage.IsEmpty()
468 && OpenGl_FrameBuffer::BufferDump (GetGlContext(), theFbo, theImage, theBufferType);
471 // =======================================================================
472 // function : ShouldRender
474 // =======================================================================
475 bool OpenGl_Workspace::ShouldRender (const OpenGl_Element* theElement)
477 // render only non-raytracable elements when RayTracing is enabled
478 if ((myRenderFilter & OpenGl_RenderFilter_NonRaytraceableOnly) != 0)
480 if (OpenGl_Raytrace::IsRaytracedElement (theElement))
485 else if ((myRenderFilter & OpenGl_RenderFilter_FillModeOnly) != 0)
487 if (!theElement->IsFillDrawMode())
493 // handle opaque/transparency render passes
494 if ((myRenderFilter & OpenGl_RenderFilter_OpaqueOnly) != 0)
496 if (!theElement->IsFillDrawMode())
501 if (OpenGl_Context::CheckIsTransparent (myAspectFaceSet, myHighlightStyle))
503 ++myNbSkippedTranspElems;
507 else if ((myRenderFilter & OpenGl_RenderFilter_TransparentOnly) != 0)
509 if (!theElement->IsFillDrawMode())
511 if (dynamic_cast<const OpenGl_AspectFace*> (theElement) == NULL)
516 else if (!OpenGl_Context::CheckIsTransparent (myAspectFaceSet, myHighlightStyle))