0025867: Visualization, TKOpenGl - fix misprint in transformation persistence math
[occt.git] / src / OpenGl / OpenGl_Workspace_Raytrace.cxx
CommitLineData
e276548b 1// Created on: 2013-08-27
2// Created by: Denis BOGOLEPOV
3// Copyright (c) 2013 OPEN CASCADE SAS
4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
e276548b 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.
e276548b 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
e276548b 15
b7cd4ba7 16#include <OpenGl_Workspace.hxx>
17
25ef750e 18#include <Graphic3d_TextureParams.hxx>
fc73a202 19#include <OpenGl_FrameBuffer.hxx>
b7cd4ba7 20#include <OpenGl_PrimitiveArray.hxx>
fc73a202 21#include <OpenGl_VertexBuffer.hxx>
e276548b 22#include <OpenGl_View.hxx>
fc73a202 23#include <OSD_File.hxx>
24#include <OSD_Protection.hxx>
e276548b 25
26using namespace OpenGl_Raytrace;
27
28//! Use this macro to output ray-tracing debug info
fc73a202 29// #define RAY_TRACE_PRINT_INFO
e276548b 30
31#ifdef RAY_TRACE_PRINT_INFO
32 #include <OSD_Timer.hxx>
33#endif
34
e276548b 35// =======================================================================
e276548b 36// function : UpdateRaytraceGeometry
37// purpose : Updates 3D scene geometry for ray tracing
38// =======================================================================
84c71f29 39Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMode)
e276548b 40{
41 if (myView.IsNull())
42 return Standard_False;
43
84c71f29 44 // Note: In 'check' mode (OpenGl_GUM_CHECK) the scene geometry is analyzed for modifications
e276548b 45 // This is light-weight procedure performed for each frame
46
84c71f29 47 if (theMode == OpenGl_GUM_CHECK)
e276548b 48 {
84c71f29 49 if (myLayersModificationStatus != myView->LayerList().ModificationState())
50 {
51 return UpdateRaytraceGeometry (OpenGl_GUM_PREPARE);
52 }
53 }
54 else if (theMode == OpenGl_GUM_PREPARE)
55 {
56 myRaytraceGeometry.ClearMaterials();
57 myArrayToTrianglesMap.clear();
e276548b 58
59 myIsRaytraceDataValid = Standard_False;
60 }
e276548b 61
62 // The set of processed structures (reflected to ray-tracing)
63 // This set is used to remove out-of-date records from the
64 // hash map of structures
65 std::set<const OpenGl_Structure*> anElements;
66
84c71f29 67 // Set of all currently visible and "raytracable" primitive arrays.
8d3f219f 68 std::set<Standard_Size> anArrayIDs;
84c71f29 69
e276548b 70 const OpenGl_LayerList& aList = myView->LayerList();
71
72 for (OpenGl_SequenceOfLayers::Iterator anLayerIt (aList.Layers()); anLayerIt.More(); anLayerIt.Next())
73 {
a1954302 74 const OpenGl_Layer& aLayer = anLayerIt.Value();
75 if (aLayer.NbStructures() == 0)
e276548b 76 continue;
77
a1954302 78 const OpenGl_ArrayOfStructure& aStructArray = aLayer.ArrayOfStructures();
68333c8f 79 for (Standard_Integer anIndex = 0; anIndex < aStructArray.Length(); ++anIndex)
e276548b 80 {
a1954302 81 for (OpenGl_SequenceOfStructure::Iterator aStructIt (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next())
e276548b 82 {
83 const OpenGl_Structure* aStructure = aStructIt.Value();
84
84c71f29 85 if (theMode == OpenGl_GUM_CHECK)
e276548b 86 {
87 if (CheckRaytraceStructure (aStructure))
88 {
84c71f29 89 return UpdateRaytraceGeometry (OpenGl_GUM_PREPARE);
e276548b 90 }
e2da917a 91 }
84c71f29 92 else if (theMode == OpenGl_GUM_PREPARE)
93 {
94 if (!aStructure->IsRaytracable()
95 || !aStructure->IsVisible())
a1954302 96 {
84c71f29 97 continue;
a1954302 98 }
84c71f29 99
100 for (OpenGl_Structure::GroupIterator aGroupIter (aStructure->DrawGroups()); aGroupIter.More(); aGroupIter.Next())
101 {
102 // OpenGL elements from group (extract primitives arrays)
103 for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
104 {
105 OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
106
107 if (aPrimArray != NULL)
108 {
109 // Collect all primitive arrays in scene.
8d3f219f 110 anArrayIDs.insert (aPrimArray->GetUID());
84c71f29 111 }
112 }
113 }
e2da917a 114 }
84c71f29 115 else if (theMode == OpenGl_GUM_UPDATE)
e276548b 116 {
117 if (!aStructure->IsRaytracable())
118 continue;
119
0717ddc1 120 AddRaytraceStructure (aStructure, anElements);
e276548b 121 }
122 }
123 }
124 }
125
84c71f29 126 if (theMode == OpenGl_GUM_PREPARE)
127 {
25ef750e 128 BVH_ObjectSet<Standard_ShortReal, 3>::BVH_ObjectList anUnchangedObjects;
84c71f29 129
130 // Leave only unchanged objects in myRaytraceGeometry so only their transforms and materials will be updated
131 // Objects which not in myArrayToTrianglesMap will be built from scratch.
132 for (Standard_Integer anObjectIdx = 0; anObjectIdx < myRaytraceGeometry.Objects().Size(); ++anObjectIdx)
133 {
134 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
135 myRaytraceGeometry.Objects().ChangeValue (anObjectIdx).operator->());
136
137 // If primitive array of object not in "anArrays" set then it was hided or deleted.
138 // If primitive array present in "anArrays" set but we don't have associated object yet, then
139 // the object is new and still has to be built.
8d3f219f 140 if ((aTriangleSet != NULL) && ((anArrayIDs.find (aTriangleSet->AssociatedPArrayID())) != anArrayIDs.end()))
84c71f29 141 {
142 anUnchangedObjects.Append (myRaytraceGeometry.Objects().Value (anObjectIdx));
143
8d3f219f 144 myArrayToTrianglesMap[aTriangleSet->AssociatedPArrayID()] = aTriangleSet;
84c71f29 145 }
146 }
147
148 myRaytraceGeometry.Objects() = anUnchangedObjects;
149
150 return UpdateRaytraceGeometry (OpenGl_GUM_UPDATE);
151 }
152
153 if (theMode == OpenGl_GUM_UPDATE)
e276548b 154 {
155 // Actualize the hash map of structures -- remove out-of-date records
156 std::map<const OpenGl_Structure*, Standard_Size>::iterator anIter = myStructureStates.begin();
157
158 while (anIter != myStructureStates.end())
159 {
160 if (anElements.find (anIter->first) == anElements.end())
161 {
162 myStructureStates.erase (anIter++);
163 }
164 else
165 {
166 ++anIter;
167 }
168 }
169
170 // Actualize OpenGL layer list state
171 myLayersModificationStatus = myView->LayerList().ModificationState();
172
265d4508 173 // Rebuild bottom-level and high-level BVHs
174 myRaytraceGeometry.ProcessAcceleration();
e276548b 175
265d4508 176 const Standard_ShortReal aMinRadius = Max (fabs (myRaytraceGeometry.Box().CornerMin().x()), Max (
177 fabs (myRaytraceGeometry.Box().CornerMin().y()), fabs (myRaytraceGeometry.Box().CornerMin().z())));
178 const Standard_ShortReal aMaxRadius = Max (fabs (myRaytraceGeometry.Box().CornerMax().x()), Max (
179 fabs (myRaytraceGeometry.Box().CornerMax().y()), fabs (myRaytraceGeometry.Box().CornerMax().z())));
e276548b 180
265d4508 181 myRaytraceSceneRadius = 2.f /* scale factor */ * Max (aMinRadius, aMaxRadius);
e276548b 182
25ef750e 183 const BVH_Vec3f aSize = myRaytraceGeometry.Box().Size();
e276548b 184
a89742cf 185 myRaytraceSceneEpsilon = Max (1e-6f, 1e-4f * sqrtf (
fc73a202 186 aSize.x() * aSize.x() + aSize.y() * aSize.y() + aSize.z() * aSize.z()));
187
188 return UploadRaytraceData();
e276548b 189 }
190
e276548b 191 return Standard_True;
192}
193
194// =======================================================================
195// function : CheckRaytraceStructure
e2da917a 196// purpose : Checks to see if the structure is modified
e276548b 197// =======================================================================
198Standard_Boolean OpenGl_Workspace::CheckRaytraceStructure (const OpenGl_Structure* theStructure)
199{
200 if (!theStructure->IsRaytracable())
201 {
202 // Checks to see if all ray-tracable elements were
203 // removed from the structure
204 if (theStructure->ModificationState() > 0)
205 {
206 theStructure->ResetModificationState();
207 return Standard_True;
208 }
209
210 return Standard_False;
211 }
212
213 std::map<const OpenGl_Structure*, Standard_Size>::iterator aStructState = myStructureStates.find (theStructure);
214
215 if (aStructState != myStructureStates.end())
216 return aStructState->second != theStructure->ModificationState();
217
218 return Standard_True;
219}
220
221// =======================================================================
25ef750e 222// function : BuildTexTransform
223// purpose : Constructs texture transformation matrix
224// =======================================================================
225void BuildTexTransform (const Handle(Graphic3d_TextureParams)& theParams, BVH_Mat4f& theMatrix)
226{
227 theMatrix.InitIdentity();
228
229 // Apply scaling
230 const Graphic3d_Vec2& aScale = theParams->Scale();
231
232 theMatrix.ChangeValue (0, 0) *= aScale.x();
233 theMatrix.ChangeValue (1, 0) *= aScale.x();
234 theMatrix.ChangeValue (2, 0) *= aScale.x();
235 theMatrix.ChangeValue (3, 0) *= aScale.x();
236
237 theMatrix.ChangeValue (0, 1) *= aScale.y();
238 theMatrix.ChangeValue (1, 1) *= aScale.y();
239 theMatrix.ChangeValue (2, 1) *= aScale.y();
240 theMatrix.ChangeValue (3, 1) *= aScale.y();
241
242 // Apply translation
243 const Graphic3d_Vec2 aTrans = -theParams->Translation();
244
245 theMatrix.ChangeValue (0, 3) = theMatrix.GetValue (0, 0) * aTrans.x() +
246 theMatrix.GetValue (0, 1) * aTrans.y();
247
248 theMatrix.ChangeValue (1, 3) = theMatrix.GetValue (1, 0) * aTrans.x() +
249 theMatrix.GetValue (1, 1) * aTrans.y();
250
251 theMatrix.ChangeValue (2, 3) = theMatrix.GetValue (2, 0) * aTrans.x() +
252 theMatrix.GetValue (2, 1) * aTrans.y();
253
254 // Apply rotation
255 const Standard_ShortReal aSin = std::sin (
256 -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
257 const Standard_ShortReal aCos = std::cos (
258 -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
259
260 BVH_Mat4f aRotationMat;
261 aRotationMat.SetValue (0, 0, aCos);
262 aRotationMat.SetValue (1, 1, aCos);
263 aRotationMat.SetValue (0, 1, -aSin);
264 aRotationMat.SetValue (1, 0, aSin);
265
266 theMatrix = theMatrix * aRotationMat;
267}
268
269// =======================================================================
e276548b 270// function : CreateMaterial
271// purpose : Creates ray-tracing material properties
272// =======================================================================
25ef750e 273Standard_Boolean OpenGl_Workspace::CreateMaterial (const OpenGl_AspectFace* theAspect, OpenGl_RaytraceMaterial& theMaterial)
e276548b 274{
25ef750e 275 const OPENGL_SURF_PROP& aProperties = theAspect->IntFront();
276
277 const Standard_ShortReal* aSrcAmbient =
278 aProperties.isphysic ? aProperties.ambcol.rgb : aProperties.matcol.rgb;
279
280 theMaterial.Ambient = BVH_Vec4f (aSrcAmbient[0] * aProperties.amb,
281 aSrcAmbient[1] * aProperties.amb,
282 aSrcAmbient[2] * aProperties.amb,
283 1.f);
284
285 const Standard_ShortReal* aSrcDiffuse =
286 aProperties.isphysic ? aProperties.difcol.rgb : aProperties.matcol.rgb;
287
288 theMaterial.Diffuse = BVH_Vec4f (aSrcDiffuse[0] * aProperties.diff,
289 aSrcDiffuse[1] * aProperties.diff,
290 aSrcDiffuse[2] * aProperties.diff,
291 -1.f /* no texture */);
292
293 theMaterial.Specular = BVH_Vec4f (
294 (aProperties.isphysic ? aProperties.speccol.rgb[0] : 1.f) * aProperties.spec,
295 (aProperties.isphysic ? aProperties.speccol.rgb[1] : 1.f) * aProperties.spec,
296 (aProperties.isphysic ? aProperties.speccol.rgb[2] : 1.f) * aProperties.spec,
297 aProperties.shine);
298
299 const Standard_ShortReal* aSrcEmission =
300 aProperties.isphysic ? aProperties.emscol.rgb : aProperties.matcol.rgb;
301
302 theMaterial.Emission = BVH_Vec4f (aSrcEmission[0] * aProperties.emsv,
303 aSrcEmission[1] * aProperties.emsv,
304 aSrcEmission[2] * aProperties.emsv,
305 1.f);
e276548b 306
307 // Note: Here we use sub-linear transparency function
308 // to produce realistic-looking transparency effect
25ef750e 309 theMaterial.Transparency = BVH_Vec4f (powf (aProperties.trans, 0.75f),
310 1.f - aProperties.trans,
311 aProperties.index == 0 ? 1.f : aProperties.index,
312 aProperties.index == 0 ? 1.f : 1.f / aProperties.index);
e276548b 313
25ef750e 314 const Standard_ShortReal aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
315 Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
316 theMaterial.Diffuse.z() + theMaterial.Specular.z()));
e276548b 317
25ef750e 318 const Standard_ShortReal aReflectionScale = 0.75f / aMaxRefl;
319
320 theMaterial.Reflection = BVH_Vec4f (
321 aProperties.speccol.rgb[0] * aProperties.spec * aReflectionScale,
322 aProperties.speccol.rgb[1] * aProperties.spec * aReflectionScale,
323 aProperties.speccol.rgb[2] * aProperties.spec * aReflectionScale,
324 0.f);
325
326 if (theAspect->DoTextureMap())
327 {
328 if (myGlContext->arbTexBindless != NULL)
329 {
330 BuildTexTransform (theAspect->TextureParams(), theMaterial.TextureTransform);
331 theMaterial.Diffuse.w() = static_cast<Standard_ShortReal> (
332 myRaytraceGeometry.AddTexture (theAspect->TextureRes (myGlContext)));
333 }
334 else if (!myIsRaytraceWarnTextures)
335 {
336 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
337 GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
338 "Warning: texturing in Ray-Trace requires GL_ARB_bindless_texture extension which is missing. "
339 "Textures will be ignored.");
340 myIsRaytraceWarnTextures = Standard_True;
341 }
342 }
e276548b 343
25ef750e 344 return Standard_True;
e276548b 345}
346
347// =======================================================================
348// function : AddRaytraceStructure
349// purpose : Adds OpenGL structure to ray-traced scene geometry
350// =======================================================================
0717ddc1 351Standard_Boolean OpenGl_Workspace::AddRaytraceStructure (const OpenGl_Structure* theStructure, std::set<const OpenGl_Structure*>& theElements)
e276548b 352{
e276548b 353 theElements.insert (theStructure);
354
355 if (!theStructure->IsVisible())
356 {
357 myStructureStates[theStructure] = theStructure->ModificationState();
358 return Standard_True;
359 }
360
361 // Get structure material
68333c8f 362 Standard_Integer aStructMatID = -1;
e276548b 363
364 if (theStructure->AspectFace() != NULL)
365 {
265d4508 366 aStructMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
e276548b 367
368 OpenGl_RaytraceMaterial aStructMaterial;
25ef750e 369 CreateMaterial (theStructure->AspectFace(), aStructMaterial);
e276548b 370
265d4508 371 myRaytraceGeometry.Materials.push_back (aStructMaterial);
e276548b 372 }
373
0717ddc1 374 Standard_ShortReal aStructTransformArr[16];
375 Standard_ShortReal* aStructTransform = NULL;
376 if (theStructure->Transformation()->mat != NULL)
377 {
378 aStructTransform = aStructTransformArr;
379 for (Standard_Integer i = 0; i < 4; ++i)
380 {
381 for (Standard_Integer j = 0; j < 4; ++j)
382 {
383 aStructTransform[j * 4 + i] = theStructure->Transformation()->mat[i][j];
384 }
385 }
386 }
387
388 AddRaytraceGroups (theStructure, aStructMatID, aStructTransform);
389
390 // Process all connected OpenGL structures
391 for (OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures()); anIts.More(); anIts.Next())
392 {
393 if (anIts.Value()->IsRaytracable())
394 AddRaytraceGroups (anIts.Value(), aStructMatID, aStructTransform);
395 }
396
397 myStructureStates[theStructure] = theStructure->ModificationState();
398 return Standard_True;
399}
400
401// =======================================================================
402// function : AddRaytraceGroups
403// purpose : Adds OpenGL groups to ray-traced scene geometry
404// =======================================================================
405Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure* theStructure,
406 const Standard_Integer theStructMatId,
407 const Standard_ShortReal* theTransform)
408{
b64d84be 409 for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->DrawGroups()); aGroupIter.More(); aGroupIter.Next())
e276548b 410 {
411 // Get group material
68333c8f 412 Standard_Integer aGroupMatID = -1;
b64d84be 413 if (aGroupIter.Value()->AspectFace() != NULL)
e276548b 414 {
265d4508 415 aGroupMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
e276548b 416
417 OpenGl_RaytraceMaterial aGroupMaterial;
25ef750e 418 CreateMaterial (aGroupIter.Value()->AspectFace(), aGroupMaterial);
e276548b 419
265d4508 420 myRaytraceGeometry.Materials.push_back (aGroupMaterial);
e276548b 421 }
422
0717ddc1 423 Standard_Integer aMatID = aGroupMatID < 0 ? theStructMatId : aGroupMatID;
e276548b 424
265d4508 425 if (aMatID < 0)
e276548b 426 {
265d4508 427 aMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
e276548b 428
265d4508 429 myRaytraceGeometry.Materials.push_back (OpenGl_RaytraceMaterial());
e276548b 430 }
431
265d4508 432 // Add OpenGL elements from group (extract primitives arrays and aspects)
b64d84be 433 for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
e276548b 434 {
5322131b 435 OpenGl_AspectFace* anAspect = dynamic_cast<OpenGl_AspectFace*> (aNode->elem);
436 if (anAspect != NULL)
e276548b 437 {
5322131b 438 aMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
e276548b 439
5322131b 440 OpenGl_RaytraceMaterial aMaterial;
25ef750e 441 CreateMaterial (anAspect, aMaterial);
e276548b 442
5322131b 443 myRaytraceGeometry.Materials.push_back (aMaterial);
e276548b 444 }
5322131b 445 else
e276548b 446 {
447 OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
84c71f29 448
e276548b 449 if (aPrimArray != NULL)
450 {
8d3f219f 451 std::map<Standard_Size, OpenGl_TriangleSet*>::iterator aSetIter = myArrayToTrianglesMap.find (aPrimArray->GetUID());
452
84c71f29 453 if (aSetIter != myArrayToTrianglesMap.end())
454 {
455 OpenGl_TriangleSet* aSet = aSetIter->second;
25ef750e 456
84c71f29 457 BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>();
458
459 if (theTransform != NULL)
460 {
461 aTransform->SetTransform (*(reinterpret_cast<const BVH_Mat4f*> (theTransform)));
462 }
463
464 aSet->SetProperties (aTransform);
465
25ef750e 466 if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID)
84c71f29 467 {
468 aSet->SetMaterialIndex (aMatID);
469 }
470 }
471 else
472 {
25ef750e 473 NCollection_Handle<BVH_Object<Standard_ShortReal, 3> > aSet =
84c71f29 474 AddRaytracePrimitiveArray (aPrimArray, aMatID, 0);
265d4508 475
84c71f29 476 if (!aSet.IsNull())
477 {
478 BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>;
479
480 if (theTransform != NULL)
481 {
482 aTransform->SetTransform (*(reinterpret_cast<const BVH_Mat4f*> (theTransform)));
483 }
484
485 aSet->SetProperties (aTransform);
486
487 myRaytraceGeometry.Objects().Append (aSet);
488 }
489 }
e276548b 490 }
491 }
492 }
e276548b 493 }
494
e276548b 495 return Standard_True;
496}
497
498// =======================================================================
499// function : AddRaytracePrimitiveArray
500// purpose : Adds OpenGL primitive array to ray-traced scene geometry
501// =======================================================================
871fa103 502OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_PrimitiveArray* theArray,
503 Standard_Integer theMatID,
25ef750e 504 const OpenGl_Mat4* theTransform)
e276548b 505{
871fa103 506 const Handle(Graphic3d_IndexBuffer)& anIndices = theArray->Indices();
507 const Handle(Graphic3d_Buffer)& anAttribs = theArray->Attributes();
508 const Handle(Graphic3d_BoundBuffer)& aBounds = theArray->Bounds();
509 if (theArray->DrawMode() < GL_TRIANGLES
ca3c13d1 510 #if !defined(GL_ES_VERSION_2_0)
871fa103 511 || theArray->DrawMode() > GL_POLYGON
ca3c13d1 512 #else
513 || theArray->DrawMode() > GL_TRIANGLE_FAN
514 #endif
871fa103 515 || anAttribs.IsNull())
e276548b 516 {
265d4508 517 return NULL;
e276548b 518 }
519
e276548b 520#ifdef RAY_TRACE_PRINT_INFO
bc8c79bb 521 switch (theArray->DrawMode())
e276548b 522 {
871fa103 523 case GL_TRIANGLES: std::cout << "\tAdding GL_TRIANGLES\n"; break;
871fa103 524 case GL_TRIANGLE_FAN: std::cout << "\tAdding GL_TRIANGLE_FAN\n"; break;
525 case GL_TRIANGLE_STRIP: std::cout << "\tAdding GL_TRIANGLE_STRIP\n"; break;
ca3c13d1 526 #if !defined(GL_ES_VERSION_2_0)
527 case GL_QUADS: std::cout << "\tAdding GL_QUADS\n"; break;
871fa103 528 case GL_QUAD_STRIP: std::cout << "\tAdding GL_QUAD_STRIP\n"; break;
ca3c13d1 529 case GL_POLYGON: std::cout << "\tAdding GL_POLYGON\n"; break;
530 #endif
e276548b 531 }
532#endif
533
25ef750e 534 OpenGl_Mat4 aNormalMatrix;
535
536 if (theTransform != NULL)
537 {
538 Standard_ASSERT_RETURN (theTransform->Inverted (aNormalMatrix),
539 "Error: Failed to compute normal transformation matrix", NULL);
540
541 aNormalMatrix.Transpose();
542 }
543
8d3f219f 544 OpenGl_TriangleSet* aSet = new OpenGl_TriangleSet (theArray->GetUID());
e276548b 545 {
871fa103 546 aSet->Vertices.reserve (anAttribs->NbElements);
547 aSet->Normals .reserve (anAttribs->NbElements);
25ef750e 548 aSet->TexCrds .reserve (anAttribs->NbElements);
549
871fa103 550 const size_t aVertFrom = aSet->Vertices.size();
551 for (Standard_Integer anAttribIter = 0; anAttribIter < anAttribs->NbAttributes; ++anAttribIter)
265d4508 552 {
871fa103 553 const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIter);
554 const size_t anOffset = anAttribs->AttributeOffset (anAttribIter);
555 if (anAttrib.Id == Graphic3d_TOA_POS)
556 {
557 if (anAttrib.DataType == Graphic3d_TOD_VEC3
558 || anAttrib.DataType == Graphic3d_TOD_VEC4)
559 {
560 for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
561 {
25ef750e 562 aSet->Vertices.push_back (
563 *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset));
871fa103 564 }
565 }
566 else if (anAttrib.DataType == Graphic3d_TOD_VEC2)
567 {
568 for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
569 {
570 const Graphic3d_Vec2& aVert = *reinterpret_cast<const Graphic3d_Vec2* >(anAttribs->value (aVertIter) + anOffset);
25ef750e 571 aSet->Vertices.push_back (BVH_Vec3f (aVert.x(), aVert.y(), 0.0f));
871fa103 572 }
573 }
574 }
575 else if (anAttrib.Id == Graphic3d_TOA_NORM)
576 {
577 if (anAttrib.DataType == Graphic3d_TOD_VEC3
578 || anAttrib.DataType == Graphic3d_TOD_VEC4)
579 {
580 for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
581 {
25ef750e 582 aSet->Normals.push_back (
583 *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset));
584 }
585 }
586 }
587 else if (anAttrib.Id == Graphic3d_TOA_UV)
588 {
589 if (anAttrib.DataType == Graphic3d_TOD_VEC2)
590 {
591 for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
592 {
593 aSet->TexCrds.push_back (
594 *reinterpret_cast<const Graphic3d_Vec2* >(anAttribs->value (aVertIter) + anOffset));
871fa103 595 }
596 }
597 }
265d4508 598 }
e276548b 599
871fa103 600 if (aSet->Normals.size() != aSet->Vertices.size())
265d4508 601 {
871fa103 602 for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
265d4508 603 {
25ef750e 604 aSet->Normals.push_back (BVH_Vec3f());
605 }
606 }
607
608 if (aSet->TexCrds.size() != aSet->Vertices.size())
609 {
610 for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
611 {
612 aSet->TexCrds.push_back (BVH_Vec2f());
265d4508 613 }
871fa103 614 }
e276548b 615
25ef750e 616 if (theTransform != NULL)
871fa103 617 {
618 for (size_t aVertIter = aVertFrom; aVertIter < aSet->Vertices.size(); ++aVertIter)
619 {
25ef750e 620 BVH_Vec3f& aVertex = aSet->Vertices[aVertIter];
621
622 BVH_Vec4f aTransVertex =
623 *theTransform * BVH_Vec4f (aVertex.x(), aVertex.y(), aVertex.z(), 1.f);
624
625 aVertex = BVH_Vec3f (aTransVertex.x(), aTransVertex.y(), aTransVertex.z());
871fa103 626 }
627 for (size_t aVertIter = aVertFrom; aVertIter < aSet->Normals.size(); ++aVertIter)
628 {
25ef750e 629 BVH_Vec3f& aNormal = aSet->Normals[aVertIter];
630
631 BVH_Vec4f aTransNormal =
632 aNormalMatrix * BVH_Vec4f (aNormal.x(), aNormal.y(), aNormal.z(), 0.f);
633
634 aNormal = BVH_Vec3f (aTransNormal.x(), aTransNormal.y(), aTransNormal.z());
871fa103 635 }
e276548b 636 }
637
871fa103 638 if (!aBounds.IsNull())
265d4508 639 {
e2da917a 640#ifdef RAY_TRACE_PRINT_INFO
bc8c79bb 641 std::cout << "\tNumber of bounds = " << aBounds->NbBounds << std::endl;
e2da917a 642#endif
e276548b 643
265d4508 644 Standard_Integer aBoundStart = 0;
871fa103 645 for (Standard_Integer aBound = 0; aBound < aBounds->NbBounds; ++aBound)
265d4508 646 {
871fa103 647 const Standard_Integer aVertNum = aBounds->Bounds[aBound];
e276548b 648
e2da917a 649#ifdef RAY_TRACE_PRINT_INFO
265d4508 650 std::cout << "\tAdding indices from bound " << aBound << ": " <<
651 aBoundStart << " .. " << aVertNum << std::endl;
e2da917a 652#endif
265d4508 653
871fa103 654 if (!AddRaytraceVertexIndices (*aSet, *theArray, aBoundStart, aVertNum, theMatID))
265d4508 655 {
656 delete aSet;
657 return NULL;
658 }
659
660 aBoundStart += aVertNum;
661 }
662 }
663 else
e276548b 664 {
871fa103 665 const Standard_Integer aVertNum = !anIndices.IsNull() ? anIndices->NbElements : anAttribs->NbElements;
e276548b 666
265d4508 667 #ifdef RAY_TRACE_PRINT_INFO
668 std::cout << "\tAdding indices from array: " << aVertNum << std::endl;
669 #endif
e276548b 670
871fa103 671 if (!AddRaytraceVertexIndices (*aSet, *theArray, 0, aVertNum, theMatID))
e276548b 672 {
265d4508 673 delete aSet;
674 return NULL;
e276548b 675 }
e276548b 676 }
677 }
e276548b 678
265d4508 679 if (aSet->Size() != 0)
680 aSet->MarkDirty();
e276548b 681
265d4508 682 return aSet;
e276548b 683}
684
685// =======================================================================
686// function : AddRaytraceVertexIndices
687// purpose : Adds vertex indices to ray-traced scene geometry
688// =======================================================================
871fa103 689Standard_Boolean OpenGl_Workspace::AddRaytraceVertexIndices (OpenGl_TriangleSet& theSet,
690 const OpenGl_PrimitiveArray& theArray,
691 Standard_Integer theOffset,
692 Standard_Integer theCount,
693 Standard_Integer theMatID)
e276548b 694{
871fa103 695 switch (theArray.DrawMode())
e276548b 696 {
871fa103 697 case GL_TRIANGLES: return AddRaytraceTriangleArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
871fa103 698 case GL_TRIANGLE_FAN: return AddRaytraceTriangleFanArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
699 case GL_TRIANGLE_STRIP: return AddRaytraceTriangleStripArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
ca3c13d1 700 #if !defined(GL_ES_VERSION_2_0)
701 case GL_QUADS: return AddRaytraceQuadrangleArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
871fa103 702 case GL_QUAD_STRIP: return AddRaytraceQuadrangleStripArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
703 case GL_POLYGON: return AddRaytracePolygonArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
ca3c13d1 704 #endif
e276548b 705 }
871fa103 706 return Standard_False;
e276548b 707}
708
709// =======================================================================
710// function : AddRaytraceTriangleArray
711// purpose : Adds OpenGL triangle array to ray-traced scene geometry
712// =======================================================================
871fa103 713Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleArray (OpenGl_TriangleSet& theSet,
714 const Handle(Graphic3d_IndexBuffer)& theIndices,
715 Standard_Integer theOffset,
716 Standard_Integer theCount,
717 Standard_Integer theMatID)
e276548b 718{
265d4508 719 if (theCount < 3)
e276548b 720 return Standard_True;
721
871fa103 722 theSet.Elements.reserve (theSet.Elements.size() + theCount / 3);
265d4508 723
871fa103 724 if (!theIndices.IsNull())
e276548b 725 {
265d4508 726 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
e276548b 727 {
871fa103 728 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
729 theIndices->Index (aVert + 1),
730 theIndices->Index (aVert + 2),
731 theMatID));
e276548b 732 }
733 }
734 else
735 {
265d4508 736 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
e276548b 737 {
871fa103 738 theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2,
739 theMatID));
e276548b 740 }
741 }
742
743 return Standard_True;
744}
745
746// =======================================================================
747// function : AddRaytraceTriangleFanArray
748// purpose : Adds OpenGL triangle fan array to ray-traced scene geometry
749// =======================================================================
871fa103 750Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleFanArray (OpenGl_TriangleSet& theSet,
751 const Handle(Graphic3d_IndexBuffer)& theIndices,
752 Standard_Integer theOffset,
753 Standard_Integer theCount,
754 Standard_Integer theMatID)
e276548b 755{
265d4508 756 if (theCount < 3)
e276548b 757 return Standard_True;
758
871fa103 759 theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
265d4508 760
871fa103 761 if (!theIndices.IsNull())
e276548b 762 {
265d4508 763 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
e276548b 764 {
871fa103 765 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
766 theIndices->Index (aVert + 1),
767 theIndices->Index (aVert + 2),
768 theMatID));
e276548b 769 }
770 }
771 else
772 {
265d4508 773 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
e276548b 774 {
871fa103 775 theSet.Elements.push_back (BVH_Vec4i (theOffset,
776 aVert + 1,
777 aVert + 2,
778 theMatID));
e276548b 779 }
780 }
781
782 return Standard_True;
783}
784
785// =======================================================================
786// function : AddRaytraceTriangleStripArray
787// purpose : Adds OpenGL triangle strip array to ray-traced scene geometry
788// =======================================================================
871fa103 789Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleStripArray (OpenGl_TriangleSet& theSet,
790 const Handle(Graphic3d_IndexBuffer)& theIndices,
791 Standard_Integer theOffset,
792 Standard_Integer theCount,
793 Standard_Integer theMatID)
e276548b 794{
265d4508 795 if (theCount < 3)
e276548b 796 return Standard_True;
797
871fa103 798 theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
265d4508 799
871fa103 800 if (!theIndices.IsNull())
e276548b 801 {
265d4508 802 for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
e276548b 803 {
871fa103 804 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + aCW ? 1 : 0),
805 theIndices->Index (aVert + aCW ? 0 : 1),
806 theIndices->Index (aVert + 2),
807 theMatID));
e276548b 808 }
809 }
810 else
811 {
265d4508 812 for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
e276548b 813 {
871fa103 814 theSet.Elements.push_back (BVH_Vec4i (aVert + aCW ? 1 : 0,
815 aVert + aCW ? 0 : 1,
816 aVert + 2,
817 theMatID));
e276548b 818 }
819 }
820
821 return Standard_True;
822}
823
824// =======================================================================
825// function : AddRaytraceQuadrangleArray
826// purpose : Adds OpenGL quad array to ray-traced scene geometry
827// =======================================================================
871fa103 828Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleArray (OpenGl_TriangleSet& theSet,
829 const Handle(Graphic3d_IndexBuffer)& theIndices,
830 Standard_Integer theOffset,
831 Standard_Integer theCount,
832 Standard_Integer theMatID)
e276548b 833{
265d4508 834 if (theCount < 4)
e276548b 835 return Standard_True;
836
871fa103 837 theSet.Elements.reserve (theSet.Elements.size() + theCount / 2);
265d4508 838
871fa103 839 if (!theIndices.IsNull())
e276548b 840 {
265d4508 841 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
e276548b 842 {
871fa103 843 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
844 theIndices->Index (aVert + 1),
845 theIndices->Index (aVert + 2),
846 theMatID));
847 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
848 theIndices->Index (aVert + 2),
849 theIndices->Index (aVert + 3),
850 theMatID));
e276548b 851 }
852 }
853 else
854 {
265d4508 855 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
e276548b 856 {
871fa103 857 theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2,
858 theMatID));
859 theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 2, aVert + 3,
860 theMatID));
e276548b 861 }
862 }
863
864 return Standard_True;
865}
866
867// =======================================================================
868// function : AddRaytraceQuadrangleStripArray
869// purpose : Adds OpenGL quad strip array to ray-traced scene geometry
870// =======================================================================
871fa103 871Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleStripArray (OpenGl_TriangleSet& theSet,
872 const Handle(Graphic3d_IndexBuffer)& theIndices,
873 Standard_Integer theOffset,
874 Standard_Integer theCount,
875 Standard_Integer theMatID)
e276548b 876{
265d4508 877 if (theCount < 4)
e276548b 878 return Standard_True;
879
871fa103 880 theSet.Elements.reserve (theSet.Elements.size() + 2 * theCount - 6);
265d4508 881
871fa103 882 if (!theIndices.IsNull())
e276548b 883 {
265d4508 884 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
e276548b 885 {
871fa103 886 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
887 theIndices->Index (aVert + 1),
888 theIndices->Index (aVert + 2),
889 theMatID));
890
891 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 1),
892 theIndices->Index (aVert + 3),
893 theIndices->Index (aVert + 2),
894 theMatID));
e276548b 895 }
896 }
897 else
898 {
265d4508 899 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
e276548b 900 {
871fa103 901 theSet.Elements.push_back (BVH_Vec4i (aVert + 0,
902 aVert + 1,
903 aVert + 2,
904 theMatID));
905
906 theSet.Elements.push_back (BVH_Vec4i (aVert + 1,
907 aVert + 3,
908 aVert + 2,
909 theMatID));
e276548b 910 }
911 }
912
913 return Standard_True;
914}
915
916// =======================================================================
917// function : AddRaytracePolygonArray
918// purpose : Adds OpenGL polygon array to ray-traced scene geometry
919// =======================================================================
871fa103 920Standard_Boolean OpenGl_Workspace::AddRaytracePolygonArray (OpenGl_TriangleSet& theSet,
921 const Handle(Graphic3d_IndexBuffer)& theIndices,
922 Standard_Integer theOffset,
923 Standard_Integer theCount,
924 Standard_Integer theMatID)
e276548b 925{
265d4508 926 if (theCount < 3)
e276548b 927 return Standard_True;
928
871fa103 929 theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
265d4508 930
871fa103 931 if (!theIndices.IsNull())
e276548b 932 {
265d4508 933 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
e276548b 934 {
871fa103 935 theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
936 theIndices->Index (aVert + 1),
937 theIndices->Index (aVert + 2),
938 theMatID));
e276548b 939 }
940 }
941 else
942 {
265d4508 943 for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
e276548b 944 {
871fa103 945 theSet.Elements.push_back (BVH_Vec4i (theOffset,
946 aVert + 1,
947 aVert + 2,
948 theMatID));
e276548b 949 }
950 }
951
952 return Standard_True;
953}
954
955// =======================================================================
956// function : UpdateRaytraceLightSources
957// purpose : Updates 3D scene light sources for ray-tracing
958// =======================================================================
25ef750e 959Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const OpenGl_Mat4& theInvModelView)
e276548b 960{
265d4508 961 myRaytraceGeometry.Sources.clear();
e276548b 962
fc73a202 963 myRaytraceGeometry.Ambient = BVH_Vec4f (0.0f, 0.0f, 0.0f, 0.0f);
265d4508 964
965 for (OpenGl_ListOfLight::Iterator anItl (myView->LightList()); anItl.More(); anItl.Next())
e276548b 966 {
12381341 967 const OpenGl_Light& aLight = anItl.Value();
265d4508 968
12381341 969 if (aLight.Type == Visual3d_TOLS_AMBIENT)
e276548b 970 {
fc73a202 971 myRaytraceGeometry.Ambient += BVH_Vec4f (aLight.Color.r(),
972 aLight.Color.g(),
973 aLight.Color.b(),
974 0.0f);
e276548b 975 continue;
976 }
977
265d4508 978 BVH_Vec4f aDiffuse (aLight.Color.r(),
979 aLight.Color.g(),
980 aLight.Color.b(),
981 1.0f);
982
983 BVH_Vec4f aPosition (-aLight.Direction.x(),
984 -aLight.Direction.y(),
985 -aLight.Direction.z(),
986 0.0f);
987
12381341 988 if (aLight.Type != Visual3d_TOLS_DIRECTIONAL)
e276548b 989 {
265d4508 990 aPosition = BVH_Vec4f (aLight.Position.x(),
991 aLight.Position.y(),
992 aLight.Position.z(),
993 1.0f);
e276548b 994 }
265d4508 995
12381341 996 if (aLight.IsHeadlight)
25ef750e 997 {
998 aPosition = theInvModelView * aPosition;
999 }
e276548b 1000
265d4508 1001 myRaytraceGeometry.Sources.push_back (OpenGl_RaytraceLight (aDiffuse, aPosition));
e276548b 1002 }
1003
fc73a202 1004 if (myRaytraceLightSrcTexture.IsNull()) // create light source buffer
e276548b 1005 {
fc73a202 1006 myRaytraceLightSrcTexture = new OpenGl_TextureBufferArb;
e276548b 1007
fc73a202 1008 if (!myRaytraceLightSrcTexture->Create (myGlContext))
1009 {
e276548b 1010#ifdef RAY_TRACE_PRINT_INFO
fc73a202 1011 std::cout << "Error: Failed to create light source buffer" << std::endl;
e276548b 1012#endif
fc73a202 1013 return Standard_False;
1014 }
e276548b 1015 }
fc73a202 1016
1017 if (myRaytraceGeometry.Sources.size() != 0)
e276548b 1018 {
fc73a202 1019 const GLfloat* aDataPtr = myRaytraceGeometry.Sources.front().Packed();
5cff985a 1020 if (!myRaytraceLightSrcTexture->Init (myGlContext, 4, GLsizei (myRaytraceGeometry.Sources.size() * 2), aDataPtr))
fc73a202 1021 {
1022#ifdef RAY_TRACE_PRINT_INFO
1023 std::cout << "Error: Failed to upload light source buffer" << std::endl;
e276548b 1024#endif
fc73a202 1025 return Standard_False;
1026 }
1027 }
e276548b 1028
1029 return Standard_True;
1030}
1031
1032// =======================================================================
fc73a202 1033// function : UpdateRaytraceEnvironmentMap
1034// purpose : Updates environment map for ray-tracing
e276548b 1035// =======================================================================
fc73a202 1036Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
e276548b 1037{
fc73a202 1038 if (myView.IsNull())
e276548b 1039 return Standard_False;
e276548b 1040
fc73a202 1041 if (myViewModificationStatus == myView->ModificationState())
1042 return Standard_True;
e276548b 1043
fc73a202 1044 for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx)
e276548b 1045 {
fc73a202 1046 const Handle(OpenGl_ShaderProgram)& aProgram =
1047 anIdx == 0 ? myRaytraceProgram : myPostFSAAProgram;
e276548b 1048
fc73a202 1049 if (!aProgram.IsNull())
e276548b 1050 {
7d3e64ef 1051 myGlContext->BindProgram (aProgram);
e276548b 1052
fc73a202 1053 if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
e276548b 1054 {
fc73a202 1055 myView->TextureEnv()->Bind (
1056 myGlContext, GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
1057
84c71f29 1058 aProgram->SetUniform (myGlContext,
25ef750e 1059 myUniformLocations[anIdx][OpenGl_RT_uEnvMapEnable], 1);
e276548b 1060 }
1061 else
1062 {
84c71f29 1063 aProgram->SetUniform (myGlContext,
25ef750e 1064 myUniformLocations[anIdx][OpenGl_RT_uEnvMapEnable], 0);
e276548b 1065 }
fc73a202 1066 }
e276548b 1067 }
1068
7d3e64ef 1069 myGlContext->BindProgram (NULL);
fc73a202 1070 myViewModificationStatus = myView->ModificationState();
e276548b 1071 return Standard_True;
1072}
1073
1074// =======================================================================
fc73a202 1075// function : Source
1076// purpose : Returns shader source combined with prefix
e276548b 1077// =======================================================================
fc73a202 1078TCollection_AsciiString OpenGl_Workspace::ShaderSource::Source() const
e276548b 1079{
fc73a202 1080 static const TCollection_AsciiString aVersion = "#version 140";
e276548b 1081
fc73a202 1082 if (myPrefix.IsEmpty())
e276548b 1083 {
fc73a202 1084 return aVersion + "\n" + mySource;
e276548b 1085 }
1086
fc73a202 1087 return aVersion + "\n" + myPrefix + "\n" + mySource;
e276548b 1088}
1089
1090// =======================================================================
fc73a202 1091// function : Load
1092// purpose : Loads shader source from specified files
e276548b 1093// =======================================================================
fc73a202 1094void OpenGl_Workspace::ShaderSource::Load (
1095 const TCollection_AsciiString* theFileNames, const Standard_Integer theCount)
e276548b 1096{
fc73a202 1097 mySource.Clear();
e276548b 1098
fc73a202 1099 for (Standard_Integer anIndex = 0; anIndex < theCount; ++anIndex)
1100 {
1101 OSD_File aFile (theFileNames[anIndex]);
e276548b 1102
fc73a202 1103 Standard_ASSERT_RETURN (aFile.Exists(),
1104 "Error: Failed to find shader source file", /* none */);
e276548b 1105
fc73a202 1106 aFile.Open (OSD_ReadOnly, OSD_Protection());
265d4508 1107
fc73a202 1108 TCollection_AsciiString aSource;
265d4508 1109
fc73a202 1110 Standard_ASSERT_RETURN (aFile.IsOpen(),
1111 "Error: Failed to open shader source file", /* none */);
e276548b 1112
fc73a202 1113 aFile.Read (aSource, (Standard_Integer) aFile.Size());
e276548b 1114
fc73a202 1115 if (!aSource.IsEmpty())
1116 {
1117 mySource += TCollection_AsciiString ("\n") + aSource;
1118 }
68333c8f 1119
fc73a202 1120 aFile.Close();
68333c8f 1121 }
e276548b 1122}
1123
1124// =======================================================================
fc73a202 1125// function : LoadShader
1126// purpose : Creates new shader object with specified source
e276548b 1127// =======================================================================
fc73a202 1128Handle(OpenGl_ShaderObject) OpenGl_Workspace::LoadShader (const ShaderSource& theSource, GLenum theType)
e276548b 1129{
fc73a202 1130 Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (theType);
e276548b 1131
fc73a202 1132 if (!aShader->Create (myGlContext))
e276548b 1133 {
fc73a202 1134 const TCollection_ExtendedString aMessage = "Error: Failed to create shader object";
1135
1136 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1137 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
e276548b 1138
fc73a202 1139 aShader->Release (myGlContext.operator->());
e276548b 1140
fc73a202 1141 return Handle(OpenGl_ShaderObject)();
e276548b 1142 }
5322131b 1143
fc73a202 1144 if (!aShader->LoadSource (myGlContext, theSource.Source()))
1145 {
1146 const TCollection_ExtendedString aMessage = "Error: Failed to set shader source";
1147
1148 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1149 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
e276548b 1150
fc73a202 1151 aShader->Release (myGlContext.operator->());
e276548b 1152
fc73a202 1153 return Handle(OpenGl_ShaderObject)();
1154 }
e276548b 1155
fc73a202 1156 TCollection_AsciiString aBuildLog;
e276548b 1157
fc73a202 1158 if (!aShader->Compile (myGlContext))
e276548b 1159 {
fc73a202 1160 if (aShader->FetchInfoLog (myGlContext, aBuildLog))
1161 {
1162 const TCollection_ExtendedString aMessage =
1163 TCollection_ExtendedString ("Error: Failed to compile shader object:\n") + aBuildLog;
1164
e276548b 1165#ifdef RAY_TRACE_PRINT_INFO
fc73a202 1166 std::cout << aBuildLog << std::endl;
e276548b 1167#endif
e276548b 1168
fc73a202 1169 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1170 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
1171 }
1172
1173 aShader->Release (myGlContext.operator->());
1174
1175 return Handle(OpenGl_ShaderObject)();
1176 }
68333c8f 1177
e276548b 1178#ifdef RAY_TRACE_PRINT_INFO
fc73a202 1179 if (aShader->FetchInfoLog (myGlContext, aBuildLog))
1180 {
1181 if (!aBuildLog.IsEmpty())
1182 {
1183 std::cout << aBuildLog << std::endl;
1184 }
1185 else
1186 {
1187 std::cout << "Info: shader build log is empty" << std::endl;
1188 }
1189 }
e276548b 1190#endif
e276548b 1191
fc73a202 1192 return aShader;
e276548b 1193}
1194
1195// =======================================================================
fc73a202 1196// function : SafeFailBack
1197// purpose : Performs safe exit when shaders initialization fails
e276548b 1198// =======================================================================
fc73a202 1199Standard_Boolean OpenGl_Workspace::SafeFailBack (const TCollection_ExtendedString& theMessage)
e276548b 1200{
fc73a202 1201 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1202 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, theMessage);
265d4508 1203
fc73a202 1204 myComputeInitStatus = OpenGl_RT_FAIL;
265d4508 1205
fc73a202 1206 ReleaseRaytraceResources();
1207
1208 return Standard_False;
1209}
e276548b 1210
fc73a202 1211// =======================================================================
25ef750e 1212// function : GenerateShaderPrefix
1213// purpose : Generates shader prefix based on current ray-tracing options
1214// =======================================================================
1215TCollection_AsciiString OpenGl_Workspace::GenerateShaderPrefix()
1216{
1217 TCollection_AsciiString aPrefixString =
1218 TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
1219 TCollection_AsciiString ("#define NB_BOUNCES ") + TCollection_AsciiString (myRaytraceParameters.NbBounces);
1220
1221 if (myRaytraceParameters.TransparentShadows)
1222 {
1223 aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
1224 }
1225
1226 // If OpenGL driver supports bindless textures
1227 // activate texturing in ray-tracing mode
1228 if (myGlContext->arbTexBindless != NULL)
1229 {
1230 aPrefixString += TCollection_AsciiString ("\n#define USE_TEXTURES") +
1231 TCollection_AsciiString ("\n#define MAX_TEX_NUMBER ") + TCollection_AsciiString (OpenGl_RaytraceGeometry::MAX_TEX_NUMBER);
1232 }
1233
1234 return aPrefixString;
1235}
1236
1237// =======================================================================
fc73a202 1238// function : InitRaytraceResources
1239// purpose : Initializes OpenGL/GLSL shader programs
1240// =======================================================================
bc8c79bb 1241Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& theCView)
fc73a202 1242{
1243 Standard_Boolean aToRebuildShaders = Standard_False;
e276548b 1244
fc73a202 1245 if (myComputeInitStatus == OpenGl_RT_INIT)
1246 {
1247 if (!myIsRaytraceDataValid)
1248 return Standard_True;
e276548b 1249
fc73a202 1250 const Standard_Integer aRequiredStackSize =
1251 myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth();
e276548b 1252
bc8c79bb 1253 if (myRaytraceParameters.StackSize < aRequiredStackSize)
fc73a202 1254 {
bc8c79bb 1255 myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
e276548b 1256
fc73a202 1257 aToRebuildShaders = Standard_True;
1258 }
1259 else
1260 {
bc8c79bb 1261 if (aRequiredStackSize < myRaytraceParameters.StackSize)
fc73a202 1262 {
bc8c79bb 1263 if (myRaytraceParameters.StackSize > THE_DEFAULT_STACK_SIZE)
fc73a202 1264 {
bc8c79bb 1265 myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
fc73a202 1266 aToRebuildShaders = Standard_True;
1267 }
1268 }
1269 }
e276548b 1270
25ef750e 1271 if (theCView.RenderParams.RaytracingDepth != myRaytraceParameters.NbBounces)
bc8c79bb 1272 {
25ef750e 1273 myRaytraceParameters.NbBounces = theCView.RenderParams.RaytracingDepth;
bc8c79bb 1274 aToRebuildShaders = Standard_True;
1275 }
1276
1277 if (theCView.RenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows)
1278 {
1279 myRaytraceParameters.TransparentShadows = theCView.RenderParams.IsTransparentShadowEnabled;
1280 aToRebuildShaders = Standard_True;
1281 }
1282
fc73a202 1283 if (aToRebuildShaders)
1284 {
e276548b 1285#ifdef RAY_TRACE_PRINT_INFO
bc8c79bb 1286 std::cout << "Info: Rebuild shaders with stack size: " << myRaytraceParameters.StackSize << std::endl;
e276548b 1287#endif
e276548b 1288
bc8c79bb 1289 // Change state to force update all uniforms
84c71f29 1290 ++myViewModificationStatus;
1291
25ef750e 1292 TCollection_AsciiString aPrefixString = GenerateShaderPrefix();
bc8c79bb 1293
1294#ifdef RAY_TRACE_PRINT_INFO
1295 std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
1296#endif
265d4508 1297
bc8c79bb 1298 myRaytraceShaderSource.SetPrefix (aPrefixString);
1299 myPostFSAAShaderSource.SetPrefix (aPrefixString);
265d4508 1300
fc73a202 1301 if (!myRaytraceShader->LoadSource (myGlContext, myRaytraceShaderSource.Source())
1302 || !myPostFSAAShader->LoadSource (myGlContext, myPostFSAAShaderSource.Source()))
1303 {
1304 return Standard_False;
1305 }
265d4508 1306
fc73a202 1307 if (!myRaytraceShader->Compile (myGlContext)
1308 || !myPostFSAAShader->Compile (myGlContext))
1309 {
1310 return Standard_False;
1311 }
1312
7d3e64ef 1313 myRaytraceProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
1314 myPostFSAAProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
fc73a202 1315 if (!myRaytraceProgram->Link (myGlContext)
1316 || !myPostFSAAProgram->Link (myGlContext))
1317 {
1318 return Standard_False;
1319 }
1320 }
e276548b 1321 }
1322
fc73a202 1323 if (myComputeInitStatus == OpenGl_RT_NONE)
1324 {
1325 if (!myGlContext->IsGlGreaterEqual (3, 1))
1326 {
fc73a202 1327 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
25ef750e 1328 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
1329 "Ray-tracing requires OpenGL 3.1 and higher");
1330 return Standard_False;
1331 }
1332 else if (!myGlContext->arbTboRGB32)
1333 {
1334 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1335 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
1336 "Ray-tracing requires OpenGL 4.0+ or GL_ARB_texture_buffer_object_rgb32 extension");
fc73a202 1337 return Standard_False;
1338 }
5322131b 1339
25ef750e 1340 myRaytraceParameters.NbBounces = theCView.RenderParams.RaytracingDepth;
bc8c79bb 1341
fc73a202 1342 TCollection_AsciiString aFolder = Graphic3d_ShaderProgram::ShadersFolder();
265d4508 1343
fc73a202 1344 if (aFolder.IsEmpty())
1345 {
1346 const TCollection_ExtendedString aMessage = "Failed to locate shaders directory";
1347
1348 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1349 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
1350
1351 return Standard_False;
1352 }
265d4508 1353
fc73a202 1354 if (myIsRaytraceDataValid)
1355 {
bc8c79bb 1356 myRaytraceParameters.StackSize = Max (THE_DEFAULT_STACK_SIZE,
fc73a202 1357 myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth());
1358 }
265d4508 1359
25ef750e 1360 TCollection_AsciiString aPrefixString = GenerateShaderPrefix();
bc8c79bb 1361
1362#ifdef RAY_TRACE_PRINT_INFO
1363 std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
1364#endif
1365
fc73a202 1366 {
1367 Handle(OpenGl_ShaderObject) aBasicVertShader = LoadShader (
1368 ShaderSource (aFolder + "/RaytraceBase.vs"), GL_VERTEX_SHADER);
265d4508 1369
fc73a202 1370 if (aBasicVertShader.IsNull())
1371 {
1372 return SafeFailBack ("Failed to set vertex shader source");
1373 }
265d4508 1374
fc73a202 1375 TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs", aFolder + "/RaytraceRender.fs" };
265d4508 1376
fc73a202 1377 myRaytraceShaderSource.Load (aFiles, 2);
e276548b 1378
bc8c79bb 1379 myRaytraceShaderSource.SetPrefix (aPrefixString);
265d4508 1380
fc73a202 1381 myRaytraceShader = LoadShader (myRaytraceShaderSource, GL_FRAGMENT_SHADER);
265d4508 1382
fc73a202 1383 if (myRaytraceShader.IsNull())
1384 {
1385 aBasicVertShader->Release (myGlContext.operator->());
265d4508 1386
fc73a202 1387 return SafeFailBack ("Failed to set ray-trace fragment shader source");
1388 }
265d4508 1389
fc73a202 1390 myRaytraceProgram = new OpenGl_ShaderProgram;
5322131b 1391
fc73a202 1392 if (!myRaytraceProgram->Create (myGlContext))
1393 {
1394 aBasicVertShader->Release (myGlContext.operator->());
265d4508 1395
fc73a202 1396 return SafeFailBack ("Failed to create ray-trace shader program");
1397 }
265d4508 1398
fc73a202 1399 if (!myRaytraceProgram->AttachShader (myGlContext, aBasicVertShader)
1400 || !myRaytraceProgram->AttachShader (myGlContext, myRaytraceShader))
1401 {
1402 aBasicVertShader->Release (myGlContext.operator->());
265d4508 1403
fc73a202 1404 return SafeFailBack ("Failed to attach ray-trace shader objects");
1405 }
265d4508 1406
7d3e64ef 1407 myRaytraceProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
fc73a202 1408 if (!myRaytraceProgram->Link (myGlContext))
1409 {
1410 TCollection_AsciiString aLinkLog;
e276548b 1411
fc73a202 1412 if (myRaytraceProgram->FetchInfoLog (myGlContext, aLinkLog))
1413 {
1414 #ifdef RAY_TRACE_PRINT_INFO
1415 std::cout << aLinkLog << std::endl;
1416 #endif
1417 }
265d4508 1418
fc73a202 1419 return SafeFailBack ("Failed to link ray-trace shader program");
1420 }
1421 }
265d4508 1422
fc73a202 1423 {
1424 Handle(OpenGl_ShaderObject) aBasicVertShader = LoadShader (
1425 ShaderSource (aFolder + "/RaytraceBase.vs"), GL_VERTEX_SHADER);
265d4508 1426
fc73a202 1427 if (aBasicVertShader.IsNull())
1428 {
1429 return SafeFailBack ("Failed to set vertex shader source");
1430 }
265d4508 1431
fc73a202 1432 TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs", aFolder + "/RaytraceSmooth.fs" };
265d4508 1433
fc73a202 1434 myPostFSAAShaderSource.Load (aFiles, 2);
265d4508 1435
bc8c79bb 1436 myPostFSAAShaderSource.SetPrefix (aPrefixString);
fc73a202 1437
1438 myPostFSAAShader = LoadShader (myPostFSAAShaderSource, GL_FRAGMENT_SHADER);
265d4508 1439
fc73a202 1440 if (myPostFSAAShader.IsNull())
1441 {
1442 aBasicVertShader->Release (myGlContext.operator->());
265d4508 1443
fc73a202 1444 return SafeFailBack ("Failed to set FSAA fragment shader source");
1445 }
265d4508 1446
fc73a202 1447 myPostFSAAProgram = new OpenGl_ShaderProgram;
265d4508 1448
fc73a202 1449 if (!myPostFSAAProgram->Create (myGlContext))
1450 {
1451 aBasicVertShader->Release (myGlContext.operator->());
265d4508 1452
fc73a202 1453 return SafeFailBack ("Failed to create FSAA shader program");
1454 }
1455
1456 if (!myPostFSAAProgram->AttachShader (myGlContext, aBasicVertShader)
1457 || !myPostFSAAProgram->AttachShader (myGlContext, myPostFSAAShader))
1458 {
1459 aBasicVertShader->Release (myGlContext.operator->());
1460
1461 return SafeFailBack ("Failed to attach FSAA shader objects");
1462 }
1463
7d3e64ef 1464 myPostFSAAProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
fc73a202 1465 if (!myPostFSAAProgram->Link (myGlContext))
1466 {
1467 TCollection_AsciiString aLinkLog;
1468
1469 if (myPostFSAAProgram->FetchInfoLog (myGlContext, aLinkLog))
1470 {
1471 #ifdef RAY_TRACE_PRINT_INFO
1472 std::cout << aLinkLog << std::endl;
1473 #endif
1474 }
1475
1476 return SafeFailBack ("Failed to link FSAA shader program");
1477 }
e276548b 1478 }
fc73a202 1479 }
e276548b 1480
fc73a202 1481 if (myComputeInitStatus == OpenGl_RT_NONE || aToRebuildShaders)
1482 {
1483 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
e276548b 1484 {
fc73a202 1485 Handle(OpenGl_ShaderProgram)& aShaderProgram =
1486 (anIndex == 0) ? myRaytraceProgram : myPostFSAAProgram;
1487
7d3e64ef 1488 myGlContext->BindProgram (aShaderProgram);
fc73a202 1489
1490 aShaderProgram->SetSampler (myGlContext,
1491 "uSceneMinPointTexture", OpenGl_RT_SceneMinPointTexture);
1492 aShaderProgram->SetSampler (myGlContext,
1493 "uSceneMaxPointTexture", OpenGl_RT_SceneMaxPointTexture);
1494 aShaderProgram->SetSampler (myGlContext,
1495 "uSceneNodeInfoTexture", OpenGl_RT_SceneNodeInfoTexture);
1496 aShaderProgram->SetSampler (myGlContext,
fc73a202 1497 "uGeometryVertexTexture", OpenGl_RT_GeometryVertexTexture);
1498 aShaderProgram->SetSampler (myGlContext,
1499 "uGeometryNormalTexture", OpenGl_RT_GeometryNormalTexture);
1500 aShaderProgram->SetSampler (myGlContext,
25ef750e 1501 "uGeometryTexCrdTexture", OpenGl_RT_GeometryTexCrdTexture);
fc73a202 1502 aShaderProgram->SetSampler (myGlContext,
25ef750e 1503 "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture);
84c71f29 1504 aShaderProgram->SetSampler (myGlContext,
1505 "uSceneTransformTexture", OpenGl_RT_SceneTransformTexture);
1506 aShaderProgram->SetSampler (myGlContext,
1507 "uEnvironmentMapTexture", OpenGl_RT_EnvironmentMapTexture);
25ef750e 1508 aShaderProgram->SetSampler (myGlContext,
1509 "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
1510 aShaderProgram->SetSampler (myGlContext,
1511 "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
fc73a202 1512
a89742cf 1513 aShaderProgram->SetSampler (myGlContext,
1514 "uOpenGlColorTexture", OpenGl_RT_OpenGlColorTexture);
1515 aShaderProgram->SetSampler (myGlContext,
1516 "uOpenGlDepthTexture", OpenGl_RT_OpenGlDepthTexture);
1517
fc73a202 1518 if (anIndex == 1)
1519 {
1520 aShaderProgram->SetSampler (myGlContext,
1521 "uFSAAInputTexture", OpenGl_RT_FSAAInputTexture);
1522 }
265d4508 1523
fc73a202 1524 myUniformLocations[anIndex][OpenGl_RT_aPosition] =
7d3e64ef 1525 aShaderProgram->GetAttributeLocation (myGlContext, "occVertex");
fc73a202 1526
1527 myUniformLocations[anIndex][OpenGl_RT_uOriginLB] =
1528 aShaderProgram->GetUniformLocation (myGlContext, "uOriginLB");
1529 myUniformLocations[anIndex][OpenGl_RT_uOriginRB] =
1530 aShaderProgram->GetUniformLocation (myGlContext, "uOriginRB");
1531 myUniformLocations[anIndex][OpenGl_RT_uOriginLT] =
1532 aShaderProgram->GetUniformLocation (myGlContext, "uOriginLT");
1533 myUniformLocations[anIndex][OpenGl_RT_uOriginRT] =
1534 aShaderProgram->GetUniformLocation (myGlContext, "uOriginRT");
1535 myUniformLocations[anIndex][OpenGl_RT_uDirectLB] =
1536 aShaderProgram->GetUniformLocation (myGlContext, "uDirectLB");
1537 myUniformLocations[anIndex][OpenGl_RT_uDirectRB] =
1538 aShaderProgram->GetUniformLocation (myGlContext, "uDirectRB");
1539 myUniformLocations[anIndex][OpenGl_RT_uDirectLT] =
1540 aShaderProgram->GetUniformLocation (myGlContext, "uDirectLT");
1541 myUniformLocations[anIndex][OpenGl_RT_uDirectRT] =
1542 aShaderProgram->GetUniformLocation (myGlContext, "uDirectRT");
25ef750e 1543 myUniformLocations[anIndex][OpenGl_RT_uUnviewMat] =
1544 aShaderProgram->GetUniformLocation (myGlContext, "uUnviewMat");
fc73a202 1545
1546 myUniformLocations[anIndex][OpenGl_RT_uSceneRad] =
1547 aShaderProgram->GetUniformLocation (myGlContext, "uSceneRadius");
1548 myUniformLocations[anIndex][OpenGl_RT_uSceneEps] =
1549 aShaderProgram->GetUniformLocation (myGlContext, "uSceneEpsilon");
25ef750e 1550 myUniformLocations[anIndex][OpenGl_RT_uLightCount] =
1551 aShaderProgram->GetUniformLocation (myGlContext, "uLightCount");
1552 myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] =
1553 aShaderProgram->GetUniformLocation (myGlContext, "uGlobalAmbient");
fc73a202 1554
1555 myUniformLocations[anIndex][OpenGl_RT_uOffsetX] =
1556 aShaderProgram->GetUniformLocation (myGlContext, "uOffsetX");
1557 myUniformLocations[anIndex][OpenGl_RT_uOffsetY] =
1558 aShaderProgram->GetUniformLocation (myGlContext, "uOffsetY");
1559 myUniformLocations[anIndex][OpenGl_RT_uSamples] =
1560 aShaderProgram->GetUniformLocation (myGlContext, "uSamples");
312a4043 1561 myUniformLocations[anIndex][OpenGl_RT_uWinSizeX] =
1562 aShaderProgram->GetUniformLocation (myGlContext, "uWinSizeX");
1563 myUniformLocations[anIndex][OpenGl_RT_uWinSizeY] =
1564 aShaderProgram->GetUniformLocation (myGlContext, "uWinSizeY");
84c71f29 1565
25ef750e 1566 myUniformLocations[anIndex][OpenGl_RT_uTextures] =
1567 aShaderProgram->GetUniformLocation (myGlContext, "uTextureSamplers");
1568
1569 myUniformLocations[anIndex][OpenGl_RT_uShadEnabled] =
1570 aShaderProgram->GetUniformLocation (myGlContext, "uShadowsEnable");
1571 myUniformLocations[anIndex][OpenGl_RT_uReflEnabled] =
1572 aShaderProgram->GetUniformLocation (myGlContext, "uReflectionsEnable");
1573 myUniformLocations[anIndex][OpenGl_RT_uEnvMapEnable] =
84c71f29 1574 aShaderProgram->GetUniformLocation (myGlContext, "uEnvironmentEnable");
fc73a202 1575 }
265d4508 1576
7d3e64ef 1577 myGlContext->BindProgram (NULL);
fc73a202 1578 }
265d4508 1579
fc73a202 1580 if (myComputeInitStatus != OpenGl_RT_NONE)
1581 {
1582 return myComputeInitStatus == OpenGl_RT_INIT;
1583 }
265d4508 1584
fc73a202 1585 if (myRaytraceFBO1.IsNull())
1586 {
1587 myRaytraceFBO1 = new OpenGl_FrameBuffer;
1588 }
265d4508 1589
fc73a202 1590 if (myRaytraceFBO2.IsNull())
1591 {
1592 myRaytraceFBO2 = new OpenGl_FrameBuffer;
1593 }
265d4508 1594
fc73a202 1595 const GLfloat aVertices[] = { -1.f, -1.f, 0.f,
1596 -1.f, 1.f, 0.f,
1597 1.f, 1.f, 0.f,
1598 1.f, 1.f, 0.f,
1599 1.f, -1.f, 0.f,
1600 -1.f, -1.f, 0.f };
265d4508 1601
fc73a202 1602 myRaytraceScreenQuad.Init (myGlContext, 3, 6, aVertices);
265d4508 1603
fc73a202 1604 myComputeInitStatus = OpenGl_RT_INIT; // initialized in normal way
ca3c13d1 1605
fc73a202 1606 return Standard_True;
1607}
265d4508 1608
fc73a202 1609// =======================================================================
1610// function : NullifyResource
1611// purpose :
1612// =======================================================================
1613inline void NullifyResource (const Handle(OpenGl_Context)& theContext,
1614 Handle(OpenGl_Resource)& theResource)
1615{
1616 if (!theResource.IsNull())
1617 {
1618 theResource->Release (theContext.operator->());
1619 theResource.Nullify();
1620 }
1621}
265d4508 1622
fc73a202 1623// =======================================================================
1624// function : ReleaseRaytraceResources
1625// purpose : Releases OpenGL/GLSL shader programs
1626// =======================================================================
1627void OpenGl_Workspace::ReleaseRaytraceResources()
1628{
a89742cf 1629 NullifyResource (myGlContext, myOpenGlFBO);
fc73a202 1630 NullifyResource (myGlContext, myRaytraceFBO1);
1631 NullifyResource (myGlContext, myRaytraceFBO2);
265d4508 1632
fc73a202 1633 NullifyResource (myGlContext, myRaytraceShader);
1634 NullifyResource (myGlContext, myPostFSAAShader);
265d4508 1635
fc73a202 1636 NullifyResource (myGlContext, myRaytraceProgram);
1637 NullifyResource (myGlContext, myPostFSAAProgram);
265d4508 1638
fc73a202 1639 NullifyResource (myGlContext, mySceneNodeInfoTexture);
1640 NullifyResource (myGlContext, mySceneMinPointTexture);
1641 NullifyResource (myGlContext, mySceneMaxPointTexture);
265d4508 1642
fc73a202 1643 NullifyResource (myGlContext, myGeometryVertexTexture);
1644 NullifyResource (myGlContext, myGeometryNormalTexture);
25ef750e 1645 NullifyResource (myGlContext, myGeometryTexCrdTexture);
fc73a202 1646 NullifyResource (myGlContext, myGeometryTriangTexture);
bc8c79bb 1647 NullifyResource (myGlContext, mySceneTransformTexture);
265d4508 1648
fc73a202 1649 NullifyResource (myGlContext, myRaytraceLightSrcTexture);
1650 NullifyResource (myGlContext, myRaytraceMaterialTexture);
265d4508 1651
fc73a202 1652 if (myRaytraceScreenQuad.IsValid())
1653 myRaytraceScreenQuad.Release (myGlContext.operator->());
1654}
265d4508 1655
fc73a202 1656// =======================================================================
1657// function : UploadRaytraceData
1658// purpose : Uploads ray-trace data to the GPU
1659// =======================================================================
1660Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
1661{
1662 if (!myGlContext->IsGlGreaterEqual (3, 1))
1663 {
265d4508 1664#ifdef RAY_TRACE_PRINT_INFO
fc73a202 1665 std::cout << "Error: OpenGL version is less than 3.1" << std::endl;
265d4508 1666#endif
fc73a202 1667 return Standard_False;
e276548b 1668 }
1669
265d4508 1670 /////////////////////////////////////////////////////////////////////////////
25ef750e 1671 // Prepare OpenGL textures
1672
1673 if (myGlContext->arbTexBindless != NULL)
1674 {
1675 // If OpenGL driver supports bindless textures we need
1676 // to get unique 64- bit handles for using on the GPU
1677 if (!myRaytraceGeometry.UpdateTextureHandles (myGlContext))
1678 {
1679#ifdef RAY_TRACE_PRINT_INFO
1680 std::cout << "Error: Failed to get OpenGL texture handles" << std::endl;
1681#endif
1682 return Standard_False;
1683 }
1684 }
1685
1686 /////////////////////////////////////////////////////////////////////////////
e2da917a 1687 // Create OpenGL BVH buffers
265d4508 1688
e2da917a 1689 if (mySceneNodeInfoTexture.IsNull()) // create scene BVH buffers
e276548b 1690 {
e2da917a 1691 mySceneNodeInfoTexture = new OpenGl_TextureBufferArb;
1692 mySceneMinPointTexture = new OpenGl_TextureBufferArb;
1693 mySceneMaxPointTexture = new OpenGl_TextureBufferArb;
84c71f29 1694 mySceneTransformTexture = new OpenGl_TextureBufferArb;
265d4508 1695
e2da917a 1696 if (!mySceneNodeInfoTexture->Create (myGlContext)
1697 || !mySceneMinPointTexture->Create (myGlContext)
1698 || !mySceneMaxPointTexture->Create (myGlContext)
84c71f29 1699 || !mySceneTransformTexture->Create (myGlContext))
e276548b 1700 {
fc73a202 1701#ifdef RAY_TRACE_PRINT_INFO
e2da917a 1702 std::cout << "Error: Failed to create scene BVH buffers" << std::endl;
fc73a202 1703#endif
1704 return Standard_False;
1705 }
1706 }
5322131b 1707
e2da917a 1708 if (myGeometryVertexTexture.IsNull()) // create geometry buffers
265d4508 1709 {
fc73a202 1710 myGeometryVertexTexture = new OpenGl_TextureBufferArb;
1711 myGeometryNormalTexture = new OpenGl_TextureBufferArb;
25ef750e 1712 myGeometryTexCrdTexture = new OpenGl_TextureBufferArb;
fc73a202 1713 myGeometryTriangTexture = new OpenGl_TextureBufferArb;
e276548b 1714
fc73a202 1715 if (!myGeometryVertexTexture->Create (myGlContext)
25ef750e 1716 || !myGeometryNormalTexture->Create (myGlContext)
1717 || !myGeometryTexCrdTexture->Create (myGlContext)
1718 || !myGeometryTriangTexture->Create (myGlContext))
fc73a202 1719 {
1720#ifdef RAY_TRACE_PRINT_INFO
1721 std::cout << "Error: Failed to create buffers for triangulation data" << std::endl;
1722#endif
1723 return Standard_False;
1724 }
265d4508 1725 }
5322131b 1726
e2da917a 1727 if (myRaytraceMaterialTexture.IsNull()) // create material buffer
fc73a202 1728 {
1729 myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
e276548b 1730
fc73a202 1731 if (!myRaytraceMaterialTexture->Create (myGlContext))
1732 {
1733#ifdef RAY_TRACE_PRINT_INFO
1734 std::cout << "Error: Failed to create buffers for material data" << std::endl;
e276548b 1735#endif
fc73a202 1736 return Standard_False;
1737 }
1738 }
e2da917a 1739
84c71f29 1740 /////////////////////////////////////////////////////////////////////////////
1741 // Write transform buffer
1742
1743 BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()];
84c71f29 1744
e2da917a 1745 bool aResult = true;
1746
84c71f29 1747 for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
1748 {
1749 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
1750 myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
1751
1752 const BVH_Transform<Standard_ShortReal, 4>* aTransform =
1753 dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (aTriangleSet->Properties().operator->());
1754
1755 Standard_ASSERT_RETURN (aTransform != NULL,
1756 "OpenGl_TriangleSet does not contain transform", Standard_False);
1757
1758 aNodeTransforms[anElemIndex] = aTransform->Inversed();
84c71f29 1759 }
1760
1761 aResult &= mySceneTransformTexture->Init (myGlContext, 4,
1762 myRaytraceGeometry.Size() * 4, reinterpret_cast<const GLfloat*> (aNodeTransforms));
1763
25ef750e 1764 delete [] aNodeTransforms;
84c71f29 1765
1766 /////////////////////////////////////////////////////////////////////////////
bc8c79bb 1767 // Write geometry and bottom-level BVH buffers
84c71f29 1768
fc73a202 1769 Standard_Size aTotalVerticesNb = 0;
1770 Standard_Size aTotalElementsNb = 0;
1771 Standard_Size aTotalBVHNodesNb = 0;
265d4508 1772
fc73a202 1773 for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
1774 {
1775 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
1776 myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
265d4508 1777
fc73a202 1778 Standard_ASSERT_RETURN (aTriangleSet != NULL,
1779 "Error: Failed to get triangulation of OpenGL element", Standard_False);
1780
1781 aTotalVerticesNb += aTriangleSet->Vertices.size();
1782 aTotalElementsNb += aTriangleSet->Elements.size();
e276548b 1783
fc73a202 1784 Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(),
1785 "Error: Failed to get bottom-level BVH of OpenGL element", Standard_False);
265d4508 1786
fc73a202 1787 aTotalBVHNodesNb += aTriangleSet->BVH()->NodeInfoBuffer().size();
1788 }
e276548b 1789
e2da917a 1790 aTotalBVHNodesNb += myRaytraceGeometry.BVH()->NodeInfoBuffer().size();
1791
fc73a202 1792 if (aTotalBVHNodesNb != 0)
e276548b 1793 {
e2da917a 1794 aResult &= mySceneNodeInfoTexture->Init (
25ef750e 1795 myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*> (NULL));
e2da917a 1796 aResult &= mySceneMinPointTexture->Init (
25ef750e 1797 myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
e2da917a 1798 aResult &= mySceneMaxPointTexture->Init (
25ef750e 1799 myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
fc73a202 1800 }
265d4508 1801
fc73a202 1802 if (!aResult)
1803 {
1804#ifdef RAY_TRACE_PRINT_INFO
1805 std::cout << "Error: Failed to upload buffers for bottom-level scene BVH" << std::endl;
1806#endif
1807 return Standard_False;
1808 }
e276548b 1809
fc73a202 1810 if (aTotalElementsNb != 0)
1811 {
25ef750e 1812 aResult &= myGeometryTriangTexture->Init (
1813 myGlContext, 4, GLsizei (aTotalElementsNb), static_cast<const GLuint*> (NULL));
fc73a202 1814 }
265d4508 1815
fc73a202 1816 if (aTotalVerticesNb != 0)
1817 {
25ef750e 1818 aResult &= myGeometryVertexTexture->Init (
1819 myGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
1820 aResult &= myGeometryNormalTexture->Init (
1821 myGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
1822 aResult &= myGeometryTexCrdTexture->Init (
1823 myGlContext, 2, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
fc73a202 1824 }
265d4508 1825
fc73a202 1826 if (!aResult)
1827 {
1828#ifdef RAY_TRACE_PRINT_INFO
1829 std::cout << "Error: Failed to upload buffers for scene geometry" << std::endl;
1830#endif
1831 return Standard_False;
1832 }
265d4508 1833
e2da917a 1834 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = myRaytraceGeometry.BVH();
1e99558f 1835 const Standard_Integer aBvhLength = aBVH->Length();
1836 if (aBvhLength > 0)
1837 {
1838 aResult &= mySceneNodeInfoTexture->SubData (myGlContext, 0, aBVH->Length(),
1839 reinterpret_cast<const GLuint*> (&aBVH->NodeInfoBuffer().front()));
1840 aResult &= mySceneMinPointTexture->SubData (myGlContext, 0, aBVH->Length(),
1841 reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
1842 aResult &= mySceneMaxPointTexture->SubData (myGlContext, 0, aBVH->Length(),
1843 reinterpret_cast<const GLfloat*> (&aBVH->MaxPointBuffer().front()));
1844 }
e2da917a 1845
fc73a202 1846 for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
1847 {
1848 if (!aBVH->IsOuter (aNodeIdx))
1849 continue;
265d4508 1850
fc73a202 1851 OpenGl_TriangleSet* aTriangleSet = myRaytraceGeometry.TriangleSet (aNodeIdx);
e276548b 1852
fc73a202 1853 Standard_ASSERT_RETURN (aTriangleSet != NULL,
1854 "Error: Failed to get triangulation of OpenGL element", Standard_False);
e276548b 1855
e2da917a 1856 Standard_Integer aBVHOffset = myRaytraceGeometry.AccelerationOffset (aNodeIdx);
e276548b 1857
fc73a202 1858 Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
1859 "Error: Failed to get offset for bottom-level BVH", Standard_False);
e276548b 1860
e2da917a 1861 const Standard_Integer aBvhBuffersSize = aTriangleSet->BVH()->Length();
265d4508 1862
e2da917a 1863 if (aBvhBuffersSize != 0)
fc73a202 1864 {
e2da917a 1865 aResult &= mySceneNodeInfoTexture->SubData (myGlContext, aBVHOffset, aBvhBuffersSize,
5cff985a 1866 reinterpret_cast<const GLuint*> (&aTriangleSet->BVH()->NodeInfoBuffer().front()));
e2da917a 1867 aResult &= mySceneMinPointTexture->SubData (myGlContext, aBVHOffset, aBvhBuffersSize,
5cff985a 1868 reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MinPointBuffer().front()));
e2da917a 1869 aResult &= mySceneMaxPointTexture->SubData (myGlContext, aBVHOffset, aBvhBuffersSize,
5cff985a 1870 reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MaxPointBuffer().front()));
fc73a202 1871 if (!aResult)
e276548b 1872 {
fc73a202 1873#ifdef RAY_TRACE_PRINT_INFO
1874 std::cout << "Error: Failed to upload buffers for bottom-level scene BVHs" << std::endl;
1875#endif
e276548b 1876 return Standard_False;
1877 }
1878 }
1879
fc73a202 1880 const Standard_Integer aVerticesOffset = myRaytraceGeometry.VerticesOffset (aNodeIdx);
265d4508 1881
fc73a202 1882 Standard_ASSERT_RETURN (aVerticesOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
1883 "Error: Failed to get offset for triangulation vertices of OpenGL element", Standard_False);
265d4508 1884
fc73a202 1885 if (!aTriangleSet->Vertices.empty())
1886 {
5cff985a 1887 aResult &= myGeometryNormalTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Normals.size()),
1888 reinterpret_cast<const GLfloat*> (&aTriangleSet->Normals.front()));
25ef750e 1889 aResult &= myGeometryTexCrdTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->TexCrds.size()),
1890 reinterpret_cast<const GLfloat*> (&aTriangleSet->TexCrds.front()));
5cff985a 1891 aResult &= myGeometryVertexTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Vertices.size()),
1892 reinterpret_cast<const GLfloat*> (&aTriangleSet->Vertices.front()));
fc73a202 1893 }
e276548b 1894
fc73a202 1895 const Standard_Integer anElementsOffset = myRaytraceGeometry.ElementsOffset (aNodeIdx);
265d4508 1896
fc73a202 1897 Standard_ASSERT_RETURN (anElementsOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
1898 "Error: Failed to get offset for triangulation elements of OpenGL element", Standard_False);
e276548b 1899
fc73a202 1900 if (!aTriangleSet->Elements.empty())
e276548b 1901 {
5cff985a 1902 aResult &= myGeometryTriangTexture->SubData (myGlContext, anElementsOffset, GLsizei (aTriangleSet->Elements.size()),
1903 reinterpret_cast<const GLuint*> (&aTriangleSet->Elements.front()));
e276548b 1904 }
265d4508 1905
fc73a202 1906 if (!aResult)
1907 {
1908#ifdef RAY_TRACE_PRINT_INFO
1909 std::cout << "Error: Failed to upload triangulation buffers for OpenGL element" << std::endl;
e276548b 1910#endif
fc73a202 1911 return Standard_False;
1912 }
e276548b 1913 }
e276548b 1914
25ef750e 1915 /////////////////////////////////////////////////////////////////////////////
1916 // Write material buffer
1917
fc73a202 1918 if (myRaytraceGeometry.Materials.size() != 0)
1919 {
25ef750e 1920 aResult &= myRaytraceMaterialTexture->Init (myGlContext, 4,
1921 GLsizei (myRaytraceGeometry.Materials.size() * 11), myRaytraceGeometry.Materials.front().Packed());
1922
fc73a202 1923 if (!aResult)
1924 {
1925#ifdef RAY_TRACE_PRINT_INFO
1926 std::cout << "Error: Failed to upload material buffer" << std::endl;
1927#endif
1928 return Standard_False;
1929 }
1930 }
e276548b 1931
fc73a202 1932 myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0;
e276548b 1933
fc73a202 1934#ifdef RAY_TRACE_PRINT_INFO
e276548b 1935
fc73a202 1936 Standard_ShortReal aMemUsed = 0.f;
e276548b 1937
fc73a202 1938 for (Standard_Integer anElemIdx = 0; anElemIdx < myRaytraceGeometry.Size(); ++anElemIdx)
1939 {
1940 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
1941 myRaytraceGeometry.Objects().ChangeValue (anElemIdx).operator->());
e276548b 1942
fc73a202 1943 aMemUsed += static_cast<Standard_ShortReal> (
25ef750e 1944 aTriangleSet->Vertices.size() * sizeof (BVH_Vec3f));
fc73a202 1945 aMemUsed += static_cast<Standard_ShortReal> (
25ef750e 1946 aTriangleSet->Normals.size() * sizeof (BVH_Vec3f));
1947 aMemUsed += static_cast<Standard_ShortReal> (
1948 aTriangleSet->TexCrds.size() * sizeof (BVH_Vec2f));
fc73a202 1949 aMemUsed += static_cast<Standard_ShortReal> (
1950 aTriangleSet->Elements.size() * sizeof (BVH_Vec4i));
e276548b 1951
fc73a202 1952 aMemUsed += static_cast<Standard_ShortReal> (
1953 aTriangleSet->BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
1954 aMemUsed += static_cast<Standard_ShortReal> (
25ef750e 1955 aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
fc73a202 1956 aMemUsed += static_cast<Standard_ShortReal> (
25ef750e 1957 aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
fc73a202 1958 }
e276548b 1959
fc73a202 1960 aMemUsed += static_cast<Standard_ShortReal> (
1961 myRaytraceGeometry.BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
1962 aMemUsed += static_cast<Standard_ShortReal> (
25ef750e 1963 myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
fc73a202 1964 aMemUsed += static_cast<Standard_ShortReal> (
25ef750e 1965 myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
e276548b 1966
fc73a202 1967 std::cout << "GPU Memory Used (MB): ~" << aMemUsed / 1048576 << std::endl;
e276548b 1968
fc73a202 1969#endif
e276548b 1970
fc73a202 1971 return aResult;
1972}
e276548b 1973
fc73a202 1974// =======================================================================
1975// function : ResizeRaytraceBuffers
1976// purpose : Resizes OpenGL frame buffers
1977// =======================================================================
1978Standard_Boolean OpenGl_Workspace::ResizeRaytraceBuffers (const Standard_Integer theSizeX,
1979 const Standard_Integer theSizeY)
1980{
1981 if (myRaytraceFBO1->GetVPSizeX() != theSizeX
1982 || myRaytraceFBO1->GetVPSizeY() != theSizeY)
1983 {
1984 myRaytraceFBO1->Init (myGlContext, theSizeX, theSizeY);
1985 myRaytraceFBO2->Init (myGlContext, theSizeX, theSizeY);
1986 }
e276548b 1987
fc73a202 1988 return Standard_True;
e276548b 1989}
1990
1991// =======================================================================
fc73a202 1992// function : UpdateCamera
1993// purpose : Generates viewing rays for corners of screen quad
e276548b 1994// =======================================================================
25ef750e 1995void OpenGl_Workspace::UpdateCamera (const OpenGl_Mat4& theOrientation,
1996 const OpenGl_Mat4& theViewMapping,
1997 OpenGl_Vec3 theOrigins[4],
1998 OpenGl_Vec3 theDirects[4],
1999 OpenGl_Mat4& theInvModelProj)
e276548b 2000{
bc8c79bb 2001 // compute inverse model-view-projection matrix
a89742cf 2002 (theViewMapping * theOrientation).Inverted (theInvModelProj);
fc73a202 2003
68333c8f 2004 Standard_Integer aOriginIndex = 0;
2005 Standard_Integer aDirectIndex = 0;
e276548b 2006
fc73a202 2007 for (Standard_Integer aY = -1; aY <= 1; aY += 2)
e276548b 2008 {
fc73a202 2009 for (Standard_Integer aX = -1; aX <= 1; aX += 2)
e276548b 2010 {
25ef750e 2011 OpenGl_Vec4 aOrigin (GLfloat(aX),
2012 GLfloat(aY),
2013 -1.0f,
2014 1.0f);
fc73a202 2015
a89742cf 2016 aOrigin = theInvModelProj * aOrigin;
e276548b 2017
b5ac8292 2018 aOrigin.x() = aOrigin.x() / aOrigin.w();
2019 aOrigin.y() = aOrigin.y() / aOrigin.w();
2020 aOrigin.z() = aOrigin.z() / aOrigin.w();
e276548b 2021
25ef750e 2022 OpenGl_Vec4 aDirect (GLfloat(aX),
2023 GLfloat(aY),
2024 1.0f,
2025 1.0f);
fc73a202 2026
a89742cf 2027 aDirect = theInvModelProj * aDirect;
e276548b 2028
b5ac8292 2029 aDirect.x() = aDirect.x() / aDirect.w();
2030 aDirect.y() = aDirect.y() / aDirect.w();
2031 aDirect.z() = aDirect.z() / aDirect.w();
b5ac8292 2032
2033 aDirect = aDirect - aOrigin;
e276548b 2034
fc73a202 2035 GLdouble aInvLen = 1.0 / sqrt (aDirect.x() * aDirect.x() +
e276548b 2036 aDirect.y() * aDirect.y() +
2037 aDirect.z() * aDirect.z());
2038
fc73a202 2039 theOrigins[aOriginIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aOrigin.x()),
2040 static_cast<GLfloat> (aOrigin.y()),
2041 static_cast<GLfloat> (aOrigin.z()));
2042
2043 theDirects[aDirectIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aDirect.x() * aInvLen),
2044 static_cast<GLfloat> (aDirect.y() * aInvLen),
2045 static_cast<GLfloat> (aDirect.z() * aInvLen));
2046 }
2047 }
2048}
2049
2050// =======================================================================
25ef750e 2051// function : SetUniformState
2052// purpose : Sets uniform state for the given ray-tracing shader program
2053// =======================================================================
2054Standard_Boolean OpenGl_Workspace::SetUniformState (const Graphic3d_CView& theCView,
312a4043 2055 const Standard_Integer theSizeX,
2056 const Standard_Integer theSizeY,
25ef750e 2057 const OpenGl_Vec3* theOrigins,
2058 const OpenGl_Vec3* theDirects,
2059 const OpenGl_Mat4& theUnviewMat,
2060 const Standard_Integer theProgramIndex,
2061 Handle(OpenGl_ShaderProgram)& theRaytraceProgram)
2062{
2063 if (theRaytraceProgram.IsNull())
2064 {
2065 return Standard_False;
2066 }
2067
2068 Standard_Integer aLightSourceBufferSize =
2069 static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
2070
2071 Standard_Boolean aResult = Standard_True;
2072
2073 // Set camera state
2074 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2075 myUniformLocations[theProgramIndex][OpenGl_RT_uOriginLB], theOrigins[0]);
2076 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2077 myUniformLocations[theProgramIndex][OpenGl_RT_uOriginRB], theOrigins[1]);
2078 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2079 myUniformLocations[theProgramIndex][OpenGl_RT_uOriginLT], theOrigins[2]);
2080 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2081 myUniformLocations[theProgramIndex][OpenGl_RT_uOriginRT], theOrigins[3]);
2082 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2083 myUniformLocations[theProgramIndex][OpenGl_RT_uDirectLB], theDirects[0]);
2084 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2085 myUniformLocations[theProgramIndex][OpenGl_RT_uDirectRB], theDirects[1]);
2086 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2087 myUniformLocations[theProgramIndex][OpenGl_RT_uDirectLT], theDirects[2]);
2088 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2089 myUniformLocations[theProgramIndex][OpenGl_RT_uDirectRT], theDirects[3]);
2090 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2091 myUniformLocations[theProgramIndex][OpenGl_RT_uUnviewMat], theUnviewMat);
2092
312a4043 2093 // Set window size
2094 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2095 myUniformLocations[theProgramIndex][OpenGl_RT_uWinSizeX], theSizeX);
2096 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2097 myUniformLocations[theProgramIndex][OpenGl_RT_uWinSizeY], theSizeY);
2098
25ef750e 2099 // Set scene parameters
2100 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2101 myUniformLocations[theProgramIndex][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
2102 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2103 myUniformLocations[theProgramIndex][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
2104 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2105 myUniformLocations[theProgramIndex][OpenGl_RT_uLightCount], aLightSourceBufferSize);
2106 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2107 myUniformLocations[theProgramIndex][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
2108
2109 // Set rendering options
2110 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2111 myUniformLocations[theProgramIndex][OpenGl_RT_uShadEnabled], theCView.RenderParams.IsShadowEnabled ? 1 : 0);
2112 aResult &= theRaytraceProgram->SetUniform (myGlContext,
2113 myUniformLocations[theProgramIndex][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0);
2114
2115 // Set array of 64-bit texture handles
2116 if (myGlContext->arbTexBindless != NULL && myRaytraceGeometry.HasTextures())
2117 {
2118 aResult &= theRaytraceProgram->SetUniform (myGlContext, "uTextureSamplers",
2119 static_cast<GLsizei> (myRaytraceGeometry.TextureHandles().size()), &myRaytraceGeometry.TextureHandles()[0]);
2120 }
2121
2122 if (!aResult)
2123 {
2124#ifdef RAY_TRACE_PRINT_INFO
312a4043 2125 std::cout << "Info: Not all uniforms were detected (for program " << theProgramIndex << ")" << std::endl;
25ef750e 2126#endif
2127 }
2128
2129 return aResult;
2130}
2131
2132// =======================================================================
fc73a202 2133// function : RunRaytraceShaders
2134// purpose : Runs ray-tracing shader programs
2135// =======================================================================
2136Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& theCView,
2137 const Standard_Integer theSizeX,
2138 const Standard_Integer theSizeY,
2139 const OpenGl_Vec3 theOrigins[4],
2140 const OpenGl_Vec3 theDirects[4],
25ef750e 2141 const OpenGl_Mat4& theUnviewMat,
fc73a202 2142 OpenGl_FrameBuffer* theFrameBuffer)
2143{
2144 mySceneMinPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
2145 mySceneMaxPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
2146 mySceneNodeInfoTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
fc73a202 2147 myGeometryVertexTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
2148 myGeometryNormalTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
25ef750e 2149 myGeometryTexCrdTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
fc73a202 2150 myGeometryTriangTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
a89742cf 2151 mySceneTransformTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
fc73a202 2152 myRaytraceMaterialTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
2153 myRaytraceLightSrcTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
a89742cf 2154
2155 myOpenGlFBO->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
2156 myOpenGlFBO->DepthStencilTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
fc73a202 2157
bc8c79bb 2158 if (theCView.RenderParams.IsAntialiasingEnabled) // render source image to FBO
fc73a202 2159 {
2160 myRaytraceFBO1->BindBuffer (myGlContext);
2161
2162 glDisable (GL_BLEND);
2163 }
2164
7d3e64ef 2165 myGlContext->BindProgram (myRaytraceProgram);
fc73a202 2166
25ef750e 2167 SetUniformState (theCView,
312a4043 2168 theSizeX,
2169 theSizeY,
25ef750e 2170 theOrigins,
2171 theDirects,
2172 theUnviewMat,
2173 0, // ID of RT program
2174 myRaytraceProgram);
fc73a202 2175
7d3e64ef 2176 myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS);
fc73a202 2177 {
7d3e64ef 2178 myGlContext->core20fwd->glVertexAttribPointer (Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL);
fc73a202 2179 myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
2180 }
7d3e64ef 2181 myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS);
25ef750e 2182
bc8c79bb 2183 if (!theCView.RenderParams.IsAntialiasingEnabled)
fc73a202 2184 {
7d3e64ef 2185 myGlContext->BindProgram (NULL);
fc73a202 2186
a89742cf 2187 myOpenGlFBO->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
2188 myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
e2da917a 2189 mySceneMinPointTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
2190 mySceneMaxPointTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
2191 mySceneNodeInfoTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
a89742cf 2192 myGeometryVertexTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
2193 myGeometryNormalTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
25ef750e 2194 myGeometryTexCrdTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
a89742cf 2195 myGeometryTriangTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
25ef750e 2196 mySceneTransformTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
a89742cf 2197 myRaytraceMaterialTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
2198 myRaytraceLightSrcTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
a89742cf 2199
2200 myGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
2201
fc73a202 2202 return Standard_True;
2203 }
2204
945c3529 2205 myRaytraceFBO1->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
fc73a202 2206
7d3e64ef 2207 myGlContext->BindProgram (myPostFSAAProgram);
fc73a202 2208
25ef750e 2209 SetUniformState (theCView,
312a4043 2210 theSizeX,
2211 theSizeY,
25ef750e 2212 theOrigins,
2213 theDirects,
2214 theUnviewMat,
2215 1, // ID of FSAA program
2216 myPostFSAAProgram);
fc73a202 2217
7d3e64ef 2218 myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS);
2219 myGlContext->core20fwd->glVertexAttribPointer (Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL);
fc73a202 2220
50d0e1ce 2221 // Perform multi-pass adaptive FSAA using ping-pong technique.
2222 // We use 'FLIPTRI' sampling pattern changing for every pixel
2223 // (3 additional samples per pixel, the 1st sample is already
2224 // available from initial ray-traced image).
2225 for (Standard_Integer anIt = 1; anIt < 4; ++anIt)
fc73a202 2226 {
2227 GLfloat aOffsetX = 1.f / theSizeX;
2228 GLfloat aOffsetY = 1.f / theSizeY;
2229
50d0e1ce 2230 if (anIt == 1)
fc73a202 2231 {
50d0e1ce 2232 aOffsetX *= -0.55f;
2233 aOffsetY *= 0.55f;
fc73a202 2234 }
50d0e1ce 2235 else if (anIt == 2)
fc73a202 2236 {
50d0e1ce 2237 aOffsetX *= 0.00f;
2238 aOffsetY *= -0.55f;
fc73a202 2239 }
50d0e1ce 2240 else if (anIt == 3)
2241 {
2242 aOffsetX *= 0.55f;
2243 aOffsetY *= 0.00f;
2244 }
2245
fc73a202 2246 myPostFSAAProgram->SetUniform (myGlContext,
50d0e1ce 2247 myUniformLocations[1][OpenGl_RT_uSamples], anIt + 1);
fc73a202 2248 myPostFSAAProgram->SetUniform (myGlContext,
2249 myUniformLocations[1][OpenGl_RT_uOffsetX], aOffsetX);
2250 myPostFSAAProgram->SetUniform (myGlContext,
2251 myUniformLocations[1][OpenGl_RT_uOffsetY], aOffsetY);
2252
50d0e1ce 2253 Handle(OpenGl_FrameBuffer)& aFramebuffer = anIt % 2 ? myRaytraceFBO2 : myRaytraceFBO1;
fc73a202 2254
2255 if (anIt == 3) // disable FBO on last iteration
2256 {
2257 glEnable (GL_BLEND);
2258
2259 if (theFrameBuffer != NULL)
2260 theFrameBuffer->BindBuffer (myGlContext);
2261 }
2262 else
2263 {
2264 aFramebuffer->BindBuffer (myGlContext);
2265 }
50d0e1ce 2266
fc73a202 2267 myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
e276548b 2268
fc73a202 2269 if (anIt != 3) // set input for the next pass
2270 {
945c3529 2271 aFramebuffer->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
fc73a202 2272 aFramebuffer->UnbindBuffer (myGlContext);
e276548b 2273 }
2274 }
fc73a202 2275
7d3e64ef 2276 myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS);
fc73a202 2277
7d3e64ef 2278 myGlContext->BindProgram (NULL);
a89742cf 2279 myRaytraceFBO1->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
2280 myOpenGlFBO->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
2281 myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
e2da917a 2282 mySceneMinPointTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
2283 mySceneMaxPointTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
2284 mySceneNodeInfoTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
a89742cf 2285 myGeometryVertexTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
2286 myGeometryNormalTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
25ef750e 2287 myGeometryTexCrdTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
a89742cf 2288 myGeometryTriangTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
25ef750e 2289 mySceneTransformTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
a89742cf 2290 myRaytraceMaterialTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
2291 myRaytraceLightSrcTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
a89742cf 2292
2293 myGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
fc73a202 2294
2295 return Standard_True;
e276548b 2296}
2297
2298// =======================================================================
2299// function : Raytrace
fc73a202 2300// purpose : Redraws the window using OpenGL/GLSL ray-tracing
e276548b 2301// =======================================================================
2302Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
68333c8f 2303 const Standard_Integer theSizeX,
2304 const Standard_Integer theSizeY,
fc73a202 2305 const Standard_Boolean theToSwap,
a89742cf 2306 const Aspect_CLayer2d& theCOverLayer,
2307 const Aspect_CLayer2d& theCUnderLayer,
fc73a202 2308 OpenGl_FrameBuffer* theFrameBuffer)
e276548b 2309{
bc8c79bb 2310 if (!InitRaytraceResources (theCView))
e276548b 2311 return Standard_False;
2312
fc73a202 2313 if (!ResizeRaytraceBuffers (theSizeX, theSizeY))
e276548b 2314 return Standard_False;
2315
fc73a202 2316 if (!UpdateRaytraceEnvironmentMap())
e276548b 2317 return Standard_False;
2318
2319 // Get model-view and projection matrices
25ef750e 2320 OpenGl_Mat4 aOrientationMatrix;
2321 OpenGl_Mat4 aViewMappingMatrix;
e276548b 2322
25ef750e 2323 myView->GetMatrices (aOrientationMatrix,
2324 aViewMappingMatrix);
e276548b 2325
25ef750e 2326 OpenGl_Mat4 aInvOrientationMatrix;
fc73a202 2327 aOrientationMatrix.Inverted (aInvOrientationMatrix);
e276548b 2328
fc73a202 2329 if (!UpdateRaytraceLightSources (aInvOrientationMatrix))
e276548b 2330 return Standard_False;
2331
fc73a202 2332 OpenGl_Vec3 aOrigins[4];
2333 OpenGl_Vec3 aDirects[4];
25ef750e 2334 OpenGl_Mat4 anUnviewMat;
e276548b 2335
fc73a202 2336 UpdateCamera (aOrientationMatrix,
2337 aViewMappingMatrix,
2338 aOrigins,
a89742cf 2339 aDirects,
25ef750e 2340 anUnviewMat);
e276548b 2341
84c71f29 2342 Standard_Boolean wasBlendingEnabled = glIsEnabled (GL_BLEND);
2343 Standard_Boolean wasDepthTestEnabled = glIsEnabled (GL_DEPTH_TEST);
e276548b 2344
2345 glDisable (GL_DEPTH_TEST);
2346
a89742cf 2347 if (theFrameBuffer != NULL)
2348 {
2349 theFrameBuffer->BindBuffer (myGlContext);
2350 }
2351
e276548b 2352 if (NamedStatus & OPENGL_NS_WHITEBACK)
2353 {
2354 glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
2355 }
2356 else
2357 {
2358 glClearColor (myBgColor.rgb[0],
2359 myBgColor.rgb[1],
2360 myBgColor.rgb[2],
2361 1.0f);
2362 }
2363
2364 glClear (GL_COLOR_BUFFER_BIT);
2365
0b0320e7 2366 myView->DrawBackground (this);
e276548b 2367
c827ea3a 2368 myView->RedrawLayer2d (myPrintContext, this, theCView, theCUnderLayer);
a89742cf 2369
c827ea3a 2370 myGlContext->WorldViewState.Push();
2371 myGlContext->ProjectionState.Push();
e276548b 2372
c827ea3a 2373 myGlContext->WorldViewState.SetIdentity();
2374 myGlContext->ProjectionState.SetIdentity();
2375
2376 myGlContext->ApplyProjectionMatrix();
2377 myGlContext->ApplyWorldViewMatrix();
e276548b 2378
fc73a202 2379 glEnable (GL_BLEND);
2380 glBlendFunc (GL_ONE, GL_SRC_ALPHA);
e276548b 2381
c827ea3a 2382 // Generate ray-traced image
e276548b 2383 if (myIsRaytraceDataValid)
2384 {
fc73a202 2385 myRaytraceScreenQuad.Bind (myGlContext);
2386
25ef750e 2387 if (!myRaytraceGeometry.AcquireTextures (myGlContext))
2388 {
2389 const TCollection_ExtendedString aMessage = "Error: Failed to acquire OpenGL image textures";
2390
2391 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
2392 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_MEDIUM_ARB, aMessage);
2393 }
2394
fc73a202 2395 RunRaytraceShaders (theCView,
2396 theSizeX,
2397 theSizeY,
2398 aOrigins,
2399 aDirects,
25ef750e 2400 anUnviewMat,
fc73a202 2401 theFrameBuffer);
2402
25ef750e 2403 if (!myRaytraceGeometry.ReleaseTextures (myGlContext))
2404 {
2405 const TCollection_ExtendedString aMessage = "Error: Failed to release OpenGL image textures";
2406
2407 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
2408 GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_MEDIUM_ARB, aMessage);
2409 }
2410
fc73a202 2411 myRaytraceScreenQuad.Unbind (myGlContext);
e276548b 2412 }
2413
84c71f29 2414 if (!wasBlendingEnabled)
2415 glDisable (GL_BLEND);
fc73a202 2416
84c71f29 2417 if (wasDepthTestEnabled)
2418 glEnable (GL_DEPTH_TEST);
e276548b 2419
c827ea3a 2420 myGlContext->WorldViewState.Pop();
2421 myGlContext->ProjectionState.Pop();
2422
2423 myGlContext->ApplyProjectionMatrix();
a89742cf 2424
2425 // Redraw trihedron
2426 myView->RedrawTrihedron (this);
2427
2428 // Redraw overlay
2429 const int aMode = 0;
2430 DisplayCallback (theCView, (aMode | OCC_PRE_OVERLAY));
c827ea3a 2431 myView->RedrawLayer2d (myPrintContext, this, theCView, theCOverLayer);
a89742cf 2432 DisplayCallback (theCView, aMode);
2433
e276548b 2434 // Swap the buffers
2435 if (theToSwap)
2436 {
2437 GetGlContext()->SwapBuffers();
2438 myBackBufferRestored = Standard_False;
2439 }
2440 else
fc73a202 2441 {
e276548b 2442 glFlush();
fc73a202 2443 }
e276548b 2444
2445 return Standard_True;
2446}
a89742cf 2447
2448IMPLEMENT_STANDARD_HANDLE(OpenGl_RaytraceFilter, OpenGl_RenderFilter)
2449IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter, OpenGl_RenderFilter)
2450
2451// =======================================================================
2452// function : CanRender
2453// purpose :
2454// =======================================================================
2455Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
2456{
2457 Standard_Boolean aPrevFilterResult = Standard_True;
2458 if (!myPrevRenderFilter.IsNull())
2459 {
2460 aPrevFilterResult = myPrevRenderFilter->CanRender(theElement);
2461 }
2462 return aPrevFilterResult &&
2463 !OpenGl_Raytrace::IsRaytracedElement (theElement);
2464}