0027787: Visualization, TKOpenGl - Optimize rendering by additional check whether...
[occt.git] / src / OpenGl / OpenGl_AspectFace.cxx
1 // Created on: 2011-07-13
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 <Aspect_PolygonOffsetMode.hxx>
17 #include <NCollection_Vec3.hxx>
18
19 #include <OpenGl_AspectFace.hxx>
20 #include <OpenGl_Context.hxx>
21 #include <OpenGl_ShaderManager.hxx>
22 #include <OpenGl_ShaderProgram.hxx>
23 #include <OpenGl_Texture.hxx>
24 #include <OpenGl_Workspace.hxx>
25
26 #include <Graphic3d_ShaderProgram.hxx>
27 #include <Graphic3d_TextureMap.hxx>
28 #include <Graphic3d_TextureParams.hxx>
29 #include <Graphic3d_TypeOfReflection.hxx>
30 #include <Graphic3d_MaterialAspect.hxx>
31
32 #include <Image_PixMap.hxx>
33
34 namespace
35 {
36   //! Initialize default material in this way for backward compatibility.
37   inline Graphic3d_MaterialAspect initDefaultMaterial()
38   {
39     Graphic3d_MaterialAspect aMat;
40     aMat.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
41     aMat.SetAmbient  (0.2);
42     aMat.SetDiffuse  (0.8);
43     aMat.SetSpecular (0.1);
44     aMat.SetEmissive (0.0);
45     aMat.SetAmbientColor (Quantity_NOC_WHITE);
46     aMat.SetDiffuseColor (Quantity_NOC_WHITE);
47     aMat.SetEmissiveColor(Quantity_NOC_WHITE);
48     aMat.SetSpecularColor(Quantity_NOC_WHITE);
49     aMat.SetShininess (10.0 / 128.0);
50     aMat.SetRefractionIndex (1.0);
51     return aMat;
52   }
53
54   static const TCollection_AsciiString  THE_EMPTY_KEY;
55   static const Graphic3d_MaterialAspect THE_DEFAULT_MATERIAL = initDefaultMaterial();
56 }
57
58 // =======================================================================
59 // function : OpenGl_AspectFace
60 // purpose  :
61 // =======================================================================
62 OpenGl_AspectFace::OpenGl_AspectFace()
63 : myAspect (new Graphic3d_AspectFillArea3d (Aspect_IS_SOLID, Quantity_NOC_WHITE,
64                                             Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0,
65                                             THE_DEFAULT_MATERIAL, THE_DEFAULT_MATERIAL)),
66   myIsNoLighting (false)
67 {
68   myAspect->SetHatchStyle (Aspect_HS_SOLID);
69 }
70
71 // =======================================================================
72 // function : OpenGl_AspectFace
73 // purpose  :
74 // =======================================================================
75 OpenGl_AspectFace::OpenGl_AspectFace (const Handle(Graphic3d_AspectFillArea3d)& theAspect)
76 : myIsNoLighting (false)
77 {
78   SetAspect (theAspect);
79 }
80
81 // =======================================================================
82 // function : SetAspect
83 // purpose  :
84 // =======================================================================
85 void OpenGl_AspectFace::SetAspect (const Handle(Graphic3d_AspectFillArea3d)& theAspect)
86 {
87   myAspect = theAspect;
88
89   const Graphic3d_MaterialAspect& aMat = theAspect->FrontMaterial();
90   myIsNoLighting = !aMat.ReflectionMode (Graphic3d_TOR_AMBIENT)
91                 && !aMat.ReflectionMode (Graphic3d_TOR_DIFFUSE)
92                 && !aMat.ReflectionMode (Graphic3d_TOR_SPECULAR)
93                 && !aMat.ReflectionMode (Graphic3d_TOR_EMISSION);
94
95   myAspectEdge.Aspect()->SetColor (theAspect->EdgeColor());
96   myAspectEdge.Aspect()->SetType  (theAspect->EdgeLineType());
97   myAspectEdge.Aspect()->SetWidth (theAspect->EdgeWidth());
98
99   // update texture binding
100   const TCollection_AsciiString& aTextureKey = myAspect->TextureMap().IsNull() ? THE_EMPTY_KEY : myAspect->TextureMap()->GetId();
101   if (aTextureKey.IsEmpty() || myResources.TextureId != aTextureKey)
102   {
103     myResources.ResetTextureReadiness();
104   }
105
106   // update shader program binding
107   const TCollection_AsciiString& aShaderKey = myAspect->ShaderProgram().IsNull() ? THE_EMPTY_KEY : myAspect->ShaderProgram()->GetId();
108   if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey)
109   {
110     myResources.ResetShaderReadiness();
111   }
112 }
113
114 // =======================================================================
115 // function : Render
116 // purpose  :
117 // =======================================================================
118 void OpenGl_AspectFace::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
119 {
120   theWorkspace->SetAspectFace (this);
121 }
122
123 // =======================================================================
124 // function : Release
125 // purpose  :
126 // =======================================================================
127 void OpenGl_AspectFace::Release (OpenGl_Context* theContext)
128 {
129   if (!myResources.Texture.IsNull())
130   {
131     if (theContext)
132     {
133       if (myResources.TextureId.IsEmpty())
134       {
135         theContext->DelayedRelease (myResources.Texture);
136       }
137       else
138       {
139         myResources.Texture.Nullify(); // we need nullify all handles before ReleaseResource() call
140         theContext->ReleaseResource (myResources.TextureId, Standard_True);
141       }
142     }
143     myResources.Texture.Nullify();
144   }
145   myResources.TextureId.Clear();
146   myResources.ResetTextureReadiness();
147
148   if (!myResources.ShaderProgram.IsNull()
149    && theContext)
150   {
151     theContext->ShaderManager()->Unregister (myResources.ShaderProgramId,
152                                              myResources.ShaderProgram);
153   }
154   myResources.ShaderProgramId.Clear();
155   myResources.ResetShaderReadiness();
156 }
157
158 // =======================================================================
159 // function : BuildTexture
160 // purpose  :
161 // =======================================================================
162 void OpenGl_AspectFace::Resources::BuildTexture (const Handle(OpenGl_Context)&       theCtx,
163                                                  const Handle(Graphic3d_TextureMap)& theTexture)
164 {
165   // release old texture resource
166   if (!Texture.IsNull())
167   {
168     if (TextureId.IsEmpty())
169     {
170       theCtx->DelayedRelease (Texture);
171       Texture.Nullify();
172     }
173     else
174     {
175       Texture.Nullify(); // we need nullify all handles before ReleaseResource() call
176       theCtx->ReleaseResource (TextureId, Standard_True);
177     }
178   }
179
180   TextureId = theTexture.IsNull() ? THE_EMPTY_KEY : theTexture->GetId();
181
182   if (!theTexture.IsNull())
183   {
184     if (TextureId.IsEmpty() || !theCtx->GetResource<Handle(OpenGl_Texture)> (TextureId, Texture))
185     {
186       Texture = new OpenGl_Texture (theTexture->GetParams());
187       Handle(Image_PixMap) anImage = theTexture->GetImage();
188       if (!anImage.IsNull())
189       {
190         Texture->Init (theCtx, *anImage.operator->(), theTexture->Type());
191       }
192       if (!TextureId.IsEmpty())
193       {
194         theCtx->ShareResource (TextureId, Texture);
195       }
196     }
197   }
198 }
199
200 // =======================================================================
201 // function : BuildShader
202 // purpose  :
203 // =======================================================================
204 void OpenGl_AspectFace::Resources::BuildShader (const Handle(OpenGl_Context)&          theCtx,
205                                                 const Handle(Graphic3d_ShaderProgram)& theShader)
206 {
207   if (theCtx->core20fwd == NULL)
208   {
209     return;
210   }
211
212   // release old shader program resources
213   if (!ShaderProgram.IsNull())
214   {
215     theCtx->ShaderManager()->Unregister (ShaderProgramId, ShaderProgram);
216     ShaderProgramId.Clear();
217     ShaderProgram.Nullify();
218   }
219   if (theShader.IsNull())
220   {
221     return;
222   }
223
224   theCtx->ShaderManager()->Create (theShader, ShaderProgramId, ShaderProgram);
225 }