Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2011-09-20 |
2 | // Created by: Sergey ZERCHANINOV | |
973c2be1 | 3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 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 | |
973c2be1 | 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. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
b311480e | 15 | |
c357e426 | 16 | #include <OpenGl_Workspace.hxx> |
5f8b738e | 17 | |
c357e426 | 18 | #include <OpenGl_ArbFBO.hxx> |
2166f0fa SK |
19 | #include <OpenGl_AspectLine.hxx> |
20 | #include <OpenGl_AspectFace.hxx> | |
21 | #include <OpenGl_AspectMarker.hxx> | |
22 | #include <OpenGl_AspectText.hxx> | |
bf75be98 | 23 | #include <OpenGl_Context.hxx> |
679ecdee | 24 | #include <OpenGl_Element.hxx> |
a174a3c5 | 25 | #include <OpenGl_FrameBuffer.hxx> |
c357e426 | 26 | #include <OpenGl_GlCore15.hxx> |
27 | #include <OpenGl_SceneGeometry.hxx> | |
679ecdee | 28 | #include <OpenGl_Structure.hxx> |
25ef750e | 29 | #include <OpenGl_Sampler.hxx> |
8613985b | 30 | #include <OpenGl_ShaderManager.hxx> |
bf75be98 | 31 | #include <OpenGl_Texture.hxx> |
e276548b | 32 | #include <OpenGl_View.hxx> |
c357e426 | 33 | #include <OpenGl_Window.hxx> |
2166f0fa | 34 | |
bf75be98 | 35 | #include <Graphic3d_TextureParams.hxx> |
825aa485 | 36 | #include <Graphic3d_TransformUtils.hxx> |
f9f740d6 | 37 | #include <NCollection_AlignedAllocator.hxx> |
2166f0fa | 38 | |
92efcf78 | 39 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient) |
40 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter,OpenGl_RenderFilter) | |
41 | ||
c357e426 | 42 | #ifdef HAVE_GL2PS |
43 | #include <gl2ps.h> | |
44 | /* OCC22216 NOTE: linker dependency can be switched off by undefining macro. | |
45 | Pragma comment for gl2ps.lib is defined only here. */ | |
46 | #ifdef _MSC_VER | |
47 | #pragma comment( lib, "gl2ps.lib" ) | |
48 | #endif | |
a174a3c5 | 49 | #endif |
50 | ||
2166f0fa SK |
51 | namespace |
52 | { | |
b6472664 | 53 | static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f); |
54 | static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f); | |
2166f0fa SK |
55 | |
56 | static const OpenGl_AspectLine myDefaultAspectLine; | |
57 | static const OpenGl_AspectFace myDefaultAspectFace; | |
58 | static const OpenGl_AspectMarker myDefaultAspectMarker; | |
2831708b | 59 | static const OpenGl_AspectText myDefaultAspectText; |
2166f0fa | 60 | |
2166f0fa SK |
61 | static const OpenGl_Matrix myDefaultMatrix = |
62 | { | |
63 | {{ 1.0F, 0.0F, 0.0F, 0.0F }, | |
64 | { 0.0F, 1.0F, 0.0F, 0.0F }, | |
65 | { 0.0F, 0.0F, 1.0F, 0.0F }, | |
66 | { 0.0F, 0.0F, 0.0F, 1.0F }} | |
67 | }; | |
bf75be98 | 68 | |
a3f6f591 | 69 | } |
2166f0fa | 70 | |
0adbd30f | 71 | // ======================================================================= |
72 | // function : Init | |
73 | // purpose : | |
74 | // ======================================================================= | |
b6472664 | 75 | void OpenGl_Material::Init (const Graphic3d_MaterialAspect& theMat, |
76 | const Quantity_Color& theInteriorColor) | |
0adbd30f | 77 | { |
4e1bc39a | 78 | const bool isPhysic = theMat.MaterialType (Graphic3d_MATERIAL_PHYSIC); |
a71a71de | 79 | ChangeShine() = 128.0f * theMat.Shininess(); |
80 | ChangeTransparency() = theMat.Alpha(); | |
b6472664 | 81 | |
0adbd30f | 82 | // ambient component |
b6472664 | 83 | if (theMat.ReflectionMode (Graphic3d_TOR_AMBIENT)) |
0adbd30f | 84 | { |
b6472664 | 85 | const OpenGl_Vec3& aSrcAmb = isPhysic ? theMat.AmbientColor() : theInteriorColor; |
4e1bc39a | 86 | Ambient = OpenGl_Vec4 (aSrcAmb * theMat.Ambient(), 1.0f); |
0adbd30f | 87 | } |
88 | else | |
89 | { | |
90 | Ambient = THE_BLACK_COLOR; | |
91 | } | |
92 | ||
93 | // diffusion component | |
b6472664 | 94 | if (theMat.ReflectionMode (Graphic3d_TOR_DIFFUSE)) |
0adbd30f | 95 | { |
b6472664 | 96 | const OpenGl_Vec3& aSrcDif = isPhysic ? theMat.DiffuseColor() : theInteriorColor; |
4e1bc39a | 97 | Diffuse = OpenGl_Vec4 (aSrcDif * theMat.Diffuse(), 1.0f); |
0adbd30f | 98 | } |
99 | else | |
100 | { | |
101 | Diffuse = THE_BLACK_COLOR; | |
102 | } | |
103 | ||
104 | // specular component | |
b6472664 | 105 | if (theMat.ReflectionMode (Graphic3d_TOR_SPECULAR)) |
0adbd30f | 106 | { |
b6472664 | 107 | const OpenGl_Vec3& aSrcSpe = isPhysic ? (const OpenGl_Vec3& )theMat.SpecularColor() : THE_WHITE_COLOR.rgb(); |
4e1bc39a | 108 | Specular = OpenGl_Vec4 (aSrcSpe * theMat.Specular(), 1.0f); |
0adbd30f | 109 | } |
110 | else | |
111 | { | |
112 | Specular = THE_BLACK_COLOR; | |
113 | } | |
114 | ||
115 | // emission component | |
b6472664 | 116 | if (theMat.ReflectionMode (Graphic3d_TOR_EMISSION)) |
0adbd30f | 117 | { |
b6472664 | 118 | const OpenGl_Vec3& aSrcEms = isPhysic ? theMat.EmissiveColor() : theInteriorColor; |
4e1bc39a | 119 | Emission = OpenGl_Vec4 (aSrcEms * theMat.Emissive(), 1.0f); |
0adbd30f | 120 | } |
121 | else | |
122 | { | |
123 | Emission = THE_BLACK_COLOR; | |
124 | } | |
0adbd30f | 125 | } |
126 | ||
2166f0fa SK |
127 | // ======================================================================= |
128 | // function : OpenGl_Workspace | |
129 | // purpose : | |
130 | // ======================================================================= | |
c357e426 | 131 | OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow) |
1a0dfc1b | 132 | : myView (theView), |
c357e426 | 133 | myWindow (theWindow), |
134 | myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL), | |
eae454e3 | 135 | myUseZBuffer (Standard_True), |
136 | myUseDepthWrite (Standard_True), | |
2166f0fa | 137 | // |
f9ba5c4d | 138 | myAspectLineSet (&myDefaultAspectLine), |
139 | myAspectFaceSet (&myDefaultAspectFace), | |
f9ba5c4d | 140 | myAspectMarkerSet (&myDefaultAspectMarker), |
f9ba5c4d | 141 | myAspectTextSet (&myDefaultAspectText), |
f9ba5c4d | 142 | // |
2166f0fa SK |
143 | ViewMatrix_applied (&myDefaultMatrix), |
144 | StructureMatrix_applied (&myDefaultMatrix), | |
b6472664 | 145 | myToAllowFaceCulling (false), |
b6472664 | 146 | myModelViewMatrix (myDefaultMatrix) |
2166f0fa | 147 | { |
c357e426 | 148 | if (!myGlContext.IsNull() && myGlContext->MakeCurrent()) |
73192b37 | 149 | { |
c357e426 | 150 | myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); |
2166f0fa | 151 | |
c357e426 | 152 | // General initialization of the context |
c357e426 | 153 | #if !defined(GL_ES_VERSION_2_0) |
154 | if (myGlContext->core11 != NULL) | |
155 | { | |
156 | // Eviter d'avoir les faces mal orientees en noir. | |
157 | // Pourrait etre utiliser pour detecter les problemes d'orientation | |
158 | glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); | |
2166f0fa | 159 | |
c357e426 | 160 | // Optimisation pour le Fog et l'antialiasing |
161 | glHint (GL_FOG_HINT, GL_FASTEST); | |
162 | glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); | |
163 | } | |
2166f0fa | 164 | |
c357e426 | 165 | glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST); |
166 | glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST); | |
167 | #endif | |
73192b37 | 168 | } |
f8ae3605 | 169 | |
b6472664 | 170 | myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter(); |
171 | ||
172 | myNoneCulling .Aspect()->SetSuppressBackFaces (false); | |
173 | myNoneCulling .Aspect()->SetDrawEdges (false); | |
174 | myFrontCulling.Aspect()->SetSuppressBackFaces (true); | |
175 | myFrontCulling.Aspect()->SetDrawEdges (false); | |
2166f0fa SK |
176 | } |
177 | ||
2166f0fa SK |
178 | // ======================================================================= |
179 | // function : Activate | |
180 | // purpose : | |
181 | // ======================================================================= | |
182 | Standard_Boolean OpenGl_Workspace::Activate() | |
183 | { | |
c357e426 | 184 | if (myWindow.IsNull() || !myWindow->Activate()) |
185 | { | |
2166f0fa | 186 | return Standard_False; |
c357e426 | 187 | } |
2166f0fa | 188 | |
2166f0fa SK |
189 | ViewMatrix_applied = &myDefaultMatrix; |
190 | StructureMatrix_applied = &myDefaultMatrix; | |
26395493 | 191 | |
192 | ResetAppliedAspect(); | |
193 | ||
8613985b | 194 | // reset state for safety |
195 | myGlContext->BindProgram (Handle(OpenGl_ShaderProgram)()); | |
196 | if (myGlContext->core20fwd != NULL) | |
197 | { | |
198 | myGlContext->core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM); | |
199 | } | |
200 | myGlContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); | |
26395493 | 201 | return Standard_True; |
2166f0fa SK |
202 | } |
203 | ||
26395493 | 204 | //======================================================================= |
205 | //function : ResetAppliedAspect | |
206 | //purpose : Sets default values of GL parameters in accordance with default aspects | |
207 | //======================================================================= | |
208 | void OpenGl_Workspace::ResetAppliedAspect() | |
209 | { | |
4e1523ef | 210 | myGlContext->BindDefaultVao(); |
211 | ||
f838dac4 | 212 | myHighlightStyle.Nullify(); |
b6472664 | 213 | myToAllowFaceCulling = false; |
f9ba5c4d | 214 | myAspectLineSet = &myDefaultAspectLine; |
215 | myAspectFaceSet = &myDefaultAspectFace; | |
b6472664 | 216 | myAspectFaceApplied.Nullify(); |
f9ba5c4d | 217 | myAspectMarkerSet = &myDefaultAspectMarker; |
b6472664 | 218 | myAspectMarkerApplied.Nullify(); |
f9ba5c4d | 219 | myAspectTextSet = &myDefaultAspectText; |
b6472664 | 220 | myPolygonOffsetApplied= Graphic3d_PolygonOffset(); |
26395493 | 221 | |
f9ba5c4d | 222 | ApplyAspectLine(); |
223 | ApplyAspectFace(); | |
224 | ApplyAspectMarker(); | |
225 | ApplyAspectText(); | |
ac116c22 | 226 | |
b6472664 | 227 | myGlContext->SetTypeOfLine (myDefaultAspectLine.Aspect()->Type()); |
228 | myGlContext->SetLineWidth (myDefaultAspectLine.Aspect()->Width()); | |
26395493 | 229 | } |
bf75be98 | 230 | |
38a0206f | 231 | // ======================================================================= |
c357e426 | 232 | // function : SetAspectLine |
38a0206f | 233 | // purpose : |
234 | // ======================================================================= | |
f9ba5c4d | 235 | const OpenGl_AspectLine* OpenGl_Workspace::SetAspectLine (const OpenGl_AspectLine* theAspect) |
38a0206f | 236 | { |
f9ba5c4d | 237 | const OpenGl_AspectLine* aPrevAspectLine = myAspectLineSet; |
238 | myAspectLineSet = theAspect; | |
239 | return aPrevAspectLine; | |
c357e426 | 240 | } |
38a0206f | 241 | |
c357e426 | 242 | // ======================================================================= |
243 | // function : SetAspectFace | |
244 | // purpose : | |
245 | // ======================================================================= | |
f9ba5c4d | 246 | const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace (const OpenGl_AspectFace* theAspect) |
c357e426 | 247 | { |
f9ba5c4d | 248 | const OpenGl_AspectFace* aPrevAspectFace = myAspectFaceSet; |
249 | myAspectFaceSet = theAspect; | |
250 | return aPrevAspectFace; | |
c357e426 | 251 | } |
38a0206f | 252 | |
c357e426 | 253 | // ======================================================================= |
254 | // function : SetAspectMarker | |
255 | // purpose : | |
256 | // ======================================================================= | |
f9ba5c4d | 257 | const OpenGl_AspectMarker* OpenGl_Workspace::SetAspectMarker (const OpenGl_AspectMarker* theAspect) |
c357e426 | 258 | { |
f9ba5c4d | 259 | const OpenGl_AspectMarker* aPrevAspectMarker = myAspectMarkerSet; |
260 | myAspectMarkerSet = theAspect; | |
261 | return aPrevAspectMarker; | |
c357e426 | 262 | } |
f978241f | 263 | |
c357e426 | 264 | // ======================================================================= |
265 | // function : SetAspectText | |
266 | // purpose : | |
267 | // ======================================================================= | |
f9ba5c4d | 268 | const OpenGl_AspectText * OpenGl_Workspace::SetAspectText (const OpenGl_AspectText* theAspect) |
c357e426 | 269 | { |
f9ba5c4d | 270 | const OpenGl_AspectText* aPrevAspectText = myAspectTextSet; |
271 | myAspectTextSet = theAspect; | |
272 | return aPrevAspectText; | |
c357e426 | 273 | } |
38a0206f | 274 | |
c357e426 | 275 | // ======================================================================= |
f9ba5c4d | 276 | // function : ApplyAspectFace |
c357e426 | 277 | // purpose : |
278 | // ======================================================================= | |
f9ba5c4d | 279 | const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace() |
c357e426 | 280 | { |
c357e426 | 281 | if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC) |
38a0206f | 282 | { |
c357e426 | 283 | // manage back face culling mode, disable culling when clipping is enabled |
b6472664 | 284 | bool toSuppressBackFaces = myToAllowFaceCulling |
285 | && myAspectFaceSet->Aspect()->ToSuppressBackFaces(); | |
286 | if (toSuppressBackFaces) | |
f978241f | 287 | { |
b6472664 | 288 | if (myGlContext->Clipping().IsClippingOrCappingOn() |
289 | || myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH) | |
f978241f | 290 | { |
b6472664 | 291 | toSuppressBackFaces = false; |
c357e426 | 292 | } |
293 | } | |
b6472664 | 294 | if (toSuppressBackFaces) |
c357e426 | 295 | { |
1a0dfc1b | 296 | if ((float )myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f) |
c357e426 | 297 | { |
b6472664 | 298 | // disable culling in case of translucent shading aspect |
299 | toSuppressBackFaces = false; | |
f978241f | 300 | } |
f978241f | 301 | } |
b6472664 | 302 | myGlContext->SetCullBackFaces (toSuppressBackFaces); |
f978241f | 303 | } |
304 | ||
b6472664 | 305 | if (myAspectFaceSet->Aspect() == myAspectFaceApplied |
8613985b | 306 | && myHighlightStyle == myAspectFaceAppliedWithHL) |
a2e4f780 | 307 | { |
f9ba5c4d | 308 | return myAspectFaceSet; |
a2e4f780 | 309 | } |
8613985b | 310 | myAspectFaceAppliedWithHL = myHighlightStyle; |
a2e4f780 | 311 | |
c357e426 | 312 | #if !defined(GL_ES_VERSION_2_0) |
b6472664 | 313 | const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle(); |
314 | if (myAspectFaceApplied.IsNull() | |
f9ba5c4d | 315 | || myAspectFaceApplied->InteriorStyle() != anIntstyle) |
b86bb3df | 316 | { |
c357e426 | 317 | switch (anIntstyle) |
760c21c2 | 318 | { |
c357e426 | 319 | case Aspect_IS_EMPTY: |
320 | case Aspect_IS_HOLLOW: | |
ee51a9fe | 321 | { |
6d0e6be5 | 322 | myGlContext->SetPolygonMode (GL_LINE); |
c357e426 | 323 | break; |
ee51a9fe | 324 | } |
c357e426 | 325 | case Aspect_IS_HATCH: |
62e1beed | 326 | { |
6d0e6be5 | 327 | myGlContext->SetPolygonMode (GL_FILL); |
328 | myGlContext->SetPolygonHatchEnabled (true); | |
c357e426 | 329 | break; |
62e1beed | 330 | } |
c357e426 | 331 | case Aspect_IS_SOLID: |
332 | case Aspect_IS_HIDDENLINE: | |
333 | { | |
6d0e6be5 | 334 | myGlContext->SetPolygonMode (GL_FILL); |
335 | myGlContext->SetPolygonHatchEnabled (false); | |
c357e426 | 336 | break; |
337 | } | |
338 | case Aspect_IS_POINT: | |
38a0206f | 339 | { |
6d0e6be5 | 340 | myGlContext->SetPolygonMode (GL_POINT); |
c357e426 | 341 | break; |
38a0206f | 342 | } |
38a0206f | 343 | } |
91c60b57 | 344 | } |
e276548b | 345 | |
c357e426 | 346 | if (anIntstyle == Aspect_IS_HATCH) |
91c60b57 | 347 | { |
6d0e6be5 | 348 | myGlContext->SetPolygonHatchStyle (myAspectFaceSet->Aspect()->HatchStyle()); |
c357e426 | 349 | } |
350 | #endif | |
38a0206f | 351 | |
c357e426 | 352 | // Aspect_POM_None means: do not change current settings |
b6472664 | 353 | if ((myAspectFaceSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None) |
c357e426 | 354 | { |
b6472664 | 355 | if (myPolygonOffsetApplied.Mode != myAspectFaceSet->Aspect()->PolygonOffset().Mode |
356 | || myPolygonOffsetApplied.Factor != myAspectFaceSet->Aspect()->PolygonOffset().Factor | |
357 | || myPolygonOffsetApplied.Units != myAspectFaceSet->Aspect()->PolygonOffset().Units) | |
38a0206f | 358 | { |
b6472664 | 359 | SetPolygonOffset (myAspectFaceSet->Aspect()->PolygonOffset()); |
38a0206f | 360 | } |
361 | } | |
c357e426 | 362 | |
8613985b | 363 | // Case of hidden line |
364 | if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) | |
365 | { | |
366 | // copy all values including line edge aspect | |
367 | *myAspectFaceHl.Aspect().operator->() = *myAspectFaceSet->Aspect(); | |
368 | myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge()); | |
369 | myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB()); | |
370 | myAspectFaceHl.SetNoLighting (true); | |
371 | myAspectFaceSet = &myAspectFaceHl; | |
372 | } | |
373 | else | |
a174a3c5 | 374 | { |
a1073ae2 | 375 | myGlContext->SetShadingMaterial (myAspectFaceSet, myHighlightStyle); |
c357e426 | 376 | } |
62e1beed | 377 | |
b6472664 | 378 | if (myAspectFaceSet->Aspect()->ToMapTexture()) |
c357e426 | 379 | { |
cc8cbabe | 380 | myGlContext->BindTextures (myAspectFaceSet->TextureSet (myGlContext)); |
83da37b1 | 381 | } |
382 | else | |
383 | { | |
cc8cbabe | 384 | myGlContext->BindTextures (myEnvironmentTexture); |
a174a3c5 | 385 | } |
386 | ||
b6472664 | 387 | myAspectFaceApplied = myAspectFaceSet->Aspect(); |
f9ba5c4d | 388 | return myAspectFaceSet; |
c357e426 | 389 | } |
a174a3c5 | 390 | |
c357e426 | 391 | //======================================================================= |
392 | //function : SetPolygonOffset | |
393 | //purpose : | |
394 | //======================================================================= | |
b6472664 | 395 | void OpenGl_Workspace::SetPolygonOffset (const Graphic3d_PolygonOffset& theParams) |
c357e426 | 396 | { |
b6472664 | 397 | myPolygonOffsetApplied = theParams; |
a174a3c5 | 398 | |
b6472664 | 399 | if ((theParams.Mode & Aspect_POM_Fill) == Aspect_POM_Fill) |
400 | { | |
401 | glEnable (GL_POLYGON_OFFSET_FILL); | |
402 | } | |
403 | else | |
404 | { | |
405 | glDisable (GL_POLYGON_OFFSET_FILL); | |
406 | } | |
407 | ||
408 | #if !defined(GL_ES_VERSION_2_0) | |
409 | if ((theParams.Mode & Aspect_POM_Line) == Aspect_POM_Line) | |
410 | { | |
411 | glEnable (GL_POLYGON_OFFSET_LINE); | |
412 | } | |
413 | else | |
414 | { | |
415 | glDisable (GL_POLYGON_OFFSET_LINE); | |
416 | } | |
417 | ||
418 | if ((theParams.Mode & Aspect_POM_Point) == Aspect_POM_Point) | |
419 | { | |
420 | glEnable (GL_POLYGON_OFFSET_POINT); | |
421 | } | |
422 | else | |
423 | { | |
424 | glDisable (GL_POLYGON_OFFSET_POINT); | |
425 | } | |
426 | #endif | |
427 | glPolygonOffset (theParams.Factor, theParams.Units); | |
c357e426 | 428 | } |
38a0206f | 429 | |
c357e426 | 430 | // ======================================================================= |
f9ba5c4d | 431 | // function : ApplyAspectMarker |
c357e426 | 432 | // purpose : |
433 | // ======================================================================= | |
f9ba5c4d | 434 | const OpenGl_AspectMarker* OpenGl_Workspace::ApplyAspectMarker() |
c357e426 | 435 | { |
b6472664 | 436 | if (myAspectMarkerSet->Aspect() != myAspectMarkerApplied) |
ee51a9fe | 437 | { |
b6472664 | 438 | if (myAspectMarkerApplied.IsNull() |
439 | || (myAspectMarkerSet->Aspect()->Scale() != myAspectMarkerApplied->Scale())) | |
ee51a9fe | 440 | { |
c357e426 | 441 | #if !defined(GL_ES_VERSION_2_0) |
b6472664 | 442 | glPointSize (myAspectMarkerSet->Aspect()->Scale()); |
c357e426 | 443 | #ifdef HAVE_GL2PS |
b6472664 | 444 | gl2psPointSize (myAspectMarkerSet->Aspect()->Scale()); |
c357e426 | 445 | #endif |
446 | #endif | |
ee51a9fe | 447 | } |
b6472664 | 448 | myAspectMarkerApplied = myAspectMarkerSet->Aspect(); |
38a0206f | 449 | } |
f9ba5c4d | 450 | return myAspectMarkerSet; |
679ecdee | 451 | } |
452 | ||
453 | // ======================================================================= | |
c357e426 | 454 | // function : Width |
679ecdee | 455 | // purpose : |
456 | // ======================================================================= | |
c357e426 | 457 | Standard_Integer OpenGl_Workspace::Width() const |
679ecdee | 458 | { |
c357e426 | 459 | return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0; |
460 | } | |
679ecdee | 461 | |
c357e426 | 462 | // ======================================================================= |
463 | // function : Height | |
464 | // purpose : | |
465 | // ======================================================================= | |
466 | Standard_Integer OpenGl_Workspace::Height() const | |
467 | { | |
468 | return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0; | |
469 | } | |
679ecdee | 470 | |
c357e426 | 471 | // ======================================================================= |
472 | // function : IsCullingEnabled | |
473 | // purpose : | |
474 | // ======================================================================= | |
475 | Standard_Boolean OpenGl_Workspace::IsCullingEnabled() const | |
476 | { | |
477 | return myView->IsCullingEnabled(); | |
679ecdee | 478 | } |
479 | ||
480 | // ======================================================================= | |
c357e426 | 481 | // function : FBOCreate |
679ecdee | 482 | // purpose : |
483 | // ======================================================================= | |
b128c892 | 484 | Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth, |
485 | const Standard_Integer theHeight) | |
679ecdee | 486 | { |
c357e426 | 487 | // activate OpenGL context |
488 | if (!Activate()) | |
b128c892 | 489 | return Handle(OpenGl_FrameBuffer)(); |
c357e426 | 490 | |
491 | // create the FBO | |
492 | const Handle(OpenGl_Context)& aCtx = GetGlContext(); | |
cc8cbabe | 493 | aCtx->BindTextures (Handle(OpenGl_TextureSet)()); |
b128c892 | 494 | Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer(); |
3c4b62a4 | 495 | if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0)) |
679ecdee | 496 | { |
c357e426 | 497 | aFrameBuffer->Release (aCtx.operator->()); |
b128c892 | 498 | return Handle(OpenGl_FrameBuffer)(); |
679ecdee | 499 | } |
b128c892 | 500 | return aFrameBuffer; |
679ecdee | 501 | } |
502 | ||
503 | // ======================================================================= | |
c357e426 | 504 | // function : FBORelease |
679ecdee | 505 | // purpose : |
506 | // ======================================================================= | |
b128c892 | 507 | void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo) |
679ecdee | 508 | { |
c357e426 | 509 | // activate OpenGL context |
510 | if (!Activate() | |
b128c892 | 511 | || theFbo.IsNull()) |
62e1beed | 512 | { |
62e1beed | 513 | return; |
514 | } | |
c357e426 | 515 | |
b128c892 | 516 | theFbo->Release (GetGlContext().operator->()); |
517 | theFbo.Nullify(); | |
c357e426 | 518 | } |
62e1beed | 519 | |
f9f740d6 | 520 | // ======================================================================= |
521 | // function : getAligned | |
522 | // purpose : | |
523 | // ======================================================================= | |
524 | inline Standard_Size getAligned (const Standard_Size theNumber, | |
525 | const Standard_Size theAlignment) | |
526 | { | |
527 | return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment; | |
528 | } | |
529 | ||
530 | template<typename T> | |
531 | inline void convertRowFromRgba (T* theRgbRow, | |
532 | const Image_ColorRGBA* theRgbaRow, | |
533 | const Standard_Size theWidth) | |
534 | { | |
535 | for (Standard_Size aCol = 0; aCol < theWidth; ++aCol) | |
536 | { | |
537 | const Image_ColorRGBA& anRgba = theRgbaRow[aCol]; | |
538 | T& anRgb = theRgbRow[aCol]; | |
539 | anRgb.r() = anRgba.r(); | |
540 | anRgb.g() = anRgba.g(); | |
541 | anRgb.b() = anRgba.b(); | |
542 | } | |
543 | } | |
544 | ||
545 | // ======================================================================= | |
546 | // function : BufferDump | |
547 | // purpose : | |
548 | // ======================================================================= | |
549 | Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo, | |
550 | Image_PixMap& theImage, | |
551 | const Graphic3d_BufferType& theBufferType) | |
c357e426 | 552 | { |
f9f740d6 | 553 | if (theImage.IsEmpty() |
554 | || !Activate()) | |
555 | { | |
556 | return Standard_False; | |
557 | } | |
558 | ||
559 | GLenum aFormat = 0; | |
560 | GLenum aType = 0; | |
561 | bool toSwapRgbaBgra = false; | |
562 | bool toConvRgba2Rgb = false; | |
563 | switch (theImage.Format()) | |
38a0206f | 564 | { |
c357e426 | 565 | #if !defined(GL_ES_VERSION_2_0) |
dc858f4c | 566 | case Image_Format_Gray: |
f9f740d6 | 567 | aFormat = GL_DEPTH_COMPONENT; |
568 | aType = GL_UNSIGNED_BYTE; | |
569 | break; | |
dc858f4c | 570 | case Image_Format_GrayF: |
f9f740d6 | 571 | aFormat = GL_DEPTH_COMPONENT; |
572 | aType = GL_FLOAT; | |
573 | break; | |
dc858f4c | 574 | case Image_Format_RGB: |
f9f740d6 | 575 | aFormat = GL_RGB; |
576 | aType = GL_UNSIGNED_BYTE; | |
577 | break; | |
dc858f4c | 578 | case Image_Format_BGR: |
f9f740d6 | 579 | aFormat = GL_BGR; |
580 | aType = GL_UNSIGNED_BYTE; | |
581 | break; | |
dc858f4c | 582 | case Image_Format_BGRA: |
583 | case Image_Format_BGR32: | |
f9f740d6 | 584 | aFormat = GL_BGRA; |
585 | aType = GL_UNSIGNED_BYTE; | |
586 | break; | |
dc858f4c | 587 | case Image_Format_BGRF: |
f9f740d6 | 588 | aFormat = GL_BGR; |
589 | aType = GL_FLOAT; | |
590 | break; | |
dc858f4c | 591 | case Image_Format_BGRAF: |
f9f740d6 | 592 | aFormat = GL_BGRA; |
593 | aType = GL_FLOAT; | |
594 | break; | |
c357e426 | 595 | #else |
dc858f4c | 596 | case Image_Format_Gray: |
597 | case Image_Format_GrayF: | |
598 | case Image_Format_BGRF: | |
599 | case Image_Format_BGRAF: | |
f9f740d6 | 600 | return Standard_False; |
dc858f4c | 601 | case Image_Format_BGRA: |
602 | case Image_Format_BGR32: | |
f9f740d6 | 603 | aFormat = GL_RGBA; |
604 | aType = GL_UNSIGNED_BYTE; | |
605 | toSwapRgbaBgra = true; | |
606 | break; | |
dc858f4c | 607 | case Image_Format_BGR: |
608 | case Image_Format_RGB: | |
f9f740d6 | 609 | aFormat = GL_RGBA; |
610 | aType = GL_UNSIGNED_BYTE; | |
611 | toConvRgba2Rgb = true; | |
612 | break; | |
613 | #endif | |
dc858f4c | 614 | case Image_Format_RGBA: |
615 | case Image_Format_RGB32: | |
f9f740d6 | 616 | aFormat = GL_RGBA; |
617 | aType = GL_UNSIGNED_BYTE; | |
618 | break; | |
dc858f4c | 619 | case Image_Format_RGBF: |
f9f740d6 | 620 | aFormat = GL_RGB; |
621 | aType = GL_FLOAT; | |
622 | break; | |
dc858f4c | 623 | case Image_Format_RGBAF: |
f9f740d6 | 624 | aFormat = GL_RGBA; |
625 | aType = GL_FLOAT; | |
626 | break; | |
dc858f4c | 627 | case Image_Format_Alpha: |
628 | case Image_Format_AlphaF: | |
f9f740d6 | 629 | return Standard_False; // GL_ALPHA is no more supported in core context |
dc858f4c | 630 | case Image_Format_UNKNOWN: |
f9f740d6 | 631 | return Standard_False; |
38a0206f | 632 | } |
c357e426 | 633 | |
f9f740d6 | 634 | if (aFormat == 0) |
38a0206f | 635 | { |
c357e426 | 636 | return Standard_False; |
38a0206f | 637 | } |
f9f740d6 | 638 | |
c357e426 | 639 | #if !defined(GL_ES_VERSION_2_0) |
640 | GLint aReadBufferPrev = GL_BACK; | |
641 | if (theBufferType == Graphic3d_BT_Depth | |
642 | && aFormat != GL_DEPTH_COMPONENT) | |
38a0206f | 643 | { |
c357e426 | 644 | return Standard_False; |
645 | } | |
20aeeb7b | 646 | #else |
647 | (void )theBufferType; | |
c357e426 | 648 | #endif |
38a0206f | 649 | |
c357e426 | 650 | // bind FBO if used |
b128c892 | 651 | if (!theFbo.IsNull() && theFbo->IsValid()) |
c357e426 | 652 | { |
b128c892 | 653 | theFbo->BindBuffer (GetGlContext()); |
38a0206f | 654 | } |
655 | else | |
a2e4f780 | 656 | { |
38a0206f | 657 | #if !defined(GL_ES_VERSION_2_0) |
c357e426 | 658 | glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev); |
659 | GLint aDrawBufferPrev = GL_BACK; | |
660 | glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev); | |
661 | glReadBuffer (aDrawBufferPrev); | |
38a0206f | 662 | #endif |
a2e4f780 | 663 | } |
664 | ||
c357e426 | 665 | // setup alignment |
666 | const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL | |
667 | glPixelStorei (GL_PACK_ALIGNMENT, anAligment); | |
668 | bool isBatchCopy = !theImage.IsTopDown(); | |
38a0206f | 669 | |
c357e426 | 670 | const GLint anExtraBytes = GLint(theImage.RowExtraBytes()); |
671 | GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes()); | |
672 | Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment); | |
673 | if (anExtraBytes < anAligment) | |
b86bb3df | 674 | { |
c357e426 | 675 | aPixelsWidth = 0; |
ee51a9fe | 676 | } |
c357e426 | 677 | else if (aSizeRowBytesEstim != theImage.SizeRowBytes()) |
ee51a9fe | 678 | { |
c357e426 | 679 | aPixelsWidth = 0; |
680 | isBatchCopy = false; | |
ee51a9fe | 681 | } |
c357e426 | 682 | #if !defined(GL_ES_VERSION_2_0) |
683 | glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth); | |
684 | #else | |
685 | if (aPixelsWidth != 0) | |
ee51a9fe | 686 | { |
c357e426 | 687 | isBatchCopy = false; |
b86bb3df | 688 | } |
c357e426 | 689 | #endif |
f9f740d6 | 690 | if (toConvRgba2Rgb) |
691 | { | |
692 | Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16); | |
693 | const Standard_Size aRowSize = theImage.SizeX() * 4; | |
694 | NCollection_Buffer aRowBuffer (anAlloc); | |
695 | if (!aRowBuffer.Allocate (aRowSize)) | |
696 | { | |
697 | return Standard_False; | |
698 | } | |
c357e426 | 699 | |
f9f740d6 | 700 | for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) |
701 | { | |
702 | // Image_PixMap rows indexation always starts from the upper corner | |
703 | // while order in memory depends on the flag and processed by ChangeRow() method | |
704 | glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, aRowBuffer.ChangeData()); | |
705 | const Image_ColorRGBA* aRowDataRgba = (const Image_ColorRGBA* )aRowBuffer.Data(); | |
dc858f4c | 706 | if (theImage.Format() == Image_Format_BGR) |
f9f740d6 | 707 | { |
708 | convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX()); | |
709 | } | |
710 | else | |
711 | { | |
712 | convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX()); | |
713 | } | |
714 | } | |
715 | } | |
716 | else if (!isBatchCopy) | |
679ecdee | 717 | { |
c357e426 | 718 | // copy row by row |
719 | for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) | |
679ecdee | 720 | { |
c357e426 | 721 | // Image_PixMap rows indexation always starts from the upper corner |
722 | // while order in memory depends on the flag and processed by ChangeRow() method | |
723 | glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow)); | |
679ecdee | 724 | } |
679ecdee | 725 | } |
726 | else | |
727 | { | |
c357e426 | 728 | glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData()); |
679ecdee | 729 | } |
f9f740d6 | 730 | const bool hasErrors = myGlContext->ResetErrors (true); |
a1954302 | 731 | |
c357e426 | 732 | glPixelStorei (GL_PACK_ALIGNMENT, 1); |
eae454e3 | 733 | #if !defined(GL_ES_VERSION_2_0) |
c357e426 | 734 | glPixelStorei (GL_PACK_ROW_LENGTH, 0); |
eae454e3 | 735 | #endif |
a1954302 | 736 | |
b128c892 | 737 | if (!theFbo.IsNull() && theFbo->IsValid()) |
c357e426 | 738 | { |
b128c892 | 739 | theFbo->UnbindBuffer (GetGlContext()); |
c357e426 | 740 | } |
741 | else | |
742 | { | |
743 | #if !defined(GL_ES_VERSION_2_0) | |
744 | glReadBuffer (aReadBufferPrev); | |
745 | #endif | |
746 | } | |
f9f740d6 | 747 | |
748 | if (toSwapRgbaBgra) | |
749 | { | |
750 | Image_PixMap::SwapRgbaBgra (theImage); | |
751 | } | |
752 | ||
753 | return !hasErrors; | |
679ecdee | 754 | } |
91c60b57 | 755 | |
91c60b57 | 756 | // ======================================================================= |
a1073ae2 | 757 | // function : ShouldRender |
91c60b57 | 758 | // purpose : |
759 | // ======================================================================= | |
a1073ae2 | 760 | Standard_Boolean OpenGl_RaytraceFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace, |
761 | const OpenGl_Element* theElement) | |
91c60b57 | 762 | { |
763 | Standard_Boolean aPrevFilterResult = Standard_True; | |
764 | if (!myPrevRenderFilter.IsNull()) | |
765 | { | |
a1073ae2 | 766 | aPrevFilterResult = myPrevRenderFilter->ShouldRender (theWorkspace, theElement); |
91c60b57 | 767 | } |
768 | return aPrevFilterResult && | |
769 | !OpenGl_Raytrace::IsRaytracedElement (theElement); | |
770 | } |