1 // Created on: 2013-09-05
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013-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_CappingAlgo.hxx>
18 #include <OpenGl_Workspace.hxx>
19 #include <OpenGl_Context.hxx>
20 #include <OpenGl_PrimitiveArray.hxx>
21 #include <OpenGl_CappingPlaneResource.hxx>
22 #include <OpenGl_Vec.hxx>
23 #include <OpenGl_Structure.hxx>
24 #include <OpenGl_ShaderManager.hxx>
26 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter,OpenGl_RenderFilter)
30 //! Render infinite capping plane.
31 //! @param theWorkspace [in] the GL workspace, context state.
32 //! @param thePlane [in] the graphical plane, for which the capping surface is rendered.
33 static void renderPlane (const Handle(OpenGl_Workspace)& theWorkspace,
34 const Handle(OpenGl_CappingPlaneResource)& thePlane,
35 const OpenGl_AspectFace* theAspectFace)
37 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
38 thePlane->Update (aContext, theAspectFace != NULL ? theAspectFace->Aspect() : Handle(Graphic3d_AspectFillArea3d)());
40 const OpenGl_AspectFace* aFaceAspect = theWorkspace->AspectFace();
41 theWorkspace->SetAspectFace (thePlane->AspectFace());
43 // set identity model matrix
44 aContext->ModelWorldState.Push();
45 aContext->ModelWorldState.SetCurrent (OpenGl_Mat4::Map (*thePlane->Orientation()->mat));
46 aContext->ApplyModelViewMatrix();
48 thePlane->Primitives().Render (theWorkspace);
50 aContext->ModelWorldState.Pop();
51 aContext->ApplyModelViewMatrix();
53 theWorkspace->SetAspectFace (aFaceAspect);
56 //! Render capping for specific structure.
57 static void renderCappingForStructure (const Handle(OpenGl_Workspace)& theWorkspace,
58 const OpenGl_Structure& theStructure,
59 const OpenGl_ClippingIterator& thePlaneIter,
60 const Handle(OpenGl_CappingPlaneResource)& thePlane)
62 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
63 const Handle(Graphic3d_ClipPlane)& aRenderPlane = thePlane->Plane();
64 for (OpenGl_Structure::GroupIterator aGroupIter (theStructure.Groups()); aGroupIter.More(); aGroupIter.Next())
66 if (!aGroupIter.Value()->IsClosed())
71 // enable only the rendering plane to generate stencil mask
72 aContext->ChangeClipping().DisableAllExcept (aContext, thePlaneIter);
73 aContext->ShaderManager()->UpdateClippingState();
75 glClear (GL_STENCIL_BUFFER_BIT);
76 const bool aColorMaskBack = aContext->SetColorMask (false);
78 // override aspects, disable culling
79 theWorkspace->SetAspectFace (&theWorkspace->NoneCulling());
80 theWorkspace->ApplyAspectFace();
82 // evaluate number of pair faces
83 if (theWorkspace->UseZBuffer())
85 glDisable (GL_DEPTH_TEST);
87 if (theWorkspace->UseDepthWrite())
89 glDepthMask (GL_FALSE);
91 glStencilFunc (GL_ALWAYS, 1, 0x01);
92 glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
94 // render closed primitives
95 if (aRenderPlane->ToUseObjectProperties())
97 aGroupIter.Value()->Render (theWorkspace);
101 for (; aGroupIter.More(); aGroupIter.Next())
103 if (aGroupIter.Value()->IsClosed())
105 aGroupIter.Value()->Render (theWorkspace);
110 // override material, cull back faces
111 theWorkspace->SetAspectFace (&theWorkspace->FrontCulling());
112 theWorkspace->ApplyAspectFace();
114 // enable all clip plane except the rendered one
115 aContext->ChangeClipping().EnableAllExcept (aContext, thePlaneIter);
116 aContext->ShaderManager()->UpdateClippingState();
118 // render capping plane using the generated stencil mask
119 aContext->SetColorMask (aColorMaskBack);
120 if (theWorkspace->UseDepthWrite())
122 glDepthMask (GL_TRUE);
124 glStencilFunc (GL_EQUAL, 1, 0x01);
125 glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
126 if (theWorkspace->UseZBuffer())
128 glEnable (GL_DEPTH_TEST);
131 renderPlane (theWorkspace, thePlane, aRenderPlane->ToUseObjectProperties()
132 ? aGroupIter.Value()->AspectFace()
135 // turn on the current plane to restore initial state
136 aContext->ChangeClipping().SetEnabled (aContext, thePlaneIter, Standard_True);
137 aContext->ShaderManager()->RevertClippingState();
138 aContext->ShaderManager()->RevertClippingState();
141 if (theStructure.InstancedStructure() != NULL)
143 renderCappingForStructure (theWorkspace, *theStructure.InstancedStructure(), thePlaneIter, thePlane);
148 // =======================================================================
149 // function : RenderCapping
151 // =======================================================================
152 void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorkspace,
153 const OpenGl_Structure& theStructure)
155 const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
156 if (!aContext->Clipping().IsCappingOn())
158 // do not perform algorithm if there is nothing to render
162 // remember current aspect face defined in workspace
163 const OpenGl_AspectFace* aFaceAsp = theWorkspace->AspectFace();
165 // replace primitive groups rendering filter
166 Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
167 Handle(OpenGl_CappingAlgoFilter) aCappingFilter = theWorkspace->DefaultCappingAlgoFilter();
168 aCappingFilter->SetPreviousFilter (aRenderFilter);
169 theWorkspace->SetRenderFilter (aCappingFilter);
171 // prepare for rendering the clip planes
172 glEnable (GL_STENCIL_TEST);
174 // remember current state of depth
175 // function and change its value
176 GLint aDepthFuncPrev;
177 glGetIntegerv (GL_DEPTH_FUNC, &aDepthFuncPrev);
178 glDepthFunc (GL_LESS);
180 // generate capping for every clip plane
181 for (OpenGl_ClippingIterator aCappingIt (aContext->Clipping()); aCappingIt.More(); aCappingIt.Next())
183 // get plane being rendered
184 const Handle(Graphic3d_ClipPlane)& aRenderPlane = aCappingIt.Value();
185 if (!aRenderPlane->IsCapping()
186 || aCappingIt.IsDisabled())
191 // get resource for the plane
192 const TCollection_AsciiString& aResId = aRenderPlane->GetId();
193 Handle(OpenGl_CappingPlaneResource) aPlaneRes;
194 if (!aContext->GetResource (aResId, aPlaneRes))
196 // share and register for release once the resource is no longer used
197 aPlaneRes = new OpenGl_CappingPlaneResource (aRenderPlane);
198 aContext->ShareResource (aResId, aPlaneRes);
201 renderCappingForStructure (theWorkspace, theStructure, aCappingIt, aPlaneRes);
203 // set delayed resource release
205 aContext->ReleaseResource (aResId, Standard_True);
208 // restore previous application state
209 glClear (GL_STENCIL_BUFFER_BIT);
210 glDepthFunc (aDepthFuncPrev);
211 glStencilFunc (GL_ALWAYS, 0, 0xFF);
212 glDisable (GL_STENCIL_TEST);
214 // restore rendering aspects
215 theWorkspace->SetAspectFace (aFaceAsp);
216 theWorkspace->SetRenderFilter (aRenderFilter);
219 // =======================================================================
220 // function : CanRender
222 // =======================================================================
223 Standard_Boolean OpenGl_CappingAlgoFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
224 const OpenGl_Element* theGlElement)
226 if (!myFilter.IsNull() && !myFilter->ShouldRender (theWorkspace, theGlElement))
228 return Standard_False;
231 return theGlElement->IsFillDrawMode();