0027900: Coding rules - drop redundant Name parameter from V3d_Viewer constructor
[occt.git] / src / OpenGl / OpenGl_View_Raytrace.cxx
1 // Created on: 2015-02-20
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2015 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_View.hxx>
17
18 #include <Graphic3d_TextureParams.hxx>
19 #include <OpenGl_PrimitiveArray.hxx>
20 #include <OpenGl_VertexBuffer.hxx>
21 #include <OSD_Protection.hxx>
22 #include <OSD_File.hxx>
23
24 using namespace OpenGl_Raytrace;
25
26 //! Use this macro to output ray-tracing debug info
27 // #define RAY_TRACE_PRINT_INFO
28
29 #ifdef RAY_TRACE_PRINT_INFO
30   #include <OSD_Timer.hxx>
31 #endif
32
33 namespace
34 {
35   static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f);
36   static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
37 }
38
39 // =======================================================================
40 // function : updateRaytraceGeometry
41 // purpose  : Updates 3D scene geometry for ray-tracing
42 // =======================================================================
43 Standard_Boolean OpenGl_View::updateRaytraceGeometry (const RaytraceUpdateMode      theMode,
44                                                       const Standard_Integer        theViewId,
45                                                       const Handle(OpenGl_Context)& theGlContext)
46 {
47   // In 'check' mode (OpenGl_GUM_CHECK) the scene geometry is analyzed for
48   // modifications. This is light-weight procedure performed on each frame
49   if (theMode == OpenGl_GUM_CHECK)
50   {
51     if (myLayerListState != myZLayers.ModificationState())
52     {
53       return updateRaytraceGeometry (OpenGl_GUM_PREPARE, theViewId, theGlContext);
54     }
55   }
56   else if (theMode == OpenGl_GUM_PREPARE)
57   {
58     myRaytraceGeometry.ClearMaterials();
59
60     myArrayToTrianglesMap.clear();
61
62     myIsRaytraceDataValid = Standard_False;
63   }
64
65   // The set of processed structures (reflected to ray-tracing)
66   // This set is used to remove out-of-date records from the
67   // hash map of structures
68   std::set<const OpenGl_Structure*> anElements;
69
70   // Set to store all currently visible OpenGL primitive arrays
71   // applicable for ray-tracing
72   std::set<Standard_Size> anArrayIDs;
73
74   // Set to store all non-raytracable elements allowing tracking
75   // of changes in OpenGL scene (only for path tracing)
76   std::set<Standard_Integer> aNonRaytraceIDs;
77
78   const OpenGl_Layer& aLayer = myZLayers.Layer (Graphic3d_ZLayerId_Default);
79
80   if (aLayer.NbStructures() != 0)
81   {
82     const OpenGl_ArrayOfIndexedMapOfStructure& aStructArray = aLayer.ArrayOfStructures();
83
84     for (Standard_Integer anIndex = 0; anIndex < aStructArray.Length(); ++anIndex)
85     {
86       for (OpenGl_IndexedMapOfStructure::Iterator aStructIt (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next())
87       {
88         const OpenGl_Structure* aStructure = aStructIt.Value();
89
90         if (theMode == OpenGl_GUM_CHECK)
91         {
92           if (toUpdateStructure (aStructure))
93           {
94             return updateRaytraceGeometry (OpenGl_GUM_PREPARE, theViewId, theGlContext);
95           }
96           else if (aStructure->IsVisible() && myRaytraceParameters.GlobalIllumination)
97           {
98             aNonRaytraceIDs.insert (aStructure->highlight ? aStructure->Id : -aStructure->Id);
99           }
100         }
101         else if (theMode == OpenGl_GUM_PREPARE)
102         {
103           if (!aStructure->IsRaytracable() || !aStructure->IsVisible())
104           {
105             continue;
106           }
107           else if (!aStructure->ViewAffinity.IsNull() && !aStructure->ViewAffinity->IsVisible (theViewId))
108           {
109             continue;
110           }
111
112           for (OpenGl_Structure::GroupIterator aGroupIter (aStructure->Groups()); aGroupIter.More(); aGroupIter.Next())
113           {
114             // Extract OpenGL elements from the group (primitives arrays)
115             for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
116             {
117               OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
118
119               if (aPrimArray != NULL)
120               {
121                 anArrayIDs.insert (aPrimArray->GetUID());
122               }
123             }
124           }
125         }
126         else if (theMode == OpenGl_GUM_REBUILD)
127         {
128           if (!aStructure->IsRaytracable())
129           {
130             continue;
131           }
132           else if (addRaytraceStructure (aStructure, theGlContext))
133           {
134             anElements.insert (aStructure); // structure was processed
135           }
136         }
137       }
138     }
139   }
140
141   if (theMode == OpenGl_GUM_PREPARE)
142   {
143     BVH_ObjectSet<Standard_ShortReal, 3>::BVH_ObjectList anUnchangedObjects;
144
145     // Filter out unchanged objects so only their transformations and materials
146     // will be updated (and newly added objects will be processed from scratch)
147     for (Standard_Integer anObjIdx = 0; anObjIdx < myRaytraceGeometry.Size(); ++anObjIdx)
148     {
149       OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
150         myRaytraceGeometry.Objects().ChangeValue (anObjIdx).operator->());
151
152       if (aTriangleSet == NULL)
153       {
154         continue;
155       }
156
157       if (anArrayIDs.find (aTriangleSet->AssociatedPArrayID()) != anArrayIDs.end())
158       {
159         anUnchangedObjects.Append (myRaytraceGeometry.Objects().Value (anObjIdx));
160
161         myArrayToTrianglesMap[aTriangleSet->AssociatedPArrayID()] = aTriangleSet;
162       }
163     }
164
165     myRaytraceGeometry.Objects() = anUnchangedObjects;
166
167     return updateRaytraceGeometry (OpenGl_GUM_REBUILD, theViewId, theGlContext);
168   }
169   else if (theMode == OpenGl_GUM_REBUILD)
170   {
171     // Actualize the hash map of structures - remove out-of-date records
172     std::map<const OpenGl_Structure*, StructState>::iterator anIter = myStructureStates.begin();
173
174     while (anIter != myStructureStates.end())
175     {
176       if (anElements.find (anIter->first) == anElements.end())
177       {
178         myStructureStates.erase (anIter++);
179       }
180       else
181       {
182         ++anIter;
183       }
184     }
185
186     // Actualize OpenGL layer list state
187     myLayerListState = myZLayers.ModificationState();
188
189     // Rebuild two-level acceleration structure
190     myRaytraceGeometry.ProcessAcceleration();
191
192     myRaytraceSceneRadius = 2.f /* scale factor */ * std::max (
193       myRaytraceGeometry.Box().CornerMin().cwiseAbs().maxComp(),
194       myRaytraceGeometry.Box().CornerMax().cwiseAbs().maxComp());
195
196     const BVH_Vec3f aSize = myRaytraceGeometry.Box().Size();
197
198     myRaytraceSceneEpsilon = Max (1.0e-6f, 1.0e-4f * aSize.Modulus());
199
200     return uploadRaytraceData (theGlContext);
201   }
202
203   if (myRaytraceParameters.GlobalIllumination)
204   {
205     Standard_Boolean toRestart =
206       aNonRaytraceIDs.size() != myNonRaytraceStructureIDs.size();
207
208     for (std::set<Standard_Integer>::iterator anID = aNonRaytraceIDs.begin(); anID != aNonRaytraceIDs.end() && !toRestart; ++anID)
209     {
210       if (myNonRaytraceStructureIDs.find (*anID) == myNonRaytraceStructureIDs.end())
211       {
212         toRestart = Standard_True;
213       }
214     }
215
216     if (toRestart)
217       myAccumFrames = 0;
218
219     myNonRaytraceStructureIDs = aNonRaytraceIDs;
220   }
221
222   return Standard_True;
223 }
224
225 // =======================================================================
226 // function : toUpdateStructure
227 // purpose  : Checks to see if the structure is modified
228 // =======================================================================
229 Standard_Boolean OpenGl_View::toUpdateStructure (const OpenGl_Structure* theStructure)
230 {
231   if (!theStructure->IsRaytracable())
232   {
233     if (theStructure->ModificationState() > 0)
234     {
235       theStructure->ResetModificationState();
236
237       return Standard_True; // ray-trace element was removed - need to rebuild
238     }
239
240     return Standard_False; // did not contain ray-trace elements
241   }
242
243   std::map<const OpenGl_Structure*, StructState>::iterator aStructState = myStructureStates.find (theStructure);
244
245   if (aStructState == myStructureStates.end() || aStructState->second.StructureState != theStructure->ModificationState())
246   {
247     return Standard_True;
248   }
249   else if (theStructure->InstancedStructure() != NULL)
250   {
251     return aStructState->second.InstancedState != theStructure->InstancedStructure()->ModificationState();
252   }
253
254   return Standard_False;
255 }
256
257 // =======================================================================
258 // function : buildTextureTransform
259 // purpose  : Constructs texture transformation matrix
260 // =======================================================================
261 void buildTextureTransform (const Handle(Graphic3d_TextureParams)& theParams, BVH_Mat4f& theMatrix)
262 {
263   theMatrix.InitIdentity();
264
265   // Apply scaling
266   const Graphic3d_Vec2& aScale = theParams->Scale();
267
268   theMatrix.ChangeValue (0, 0) *= aScale.x();
269   theMatrix.ChangeValue (1, 0) *= aScale.x();
270   theMatrix.ChangeValue (2, 0) *= aScale.x();
271   theMatrix.ChangeValue (3, 0) *= aScale.x();
272
273   theMatrix.ChangeValue (0, 1) *= aScale.y();
274   theMatrix.ChangeValue (1, 1) *= aScale.y();
275   theMatrix.ChangeValue (2, 1) *= aScale.y();
276   theMatrix.ChangeValue (3, 1) *= aScale.y();
277
278   // Apply translation
279   const Graphic3d_Vec2 aTrans = -theParams->Translation();
280
281   theMatrix.ChangeValue (0, 3) = theMatrix.GetValue (0, 0) * aTrans.x() +
282                                  theMatrix.GetValue (0, 1) * aTrans.y();
283
284   theMatrix.ChangeValue (1, 3) = theMatrix.GetValue (1, 0) * aTrans.x() +
285                                  theMatrix.GetValue (1, 1) * aTrans.y();
286
287   theMatrix.ChangeValue (2, 3) = theMatrix.GetValue (2, 0) * aTrans.x() +
288                                  theMatrix.GetValue (2, 1) * aTrans.y();
289
290   // Apply rotation
291   const Standard_ShortReal aSin = std::sin (
292     -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
293   const Standard_ShortReal aCos = std::cos (
294     -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
295
296   BVH_Mat4f aRotationMat;
297   aRotationMat.SetValue (0, 0,  aCos);
298   aRotationMat.SetValue (1, 1,  aCos);
299   aRotationMat.SetValue (0, 1, -aSin);
300   aRotationMat.SetValue (1, 0,  aSin);
301
302   theMatrix = theMatrix * aRotationMat;
303 }
304
305 // =======================================================================
306 // function : convertMaterial
307 // purpose  : Creates ray-tracing material properties
308 // =======================================================================
309 OpenGl_RaytraceMaterial OpenGl_View::convertMaterial (const OpenGl_AspectFace*      theAspect,
310                                                       const Handle(OpenGl_Context)& theGlContext)
311 {
312   OpenGl_RaytraceMaterial theMaterial;
313
314   const Graphic3d_MaterialAspect& aSrcMat = theAspect->Aspect()->FrontMaterial();
315   const OpenGl_Vec3& aMatCol  = theAspect->Aspect()->InteriorColor();
316   const float        aShine   = 128.0f * float(aSrcMat.Shininess());
317   const bool         isPhysic = aSrcMat.MaterialType (Graphic3d_MATERIAL_PHYSIC) == Standard_True;
318
319   // ambient component
320   if (aSrcMat.ReflectionMode (Graphic3d_TOR_AMBIENT))
321   {
322     const OpenGl_Vec3& aSrcAmb = isPhysic ? aSrcMat.AmbientColor() : aMatCol;
323     theMaterial.Ambient = BVH_Vec4f (aSrcAmb * (float )aSrcMat.Ambient(),  1.0f);
324   }
325   else
326   {
327     theMaterial.Ambient = THE_BLACK_COLOR;
328   }
329
330   // diffusion component
331   if (aSrcMat.ReflectionMode (Graphic3d_TOR_DIFFUSE))
332   {
333     const OpenGl_Vec3& aSrcDif = isPhysic ? aSrcMat.DiffuseColor() : aMatCol;
334     theMaterial.Diffuse = BVH_Vec4f (aSrcDif * (float )aSrcMat.Diffuse(), -1.0f); // -1 is no texture
335   }
336   else
337   {
338     theMaterial.Diffuse = BVH_Vec4f (THE_BLACK_COLOR.rgb(), -1.0f);
339   }
340
341   // specular component
342   if (aSrcMat.ReflectionMode (Graphic3d_TOR_SPECULAR))
343   {
344     const OpenGl_Vec3& aSrcSpe  = aSrcMat.SpecularColor();
345     const OpenGl_Vec3& aSrcSpe2 = isPhysic ? aSrcSpe : THE_WHITE_COLOR.rgb();
346     theMaterial.Specular = BVH_Vec4f (aSrcSpe2 * (float )aSrcMat.Specular(), aShine);
347
348     const Standard_ShortReal aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
349                                         Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
350                                              theMaterial.Diffuse.z() + theMaterial.Specular.z()));
351
352     const Standard_ShortReal aReflectionScale = 0.75f / aMaxRefl;
353
354     // ignore isPhysic here
355     theMaterial.Reflection = BVH_Vec4f (aSrcSpe * (float )aSrcMat.Specular() * aReflectionScale, 0.0f);
356   }
357   else
358   {
359     theMaterial.Specular = BVH_Vec4f (THE_BLACK_COLOR.rgb(), aShine);
360   }
361
362   // emission component
363   if (aSrcMat.ReflectionMode (Graphic3d_TOR_EMISSION))
364   {
365     const OpenGl_Vec3& aSrcEms = isPhysic ? aSrcMat.EmissiveColor() : aMatCol;
366     theMaterial.Emission = BVH_Vec4f (aSrcEms * (float )aSrcMat.Emissive(), 1.0f);
367   }
368   else
369   {
370     theMaterial.Emission = THE_BLACK_COLOR;
371   }
372
373   const float anIndex = (float )aSrcMat.RefractionIndex();
374   theMaterial.Transparency = BVH_Vec4f (1.0f - (float )aSrcMat.Transparency(),
375                                         (float )aSrcMat.Transparency(),
376                                         anIndex == 0 ? 1.0f : anIndex,
377                                         anIndex == 0 ? 1.0f : 1.0f / anIndex);
378
379   // Serialize physically-based material properties
380   const Graphic3d_BSDF& aBSDF = aSrcMat.BSDF();
381
382   theMaterial.BSDF.Le = BVH_Vec4f (aBSDF.Le,               0.f);
383   theMaterial.BSDF.Kd = BVH_Vec4f (aBSDF.Kd, -1.f /* no tex */);
384   theMaterial.BSDF.Kr = BVH_Vec4f (aBSDF.Kr,               0.f);
385   theMaterial.BSDF.Kt = BVH_Vec4f (aBSDF.Kt,               0.f);
386   theMaterial.BSDF.Ks = BVH_Vec4f (aBSDF.Ks,   aBSDF.Roughness);
387
388   theMaterial.BSDF.Fresnel = aBSDF.Fresnel.Serialize();
389
390   theMaterial.BSDF.Absorption = BVH_Vec4f (aBSDF.AbsorptionColor,
391                                            aBSDF.AbsorptionCoeff);
392
393   // Handle material textures
394   if (theAspect->Aspect()->ToMapTexture())
395   {
396     if (theGlContext->arbTexBindless != NULL)
397     {
398       buildTextureTransform (theAspect->TextureParams(), theMaterial.TextureTransform);
399
400       // write texture ID to diffuse w-component
401       theMaterial.Diffuse.w() = theMaterial.BSDF.Kd.w() =
402         static_cast<Standard_ShortReal> (myRaytraceGeometry.AddTexture (theAspect->TextureRes (theGlContext)));
403     }
404     else if (!myIsRaytraceWarnTextures)
405     {
406       const TCollection_ExtendedString aWarnMessage =
407         "Warning: texturing in Ray-Trace requires GL_ARB_bindless_texture extension which is missing. "
408         "Please try to update graphics card driver. At the moment textures will be ignored.";
409
410       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
411         GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
412
413       myIsRaytraceWarnTextures = Standard_True;
414     }
415   }
416
417   return theMaterial;
418 }
419
420 // =======================================================================
421 // function : addRaytraceStructure
422 // purpose  : Adds OpenGL structure to ray-traced scene geometry
423 // =======================================================================
424 Standard_Boolean OpenGl_View::addRaytraceStructure (const OpenGl_Structure*       theStructure,
425                                                     const Handle(OpenGl_Context)& theGlContext)
426 {
427   if (!theStructure->IsVisible())
428   {
429     myStructureStates[theStructure] = StructState (theStructure);
430
431     return Standard_True;
432   }
433
434   // Get structure material
435   OpenGl_RaytraceMaterial aDefaultMaterial;
436   Standard_Boolean aResult = addRaytraceGroups (theStructure, aDefaultMaterial, theStructure->Transformation(), theGlContext);
437
438   // Process all connected OpenGL structures
439   const OpenGl_Structure* anInstanced = theStructure->InstancedStructure();
440
441   if (anInstanced != NULL && anInstanced->IsRaytracable())
442   {
443     aResult &= addRaytraceGroups (anInstanced, aDefaultMaterial, theStructure->Transformation(), theGlContext);
444   }
445
446   myStructureStates[theStructure] = StructState (theStructure);
447
448   return aResult;
449 }
450
451 // =======================================================================
452 // function : addRaytraceGroups
453 // purpose  : Adds OpenGL groups to ray-traced scene geometry
454 // =======================================================================
455 Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*        theStructure,
456                                                  const OpenGl_RaytraceMaterial& theStructMat,
457                                                  const Handle(Geom_Transformation)& theTrsf,
458                                                  const Handle(OpenGl_Context)&  theGlContext)
459 {
460   OpenGl_Mat4 aMat4;
461   for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->Groups()); aGroupIter.More(); aGroupIter.Next())
462   {
463     // Get group material
464     OpenGl_RaytraceMaterial aGroupMaterial;
465     if (aGroupIter.Value()->AspectFace() != NULL)
466     {
467       aGroupMaterial = convertMaterial (
468         aGroupIter.Value()->AspectFace(), theGlContext);
469     }
470
471     Standard_Integer aMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
472
473     // Use group material if available, otherwise use structure material
474     myRaytraceGeometry.Materials.push_back (
475       aGroupIter.Value()->AspectFace() != NULL ? aGroupMaterial : theStructMat);
476
477     // Add OpenGL elements from group (extract primitives arrays and aspects)
478     for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
479     {
480       OpenGl_AspectFace* anAspect = dynamic_cast<OpenGl_AspectFace*> (aNode->elem);
481
482       if (anAspect != NULL)
483       {
484         aMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
485
486         OpenGl_RaytraceMaterial aMaterial = convertMaterial (anAspect, theGlContext);
487
488         myRaytraceGeometry.Materials.push_back (aMaterial);
489       }
490       else
491       {
492         OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
493
494         if (aPrimArray != NULL)
495         {
496           std::map<Standard_Size, OpenGl_TriangleSet*>::iterator aSetIter = myArrayToTrianglesMap.find (aPrimArray->GetUID());
497
498           if (aSetIter != myArrayToTrianglesMap.end())
499           {
500             OpenGl_TriangleSet* aSet = aSetIter->second;
501
502             BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>();
503
504             if (!theTrsf.IsNull())
505             {
506               theTrsf->Trsf().GetMat4 (aMat4);
507               aTransform->SetTransform (aMat4);
508             }
509
510             aSet->SetProperties (aTransform);
511
512             if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID)
513             {
514               aSet->SetMaterialIndex (aMatID);
515             }
516           }
517           else
518           {
519             NCollection_Handle<BVH_Object<Standard_ShortReal, 3> > aSet =
520               addRaytracePrimitiveArray (aPrimArray, aMatID, 0);
521
522             if (!aSet.IsNull())
523             {
524               BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>;
525
526               if (!theTrsf.IsNull())
527               {
528                 theTrsf->Trsf().GetMat4 (aMat4);
529                 aTransform->SetTransform (aMat4);
530               }
531
532               aSet->SetProperties (aTransform);
533
534               myRaytraceGeometry.Objects().Append (aSet);
535             }
536           }
537         }
538       }
539     }
540   }
541
542   return Standard_True;
543 }
544
545 // =======================================================================
546 // function : addRaytracePrimitiveArray
547 // purpose  : Adds OpenGL primitive array to ray-traced scene geometry
548 // =======================================================================
549 OpenGl_TriangleSet* OpenGl_View::addRaytracePrimitiveArray (const OpenGl_PrimitiveArray* theArray,
550                                                             const Standard_Integer       theMaterial,
551                                                             const OpenGl_Mat4*           theTransform)
552 {
553   const Handle(Graphic3d_BoundBuffer)& aBounds   = theArray->Bounds();
554   const Handle(Graphic3d_IndexBuffer)& anIndices = theArray->Indices();
555   const Handle(Graphic3d_Buffer)&      anAttribs = theArray->Attributes();
556
557   if (theArray->DrawMode() < GL_TRIANGLES
558   #ifndef GL_ES_VERSION_2_0
559    || theArray->DrawMode() > GL_POLYGON
560   #else
561    || theArray->DrawMode() > GL_TRIANGLE_FAN
562   #endif
563    || anAttribs.IsNull())
564   {
565     return NULL;
566   }
567
568   OpenGl_Mat4 aNormalMatrix;
569
570   if (theTransform != NULL)
571   {
572     Standard_ASSERT_RETURN (theTransform->Inverted (aNormalMatrix),
573       "Error: Failed to compute normal transformation matrix", NULL);
574
575     aNormalMatrix.Transpose();
576   }
577
578   OpenGl_TriangleSet* aSet = new OpenGl_TriangleSet (theArray->GetUID());
579   {
580     aSet->Vertices.reserve (anAttribs->NbElements);
581     aSet->Normals.reserve  (anAttribs->NbElements);
582     aSet->TexCrds.reserve  (anAttribs->NbElements);
583
584     const size_t aVertFrom = aSet->Vertices.size();
585
586     for (Standard_Integer anAttribIter = 0; anAttribIter < anAttribs->NbAttributes; ++anAttribIter)
587     {
588       const Graphic3d_Attribute& anAttrib = anAttribs->Attribute       (anAttribIter);
589       const size_t               anOffset = anAttribs->AttributeOffset (anAttribIter);
590       if (anAttrib.Id == Graphic3d_TOA_POS)
591       {
592         if (anAttrib.DataType == Graphic3d_TOD_VEC3
593          || anAttrib.DataType == Graphic3d_TOD_VEC4)
594         {
595           for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
596           {
597             aSet->Vertices.push_back (
598               *reinterpret_cast<const Graphic3d_Vec3*> (anAttribs->value (aVertIter) + anOffset));
599           }
600         }
601         else if (anAttrib.DataType == Graphic3d_TOD_VEC2)
602         {
603           for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
604           {
605             const Standard_ShortReal* aCoords =
606               reinterpret_cast<const Standard_ShortReal*> (anAttribs->value (aVertIter) + anOffset);
607
608             aSet->Vertices.push_back (BVH_Vec3f (aCoords[0], aCoords[1], 0.0f));
609           }
610         }
611       }
612       else if (anAttrib.Id == Graphic3d_TOA_NORM)
613       {
614         if (anAttrib.DataType == Graphic3d_TOD_VEC3
615          || anAttrib.DataType == Graphic3d_TOD_VEC4)
616         {
617           for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
618           {
619             aSet->Normals.push_back (
620               *reinterpret_cast<const Graphic3d_Vec3*> (anAttribs->value (aVertIter) + anOffset));
621           }
622         }
623       }
624       else if (anAttrib.Id == Graphic3d_TOA_UV)
625       {
626         if (anAttrib.DataType == Graphic3d_TOD_VEC2)
627         {
628           for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
629           {
630             aSet->TexCrds.push_back (
631               *reinterpret_cast<const Graphic3d_Vec2*> (anAttribs->value (aVertIter) + anOffset));
632           }
633         }
634       }
635     }
636
637     if (aSet->Normals.size() != aSet->Vertices.size())
638     {
639       for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
640       {
641         aSet->Normals.push_back (BVH_Vec3f());
642       }
643     }
644
645     if (aSet->TexCrds.size() != aSet->Vertices.size())
646     {
647       for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
648       {
649         aSet->TexCrds.push_back (BVH_Vec2f());
650       }
651     }
652
653     if (theTransform != NULL)
654     {
655       for (size_t aVertIter = aVertFrom; aVertIter < aSet->Vertices.size(); ++aVertIter)
656       {
657         BVH_Vec3f& aVertex = aSet->Vertices[aVertIter];
658
659         BVH_Vec4f aTransVertex = *theTransform *
660           BVH_Vec4f (aVertex.x(), aVertex.y(), aVertex.z(), 1.f);
661
662         aVertex = BVH_Vec3f (aTransVertex.x(), aTransVertex.y(), aTransVertex.z());
663       }
664       for (size_t aVertIter = aVertFrom; aVertIter < aSet->Normals.size(); ++aVertIter)
665       {
666         BVH_Vec3f& aNormal = aSet->Normals[aVertIter];
667
668         BVH_Vec4f aTransNormal = aNormalMatrix *
669           BVH_Vec4f (aNormal.x(), aNormal.y(), aNormal.z(), 0.f);
670
671         aNormal = BVH_Vec3f (aTransNormal.x(), aTransNormal.y(), aTransNormal.z());
672       }
673     }
674
675     if (!aBounds.IsNull())
676     {
677       for (Standard_Integer aBound = 0, aBoundStart = 0; aBound < aBounds->NbBounds; ++aBound)
678       {
679         const Standard_Integer aVertNum = aBounds->Bounds[aBound];
680
681         if (!addRaytraceVertexIndices (*aSet, theMaterial, aVertNum, aBoundStart, *theArray))
682         {
683           delete aSet;
684           return NULL;
685         }
686
687         aBoundStart += aVertNum;
688       }
689     }
690     else
691     {
692       const Standard_Integer aVertNum = !anIndices.IsNull() ? anIndices->NbElements : anAttribs->NbElements;
693
694       if (!addRaytraceVertexIndices (*aSet, theMaterial, aVertNum, 0, *theArray))
695       {
696         delete aSet;
697         return NULL;
698       }
699     }
700   }
701
702   if (aSet->Size() != 0)
703   {
704     aSet->MarkDirty();
705   }
706
707   return aSet;
708 }
709
710 // =======================================================================
711 // function : addRaytraceVertexIndices
712 // purpose  : Adds vertex indices to ray-traced scene geometry
713 // =======================================================================
714 Standard_Boolean OpenGl_View::addRaytraceVertexIndices (OpenGl_TriangleSet&                  theSet,
715                                                         const Standard_Integer               theMatID,
716                                                         const Standard_Integer               theCount,
717                                                         const Standard_Integer               theOffset,
718                                                         const OpenGl_PrimitiveArray&         theArray)
719 {
720   switch (theArray.DrawMode())
721   {
722     case GL_TRIANGLES:      return addRaytraceTriangleArray        (theSet, theMatID, theCount, theOffset, theArray.Indices());
723     case GL_TRIANGLE_FAN:   return addRaytraceTriangleFanArray     (theSet, theMatID, theCount, theOffset, theArray.Indices());
724     case GL_TRIANGLE_STRIP: return addRaytraceTriangleStripArray   (theSet, theMatID, theCount, theOffset, theArray.Indices());
725   #if !defined(GL_ES_VERSION_2_0)
726     case GL_QUAD_STRIP:     return addRaytraceQuadrangleStripArray (theSet, theMatID, theCount, theOffset, theArray.Indices());
727     case GL_QUADS:          return addRaytraceQuadrangleArray      (theSet, theMatID, theCount, theOffset, theArray.Indices());
728     case GL_POLYGON:        return addRaytracePolygonArray         (theSet, theMatID, theCount, theOffset, theArray.Indices());
729   #endif
730   }
731
732   return Standard_False;
733 }
734
735 // =======================================================================
736 // function : addRaytraceTriangleArray
737 // purpose  : Adds OpenGL triangle array to ray-traced scene geometry
738 // =======================================================================
739 Standard_Boolean OpenGl_View::addRaytraceTriangleArray (OpenGl_TriangleSet&                  theSet,
740                                                         const Standard_Integer               theMatID,
741                                                         const Standard_Integer               theCount,
742                                                         const Standard_Integer               theOffset,
743                                                         const Handle(Graphic3d_IndexBuffer)& theIndices)
744 {
745   if (theCount < 3)
746   {
747     return Standard_True;
748   }
749
750   theSet.Elements.reserve (theSet.Elements.size() + theCount / 3);
751
752   if (!theIndices.IsNull())
753   {
754     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
755     {
756       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
757                                             theIndices->Index (aVert + 1),
758                                             theIndices->Index (aVert + 2),
759                                             theMatID));
760     }
761   }
762   else
763   {
764     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
765     {
766       theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2, theMatID));
767     }
768   }
769
770   return Standard_True;
771 }
772
773 // =======================================================================
774 // function : addRaytraceTriangleFanArray
775 // purpose  : Adds OpenGL triangle fan array to ray-traced scene geometry
776 // =======================================================================
777 Standard_Boolean OpenGl_View::addRaytraceTriangleFanArray (OpenGl_TriangleSet&                  theSet,
778                                                            const Standard_Integer               theMatID,
779                                                            const Standard_Integer               theCount,
780                                                            const Standard_Integer               theOffset,
781                                                            const Handle(Graphic3d_IndexBuffer)& theIndices)
782 {
783   if (theCount < 3)
784   {
785     return Standard_True;
786   }
787
788   theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
789
790   if (!theIndices.IsNull())
791   {
792     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
793     {
794       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
795                                             theIndices->Index (aVert + 1),
796                                             theIndices->Index (aVert + 2),
797                                             theMatID));
798     }
799   }
800   else
801   {
802     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
803     {
804       theSet.Elements.push_back (BVH_Vec4i (theOffset,
805                                             aVert + 1,
806                                             aVert + 2,
807                                             theMatID));
808     }
809   }
810
811   return Standard_True;
812 }
813
814 // =======================================================================
815 // function : addRaytraceTriangleStripArray
816 // purpose  : Adds OpenGL triangle strip array to ray-traced scene geometry
817 // =======================================================================
818 Standard_Boolean OpenGl_View::addRaytraceTriangleStripArray (OpenGl_TriangleSet&                  theSet,
819                                                              const Standard_Integer               theMatID,
820                                                              const Standard_Integer               theCount,
821                                                              const Standard_Integer               theOffset,
822                                                              const Handle(Graphic3d_IndexBuffer)& theIndices)
823 {
824   if (theCount < 3)
825   {
826     return Standard_True;
827   }
828
829   theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
830
831   if (!theIndices.IsNull())
832   {
833     for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
834     {
835       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + (aCW ? 1 : 0)),
836                                             theIndices->Index (aVert + (aCW ? 0 : 1)),
837                                             theIndices->Index (aVert + 2),
838                                             theMatID));
839     }
840   }
841   else
842   {
843     for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
844     {
845       theSet.Elements.push_back (BVH_Vec4i (aVert + (aCW ? 1 : 0),
846                                             aVert + (aCW ? 0 : 1),
847                                             aVert + 2,
848                                             theMatID));
849     }
850   }
851
852   return Standard_True;
853 }
854
855 // =======================================================================
856 // function : addRaytraceQuadrangleArray
857 // purpose  : Adds OpenGL quad array to ray-traced scene geometry
858 // =======================================================================
859 Standard_Boolean OpenGl_View::addRaytraceQuadrangleArray (OpenGl_TriangleSet&                  theSet,
860                                                           const Standard_Integer               theMatID,
861                                                           const Standard_Integer               theCount,
862                                                           const Standard_Integer               theOffset,
863                                                           const Handle(Graphic3d_IndexBuffer)& theIndices)
864 {
865   if (theCount < 4)
866   {
867     return Standard_True;
868   }
869
870   theSet.Elements.reserve (theSet.Elements.size() + theCount / 2);
871
872   if (!theIndices.IsNull())
873   {
874     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
875     {
876       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
877                                             theIndices->Index (aVert + 1),
878                                             theIndices->Index (aVert + 2),
879                                             theMatID));
880       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
881                                             theIndices->Index (aVert + 2),
882                                             theIndices->Index (aVert + 3),
883                                             theMatID));
884     }
885   }
886   else
887   {
888     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
889     {
890       theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2,
891                                             theMatID));
892       theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 2, aVert + 3,
893                                             theMatID));
894     }
895   }
896
897   return Standard_True;
898 }
899
900 // =======================================================================
901 // function : addRaytraceQuadrangleStripArray
902 // purpose  : Adds OpenGL quad strip array to ray-traced scene geometry
903 // =======================================================================
904 Standard_Boolean OpenGl_View::addRaytraceQuadrangleStripArray (OpenGl_TriangleSet&                  theSet,
905                                                                const Standard_Integer               theMatID,
906                                                                const Standard_Integer               theCount,
907                                                                const Standard_Integer               theOffset,
908                                                                const Handle(Graphic3d_IndexBuffer)& theIndices)
909 {
910   if (theCount < 4)
911   {
912     return Standard_True;
913   }
914
915   theSet.Elements.reserve (theSet.Elements.size() + 2 * theCount - 6);
916
917   if (!theIndices.IsNull())
918   {
919     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
920     {
921       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
922                                             theIndices->Index (aVert + 1),
923                                             theIndices->Index (aVert + 2),
924                                             theMatID));
925
926       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 1),
927                                             theIndices->Index (aVert + 3),
928                                             theIndices->Index (aVert + 2),
929                                             theMatID));
930     }
931   }
932   else
933   {
934     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
935     {
936       theSet.Elements.push_back (BVH_Vec4i (aVert + 0,
937                                             aVert + 1,
938                                             aVert + 2,
939                                             theMatID));
940
941       theSet.Elements.push_back (BVH_Vec4i (aVert + 1,
942                                             aVert + 3,
943                                             aVert + 2,
944                                             theMatID));
945     }
946   }
947
948   return Standard_True;
949 }
950
951 // =======================================================================
952 // function : addRaytracePolygonArray
953 // purpose  : Adds OpenGL polygon array to ray-traced scene geometry
954 // =======================================================================
955 Standard_Boolean OpenGl_View::addRaytracePolygonArray (OpenGl_TriangleSet&                  theSet,
956                                                        const Standard_Integer               theMatID,
957                                                        const Standard_Integer               theCount,
958                                                        const Standard_Integer               theOffset,
959                                                        const Handle(Graphic3d_IndexBuffer)& theIndices)
960 {
961   if (theCount < 3)
962   {
963     return Standard_True;
964   }
965
966   theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
967
968   if (!theIndices.IsNull())
969   {
970     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
971     {
972       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
973                                             theIndices->Index (aVert + 1),
974                                             theIndices->Index (aVert + 2),
975                                             theMatID));
976     }
977   }
978   else
979   {
980     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
981     {
982       theSet.Elements.push_back (BVH_Vec4i (theOffset,
983                                             aVert + 1,
984                                             aVert + 2,
985                                             theMatID));
986     }
987   }
988
989   return Standard_True;
990 }
991
992 const TCollection_AsciiString OpenGl_View::ShaderSource::EMPTY_PREFIX;
993
994 // =======================================================================
995 // function : Source
996 // purpose  : Returns shader source combined with prefix
997 // =======================================================================
998 TCollection_AsciiString OpenGl_View::ShaderSource::Source() const
999 {
1000   const TCollection_AsciiString aVersion = "#version 140";
1001
1002   if (myPrefix.IsEmpty())
1003   {
1004     return aVersion + "\n" + mySource;
1005   }
1006
1007   return aVersion + "\n" + myPrefix + "\n" + mySource;
1008 }
1009
1010 // =======================================================================
1011 // function : Load
1012 // purpose  : Loads shader source from specified files
1013 // =======================================================================
1014 Standard_Boolean OpenGl_View::ShaderSource::Load (const TCollection_AsciiString* theFileNames,
1015                                                   const TCollection_AsciiString& thePrefix)
1016 {
1017   myError.Clear();
1018   mySource.Clear();
1019   TCollection_AsciiString aMissingFiles;
1020   for (Standard_Integer anIndex = 0; !theFileNames[anIndex].IsEmpty(); ++anIndex)
1021   {
1022     OSD_File aFile (theFileNames[anIndex]);
1023     if (aFile.Exists())
1024     {
1025       aFile.Open (OSD_ReadOnly, OSD_Protection());
1026     }
1027     if (!aFile.IsOpen())
1028     {
1029       if (!aMissingFiles.IsEmpty())
1030       {
1031         aMissingFiles += ", ";
1032       }
1033       aMissingFiles += TCollection_AsciiString("'") + theFileNames[anIndex] + "'";
1034       continue;
1035     }
1036     else if (!aMissingFiles.IsEmpty())
1037     {
1038       aFile.Close();
1039       continue;
1040     }
1041
1042     TCollection_AsciiString aSource;
1043     aFile.Read (aSource, (Standard_Integer) aFile.Size());
1044     if (!aSource.IsEmpty())
1045     {
1046       mySource += TCollection_AsciiString ("\n") + aSource;
1047     }
1048     aFile.Close();
1049   }
1050
1051   myPrefix = thePrefix;
1052   if (!aMissingFiles.IsEmpty())
1053   {
1054     myError = TCollection_AsciiString("Shader files ") + aMissingFiles + " are missing or inaccessible";
1055     return Standard_False;
1056   }
1057   return Standard_True;
1058 }
1059
1060 // =======================================================================
1061 // function : generateShaderPrefix
1062 // purpose  : Generates shader prefix based on current ray-tracing options
1063 // =======================================================================
1064 TCollection_AsciiString OpenGl_View::generateShaderPrefix (const Handle(OpenGl_Context)& theGlContext) const
1065 {
1066   TCollection_AsciiString aPrefixString =
1067     TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
1068     TCollection_AsciiString ("#define NB_BOUNCES ") + TCollection_AsciiString (myRaytraceParameters.NbBounces);
1069
1070   if (myRaytraceParameters.TransparentShadows)
1071   {
1072     aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
1073   }
1074
1075   // If OpenGL driver supports bindless textures and texturing
1076   // is actually used, activate texturing in ray-tracing mode
1077   if (myRaytraceParameters.UseBindlessTextures && theGlContext->arbTexBindless != NULL)
1078   {
1079     aPrefixString += TCollection_AsciiString ("\n#define USE_TEXTURES") +
1080       TCollection_AsciiString ("\n#define MAX_TEX_NUMBER ") + TCollection_AsciiString (OpenGl_RaytraceGeometry::MAX_TEX_NUMBER);
1081   }
1082
1083   if (myRaytraceParameters.GlobalIllumination)
1084   {
1085     aPrefixString += TCollection_AsciiString ("\n#define PATH_TRACING");
1086   }
1087
1088   return aPrefixString;
1089 }
1090
1091 // =======================================================================
1092 // function : safeFailBack
1093 // purpose  : Performs safe exit when shaders initialization fails
1094 // =======================================================================
1095 Standard_Boolean OpenGl_View::safeFailBack (const TCollection_ExtendedString& theMessage,
1096                                             const Handle(OpenGl_Context)&     theGlContext)
1097 {
1098   theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1099     GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, theMessage);
1100
1101   myRaytraceInitStatus = OpenGl_RT_FAIL;
1102
1103   releaseRaytraceResources (theGlContext);
1104
1105   return Standard_False;
1106 }
1107
1108 // =======================================================================
1109 // function : initShader
1110 // purpose  : Creates new shader object with specified source
1111 // =======================================================================
1112 Handle(OpenGl_ShaderObject) OpenGl_View::initShader (const GLenum                  theType,
1113                                                      const ShaderSource&           theSource,
1114                                                      const Handle(OpenGl_Context)& theGlContext)
1115 {
1116   Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (theType);
1117
1118   if (!aShader->Create (theGlContext))
1119   {
1120     const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to create ") +
1121       (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object";
1122
1123     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1124       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1125
1126     aShader->Release (theGlContext.operator->());
1127
1128     return Handle(OpenGl_ShaderObject)();
1129   }
1130
1131   if (!aShader->LoadSource (theGlContext, theSource.Source()))
1132   {
1133     const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to set ") +
1134       (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader source";
1135
1136     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1137       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1138
1139     aShader->Release (theGlContext.operator->());
1140
1141     return Handle(OpenGl_ShaderObject)();
1142   }
1143
1144   TCollection_AsciiString aBuildLog;
1145
1146   if (!aShader->Compile (theGlContext))
1147   {
1148     aShader->FetchInfoLog (theGlContext, aBuildLog);
1149
1150     const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to compile ") +
1151       (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object:\n" + aBuildLog;
1152
1153     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1154       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1155
1156     aShader->Release (theGlContext.operator->());
1157
1158     return Handle(OpenGl_ShaderObject)();
1159   }
1160   else if (theGlContext->caps->glslWarnings)
1161   {
1162     aShader->FetchInfoLog (theGlContext, aBuildLog);
1163
1164     if (!aBuildLog.IsEmpty() && !aBuildLog.IsEqual ("No errors.\n"))
1165     {
1166       const TCollection_ExtendedString aMessage = TCollection_ExtendedString (theType == GL_VERTEX_SHADER ?
1167         "Vertex" : "Fragment") + " shader was compiled with following warnings:\n" + aBuildLog;
1168
1169       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1170         GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMessage);
1171     }
1172   }
1173
1174   return aShader;
1175 }
1176
1177 // =======================================================================
1178 // function : initProgram
1179 // purpose  : Creates GLSL program from the given shader objects
1180 // =======================================================================
1181 Handle(OpenGl_ShaderProgram) OpenGl_View::initProgram (const Handle(OpenGl_Context)&      theGlContext,
1182                                                        const Handle(OpenGl_ShaderObject)& theVertShader,
1183                                                        const Handle(OpenGl_ShaderObject)& theFragShader)
1184 {
1185   Handle(OpenGl_ShaderProgram) aProgram = new OpenGl_ShaderProgram;
1186
1187   if (!aProgram->Create (theGlContext))
1188   {
1189     theVertShader->Release (theGlContext.operator->());
1190
1191     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1192       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Failed to create shader program");
1193
1194     return Handle(OpenGl_ShaderProgram)();
1195   }
1196
1197   if (!aProgram->AttachShader (theGlContext, theVertShader)
1198    || !aProgram->AttachShader (theGlContext, theFragShader))
1199   {
1200     theVertShader->Release (theGlContext.operator->());
1201
1202     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1203       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Failed to attach shader objects");
1204
1205     return Handle(OpenGl_ShaderProgram)();
1206   }
1207
1208   aProgram->SetAttributeName (theGlContext, Graphic3d_TOA_POS, "occVertex");
1209
1210   TCollection_AsciiString aLinkLog;
1211
1212   if (!aProgram->Link (theGlContext))
1213   {
1214     aProgram->FetchInfoLog (theGlContext, aLinkLog);
1215
1216     const TCollection_ExtendedString aMessage = TCollection_ExtendedString (
1217       "Failed to link shader program:\n") + aLinkLog;
1218
1219     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1220       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1221
1222     return Handle(OpenGl_ShaderProgram)();
1223   }
1224   else if (theGlContext->caps->glslWarnings)
1225   {
1226     aProgram->FetchInfoLog (theGlContext, aLinkLog);
1227     if (!aLinkLog.IsEmpty() && !aLinkLog.IsEqual ("No errors.\n"))
1228     {
1229       const TCollection_ExtendedString aMessage = TCollection_ExtendedString (
1230         "Shader program was linked with following warnings:\n") + aLinkLog;
1231
1232       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1233         GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMessage);
1234     }
1235   }
1236
1237   return aProgram;
1238 }
1239
1240 // =======================================================================
1241 // function : initRaytraceResources
1242 // purpose  : Initializes OpenGL/GLSL shader programs
1243 // =======================================================================
1244 Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context)& theGlContext)
1245 {
1246   if (myRaytraceInitStatus == OpenGl_RT_FAIL)
1247   {
1248     return Standard_False;
1249   }
1250
1251   Standard_Boolean aToRebuildShaders = Standard_False;
1252
1253   if (myRaytraceInitStatus == OpenGl_RT_INIT)
1254   {
1255     if (!myIsRaytraceDataValid)
1256       return Standard_True;
1257
1258     const Standard_Integer aRequiredStackSize =
1259       myRaytraceGeometry.TopLevelTreeDepth() + myRaytraceGeometry.BotLevelTreeDepth();
1260
1261     if (myRaytraceParameters.StackSize < aRequiredStackSize)
1262     {
1263       myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
1264
1265       aToRebuildShaders = Standard_True;
1266     }
1267     else
1268     {
1269       if (aRequiredStackSize < myRaytraceParameters.StackSize)
1270       {
1271         if (myRaytraceParameters.StackSize > THE_DEFAULT_STACK_SIZE)
1272         {
1273           myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
1274           aToRebuildShaders = Standard_True;
1275         }
1276       }
1277     }
1278
1279     if (myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces)
1280     {
1281       myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth;
1282       aToRebuildShaders = Standard_True;
1283     }
1284
1285     if (myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures)
1286     {
1287       myRaytraceParameters.UseBindlessTextures = myRaytraceGeometry.HasTextures();
1288       aToRebuildShaders = Standard_True;
1289     }
1290
1291     if (myRenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows)
1292     {
1293       myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled;
1294       aToRebuildShaders = Standard_True;
1295     }
1296
1297     if (myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination)
1298     {
1299       myRaytraceParameters.GlobalIllumination = myRenderParams.IsGlobalIlluminationEnabled;
1300       aToRebuildShaders = Standard_True;
1301     }
1302
1303     if (aToRebuildShaders)
1304     {
1305       // Reject accumulated frames
1306       myAccumFrames = 0;
1307
1308       // We need to update environment texture
1309       myToUpdateEnvironmentMap = Standard_True;
1310
1311       TCollection_AsciiString aPrefixString = generateShaderPrefix (theGlContext);
1312
1313 #ifdef RAY_TRACE_PRINT_INFO
1314       std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
1315 #endif
1316
1317       myRaytraceShaderSource.SetPrefix (aPrefixString);
1318       myPostFSAAShaderSource.SetPrefix (aPrefixString);
1319
1320       if (!myRaytraceShader->LoadSource (theGlContext, myRaytraceShaderSource.Source())
1321        || !myPostFSAAShader->LoadSource (theGlContext, myPostFSAAShaderSource.Source()))
1322       {
1323         return safeFailBack ("Failed to load source into ray-tracing fragment shaders", theGlContext);
1324       }
1325
1326       if (!myRaytraceShader->Compile (theGlContext)
1327        || !myPostFSAAShader->Compile (theGlContext))
1328       {
1329         return safeFailBack ("Failed to compile ray-tracing fragment shaders", theGlContext);
1330       }
1331
1332       myRaytraceProgram->SetAttributeName (theGlContext, Graphic3d_TOA_POS, "occVertex");
1333       myPostFSAAProgram->SetAttributeName (theGlContext, Graphic3d_TOA_POS, "occVertex");
1334       if (!myRaytraceProgram->Link (theGlContext)
1335        || !myPostFSAAProgram->Link (theGlContext))
1336       {
1337         return safeFailBack ("Failed to initialize vertex attributes for ray-tracing program", theGlContext);
1338       }
1339     }
1340   }
1341
1342   if (myRaytraceInitStatus == OpenGl_RT_NONE)
1343   {
1344     if (!theGlContext->IsGlGreaterEqual (3, 1))
1345     {
1346       return safeFailBack ("Ray-tracing requires OpenGL 3.1 and higher", theGlContext);
1347     }
1348     else if (!theGlContext->arbTboRGB32)
1349     {
1350       return safeFailBack ("Ray-tracing requires OpenGL 4.0+ or GL_ARB_texture_buffer_object_rgb32 extension", theGlContext);
1351     }
1352     else if (!theGlContext->arbFBOBlit)
1353     {
1354       return safeFailBack ("Ray-tracing requires EXT_framebuffer_blit extension", theGlContext);
1355     }
1356
1357     myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth;
1358
1359     TCollection_AsciiString aFolder = Graphic3d_ShaderProgram::ShadersFolder();
1360
1361     if (aFolder.IsEmpty())
1362     {
1363       return safeFailBack ("Failed to locate shaders directory", theGlContext);
1364     }
1365
1366     if (myIsRaytraceDataValid)
1367     {
1368       myRaytraceParameters.StackSize = Max (THE_DEFAULT_STACK_SIZE,
1369         myRaytraceGeometry.TopLevelTreeDepth() + myRaytraceGeometry.BotLevelTreeDepth());
1370     }
1371
1372     TCollection_AsciiString aPrefixString  = generateShaderPrefix (theGlContext);
1373
1374 #ifdef RAY_TRACE_PRINT_INFO
1375     std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
1376 #endif
1377
1378     ShaderSource aBasicVertShaderSrc;
1379     {
1380       TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.vs", "" };
1381       if (!aBasicVertShaderSrc.Load (aFiles))
1382       {
1383         return safeFailBack (aBasicVertShaderSrc.ErrorDescription(), theGlContext);
1384       }
1385     }
1386
1387     {
1388       TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs",
1389                                            aFolder + "/PathtraceBase.fs",
1390                                            aFolder + "/RaytraceRender.fs",
1391                                            "" };
1392       if (!myRaytraceShaderSource.Load (aFiles, aPrefixString))
1393       {
1394         return safeFailBack (myRaytraceShaderSource.ErrorDescription(), theGlContext);
1395       }
1396
1397       Handle(OpenGl_ShaderObject) aBasicVertShader = initShader (GL_VERTEX_SHADER, aBasicVertShaderSrc, theGlContext);
1398       if (aBasicVertShader.IsNull())
1399       {
1400         return safeFailBack ("Failed to initialize ray-trace vertex shader", theGlContext);
1401       }
1402
1403       myRaytraceShader = initShader (GL_FRAGMENT_SHADER, myRaytraceShaderSource, theGlContext);
1404       if (myRaytraceShader.IsNull())
1405       {
1406         aBasicVertShader->Release (theGlContext.operator->());
1407         return safeFailBack ("Failed to initialize ray-trace fragment shader", theGlContext);
1408       }
1409
1410       myRaytraceProgram = initProgram (theGlContext, aBasicVertShader, myRaytraceShader);
1411       if (myRaytraceProgram.IsNull())
1412       {
1413         return safeFailBack ("Failed to initialize ray-trace shader program", theGlContext);
1414       }
1415     }
1416
1417     {
1418       TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs",
1419                                            aFolder + "/RaytraceSmooth.fs",
1420                                            "" };
1421       if (!myPostFSAAShaderSource.Load (aFiles, aPrefixString))
1422       {
1423         return safeFailBack (myPostFSAAShaderSource.ErrorDescription(), theGlContext);
1424       }
1425
1426       Handle(OpenGl_ShaderObject) aBasicVertShader = initShader (GL_VERTEX_SHADER, aBasicVertShaderSrc, theGlContext);
1427       if (aBasicVertShader.IsNull())
1428       {
1429         return safeFailBack ("Failed to initialize FSAA vertex shader", theGlContext);
1430       }
1431
1432       myPostFSAAShader = initShader (GL_FRAGMENT_SHADER, myPostFSAAShaderSource, theGlContext);
1433       if (myPostFSAAShader.IsNull())
1434       {
1435         aBasicVertShader->Release (theGlContext.operator->());
1436         return safeFailBack ("Failed to initialize FSAA fragment shader", theGlContext);
1437       }
1438
1439       myPostFSAAProgram = initProgram (theGlContext, aBasicVertShader, myPostFSAAShader);
1440       if (myPostFSAAProgram.IsNull())
1441       {
1442         return safeFailBack ("Failed to initialize FSAA shader program", theGlContext);
1443       }
1444     }
1445
1446     {
1447       ShaderSource aDispShaderSrc;
1448       TCollection_AsciiString aFiles[] = { aFolder + "/Display.fs", "" };
1449       if (!aDispShaderSrc.Load (aFiles, aPrefixString))
1450       {
1451         return safeFailBack (aDispShaderSrc.ErrorDescription(), theGlContext);
1452       }
1453
1454       Handle(OpenGl_ShaderObject) aBasicVertShader = initShader (GL_VERTEX_SHADER, aBasicVertShaderSrc, theGlContext);
1455       if (aBasicVertShader.IsNull())
1456       {
1457         return safeFailBack ("Failed to set vertex shader source", theGlContext);
1458       }
1459
1460       Handle(OpenGl_ShaderObject) aDisplayShader = initShader (GL_FRAGMENT_SHADER, aDispShaderSrc, theGlContext);
1461       if (aDisplayShader.IsNull())
1462       {
1463         aBasicVertShader->Release (theGlContext.operator->());
1464         return safeFailBack ("Failed to set display fragment shader source", theGlContext);
1465       }
1466
1467       myOutImageProgram = initProgram (theGlContext, aBasicVertShader, aDisplayShader);
1468       if (myOutImageProgram.IsNull())
1469       {
1470         return safeFailBack ("Failed to initialize output shader program", theGlContext);
1471       }
1472     }
1473   }
1474
1475   if (myRaytraceInitStatus == OpenGl_RT_NONE || aToRebuildShaders)
1476   {
1477     for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
1478     {
1479       Handle(OpenGl_ShaderProgram)& aShaderProgram =
1480         (anIndex == 0) ? myRaytraceProgram : myPostFSAAProgram;
1481
1482       theGlContext->BindProgram (aShaderProgram);
1483
1484       aShaderProgram->SetSampler (theGlContext,
1485         "uSceneMinPointTexture", OpenGl_RT_SceneMinPointTexture);
1486       aShaderProgram->SetSampler (theGlContext,
1487         "uSceneMaxPointTexture", OpenGl_RT_SceneMaxPointTexture);
1488       aShaderProgram->SetSampler (theGlContext,
1489         "uSceneNodeInfoTexture", OpenGl_RT_SceneNodeInfoTexture);
1490       aShaderProgram->SetSampler (theGlContext,
1491         "uGeometryVertexTexture", OpenGl_RT_GeometryVertexTexture);
1492       aShaderProgram->SetSampler (theGlContext,
1493         "uGeometryNormalTexture", OpenGl_RT_GeometryNormalTexture);
1494       aShaderProgram->SetSampler (theGlContext,
1495         "uGeometryTexCrdTexture", OpenGl_RT_GeometryTexCrdTexture);
1496       aShaderProgram->SetSampler (theGlContext,
1497         "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture);
1498       aShaderProgram->SetSampler (theGlContext, 
1499         "uSceneTransformTexture", OpenGl_RT_SceneTransformTexture);
1500       aShaderProgram->SetSampler (theGlContext,
1501         "uEnvironmentMapTexture", OpenGl_RT_EnvironmentMapTexture);
1502       aShaderProgram->SetSampler (theGlContext,
1503         "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
1504       aShaderProgram->SetSampler (theGlContext,
1505         "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
1506
1507       aShaderProgram->SetSampler (theGlContext,
1508         "uOpenGlColorTexture", OpenGl_RT_OpenGlColorTexture);
1509       aShaderProgram->SetSampler (theGlContext,
1510         "uOpenGlDepthTexture", OpenGl_RT_OpenGlDepthTexture);
1511
1512       if (anIndex == 1)
1513       {
1514         aShaderProgram->SetSampler (theGlContext,
1515           "uFSAAInputTexture", OpenGl_RT_FsaaInputTexture);
1516       }
1517       else
1518       {
1519         aShaderProgram->SetSampler (theGlContext,
1520           "uAccumTexture", OpenGl_RT_PrevAccumTexture);
1521       }
1522
1523       myUniformLocations[anIndex][OpenGl_RT_aPosition] =
1524         aShaderProgram->GetAttributeLocation (theGlContext, "occVertex");
1525
1526       myUniformLocations[anIndex][OpenGl_RT_uOriginLB] =
1527         aShaderProgram->GetUniformLocation (theGlContext, "uOriginLB");
1528       myUniformLocations[anIndex][OpenGl_RT_uOriginRB] =
1529         aShaderProgram->GetUniformLocation (theGlContext, "uOriginRB");
1530       myUniformLocations[anIndex][OpenGl_RT_uOriginLT] =
1531         aShaderProgram->GetUniformLocation (theGlContext, "uOriginLT");
1532       myUniformLocations[anIndex][OpenGl_RT_uOriginRT] =
1533         aShaderProgram->GetUniformLocation (theGlContext, "uOriginRT");
1534       myUniformLocations[anIndex][OpenGl_RT_uDirectLB] =
1535         aShaderProgram->GetUniformLocation (theGlContext, "uDirectLB");
1536       myUniformLocations[anIndex][OpenGl_RT_uDirectRB] =
1537         aShaderProgram->GetUniformLocation (theGlContext, "uDirectRB");
1538       myUniformLocations[anIndex][OpenGl_RT_uDirectLT] =
1539         aShaderProgram->GetUniformLocation (theGlContext, "uDirectLT");
1540       myUniformLocations[anIndex][OpenGl_RT_uDirectRT] =
1541         aShaderProgram->GetUniformLocation (theGlContext, "uDirectRT");
1542       myUniformLocations[anIndex][OpenGl_RT_uViewMat] =
1543         aShaderProgram->GetUniformLocation (theGlContext, "uViewMat");
1544       myUniformLocations[anIndex][OpenGl_RT_uUnviewMat] =
1545         aShaderProgram->GetUniformLocation (theGlContext, "uUnviewMat");
1546
1547       myUniformLocations[anIndex][OpenGl_RT_uSceneRad] =
1548         aShaderProgram->GetUniformLocation (theGlContext, "uSceneRadius");
1549       myUniformLocations[anIndex][OpenGl_RT_uSceneEps] =
1550         aShaderProgram->GetUniformLocation (theGlContext, "uSceneEpsilon");
1551       myUniformLocations[anIndex][OpenGl_RT_uLightCount] =
1552         aShaderProgram->GetUniformLocation (theGlContext, "uLightCount");
1553       myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] =
1554         aShaderProgram->GetUniformLocation (theGlContext, "uGlobalAmbient");
1555
1556       myUniformLocations[anIndex][OpenGl_RT_uOffsetX] =
1557         aShaderProgram->GetUniformLocation (theGlContext, "uOffsetX");
1558       myUniformLocations[anIndex][OpenGl_RT_uOffsetY] =
1559         aShaderProgram->GetUniformLocation (theGlContext, "uOffsetY");
1560       myUniformLocations[anIndex][OpenGl_RT_uSamples] =
1561         aShaderProgram->GetUniformLocation (theGlContext, "uSamples");
1562
1563       myUniformLocations[anIndex][OpenGl_RT_uTexSamplersArray] =
1564         aShaderProgram->GetUniformLocation (theGlContext, "uTextureSamplers");
1565
1566       myUniformLocations[anIndex][OpenGl_RT_uShadowsEnabled] =
1567         aShaderProgram->GetUniformLocation (theGlContext, "uShadowsEnabled");
1568       myUniformLocations[anIndex][OpenGl_RT_uReflectEnabled] =
1569         aShaderProgram->GetUniformLocation (theGlContext, "uReflectEnabled");
1570       myUniformLocations[anIndex][OpenGl_RT_uSphereMapEnabled] =
1571         aShaderProgram->GetUniformLocation (theGlContext, "uSphereMapEnabled");
1572       myUniformLocations[anIndex][OpenGl_RT_uSphereMapForBack] =
1573         aShaderProgram->GetUniformLocation (theGlContext, "uSphereMapForBack");
1574       myUniformLocations[anIndex][OpenGl_RT_uBlockedRngEnabled] =
1575         aShaderProgram->GetUniformLocation (theGlContext, "uBlockedRngEnabled");
1576
1577       myUniformLocations[anIndex][OpenGl_RT_uSampleWeight] =
1578         aShaderProgram->GetUniformLocation (theGlContext, "uSampleWeight");
1579       myUniformLocations[anIndex][OpenGl_RT_uFrameRndSeed] =
1580         aShaderProgram->GetUniformLocation (theGlContext, "uFrameRndSeed");
1581
1582       myUniformLocations[anIndex][OpenGl_RT_uBackColorTop] =
1583         aShaderProgram->GetUniformLocation (theGlContext, "uBackColorTop");
1584       myUniformLocations[anIndex][OpenGl_RT_uBackColorBot] =
1585         aShaderProgram->GetUniformLocation (theGlContext, "uBackColorBot");
1586     }
1587
1588     theGlContext->BindProgram (myOutImageProgram);
1589
1590     myOutImageProgram->SetSampler (theGlContext,
1591       "uInputTexture", OpenGl_RT_PrevAccumTexture);
1592
1593     myOutImageProgram->SetSampler (theGlContext,
1594       "uDepthTexture", OpenGl_RT_DepthTexture);
1595
1596     theGlContext->BindProgram (NULL);
1597   }
1598
1599   if (myRaytraceInitStatus != OpenGl_RT_NONE)
1600   {
1601     return myRaytraceInitStatus == OpenGl_RT_INIT;
1602   }
1603
1604   const GLfloat aVertices[] = { -1.f, -1.f,  0.f,
1605                                 -1.f,  1.f,  0.f,
1606                                  1.f,  1.f,  0.f,
1607                                  1.f,  1.f,  0.f,
1608                                  1.f, -1.f,  0.f,
1609                                 -1.f, -1.f,  0.f };
1610
1611   myRaytraceScreenQuad.Init (theGlContext, 3, 6, aVertices);
1612
1613   myRaytraceInitStatus = OpenGl_RT_INIT; // initialized in normal way
1614
1615   return Standard_True;
1616 }
1617
1618 // =======================================================================
1619 // function : nullifyResource
1620 // purpose  :
1621 // =======================================================================
1622 template <class T>
1623 inline void nullifyResource (const Handle(OpenGl_Context)& theGlContext,
1624                              Handle(T)& theResource)
1625 {
1626   if (!theResource.IsNull())
1627   {
1628     theResource->Release (theGlContext.operator->());
1629     theResource.Nullify();
1630   }
1631 }
1632
1633 // =======================================================================
1634 // function : releaseRaytraceResources
1635 // purpose  : Releases OpenGL/GLSL shader programs
1636 // =======================================================================
1637 void OpenGl_View::releaseRaytraceResources (const Handle(OpenGl_Context)& theGlContext)
1638 {
1639   myRaytraceFBO1[0]->Release (theGlContext.operator->());
1640   myRaytraceFBO1[1]->Release (theGlContext.operator->());
1641   myRaytraceFBO2[0]->Release (theGlContext.operator->());
1642   myRaytraceFBO2[1]->Release (theGlContext.operator->());
1643
1644   nullifyResource (theGlContext, myRaytraceShader);
1645   nullifyResource (theGlContext, myPostFSAAShader);
1646
1647   nullifyResource (theGlContext, myRaytraceProgram);
1648   nullifyResource (theGlContext, myPostFSAAProgram);
1649   nullifyResource (theGlContext, myOutImageProgram);
1650
1651   nullifyResource (theGlContext, mySceneNodeInfoTexture);
1652   nullifyResource (theGlContext, mySceneMinPointTexture);
1653   nullifyResource (theGlContext, mySceneMaxPointTexture);
1654
1655   nullifyResource (theGlContext, myGeometryVertexTexture);
1656   nullifyResource (theGlContext, myGeometryNormalTexture);
1657   nullifyResource (theGlContext, myGeometryTexCrdTexture);
1658   nullifyResource (theGlContext, myGeometryTriangTexture);
1659   nullifyResource (theGlContext, mySceneTransformTexture);
1660
1661   nullifyResource (theGlContext, myRaytraceLightSrcTexture);
1662   nullifyResource (theGlContext, myRaytraceMaterialTexture);
1663
1664   myRaytraceGeometry.ReleaseResources (theGlContext);
1665
1666   if (myRaytraceScreenQuad.IsValid())
1667     myRaytraceScreenQuad.Release (theGlContext.operator->());
1668 }
1669
1670 // =======================================================================
1671 // function : updateRaytraceBuffers
1672 // purpose  : Updates auxiliary OpenGL frame buffers.
1673 // =======================================================================
1674 Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer        theSizeX,
1675                                                      const Standard_Integer        theSizeY,
1676                                                      const Handle(OpenGl_Context)& theGlContext)
1677 {
1678   // Auxiliary buffers are not used.
1679   if (!myRaytraceParameters.GlobalIllumination && !myRenderParams.IsAntialiasingEnabled)
1680   {
1681     myRaytraceFBO1[0]->Release (theGlContext.operator->());
1682     myRaytraceFBO2[0]->Release (theGlContext.operator->());
1683     myRaytraceFBO1[1]->Release (theGlContext.operator->());
1684     myRaytraceFBO2[1]->Release (theGlContext.operator->());
1685     return Standard_True;
1686   }
1687
1688   myRaytraceFBO1[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
1689   myRaytraceFBO2[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
1690
1691   // Init second set of buffers for stereographic rendering.
1692   if (myCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
1693   {
1694     myRaytraceFBO1[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
1695     myRaytraceFBO2[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
1696   }
1697   else
1698   {
1699     myRaytraceFBO1[1]->Release (theGlContext.operator->());
1700     myRaytraceFBO2[1]->Release (theGlContext.operator->());
1701   }
1702
1703   return Standard_True;
1704 }
1705
1706 // =======================================================================
1707 // function : updateCamera
1708 // purpose  : Generates viewing rays for corners of screen quad
1709 // =======================================================================
1710 void OpenGl_View::updateCamera (const OpenGl_Mat4& theOrientation,
1711                                 const OpenGl_Mat4& theViewMapping,
1712                                 OpenGl_Vec3*       theOrigins,
1713                                 OpenGl_Vec3*       theDirects,
1714                                 OpenGl_Mat4&       theView,
1715                                 OpenGl_Mat4&       theUnview)
1716 {
1717   // compute view-projection matrix
1718   theView = theViewMapping * theOrientation;
1719
1720   // compute inverse view-projection matrix
1721   theView.Inverted (theUnview);
1722
1723   Standard_Integer aOriginIndex = 0;
1724   Standard_Integer aDirectIndex = 0;
1725
1726   for (Standard_Integer aY = -1; aY <= 1; aY += 2)
1727   {
1728     for (Standard_Integer aX = -1; aX <= 1; aX += 2)
1729     {
1730       OpenGl_Vec4 aOrigin (GLfloat(aX),
1731                            GLfloat(aY),
1732                           -1.0f,
1733                            1.0f);
1734
1735       aOrigin = theUnview * aOrigin;
1736
1737       aOrigin.x() = aOrigin.x() / aOrigin.w();
1738       aOrigin.y() = aOrigin.y() / aOrigin.w();
1739       aOrigin.z() = aOrigin.z() / aOrigin.w();
1740
1741       OpenGl_Vec4 aDirect (GLfloat(aX),
1742                            GLfloat(aY),
1743                            1.0f,
1744                            1.0f);
1745
1746       aDirect = theUnview * aDirect;
1747
1748       aDirect.x() = aDirect.x() / aDirect.w();
1749       aDirect.y() = aDirect.y() / aDirect.w();
1750       aDirect.z() = aDirect.z() / aDirect.w();
1751
1752       aDirect = aDirect - aOrigin;
1753
1754       theOrigins[aOriginIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aOrigin.x()),
1755                                                 static_cast<GLfloat> (aOrigin.y()),
1756                                                 static_cast<GLfloat> (aOrigin.z()));
1757
1758       theDirects[aDirectIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aDirect.x()),
1759                                                 static_cast<GLfloat> (aDirect.y()),
1760                                                 static_cast<GLfloat> (aDirect.z()));
1761     }
1762   }
1763 }
1764
1765 // =======================================================================
1766 // function : uploadRaytraceData
1767 // purpose  : Uploads ray-trace data to the GPU
1768 // =======================================================================
1769 Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& theGlContext)
1770 {
1771   if (!theGlContext->IsGlGreaterEqual (3, 1))
1772   {
1773 #ifdef RAY_TRACE_PRINT_INFO
1774     std::cout << "Error: OpenGL version is less than 3.1" << std::endl;
1775 #endif
1776     return Standard_False;
1777   }
1778
1779   myAccumFrames = 0; // accumulation should be restarted
1780
1781   /////////////////////////////////////////////////////////////////////////////
1782   // Prepare OpenGL textures
1783
1784   if (theGlContext->arbTexBindless != NULL)
1785   {
1786     // If OpenGL driver supports bindless textures we need
1787     // to get unique 64- bit handles for using on the GPU
1788     if (!myRaytraceGeometry.UpdateTextureHandles (theGlContext))
1789     {
1790 #ifdef RAY_TRACE_PRINT_INFO
1791       std::cout << "Error: Failed to get OpenGL texture handles" << std::endl;
1792 #endif
1793       return Standard_False;
1794     }
1795   }
1796
1797   /////////////////////////////////////////////////////////////////////////////
1798   // Create OpenGL BVH buffers
1799
1800   if (mySceneNodeInfoTexture.IsNull())  // create scene BVH buffers
1801   {
1802     mySceneNodeInfoTexture  = new OpenGl_TextureBufferArb;
1803     mySceneMinPointTexture  = new OpenGl_TextureBufferArb;
1804     mySceneMaxPointTexture  = new OpenGl_TextureBufferArb;
1805     mySceneTransformTexture = new OpenGl_TextureBufferArb;
1806
1807     if (!mySceneNodeInfoTexture->Create  (theGlContext)
1808      || !mySceneMinPointTexture->Create  (theGlContext)
1809      || !mySceneMaxPointTexture->Create  (theGlContext)
1810      || !mySceneTransformTexture->Create (theGlContext))
1811     {
1812 #ifdef RAY_TRACE_PRINT_INFO
1813       std::cout << "Error: Failed to create scene BVH buffers" << std::endl;
1814 #endif
1815       return Standard_False;
1816     }
1817   }
1818
1819   if  (myGeometryVertexTexture.IsNull())  // create geometry buffers
1820   {
1821     myGeometryVertexTexture = new OpenGl_TextureBufferArb;
1822     myGeometryNormalTexture = new OpenGl_TextureBufferArb;
1823     myGeometryTexCrdTexture = new OpenGl_TextureBufferArb;
1824     myGeometryTriangTexture = new OpenGl_TextureBufferArb;
1825
1826     if (!myGeometryVertexTexture->Create (theGlContext)
1827      || !myGeometryNormalTexture->Create (theGlContext)
1828      || !myGeometryTexCrdTexture->Create (theGlContext)
1829      || !myGeometryTriangTexture->Create (theGlContext))
1830     {
1831 #ifdef RAY_TRACE_PRINT_INFO
1832       std::cout << "Error: Failed to create buffers for triangulation data" << std::endl;
1833 #endif
1834       return Standard_False;
1835     }
1836   }
1837
1838   if (myRaytraceMaterialTexture.IsNull()) // create material buffer
1839   {
1840     myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
1841
1842     if (!myRaytraceMaterialTexture->Create (theGlContext))
1843     {
1844 #ifdef RAY_TRACE_PRINT_INFO
1845       std::cout << "Error: Failed to create buffers for material data" << std::endl;
1846 #endif
1847       return Standard_False;
1848     }
1849   }
1850   
1851   /////////////////////////////////////////////////////////////////////////////
1852   // Write transform buffer
1853
1854   BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()];
1855
1856   bool aResult = true;
1857
1858   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
1859   {
1860     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
1861       myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
1862
1863     const BVH_Transform<Standard_ShortReal, 4>* aTransform = 
1864       dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (aTriangleSet->Properties().operator->());
1865
1866     Standard_ASSERT_RETURN (aTransform != NULL,
1867       "OpenGl_TriangleSet does not contain transform", Standard_False);
1868
1869     aNodeTransforms[anElemIndex] = aTransform->Inversed();
1870   }
1871
1872   aResult &= mySceneTransformTexture->Init (theGlContext, 4,
1873     myRaytraceGeometry.Size() * 4, reinterpret_cast<const GLfloat*> (aNodeTransforms));
1874
1875   delete [] aNodeTransforms;
1876
1877   /////////////////////////////////////////////////////////////////////////////
1878   // Write geometry and bottom-level BVH buffers
1879
1880   Standard_Size aTotalVerticesNb = 0;
1881   Standard_Size aTotalElementsNb = 0;
1882   Standard_Size aTotalBVHNodesNb = 0;
1883
1884   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
1885   {
1886     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
1887       myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
1888
1889     Standard_ASSERT_RETURN (aTriangleSet != NULL,
1890       "Error: Failed to get triangulation of OpenGL element", Standard_False);
1891
1892     aTotalVerticesNb += aTriangleSet->Vertices.size();
1893     aTotalElementsNb += aTriangleSet->Elements.size();
1894
1895     Standard_ASSERT_RETURN (!aTriangleSet->QuadBVH().IsNull(),
1896       "Error: Failed to get bottom-level BVH of OpenGL element", Standard_False);
1897
1898     aTotalBVHNodesNb += aTriangleSet->QuadBVH()->NodeInfoBuffer().size();
1899   }
1900
1901   aTotalBVHNodesNb += myRaytraceGeometry.QuadBVH()->NodeInfoBuffer().size();
1902
1903   if (aTotalBVHNodesNb != 0)
1904   {
1905     aResult &= mySceneNodeInfoTexture->Init (
1906       theGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*>  (NULL));
1907     aResult &= mySceneMinPointTexture->Init (
1908       theGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
1909     aResult &= mySceneMaxPointTexture->Init (
1910       theGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
1911   }
1912
1913   if (!aResult)
1914   {
1915 #ifdef RAY_TRACE_PRINT_INFO
1916     std::cout << "Error: Failed to upload buffers for bottom-level scene BVH" << std::endl;
1917 #endif
1918     return Standard_False;
1919   }
1920
1921   if (aTotalElementsNb != 0)
1922   {
1923     aResult &= myGeometryTriangTexture->Init (
1924       theGlContext, 4, GLsizei (aTotalElementsNb), static_cast<const GLuint*> (NULL));
1925   }
1926
1927   if (aTotalVerticesNb != 0)
1928   {
1929     aResult &= myGeometryVertexTexture->Init (
1930       theGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
1931     aResult &= myGeometryNormalTexture->Init (
1932       theGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
1933     aResult &= myGeometryTexCrdTexture->Init (
1934       theGlContext, 2, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
1935   }
1936
1937   if (!aResult)
1938   {
1939 #ifdef RAY_TRACE_PRINT_INFO
1940     std::cout << "Error: Failed to upload buffers for scene geometry" << std::endl;
1941 #endif
1942     return Standard_False;
1943   }
1944
1945   const QuadBvhHandle& aBVH = myRaytraceGeometry.QuadBVH();
1946
1947   if (aBVH->Length() > 0)
1948   {
1949     aResult &= mySceneNodeInfoTexture->SubData (theGlContext, 0, aBVH->Length(),
1950       reinterpret_cast<const GLuint*> (&aBVH->NodeInfoBuffer().front()));
1951     aResult &= mySceneMinPointTexture->SubData (theGlContext, 0, aBVH->Length(),
1952       reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
1953     aResult &= mySceneMaxPointTexture->SubData (theGlContext, 0, aBVH->Length(),
1954       reinterpret_cast<const GLfloat*> (&aBVH->MaxPointBuffer().front()));
1955   }
1956
1957   for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
1958   {
1959     if (!aBVH->IsOuter (aNodeIdx))
1960       continue;
1961
1962     OpenGl_TriangleSet* aTriangleSet = myRaytraceGeometry.TriangleSet (aNodeIdx);
1963
1964     Standard_ASSERT_RETURN (aTriangleSet != NULL,
1965       "Error: Failed to get triangulation of OpenGL element", Standard_False);
1966
1967     Standard_Integer aBVHOffset = myRaytraceGeometry.AccelerationOffset (aNodeIdx);
1968
1969     Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
1970       "Error: Failed to get offset for bottom-level BVH", Standard_False);
1971
1972     const Standard_Integer aBvhBuffersSize = aTriangleSet->QuadBVH()->Length();
1973
1974     if (aBvhBuffersSize != 0)
1975     {
1976       aResult &= mySceneNodeInfoTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
1977         reinterpret_cast<const GLuint*> (&aTriangleSet->QuadBVH()->NodeInfoBuffer().front()));
1978       aResult &= mySceneMinPointTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
1979         reinterpret_cast<const GLfloat*> (&aTriangleSet->QuadBVH()->MinPointBuffer().front()));
1980       aResult &= mySceneMaxPointTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
1981         reinterpret_cast<const GLfloat*> (&aTriangleSet->QuadBVH()->MaxPointBuffer().front()));
1982
1983       if (!aResult)
1984       {
1985 #ifdef RAY_TRACE_PRINT_INFO
1986         std::cout << "Error: Failed to upload buffers for bottom-level scene BVHs" << std::endl;
1987 #endif
1988         return Standard_False;
1989       }
1990     }
1991
1992     const Standard_Integer aVerticesOffset = myRaytraceGeometry.VerticesOffset (aNodeIdx);
1993
1994     Standard_ASSERT_RETURN (aVerticesOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
1995       "Error: Failed to get offset for triangulation vertices of OpenGL element", Standard_False);
1996
1997     if (!aTriangleSet->Vertices.empty())
1998     {
1999       aResult &= myGeometryNormalTexture->SubData (theGlContext, aVerticesOffset,
2000         GLsizei (aTriangleSet->Normals.size()), reinterpret_cast<const GLfloat*> (&aTriangleSet->Normals.front()));
2001       aResult &= myGeometryTexCrdTexture->SubData (theGlContext, aVerticesOffset,
2002         GLsizei (aTriangleSet->TexCrds.size()), reinterpret_cast<const GLfloat*> (&aTriangleSet->TexCrds.front()));
2003       aResult &= myGeometryVertexTexture->SubData (theGlContext, aVerticesOffset,
2004         GLsizei (aTriangleSet->Vertices.size()), reinterpret_cast<const GLfloat*> (&aTriangleSet->Vertices.front()));
2005     }
2006
2007     const Standard_Integer anElementsOffset = myRaytraceGeometry.ElementsOffset (aNodeIdx);
2008
2009     Standard_ASSERT_RETURN (anElementsOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
2010       "Error: Failed to get offset for triangulation elements of OpenGL element", Standard_False);
2011
2012     if (!aTriangleSet->Elements.empty())
2013     {
2014       aResult &= myGeometryTriangTexture->SubData (theGlContext, anElementsOffset, GLsizei (aTriangleSet->Elements.size()),
2015                                                    reinterpret_cast<const GLuint*> (&aTriangleSet->Elements.front()));
2016     }
2017
2018     if (!aResult)
2019     {
2020 #ifdef RAY_TRACE_PRINT_INFO
2021       std::cout << "Error: Failed to upload triangulation buffers for OpenGL element" << std::endl;
2022 #endif
2023       return Standard_False;
2024     }
2025   }
2026
2027   /////////////////////////////////////////////////////////////////////////////
2028   // Write material buffer
2029
2030   if (myRaytraceGeometry.Materials.size() != 0)
2031   {
2032     aResult &= myRaytraceMaterialTexture->Init (theGlContext, 4,
2033       GLsizei (myRaytraceGeometry.Materials.size() * 18), myRaytraceGeometry.Materials.front().Packed());
2034
2035     if (!aResult)
2036     {
2037 #ifdef RAY_TRACE_PRINT_INFO
2038       std::cout << "Error: Failed to upload material buffer" << std::endl;
2039 #endif
2040       return Standard_False;
2041     }
2042   }
2043
2044   myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0;
2045
2046 #ifdef RAY_TRACE_PRINT_INFO
2047
2048   Standard_ShortReal aMemTrgUsed = 0.f;
2049   Standard_ShortReal aMemBvhUsed = 0.f;
2050
2051   for (Standard_Integer anElemIdx = 0; anElemIdx < myRaytraceGeometry.Size(); ++anElemIdx)
2052   {
2053     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (myRaytraceGeometry.Objects()(anElemIdx).get());
2054
2055     aMemTrgUsed += static_cast<Standard_ShortReal> (
2056       aTriangleSet->Vertices.size() * sizeof (BVH_Vec3f));
2057     aMemTrgUsed += static_cast<Standard_ShortReal> (
2058       aTriangleSet->Normals.size() * sizeof (BVH_Vec3f));
2059     aMemTrgUsed += static_cast<Standard_ShortReal> (
2060       aTriangleSet->TexCrds.size() * sizeof (BVH_Vec2f));
2061     aMemTrgUsed += static_cast<Standard_ShortReal> (
2062       aTriangleSet->Elements.size() * sizeof (BVH_Vec4i));
2063
2064     aMemBvhUsed += static_cast<Standard_ShortReal> (
2065       aTriangleSet->QuadBVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
2066     aMemBvhUsed += static_cast<Standard_ShortReal> (
2067       aTriangleSet->QuadBVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
2068     aMemBvhUsed += static_cast<Standard_ShortReal> (
2069       aTriangleSet->QuadBVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
2070   }
2071
2072   aMemBvhUsed += static_cast<Standard_ShortReal> (
2073     myRaytraceGeometry.QuadBVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
2074   aMemBvhUsed += static_cast<Standard_ShortReal> (
2075     myRaytraceGeometry.QuadBVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
2076   aMemBvhUsed += static_cast<Standard_ShortReal> (
2077     myRaytraceGeometry.QuadBVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
2078
2079   std::cout << "GPU Memory Used (Mb):\n"
2080     << "\tFor mesh: " << aMemTrgUsed / 1048576 << "\n"
2081     << "\tFor BVHs: " << aMemBvhUsed / 1048576 << "\n";
2082
2083 #endif
2084
2085   return aResult;
2086 }
2087
2088 // =======================================================================
2089 // function : updateRaytraceLightSources
2090 // purpose  : Updates 3D scene light sources for ray-tracing
2091 // =======================================================================
2092 Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& theInvModelView, const Handle(OpenGl_Context)& theGlContext)
2093 {
2094   myRaytraceGeometry.Sources.clear();
2095
2096   myRaytraceGeometry.Ambient = BVH_Vec4f (0.0f, 0.0f, 0.0f, 0.0f);
2097
2098   OpenGl_ListOfLight::Iterator aLightIter (myShadingModel == Graphic3d_TOSM_NONE ? myNoShadingLight : myLights);
2099   for (; aLightIter.More(); aLightIter.Next())
2100   {
2101     const OpenGl_Light& aLight = aLightIter.Value();
2102
2103     if (aLight.Type == Graphic3d_TOLS_AMBIENT)
2104     {
2105       myRaytraceGeometry.Ambient += BVH_Vec4f (aLight.Color.r() * aLight.Intensity,
2106                                                aLight.Color.g() * aLight.Intensity,
2107                                                aLight.Color.b() * aLight.Intensity,
2108                                                0.0f);
2109       continue;
2110     }
2111
2112     BVH_Vec4f aDiffuse  (aLight.Color.r() * aLight.Intensity,
2113                          aLight.Color.g() * aLight.Intensity,
2114                          aLight.Color.b() * aLight.Intensity,
2115                          1.0f);
2116
2117     BVH_Vec4f aPosition (-aLight.Direction.x(),
2118                          -aLight.Direction.y(),
2119                          -aLight.Direction.z(),
2120                          0.0f);
2121
2122     if (aLight.Type != Graphic3d_TOLS_DIRECTIONAL)
2123     {
2124       aPosition = BVH_Vec4f (aLight.Position.x(),
2125                              aLight.Position.y(),
2126                              aLight.Position.z(),
2127                              1.0f);
2128
2129       // store smoothing radius in w-component
2130       aDiffuse.w() = Max (aLight.Smoothness, 0.f);
2131     }
2132     else
2133     {
2134       // store cosine of smoothing angle in w-component
2135       aDiffuse.w() = cosf (Min (Max (aLight.Smoothness, 0.f), static_cast<Standard_ShortReal> (M_PI / 2.0)));
2136     }
2137
2138     if (aLight.IsHeadlight)
2139     {
2140       aPosition = theInvModelView * aPosition;
2141     }
2142
2143     myRaytraceGeometry.Sources.push_back (OpenGl_RaytraceLight (aDiffuse, aPosition));
2144   }
2145
2146   if (myRaytraceLightSrcTexture.IsNull())  // create light source buffer
2147   {
2148     myRaytraceLightSrcTexture = new OpenGl_TextureBufferArb;
2149
2150     if (!myRaytraceLightSrcTexture->Create (theGlContext))
2151     {
2152 #ifdef RAY_TRACE_PRINT_INFO
2153       std::cout << "Error: Failed to create light source buffer" << std::endl;
2154 #endif
2155       return Standard_False;
2156     }
2157   }
2158
2159   if (myRaytraceGeometry.Sources.size() != 0)
2160   {
2161     const GLfloat* aDataPtr = myRaytraceGeometry.Sources.front().Packed();
2162     if (!myRaytraceLightSrcTexture->Init (theGlContext, 4, GLsizei (myRaytraceGeometry.Sources.size() * 2), aDataPtr))
2163     {
2164 #ifdef RAY_TRACE_PRINT_INFO
2165       std::cout << "Error: Failed to upload light source buffer" << std::endl;
2166 #endif
2167       return Standard_False;
2168     }
2169   }
2170
2171   return Standard_True;
2172 }
2173
2174 // =======================================================================
2175 // function : updateRaytraceEnvironmentMap
2176 // purpose  : Updates environment map for ray-tracing
2177 // =======================================================================
2178 Standard_Boolean OpenGl_View::updateRaytraceEnvironmentMap (const Handle(OpenGl_Context)& theGlContext)
2179 {
2180   Standard_Boolean aResult = Standard_True;
2181
2182   if (!myToUpdateEnvironmentMap)
2183   {
2184     return aResult;
2185   }
2186
2187   for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx)
2188   {
2189     const Handle(OpenGl_ShaderProgram)& aProgram =
2190       anIdx == 0 ? myRaytraceProgram : myPostFSAAProgram;
2191
2192     if (!aProgram.IsNull())
2193     {
2194       aResult &= theGlContext->BindProgram (aProgram);
2195
2196       if (!myTextureEnv.IsNull())
2197       {
2198         myTextureEnv->Bind (theGlContext,
2199           GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
2200
2201         aResult &= aProgram->SetUniform (theGlContext,
2202           myUniformLocations[anIdx][OpenGl_RT_uSphereMapEnabled], 1);
2203       }
2204       else
2205       {
2206         aResult &= aProgram->SetUniform (theGlContext,
2207           myUniformLocations[anIdx][OpenGl_RT_uSphereMapEnabled], 0);
2208       }
2209     }
2210   }
2211
2212   myToUpdateEnvironmentMap = Standard_False;
2213
2214   theGlContext->BindProgram (NULL);
2215
2216   return aResult;
2217 }
2218
2219 // =======================================================================
2220 // function : setUniformState
2221 // purpose  : Sets uniform state for the given ray-tracing shader program
2222 // =======================================================================
2223 Standard_Boolean OpenGl_View::setUniformState (const OpenGl_Vec3*            theOrigins,
2224                                                const OpenGl_Vec3*            theDirects,
2225                                                const OpenGl_Mat4&            theViewMat,
2226                                                const OpenGl_Mat4&            theUnviewMat,
2227                                                const Standard_Integer        theProgramId,
2228                                                const Handle(OpenGl_Context)& theGlContext)
2229 {
2230   Handle(OpenGl_ShaderProgram)& theProgram =
2231     theProgramId == 0 ? myRaytraceProgram : myPostFSAAProgram;
2232
2233   if (theProgram.IsNull())
2234   {
2235     return Standard_False;
2236   }
2237
2238   const Standard_Integer aLightSourceBufferSize =
2239     static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
2240
2241   // Set camera state
2242   theProgram->SetUniform (theGlContext,
2243     myUniformLocations[theProgramId][OpenGl_RT_uOriginLB], theOrigins[0]);
2244   theProgram->SetUniform (theGlContext,
2245     myUniformLocations[theProgramId][OpenGl_RT_uOriginRB], theOrigins[1]);
2246   theProgram->SetUniform (theGlContext,
2247     myUniformLocations[theProgramId][OpenGl_RT_uOriginLT], theOrigins[2]);
2248   theProgram->SetUniform (theGlContext,
2249     myUniformLocations[theProgramId][OpenGl_RT_uOriginRT], theOrigins[3]);
2250   theProgram->SetUniform (theGlContext,
2251     myUniformLocations[theProgramId][OpenGl_RT_uDirectLB], theDirects[0]);
2252   theProgram->SetUniform (theGlContext,
2253     myUniformLocations[theProgramId][OpenGl_RT_uDirectRB], theDirects[1]);
2254   theProgram->SetUniform (theGlContext,
2255     myUniformLocations[theProgramId][OpenGl_RT_uDirectLT], theDirects[2]);
2256   theProgram->SetUniform (theGlContext,
2257     myUniformLocations[theProgramId][OpenGl_RT_uDirectRT], theDirects[3]);
2258   theProgram->SetUniform (theGlContext,
2259     myUniformLocations[theProgramId][OpenGl_RT_uViewMat], theViewMat);
2260   theProgram->SetUniform (theGlContext,
2261     myUniformLocations[theProgramId][OpenGl_RT_uUnviewMat], theUnviewMat);
2262
2263   // Set scene parameters
2264   theProgram->SetUniform (theGlContext,
2265     myUniformLocations[theProgramId][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
2266   theProgram->SetUniform (theGlContext,
2267     myUniformLocations[theProgramId][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
2268   theProgram->SetUniform (theGlContext,
2269     myUniformLocations[theProgramId][OpenGl_RT_uLightCount], aLightSourceBufferSize);
2270   theProgram->SetUniform (theGlContext,
2271     myUniformLocations[theProgramId][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
2272
2273   // Set run-time rendering options
2274   theProgram->SetUniform (theGlContext,
2275     myUniformLocations[theProgramId][OpenGl_RT_uShadowsEnabled], myRenderParams.IsShadowEnabled ?  1 : 0);
2276   theProgram->SetUniform (theGlContext,
2277     myUniformLocations[theProgramId][OpenGl_RT_uReflectEnabled], myRenderParams.IsReflectionEnabled ?  1 : 0);
2278
2279   if (myRenderParams.IsGlobalIlluminationEnabled)
2280   {
2281     theProgram->SetUniform (theGlContext,
2282       myUniformLocations[theProgramId][OpenGl_RT_uBlockedRngEnabled], myRenderParams.CoherentPathTracingMode ?  1 : 0);
2283   }
2284
2285   // Set array of 64-bit texture handles
2286   if (theGlContext->arbTexBindless != NULL && myRaytraceGeometry.HasTextures())
2287   {
2288     const std::vector<GLuint64>& aTextures = myRaytraceGeometry.TextureHandles();
2289
2290     theProgram->SetUniform (theGlContext, myUniformLocations[theProgramId][OpenGl_RT_uTexSamplersArray],
2291       static_cast<GLsizei> (aTextures.size()), (OpenGl_Vec2u* )&aTextures.front());
2292   }
2293
2294   // Set background colors (only gradient background supported)
2295   if (myBgGradientArray != NULL
2296    && myBgGradientArray->IsDefined())
2297   {
2298     theProgram->SetUniform (theGlContext,
2299       myUniformLocations[theProgramId][OpenGl_RT_uBackColorTop], myBgGradientArray->GradientColor (0));
2300     theProgram->SetUniform (theGlContext,
2301       myUniformLocations[theProgramId][OpenGl_RT_uBackColorBot], myBgGradientArray->GradientColor (1));
2302   }
2303   else
2304   {
2305     const OpenGl_Vec4& aBackColor = myBgColor;
2306     theProgram->SetUniform (theGlContext,
2307       myUniformLocations[theProgramId][OpenGl_RT_uBackColorTop], aBackColor);
2308     theProgram->SetUniform (theGlContext,
2309       myUniformLocations[theProgramId][OpenGl_RT_uBackColorBot], aBackColor);
2310   }
2311
2312   theProgram->SetUniform (theGlContext,
2313     myUniformLocations[theProgramId][OpenGl_RT_uSphereMapForBack], myRenderParams.UseEnvironmentMapBackground ?  1 : 0);
2314
2315   return Standard_True;
2316 }
2317
2318 // =======================================================================
2319 // function : bindRaytraceTextures
2320 // purpose  : Binds ray-trace textures to corresponding texture units
2321 // =======================================================================
2322 void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlContext)
2323 {
2324   mySceneMinPointTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
2325   mySceneMaxPointTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
2326   mySceneNodeInfoTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
2327   myGeometryVertexTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
2328   myGeometryNormalTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
2329   myGeometryTexCrdTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
2330   myGeometryTriangTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
2331   mySceneTransformTexture->BindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
2332   myRaytraceMaterialTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
2333   myRaytraceLightSrcTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
2334
2335   if (!myOpenGlFBO.IsNull())
2336   {
2337     myOpenGlFBO->ColorTexture()->Bind        (theGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
2338     myOpenGlFBO->DepthStencilTexture()->Bind (theGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
2339   }
2340 }
2341
2342 // =======================================================================
2343 // function : unbindRaytraceTextures
2344 // purpose  : Unbinds ray-trace textures from corresponding texture units
2345 // =======================================================================
2346 void OpenGl_View::unbindRaytraceTextures (const Handle(OpenGl_Context)& theGlContext)
2347 {
2348   mySceneMinPointTexture->UnbindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
2349   mySceneMaxPointTexture->UnbindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
2350   mySceneNodeInfoTexture->UnbindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
2351   myGeometryVertexTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
2352   myGeometryNormalTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
2353   myGeometryTexCrdTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
2354   myGeometryTriangTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
2355   mySceneTransformTexture->UnbindTexture   (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
2356   myRaytraceMaterialTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
2357   myRaytraceLightSrcTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
2358
2359   if (!myOpenGlFBO.IsNull())
2360   {
2361     myOpenGlFBO->ColorTexture()->Unbind        (theGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
2362     myOpenGlFBO->DepthStencilTexture()->Unbind (theGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
2363   }
2364
2365   theGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
2366 }
2367
2368 // =======================================================================
2369 // function : runRaytraceShaders
2370 // purpose  : Runs ray-tracing shader programs
2371 // =======================================================================
2372 Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer        theSizeX,
2373                                                   const Standard_Integer        theSizeY,
2374                                                   const OpenGl_Vec3*            theOrigins,
2375                                                   const OpenGl_Vec3*            theDirects,
2376                                                   const OpenGl_Mat4&            theViewMat,
2377                                                   const OpenGl_Mat4&            theUnviewMat,
2378                                                   Graphic3d_Camera::Projection  theProjection,
2379                                                   OpenGl_FrameBuffer*           theReadDrawFbo,
2380                                                   const Handle(OpenGl_Context)& theGlContext)
2381 {
2382   bindRaytraceTextures (theGlContext);
2383
2384   Handle(OpenGl_FrameBuffer) aRenderFramebuffer;
2385   Handle(OpenGl_FrameBuffer) aDepthSourceFramebuffer;
2386   Handle(OpenGl_FrameBuffer) anAccumFramebuffer;
2387
2388   // Choose proper set of framebuffers for stereo rendering
2389   Standard_Boolean isStereo   = myCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo;
2390   Standard_Boolean isRightEye = theProjection              == Graphic3d_Camera::Projection_MonoRightEye;
2391   Standard_Integer aFBOIdx    = (isStereo && isRightEye) ? 1 : 0;
2392
2393   if (myRaytraceParameters.GlobalIllumination) // if path-tracing is used
2394   {
2395     aRenderFramebuffer = myAccumFrames % 2 ? myRaytraceFBO1[aFBOIdx] : myRaytraceFBO2[aFBOIdx];
2396     anAccumFramebuffer = myAccumFrames % 2 ? myRaytraceFBO2[aFBOIdx] : myRaytraceFBO1[aFBOIdx];
2397     aDepthSourceFramebuffer = aRenderFramebuffer;
2398
2399     anAccumFramebuffer->ColorTexture()->Bind (
2400       theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
2401
2402     aRenderFramebuffer->BindBuffer (theGlContext);
2403   }
2404   else if (myRenderParams.IsAntialiasingEnabled) // if 2-pass ray-tracing is used
2405   {
2406     myRaytraceFBO1[aFBOIdx]->BindBuffer (theGlContext);
2407   }
2408
2409   Standard_Boolean aResult = theGlContext->BindProgram (myRaytraceProgram);
2410
2411   aResult &= setUniformState (theOrigins,
2412                               theDirects,
2413                               theViewMat,
2414                               theUnviewMat,
2415                               0, // ID of RT program
2416                               theGlContext);
2417
2418   if (myRaytraceParameters.GlobalIllumination)
2419   {
2420     if (myAccumFrames == 0)
2421     {
2422       myRNG.SetSeed();
2423     }
2424
2425     // Set frame accumulation weight
2426     myRaytraceProgram->SetUniform (theGlContext,
2427       myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
2428
2429     // Set random number generator seed
2430     myRaytraceProgram->SetUniform (theGlContext,
2431       myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
2432   }
2433
2434   theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
2435
2436   if (myRenderParams.IsAntialiasingEnabled && !myRenderParams.IsGlobalIlluminationEnabled)
2437   {
2438     glDepthMask (GL_FALSE);
2439
2440     myRaytraceFBO1[aFBOIdx]->ColorTexture()->Bind (theGlContext, GL_TEXTURE0 + OpenGl_RT_FsaaInputTexture);
2441
2442     aResult &= theGlContext->BindProgram (myPostFSAAProgram);
2443
2444     aResult &= setUniformState (theOrigins,
2445                                 theDirects,
2446                                 theViewMat,
2447                                 theUnviewMat,
2448                                 1, // ID of FSAA program
2449                                 theGlContext);
2450
2451     // Perform multi-pass adaptive FSAA using ping-pong technique.
2452     // We use 'FLIPTRI' sampling pattern changing for every pixel
2453     // (3 additional samples per pixel, the 1st sample is already
2454     // available from initial ray-traced image).
2455     for (Standard_Integer anIt = 1; anIt < 4; ++anIt)
2456     {
2457       GLfloat aOffsetX = 1.f / theSizeX;
2458       GLfloat aOffsetY = 1.f / theSizeY;
2459
2460       if (anIt == 1)
2461       {
2462         aOffsetX *= -0.55f;
2463         aOffsetY *=  0.55f;
2464       }
2465       else if (anIt == 2)
2466       {
2467         aOffsetX *=  0.00f;
2468         aOffsetY *= -0.55f;
2469       }
2470       else if (anIt == 3)
2471       {
2472         aOffsetX *= 0.55f;
2473         aOffsetY *= 0.00f;
2474       }
2475
2476       aResult &= myPostFSAAProgram->SetUniform (theGlContext,
2477         myUniformLocations[1][OpenGl_RT_uSamples], anIt + 1);
2478       aResult &= myPostFSAAProgram->SetUniform (theGlContext,
2479         myUniformLocations[1][OpenGl_RT_uOffsetX], aOffsetX);
2480       aResult &= myPostFSAAProgram->SetUniform (theGlContext,
2481         myUniformLocations[1][OpenGl_RT_uOffsetY], aOffsetY);
2482
2483       Handle(OpenGl_FrameBuffer)& aFramebuffer = anIt % 2 ? myRaytraceFBO2[aFBOIdx] : myRaytraceFBO1[aFBOIdx];
2484
2485       aFramebuffer->BindBuffer (theGlContext);
2486
2487       theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
2488
2489       aFramebuffer->ColorTexture()->Bind (theGlContext, GL_TEXTURE0 + OpenGl_RT_FsaaInputTexture);
2490     }
2491
2492     aRenderFramebuffer = myRaytraceFBO2[aFBOIdx];
2493     aDepthSourceFramebuffer = myRaytraceFBO1[aFBOIdx];
2494   }
2495
2496   if (myRaytraceParameters.GlobalIllumination || myRenderParams.IsAntialiasingEnabled)
2497   {
2498     // Output accumulated image
2499     glDepthMask (GL_TRUE);
2500
2501     theGlContext->BindProgram (myOutImageProgram);
2502
2503     myOutImageProgram->SetUniform (theGlContext, "uApplyGamma", static_cast<Standard_Integer> (myRaytraceParameters.GlobalIllumination));
2504
2505     if (theReadDrawFbo != NULL)
2506     {
2507       theReadDrawFbo->BindBuffer (theGlContext);
2508     }
2509     else
2510     {
2511       aRenderFramebuffer->UnbindBuffer (theGlContext);
2512     }
2513
2514     aRenderFramebuffer->ColorTexture()->Bind (
2515       theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
2516
2517     aDepthSourceFramebuffer->DepthStencilTexture()->Bind (
2518       theGlContext, GL_TEXTURE0 + OpenGl_RT_DepthTexture);
2519
2520     theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
2521
2522     aDepthSourceFramebuffer->DepthStencilTexture()->Unbind (
2523       theGlContext, GL_TEXTURE0 + OpenGl_RT_DepthTexture);
2524
2525     aRenderFramebuffer->ColorTexture()->Unbind (
2526       theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
2527   }
2528
2529   unbindRaytraceTextures (theGlContext);
2530
2531   theGlContext->BindProgram (NULL);
2532
2533   return aResult;
2534 }
2535
2536 // =======================================================================
2537 // function : raytrace
2538 // purpose  : Redraws the window using OpenGL/GLSL ray-tracing
2539 // =======================================================================
2540 Standard_Boolean OpenGl_View::raytrace (const Standard_Integer        theSizeX,
2541                                         const Standard_Integer        theSizeY,
2542                                         Graphic3d_Camera::Projection  theProjection,
2543                                         OpenGl_FrameBuffer*           theReadDrawFbo,
2544                                         const Handle(OpenGl_Context)& theGlContext)
2545 {
2546   if (!initRaytraceResources (theGlContext))
2547   {
2548     return Standard_False;
2549   }
2550
2551   if (!updateRaytraceBuffers (theSizeX, theSizeY, theGlContext))
2552   {
2553     return Standard_False;
2554   }
2555
2556   if (!updateRaytraceEnvironmentMap (theGlContext))
2557   {
2558     return Standard_False;
2559   }
2560
2561   // Get model-view and projection matrices
2562   OpenGl_Mat4 aOrientationMatrix = myCamera->OrientationMatrixF();
2563   OpenGl_Mat4 aViewMappingMatrix = theGlContext->ProjectionState.Current();
2564
2565   OpenGl_Mat4 aInverOrientMatrix;
2566   aOrientationMatrix.Inverted (aInverOrientMatrix);
2567   if (!updateRaytraceLightSources (aInverOrientMatrix, theGlContext))
2568   {
2569     return Standard_False;
2570   }
2571
2572   OpenGl_Vec3 aOrigins[4];
2573   OpenGl_Vec3 aDirects[4];
2574   OpenGl_Mat4 aViewMat;
2575   OpenGl_Mat4 anUnviewMat;
2576
2577   updateCamera (aOrientationMatrix,
2578                 aViewMappingMatrix,
2579                 aOrigins,
2580                 aDirects,
2581                 aViewMat,
2582                 anUnviewMat);
2583
2584   if (theReadDrawFbo != NULL)
2585   {
2586     theReadDrawFbo->BindBuffer (theGlContext);
2587   }
2588
2589   // Generate ray-traced image
2590   if (myIsRaytraceDataValid)
2591   {
2592     myRaytraceScreenQuad.BindVertexAttrib (theGlContext, Graphic3d_TOA_POS);
2593
2594     if (!myRaytraceGeometry.AcquireTextures (theGlContext))
2595     {
2596       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR,
2597         0, GL_DEBUG_SEVERITY_MEDIUM, "Error: Failed to acquire OpenGL image textures");
2598     }
2599
2600     // Remember the old depth function and mask
2601     GLint aDepthFunc;
2602     theGlContext->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aDepthFunc);
2603
2604     GLboolean aDepthMask;
2605     theGlContext->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aDepthMask);
2606
2607     glDisable (GL_BLEND);
2608     glDepthFunc (GL_ALWAYS);
2609
2610     Standard_Boolean aResult = runRaytraceShaders (theSizeX,
2611                                                    theSizeY,
2612                                                    aOrigins,
2613                                                    aDirects,
2614                                                    aViewMat,
2615                                                    anUnviewMat,
2616                                                    theProjection,
2617                                                    theReadDrawFbo,
2618                                                    theGlContext);
2619
2620     // Restore depth function and mask
2621     glDepthFunc (aDepthFunc);
2622     glDepthMask (aDepthMask);
2623
2624     if (!aResult)
2625     {
2626       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR,
2627         0, GL_DEBUG_SEVERITY_MEDIUM, "Error: Failed to execute ray-tracing shaders");
2628     }
2629
2630     if (!myRaytraceGeometry.ReleaseTextures (theGlContext))
2631     {
2632       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR,
2633         0, GL_DEBUG_SEVERITY_MEDIUM, "Error: Failed to release OpenGL image textures");
2634     }
2635
2636     myRaytraceScreenQuad.UnbindVertexAttrib (theGlContext, Graphic3d_TOA_POS);
2637   }
2638
2639   return Standard_True;
2640 }