0029570: Visualization, Graphic3d_Aspect - merge Graphic3d_Group aspects
[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 <OpenGl_GlCore44.hxx>
22 #include <OSD_Protection.hxx>
23 #include <OSD_File.hxx>
24
25 #include "../Shaders/Shaders_RaytraceBase_vs.pxx"
26 #include "../Shaders/Shaders_RaytraceBase_fs.pxx"
27 #include "../Shaders/Shaders_PathtraceBase_fs.pxx"
28 #include "../Shaders/Shaders_RaytraceRender_fs.pxx"
29 #include "../Shaders/Shaders_RaytraceSmooth_fs.pxx"
30 #include "../Shaders/Shaders_Display_fs.pxx"
31
32 using namespace OpenGl_Raytrace;
33
34 //! Use this macro to output ray-tracing debug info
35 // #define RAY_TRACE_PRINT_INFO
36
37 #ifdef RAY_TRACE_PRINT_INFO
38   #include <OSD_Timer.hxx>
39 #endif
40
41 namespace
42 {
43   static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f);
44   static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
45 }
46
47 namespace
48 {
49   //! Defines OpenGL texture samplers.
50   static const Graphic3d_TextureUnit OpenGl_RT_EnvironmentMapTexture = Graphic3d_TextureUnit_0;
51
52   static const Graphic3d_TextureUnit OpenGl_RT_SceneNodeInfoTexture  = Graphic3d_TextureUnit_1;
53   static const Graphic3d_TextureUnit OpenGl_RT_SceneMinPointTexture  = Graphic3d_TextureUnit_2;
54   static const Graphic3d_TextureUnit OpenGl_RT_SceneMaxPointTexture  = Graphic3d_TextureUnit_3;
55   static const Graphic3d_TextureUnit OpenGl_RT_SceneTransformTexture = Graphic3d_TextureUnit_4;
56
57   static const Graphic3d_TextureUnit OpenGl_RT_GeometryVertexTexture = Graphic3d_TextureUnit_5;
58   static const Graphic3d_TextureUnit OpenGl_RT_GeometryNormalTexture = Graphic3d_TextureUnit_6;
59   static const Graphic3d_TextureUnit OpenGl_RT_GeometryTexCrdTexture = Graphic3d_TextureUnit_7;
60   static const Graphic3d_TextureUnit OpenGl_RT_GeometryTriangTexture = Graphic3d_TextureUnit_8;
61
62   static const Graphic3d_TextureUnit OpenGl_RT_RaytraceMaterialTexture = Graphic3d_TextureUnit_9;
63   static const Graphic3d_TextureUnit OpenGl_RT_RaytraceLightSrcTexture = Graphic3d_TextureUnit_10;
64
65   static const Graphic3d_TextureUnit OpenGl_RT_FsaaInputTexture = Graphic3d_TextureUnit_11;
66   static const Graphic3d_TextureUnit OpenGl_RT_PrevAccumTexture = Graphic3d_TextureUnit_12;
67
68   static const Graphic3d_TextureUnit OpenGl_RT_RaytraceDepthTexture = Graphic3d_TextureUnit_13;
69 }
70
71 // =======================================================================
72 // function : updateRaytraceGeometry
73 // purpose  : Updates 3D scene geometry for ray-tracing
74 // =======================================================================
75 Standard_Boolean OpenGl_View::updateRaytraceGeometry (const RaytraceUpdateMode      theMode,
76                                                       const Standard_Integer        theViewId,
77                                                       const Handle(OpenGl_Context)& theGlContext)
78 {
79   // In 'check' mode (OpenGl_GUM_CHECK) the scene geometry is analyzed for
80   // modifications. This is light-weight procedure performed on each frame
81   if (theMode == OpenGl_GUM_CHECK)
82   {
83     if (myRaytraceLayerListState != myZLayers.ModificationStateOfRaytracable())
84     {
85       return updateRaytraceGeometry (OpenGl_GUM_PREPARE, theViewId, theGlContext);
86     }
87   }
88   else if (theMode == OpenGl_GUM_PREPARE)
89   {
90     myRaytraceGeometry.ClearMaterials();
91
92     myArrayToTrianglesMap.clear();
93
94     myIsRaytraceDataValid = Standard_False;
95   }
96
97   // The set of processed structures (reflected to ray-tracing)
98   // This set is used to remove out-of-date records from the
99   // hash map of structures
100   std::set<const OpenGl_Structure*> anElements;
101
102   // Set to store all currently visible OpenGL primitive arrays
103   // applicable for ray-tracing
104   std::set<Standard_Size> anArrayIDs;
105
106   // Set to store all non-raytracable elements allowing tracking
107   // of changes in OpenGL scene (only for path tracing)
108   std::set<Standard_Integer> aNonRaytraceIDs;
109
110   const OpenGl_Layer& aLayer = myZLayers.Layer (Graphic3d_ZLayerId_Default);
111
112   if (aLayer.NbStructures() != 0)
113   {
114     const OpenGl_ArrayOfIndexedMapOfStructure& aStructArray = aLayer.ArrayOfStructures();
115
116     for (Standard_Integer anIndex = 0; anIndex < aStructArray.Length(); ++anIndex)
117     {
118       for (OpenGl_IndexedMapOfStructure::Iterator aStructIt (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next())
119       {
120         const OpenGl_Structure* aStructure = aStructIt.Value();
121
122         if (theMode == OpenGl_GUM_CHECK)
123         {
124           if (toUpdateStructure (aStructure))
125           {
126             return updateRaytraceGeometry (OpenGl_GUM_PREPARE, theViewId, theGlContext);
127           }
128           else if (aStructure->IsVisible() && myRaytraceParameters.GlobalIllumination)
129           {
130             aNonRaytraceIDs.insert (aStructure->highlight ? aStructure->Id : -aStructure->Id);
131           }
132         }
133         else if (theMode == OpenGl_GUM_PREPARE)
134         {
135           if (!aStructure->IsRaytracable() || !aStructure->IsVisible())
136           {
137             continue;
138           }
139           else if (!aStructure->ViewAffinity.IsNull() && !aStructure->ViewAffinity->IsVisible (theViewId))
140           {
141             continue;
142           }
143
144           for (OpenGl_Structure::GroupIterator aGroupIter (aStructure->Groups()); aGroupIter.More(); aGroupIter.Next())
145           {
146             // Extract OpenGL elements from the group (primitives arrays)
147             for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
148             {
149               OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
150
151               if (aPrimArray != NULL)
152               {
153                 anArrayIDs.insert (aPrimArray->GetUID());
154               }
155             }
156           }
157         }
158         else if (theMode == OpenGl_GUM_REBUILD)
159         {
160           if (!aStructure->IsRaytracable())
161           {
162             continue;
163           }
164           else if (addRaytraceStructure (aStructure, theGlContext))
165           {
166             anElements.insert (aStructure); // structure was processed
167           }
168         }
169       }
170     }
171   }
172
173   if (theMode == OpenGl_GUM_PREPARE)
174   {
175     BVH_ObjectSet<Standard_ShortReal, 3>::BVH_ObjectList anUnchangedObjects;
176
177     // Filter out unchanged objects so only their transformations and materials
178     // will be updated (and newly added objects will be processed from scratch)
179     for (Standard_Integer anObjIdx = 0; anObjIdx < myRaytraceGeometry.Size(); ++anObjIdx)
180     {
181       OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
182         myRaytraceGeometry.Objects().ChangeValue (anObjIdx).operator->());
183
184       if (aTriangleSet == NULL)
185       {
186         continue;
187       }
188
189       if (anArrayIDs.find (aTriangleSet->AssociatedPArrayID()) != anArrayIDs.end())
190       {
191         anUnchangedObjects.Append (myRaytraceGeometry.Objects().Value (anObjIdx));
192
193         myArrayToTrianglesMap[aTriangleSet->AssociatedPArrayID()] = aTriangleSet;
194       }
195     }
196
197     myRaytraceGeometry.Objects() = anUnchangedObjects;
198
199     return updateRaytraceGeometry (OpenGl_GUM_REBUILD, theViewId, theGlContext);
200   }
201   else if (theMode == OpenGl_GUM_REBUILD)
202   {
203     // Actualize the hash map of structures - remove out-of-date records
204     std::map<const OpenGl_Structure*, StructState>::iterator anIter = myStructureStates.begin();
205
206     while (anIter != myStructureStates.end())
207     {
208       if (anElements.find (anIter->first) == anElements.end())
209       {
210         myStructureStates.erase (anIter++);
211       }
212       else
213       {
214         ++anIter;
215       }
216     }
217
218     // Actualize OpenGL layer list state
219     myRaytraceLayerListState = myZLayers.ModificationStateOfRaytracable();
220
221     // Rebuild two-level acceleration structure
222     myRaytraceGeometry.ProcessAcceleration();
223
224     myRaytraceSceneRadius = 2.f /* scale factor */ * std::max (
225       myRaytraceGeometry.Box().CornerMin().cwiseAbs().maxComp(),
226       myRaytraceGeometry.Box().CornerMax().cwiseAbs().maxComp());
227
228     const BVH_Vec3f aSize = myRaytraceGeometry.Box().Size();
229
230     myRaytraceSceneEpsilon = Max (1.0e-6f, 1.0e-4f * aSize.Modulus());
231
232     return uploadRaytraceData (theGlContext);
233   }
234
235   if (myRaytraceParameters.GlobalIllumination)
236   {
237     Standard_Boolean toRestart =
238       aNonRaytraceIDs.size() != myNonRaytraceStructureIDs.size();
239
240     for (std::set<Standard_Integer>::iterator anID = aNonRaytraceIDs.begin(); anID != aNonRaytraceIDs.end() && !toRestart; ++anID)
241     {
242       if (myNonRaytraceStructureIDs.find (*anID) == myNonRaytraceStructureIDs.end())
243       {
244         toRestart = Standard_True;
245       }
246     }
247
248     if (toRestart)
249     {
250       myAccumFrames = 0;
251     }
252
253     myNonRaytraceStructureIDs = aNonRaytraceIDs;
254   }
255
256   return Standard_True;
257 }
258
259 // =======================================================================
260 // function : toUpdateStructure
261 // purpose  : Checks to see if the structure is modified
262 // =======================================================================
263 Standard_Boolean OpenGl_View::toUpdateStructure (const OpenGl_Structure* theStructure)
264 {
265   if (!theStructure->IsRaytracable())
266   {
267     if (theStructure->ModificationState() > 0)
268     {
269       theStructure->ResetModificationState();
270
271       return Standard_True; // ray-trace element was removed - need to rebuild
272     }
273
274     return Standard_False; // did not contain ray-trace elements
275   }
276
277   std::map<const OpenGl_Structure*, StructState>::iterator aStructState = myStructureStates.find (theStructure);
278
279   if (aStructState == myStructureStates.end() || aStructState->second.StructureState != theStructure->ModificationState())
280   {
281     return Standard_True;
282   }
283   else if (theStructure->InstancedStructure() != NULL)
284   {
285     return aStructState->second.InstancedState != theStructure->InstancedStructure()->ModificationState();
286   }
287
288   return Standard_False;
289 }
290
291 // =======================================================================
292 // function : buildTextureTransform
293 // purpose  : Constructs texture transformation matrix
294 // =======================================================================
295 void buildTextureTransform (const Handle(Graphic3d_TextureParams)& theParams, BVH_Mat4f& theMatrix)
296 {
297   theMatrix.InitIdentity();
298   if (theParams.IsNull())
299   {
300     return;
301   }
302
303   // Apply scaling
304   const Graphic3d_Vec2& aScale = theParams->Scale();
305
306   theMatrix.ChangeValue (0, 0) *= aScale.x();
307   theMatrix.ChangeValue (1, 0) *= aScale.x();
308   theMatrix.ChangeValue (2, 0) *= aScale.x();
309   theMatrix.ChangeValue (3, 0) *= aScale.x();
310
311   theMatrix.ChangeValue (0, 1) *= aScale.y();
312   theMatrix.ChangeValue (1, 1) *= aScale.y();
313   theMatrix.ChangeValue (2, 1) *= aScale.y();
314   theMatrix.ChangeValue (3, 1) *= aScale.y();
315
316   // Apply translation
317   const Graphic3d_Vec2 aTrans = -theParams->Translation();
318
319   theMatrix.ChangeValue (0, 3) = theMatrix.GetValue (0, 0) * aTrans.x() +
320                                  theMatrix.GetValue (0, 1) * aTrans.y();
321
322   theMatrix.ChangeValue (1, 3) = theMatrix.GetValue (1, 0) * aTrans.x() +
323                                  theMatrix.GetValue (1, 1) * aTrans.y();
324
325   theMatrix.ChangeValue (2, 3) = theMatrix.GetValue (2, 0) * aTrans.x() +
326                                  theMatrix.GetValue (2, 1) * aTrans.y();
327
328   // Apply rotation
329   const Standard_ShortReal aSin = std::sin (
330     -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
331   const Standard_ShortReal aCos = std::cos (
332     -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
333
334   BVH_Mat4f aRotationMat;
335   aRotationMat.SetValue (0, 0,  aCos);
336   aRotationMat.SetValue (1, 1,  aCos);
337   aRotationMat.SetValue (0, 1, -aSin);
338   aRotationMat.SetValue (1, 0,  aSin);
339
340   theMatrix = theMatrix * aRotationMat;
341 }
342
343 // =======================================================================
344 // function : convertMaterial
345 // purpose  : Creates ray-tracing material properties
346 // =======================================================================
347 OpenGl_RaytraceMaterial OpenGl_View::convertMaterial (const OpenGl_Aspects* theAspect,
348                                                       const Handle(OpenGl_Context)& theGlContext)
349 {
350   OpenGl_RaytraceMaterial theMaterial;
351
352   const Graphic3d_MaterialAspect& aSrcMat = theAspect->Aspect()->FrontMaterial();
353   const OpenGl_Vec3& aMatCol  = theAspect->Aspect()->InteriorColor();
354   const bool         isPhysic = aSrcMat.MaterialType (Graphic3d_MATERIAL_PHYSIC);
355   const float        aShine   = 128.0f * float(aSrcMat.Shininess());
356
357   // ambient component
358   if (aSrcMat.ReflectionMode (Graphic3d_TOR_AMBIENT))
359   {
360     const OpenGl_Vec3& aSrcAmb = isPhysic ? aSrcMat.AmbientColor() : aMatCol;
361     theMaterial.Ambient = BVH_Vec4f (aSrcAmb * (float )aSrcMat.Ambient(),  1.0f);
362   }
363   else
364   {
365     theMaterial.Ambient = THE_BLACK_COLOR;
366   }
367
368   // diffusion component
369   if (aSrcMat.ReflectionMode (Graphic3d_TOR_DIFFUSE))
370   {
371     const OpenGl_Vec3& aSrcDif = isPhysic ? aSrcMat.DiffuseColor() : aMatCol;
372     theMaterial.Diffuse = BVH_Vec4f (aSrcDif * (float )aSrcMat.Diffuse(), -1.0f); // -1 is no texture
373   }
374   else
375   {
376     theMaterial.Diffuse = BVH_Vec4f (THE_BLACK_COLOR.rgb(), -1.0f);
377   }
378
379   // specular component
380   if (aSrcMat.ReflectionMode (Graphic3d_TOR_SPECULAR))
381   {
382     const OpenGl_Vec3& aSrcSpe  = aSrcMat.SpecularColor();
383     const OpenGl_Vec3& aSrcSpe2 = isPhysic ? aSrcSpe : THE_WHITE_COLOR.rgb();
384     theMaterial.Specular = BVH_Vec4f (aSrcSpe2 * (float )aSrcMat.Specular(), aShine);
385
386     const Standard_ShortReal aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
387                                         Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
388                                              theMaterial.Diffuse.z() + theMaterial.Specular.z()));
389
390     const Standard_ShortReal aReflectionScale = 0.75f / aMaxRefl;
391
392     // ignore isPhysic here
393     theMaterial.Reflection = BVH_Vec4f (aSrcSpe * (float )aSrcMat.Specular() * aReflectionScale, 0.0f);
394   }
395   else
396   {
397     theMaterial.Specular = BVH_Vec4f (THE_BLACK_COLOR.rgb(), aShine);
398   }
399
400   // emission component
401   if (aSrcMat.ReflectionMode (Graphic3d_TOR_EMISSION))
402   {
403     const OpenGl_Vec3& aSrcEms = isPhysic ? aSrcMat.EmissiveColor() : aMatCol;
404     theMaterial.Emission = BVH_Vec4f (aSrcEms * (float )aSrcMat.Emissive(), 1.0f);
405   }
406   else
407   {
408     theMaterial.Emission = THE_BLACK_COLOR;
409   }
410
411   const float anIndex = (float )aSrcMat.RefractionIndex();
412   theMaterial.Transparency = BVH_Vec4f (aSrcMat.Alpha(), aSrcMat.Transparency(),
413                                         anIndex == 0 ? 1.0f : anIndex,
414                                         anIndex == 0 ? 1.0f : 1.0f / anIndex);
415
416   // Serialize physically-based material properties
417   const Graphic3d_BSDF& aBSDF = aSrcMat.BSDF();
418
419   theMaterial.BSDF.Kc = aBSDF.Kc;
420   theMaterial.BSDF.Ks = aBSDF.Ks;
421   theMaterial.BSDF.Kd = BVH_Vec4f (aBSDF.Kd, -1.f); // no texture
422   theMaterial.BSDF.Kt = BVH_Vec4f (aBSDF.Kt,  0.f);
423   theMaterial.BSDF.Le = BVH_Vec4f (aBSDF.Le,  0.f);
424
425   theMaterial.BSDF.Absorption = aBSDF.Absorption;
426
427   theMaterial.BSDF.FresnelCoat = aBSDF.FresnelCoat.Serialize ();
428   theMaterial.BSDF.FresnelBase = aBSDF.FresnelBase.Serialize ();
429
430   // Handle material textures
431   if (!theAspect->Aspect()->ToMapTexture())
432   {
433     return theMaterial;
434   }
435
436   const Handle(OpenGl_TextureSet)& aTextureSet = theAspect->TextureSet (theGlContext);
437   if (aTextureSet.IsNull()
438    || aTextureSet->IsEmpty()
439    || aTextureSet->First().IsNull())
440   {
441     return theMaterial;
442   }
443
444   if (theGlContext->HasRayTracingTextures())
445   {
446     const Handle(OpenGl_Texture)& aTexture = aTextureSet->First();
447     buildTextureTransform (aTexture->Sampler()->Parameters(), theMaterial.TextureTransform);
448
449     // write texture ID to diffuse w-component
450     theMaterial.Diffuse.w() = theMaterial.BSDF.Kd.w() = static_cast<Standard_ShortReal> (myRaytraceGeometry.AddTexture (aTexture));
451   }
452   else if (!myIsRaytraceWarnTextures)
453   {
454     const TCollection_ExtendedString aWarnMessage =
455       "Warning: texturing in Ray-Trace requires GL_ARB_bindless_texture extension which is missing. "
456       "Please try to update graphics card driver. At the moment textures will be ignored.";
457
458     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
459       GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
460
461     myIsRaytraceWarnTextures = Standard_True;
462   }
463
464   return theMaterial;
465 }
466
467 // =======================================================================
468 // function : addRaytraceStructure
469 // purpose  : Adds OpenGL structure to ray-traced scene geometry
470 // =======================================================================
471 Standard_Boolean OpenGl_View::addRaytraceStructure (const OpenGl_Structure*       theStructure,
472                                                     const Handle(OpenGl_Context)& theGlContext)
473 {
474   if (!theStructure->IsVisible())
475   {
476     myStructureStates[theStructure] = StructState (theStructure);
477
478     return Standard_True;
479   }
480
481   // Get structure material
482   OpenGl_RaytraceMaterial aDefaultMaterial;
483   Standard_Boolean aResult = addRaytraceGroups (theStructure, aDefaultMaterial, theStructure->Transformation(), theGlContext);
484
485   // Process all connected OpenGL structures
486   const OpenGl_Structure* anInstanced = theStructure->InstancedStructure();
487
488   if (anInstanced != NULL && anInstanced->IsRaytracable())
489   {
490     aResult &= addRaytraceGroups (anInstanced, aDefaultMaterial, theStructure->Transformation(), theGlContext);
491   }
492
493   myStructureStates[theStructure] = StructState (theStructure);
494
495   return aResult;
496 }
497
498 // =======================================================================
499 // function : addRaytraceGroups
500 // purpose  : Adds OpenGL groups to ray-traced scene geometry
501 // =======================================================================
502 Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*        theStructure,
503                                                  const OpenGl_RaytraceMaterial& theStructMat,
504                                                  const Handle(Geom_Transformation)& theTrsf,
505                                                  const Handle(OpenGl_Context)&  theGlContext)
506 {
507   OpenGl_Mat4 aMat4;
508   for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->Groups()); aGroupIter.More(); aGroupIter.Next())
509   {
510     // Get group material
511     OpenGl_RaytraceMaterial aGroupMaterial;
512     if (aGroupIter.Value()->GlAspects() != NULL)
513     {
514       aGroupMaterial = convertMaterial (aGroupIter.Value()->GlAspects(), theGlContext);
515     }
516
517     Standard_Integer aMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
518
519     // Use group material if available, otherwise use structure material
520     myRaytraceGeometry.Materials.push_back (aGroupIter.Value()->GlAspects() != NULL ? aGroupMaterial : theStructMat);
521
522     // Add OpenGL elements from group (extract primitives arrays and aspects)
523     for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
524     {
525       OpenGl_Aspects* anAspect = dynamic_cast<OpenGl_Aspects*> (aNode->elem);
526
527       if (anAspect != NULL)
528       {
529         aMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
530
531         OpenGl_RaytraceMaterial aMaterial = convertMaterial (anAspect, theGlContext);
532
533         myRaytraceGeometry.Materials.push_back (aMaterial);
534       }
535       else
536       {
537         OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
538
539         if (aPrimArray != NULL)
540         {
541           std::map<Standard_Size, OpenGl_TriangleSet*>::iterator aSetIter = myArrayToTrianglesMap.find (aPrimArray->GetUID());
542
543           if (aSetIter != myArrayToTrianglesMap.end())
544           {
545             OpenGl_TriangleSet* aSet = aSetIter->second;
546             opencascade::handle<BVH_Transform<Standard_ShortReal, 4> > aTransform = new BVH_Transform<Standard_ShortReal, 4>();
547             if (!theTrsf.IsNull())
548             {
549               theTrsf->Trsf().GetMat4 (aMat4);
550               aTransform->SetTransform (aMat4);
551             }
552
553             aSet->SetProperties (aTransform);
554             if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID)
555             {
556               aSet->SetMaterialIndex (aMatID);
557             }
558           }
559           else
560           {
561             if (Handle(OpenGl_TriangleSet) aSet = addRaytracePrimitiveArray (aPrimArray, aMatID, 0))
562             {
563               opencascade::handle<BVH_Transform<Standard_ShortReal, 4> > aTransform = new BVH_Transform<Standard_ShortReal, 4>();
564               if (!theTrsf.IsNull())
565               {
566                 theTrsf->Trsf().GetMat4 (aMat4);
567                 aTransform->SetTransform (aMat4);
568               }
569
570               aSet->SetProperties (aTransform);
571               myRaytraceGeometry.Objects().Append (aSet);
572             }
573           }
574         }
575       }
576     }
577   }
578
579   return Standard_True;
580 }
581
582 // =======================================================================
583 // function : addRaytracePrimitiveArray
584 // purpose  : Adds OpenGL primitive array to ray-traced scene geometry
585 // =======================================================================
586 Handle(OpenGl_TriangleSet) OpenGl_View::addRaytracePrimitiveArray (const OpenGl_PrimitiveArray* theArray,
587                                                                    const Standard_Integer       theMaterial,
588                                                                    const OpenGl_Mat4*           theTransform)
589 {
590   const Handle(Graphic3d_BoundBuffer)& aBounds   = theArray->Bounds();
591   const Handle(Graphic3d_IndexBuffer)& anIndices = theArray->Indices();
592   const Handle(Graphic3d_Buffer)&      anAttribs = theArray->Attributes();
593
594   if (theArray->DrawMode() < GL_TRIANGLES
595   #ifndef GL_ES_VERSION_2_0
596    || theArray->DrawMode() > GL_POLYGON
597   #else
598    || theArray->DrawMode() > GL_TRIANGLE_FAN
599   #endif
600    || anAttribs.IsNull())
601   {
602     return Handle(OpenGl_TriangleSet)();
603   }
604
605   OpenGl_Mat4 aNormalMatrix;
606   if (theTransform != NULL)
607   {
608     Standard_ASSERT_RETURN (theTransform->Inverted (aNormalMatrix),
609       "Error: Failed to compute normal transformation matrix", NULL);
610
611     aNormalMatrix.Transpose();
612   }
613
614   Handle(OpenGl_TriangleSet) aSet = new OpenGl_TriangleSet (theArray->GetUID(), myRaytraceBVHBuilder);
615   {
616     aSet->Vertices.reserve (anAttribs->NbElements);
617     aSet->Normals.reserve  (anAttribs->NbElements);
618     aSet->TexCrds.reserve  (anAttribs->NbElements);
619
620     const size_t aVertFrom = aSet->Vertices.size();
621
622     Standard_Integer anAttribIndex = 0;
623     Standard_Size anAttribStride = 0;
624     if (const Standard_Byte* aPosData = anAttribs->AttributeData (Graphic3d_TOA_POS, anAttribIndex, anAttribStride))
625     {
626       const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIndex);
627       if (anAttrib.DataType == Graphic3d_TOD_VEC2
628        || anAttrib.DataType == Graphic3d_TOD_VEC3
629        || anAttrib.DataType == Graphic3d_TOD_VEC4)
630       {
631         for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
632         {
633           const float* aCoords = reinterpret_cast<const float*> (aPosData + anAttribStride * aVertIter);
634           aSet->Vertices.push_back (BVH_Vec3f (aCoords[0], aCoords[1], anAttrib.DataType != Graphic3d_TOD_VEC2 ? aCoords[2] : 0.0f));
635         }
636       }
637     }
638     if (const Standard_Byte* aNormData = anAttribs->AttributeData (Graphic3d_TOA_NORM, anAttribIndex, anAttribStride))
639     {
640       const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIndex);
641       if (anAttrib.DataType == Graphic3d_TOD_VEC3
642        || anAttrib.DataType == Graphic3d_TOD_VEC4)
643       {
644         for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
645         {
646           aSet->Normals.push_back (*reinterpret_cast<const Graphic3d_Vec3*> (aNormData + anAttribStride * aVertIter));
647         }
648       }
649     }
650     if (const Standard_Byte* aTexData = anAttribs->AttributeData (Graphic3d_TOA_UV, anAttribIndex, anAttribStride))
651     {
652       const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIndex);
653       if (anAttrib.DataType == Graphic3d_TOD_VEC2)
654       {
655         for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
656         {
657           aSet->TexCrds.push_back (*reinterpret_cast<const Graphic3d_Vec2*> (aTexData + anAttribStride * aVertIter));
658         }
659       }
660     }
661
662     if (aSet->Normals.size() != aSet->Vertices.size())
663     {
664       for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
665       {
666         aSet->Normals.push_back (BVH_Vec3f());
667       }
668     }
669
670     if (aSet->TexCrds.size() != aSet->Vertices.size())
671     {
672       for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
673       {
674         aSet->TexCrds.push_back (BVH_Vec2f());
675       }
676     }
677
678     if (theTransform != NULL)
679     {
680       for (size_t aVertIter = aVertFrom; aVertIter < aSet->Vertices.size(); ++aVertIter)
681       {
682         BVH_Vec3f& aVertex = aSet->Vertices[aVertIter];
683
684         BVH_Vec4f aTransVertex = *theTransform *
685           BVH_Vec4f (aVertex.x(), aVertex.y(), aVertex.z(), 1.f);
686
687         aVertex = BVH_Vec3f (aTransVertex.x(), aTransVertex.y(), aTransVertex.z());
688       }
689       for (size_t aVertIter = aVertFrom; aVertIter < aSet->Normals.size(); ++aVertIter)
690       {
691         BVH_Vec3f& aNormal = aSet->Normals[aVertIter];
692
693         BVH_Vec4f aTransNormal = aNormalMatrix *
694           BVH_Vec4f (aNormal.x(), aNormal.y(), aNormal.z(), 0.f);
695
696         aNormal = BVH_Vec3f (aTransNormal.x(), aTransNormal.y(), aTransNormal.z());
697       }
698     }
699
700     if (!aBounds.IsNull())
701     {
702       for (Standard_Integer aBound = 0, aBoundStart = 0; aBound < aBounds->NbBounds; ++aBound)
703       {
704         const Standard_Integer aVertNum = aBounds->Bounds[aBound];
705
706         if (!addRaytraceVertexIndices (*aSet, theMaterial, aVertNum, aBoundStart, *theArray))
707         {
708           aSet.Nullify();
709           return Handle(OpenGl_TriangleSet)();
710         }
711
712         aBoundStart += aVertNum;
713       }
714     }
715     else
716     {
717       const Standard_Integer aVertNum = !anIndices.IsNull() ? anIndices->NbElements : anAttribs->NbElements;
718
719       if (!addRaytraceVertexIndices (*aSet, theMaterial, aVertNum, 0, *theArray))
720       {
721         aSet.Nullify();
722         return Handle(OpenGl_TriangleSet)();
723       }
724     }
725   }
726
727   if (aSet->Size() != 0)
728   {
729     aSet->MarkDirty();
730   }
731
732   return aSet;
733 }
734
735 // =======================================================================
736 // function : addRaytraceVertexIndices
737 // purpose  : Adds vertex indices to ray-traced scene geometry
738 // =======================================================================
739 Standard_Boolean OpenGl_View::addRaytraceVertexIndices (OpenGl_TriangleSet&                  theSet,
740                                                         const Standard_Integer               theMatID,
741                                                         const Standard_Integer               theCount,
742                                                         const Standard_Integer               theOffset,
743                                                         const OpenGl_PrimitiveArray&         theArray)
744 {
745   switch (theArray.DrawMode())
746   {
747     case GL_TRIANGLES:      return addRaytraceTriangleArray        (theSet, theMatID, theCount, theOffset, theArray.Indices());
748     case GL_TRIANGLE_FAN:   return addRaytraceTriangleFanArray     (theSet, theMatID, theCount, theOffset, theArray.Indices());
749     case GL_TRIANGLE_STRIP: return addRaytraceTriangleStripArray   (theSet, theMatID, theCount, theOffset, theArray.Indices());
750   #if !defined(GL_ES_VERSION_2_0)
751     case GL_QUAD_STRIP:     return addRaytraceQuadrangleStripArray (theSet, theMatID, theCount, theOffset, theArray.Indices());
752     case GL_QUADS:          return addRaytraceQuadrangleArray      (theSet, theMatID, theCount, theOffset, theArray.Indices());
753     case GL_POLYGON:        return addRaytracePolygonArray         (theSet, theMatID, theCount, theOffset, theArray.Indices());
754   #endif
755   }
756
757   return Standard_False;
758 }
759
760 // =======================================================================
761 // function : addRaytraceTriangleArray
762 // purpose  : Adds OpenGL triangle array to ray-traced scene geometry
763 // =======================================================================
764 Standard_Boolean OpenGl_View::addRaytraceTriangleArray (OpenGl_TriangleSet&                  theSet,
765                                                         const Standard_Integer               theMatID,
766                                                         const Standard_Integer               theCount,
767                                                         const Standard_Integer               theOffset,
768                                                         const Handle(Graphic3d_IndexBuffer)& theIndices)
769 {
770   if (theCount < 3)
771   {
772     return Standard_True;
773   }
774
775   theSet.Elements.reserve (theSet.Elements.size() + theCount / 3);
776
777   if (!theIndices.IsNull())
778   {
779     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
780     {
781       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
782                                             theIndices->Index (aVert + 1),
783                                             theIndices->Index (aVert + 2),
784                                             theMatID));
785     }
786   }
787   else
788   {
789     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
790     {
791       theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2, theMatID));
792     }
793   }
794
795   return Standard_True;
796 }
797
798 // =======================================================================
799 // function : addRaytraceTriangleFanArray
800 // purpose  : Adds OpenGL triangle fan array to ray-traced scene geometry
801 // =======================================================================
802 Standard_Boolean OpenGl_View::addRaytraceTriangleFanArray (OpenGl_TriangleSet&                  theSet,
803                                                            const Standard_Integer               theMatID,
804                                                            const Standard_Integer               theCount,
805                                                            const Standard_Integer               theOffset,
806                                                            const Handle(Graphic3d_IndexBuffer)& theIndices)
807 {
808   if (theCount < 3)
809   {
810     return Standard_True;
811   }
812
813   theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
814
815   if (!theIndices.IsNull())
816   {
817     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
818     {
819       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
820                                             theIndices->Index (aVert + 1),
821                                             theIndices->Index (aVert + 2),
822                                             theMatID));
823     }
824   }
825   else
826   {
827     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
828     {
829       theSet.Elements.push_back (BVH_Vec4i (theOffset,
830                                             aVert + 1,
831                                             aVert + 2,
832                                             theMatID));
833     }
834   }
835
836   return Standard_True;
837 }
838
839 // =======================================================================
840 // function : addRaytraceTriangleStripArray
841 // purpose  : Adds OpenGL triangle strip array to ray-traced scene geometry
842 // =======================================================================
843 Standard_Boolean OpenGl_View::addRaytraceTriangleStripArray (OpenGl_TriangleSet&                  theSet,
844                                                              const Standard_Integer               theMatID,
845                                                              const Standard_Integer               theCount,
846                                                              const Standard_Integer               theOffset,
847                                                              const Handle(Graphic3d_IndexBuffer)& theIndices)
848 {
849   if (theCount < 3)
850   {
851     return Standard_True;
852   }
853
854   theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
855
856   if (!theIndices.IsNull())
857   {
858     for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
859     {
860       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + (aCW ? 1 : 0)),
861                                             theIndices->Index (aVert + (aCW ? 0 : 1)),
862                                             theIndices->Index (aVert + 2),
863                                             theMatID));
864     }
865   }
866   else
867   {
868     for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
869     {
870       theSet.Elements.push_back (BVH_Vec4i (aVert + (aCW ? 1 : 0),
871                                             aVert + (aCW ? 0 : 1),
872                                             aVert + 2,
873                                             theMatID));
874     }
875   }
876
877   return Standard_True;
878 }
879
880 // =======================================================================
881 // function : addRaytraceQuadrangleArray
882 // purpose  : Adds OpenGL quad array to ray-traced scene geometry
883 // =======================================================================
884 Standard_Boolean OpenGl_View::addRaytraceQuadrangleArray (OpenGl_TriangleSet&                  theSet,
885                                                           const Standard_Integer               theMatID,
886                                                           const Standard_Integer               theCount,
887                                                           const Standard_Integer               theOffset,
888                                                           const Handle(Graphic3d_IndexBuffer)& theIndices)
889 {
890   if (theCount < 4)
891   {
892     return Standard_True;
893   }
894
895   theSet.Elements.reserve (theSet.Elements.size() + theCount / 2);
896
897   if (!theIndices.IsNull())
898   {
899     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
900     {
901       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
902                                             theIndices->Index (aVert + 1),
903                                             theIndices->Index (aVert + 2),
904                                             theMatID));
905       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
906                                             theIndices->Index (aVert + 2),
907                                             theIndices->Index (aVert + 3),
908                                             theMatID));
909     }
910   }
911   else
912   {
913     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
914     {
915       theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2,
916                                             theMatID));
917       theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 2, aVert + 3,
918                                             theMatID));
919     }
920   }
921
922   return Standard_True;
923 }
924
925 // =======================================================================
926 // function : addRaytraceQuadrangleStripArray
927 // purpose  : Adds OpenGL quad strip array to ray-traced scene geometry
928 // =======================================================================
929 Standard_Boolean OpenGl_View::addRaytraceQuadrangleStripArray (OpenGl_TriangleSet&                  theSet,
930                                                                const Standard_Integer               theMatID,
931                                                                const Standard_Integer               theCount,
932                                                                const Standard_Integer               theOffset,
933                                                                const Handle(Graphic3d_IndexBuffer)& theIndices)
934 {
935   if (theCount < 4)
936   {
937     return Standard_True;
938   }
939
940   theSet.Elements.reserve (theSet.Elements.size() + 2 * theCount - 6);
941
942   if (!theIndices.IsNull())
943   {
944     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
945     {
946       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
947                                             theIndices->Index (aVert + 1),
948                                             theIndices->Index (aVert + 2),
949                                             theMatID));
950
951       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 1),
952                                             theIndices->Index (aVert + 3),
953                                             theIndices->Index (aVert + 2),
954                                             theMatID));
955     }
956   }
957   else
958   {
959     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
960     {
961       theSet.Elements.push_back (BVH_Vec4i (aVert + 0,
962                                             aVert + 1,
963                                             aVert + 2,
964                                             theMatID));
965
966       theSet.Elements.push_back (BVH_Vec4i (aVert + 1,
967                                             aVert + 3,
968                                             aVert + 2,
969                                             theMatID));
970     }
971   }
972
973   return Standard_True;
974 }
975
976 // =======================================================================
977 // function : addRaytracePolygonArray
978 // purpose  : Adds OpenGL polygon array to ray-traced scene geometry
979 // =======================================================================
980 Standard_Boolean OpenGl_View::addRaytracePolygonArray (OpenGl_TriangleSet&                  theSet,
981                                                        const Standard_Integer               theMatID,
982                                                        const Standard_Integer               theCount,
983                                                        const Standard_Integer               theOffset,
984                                                        const Handle(Graphic3d_IndexBuffer)& theIndices)
985 {
986   if (theCount < 3)
987   {
988     return Standard_True;
989   }
990
991   theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
992
993   if (!theIndices.IsNull())
994   {
995     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
996     {
997       theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
998                                             theIndices->Index (aVert + 1),
999                                             theIndices->Index (aVert + 2),
1000                                             theMatID));
1001     }
1002   }
1003   else
1004   {
1005     for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
1006     {
1007       theSet.Elements.push_back (BVH_Vec4i (theOffset,
1008                                             aVert + 1,
1009                                             aVert + 2,
1010                                             theMatID));
1011     }
1012   }
1013
1014   return Standard_True;
1015 }
1016
1017 const TCollection_AsciiString OpenGl_View::ShaderSource::EMPTY_PREFIX;
1018
1019 // =======================================================================
1020 // function : Source
1021 // purpose  : Returns shader source combined with prefix
1022 // =======================================================================
1023 TCollection_AsciiString OpenGl_View::ShaderSource::Source() const
1024 {
1025   const TCollection_AsciiString aVersion = "#version 140";
1026
1027   if (myPrefix.IsEmpty())
1028   {
1029     return aVersion + "\n" + mySource;
1030   }
1031
1032   return aVersion + "\n" + myPrefix + "\n" + mySource;
1033 }
1034
1035 // =======================================================================
1036 // function : LoadFromFiles
1037 // purpose  : Loads shader source from specified files
1038 // =======================================================================
1039 Standard_Boolean OpenGl_View::ShaderSource::LoadFromFiles (const TCollection_AsciiString* theFileNames,
1040                                                            const TCollection_AsciiString& thePrefix)
1041 {
1042   myError.Clear();
1043   mySource.Clear();
1044   myPrefix = thePrefix;
1045
1046   TCollection_AsciiString aMissingFiles;
1047   for (Standard_Integer anIndex = 0; !theFileNames[anIndex].IsEmpty(); ++anIndex)
1048   {
1049     OSD_File aFile (theFileNames[anIndex]);
1050     if (aFile.Exists())
1051     {
1052       aFile.Open (OSD_ReadOnly, OSD_Protection());
1053     }
1054     if (!aFile.IsOpen())
1055     {
1056       if (!aMissingFiles.IsEmpty())
1057       {
1058         aMissingFiles += ", ";
1059       }
1060       aMissingFiles += TCollection_AsciiString("'") + theFileNames[anIndex] + "'";
1061       continue;
1062     }
1063     else if (!aMissingFiles.IsEmpty())
1064     {
1065       aFile.Close();
1066       continue;
1067     }
1068
1069     TCollection_AsciiString aSource;
1070     aFile.Read (aSource, (Standard_Integer) aFile.Size());
1071     if (!aSource.IsEmpty())
1072     {
1073       mySource += TCollection_AsciiString ("\n") + aSource;
1074     }
1075     aFile.Close();
1076   }
1077
1078   if (!aMissingFiles.IsEmpty())
1079   {
1080     myError = TCollection_AsciiString("Shader files ") + aMissingFiles + " are missing or inaccessible";
1081     return Standard_False;
1082   }
1083   return Standard_True;
1084 }
1085
1086 // =======================================================================
1087 // function : LoadFromStrings
1088 // purpose  :
1089 // =======================================================================
1090 Standard_Boolean OpenGl_View::ShaderSource::LoadFromStrings (const TCollection_AsciiString* theStrings,
1091                                                              const TCollection_AsciiString& thePrefix)
1092 {
1093   myError.Clear();
1094   mySource.Clear();
1095   myPrefix = thePrefix;
1096
1097   for (Standard_Integer anIndex = 0; !theStrings[anIndex].IsEmpty(); ++anIndex)
1098   {
1099     TCollection_AsciiString aSource = theStrings[anIndex];
1100     if (!aSource.IsEmpty())
1101     {
1102       mySource += TCollection_AsciiString ("\n") + aSource;
1103     }
1104   }
1105   return Standard_True;
1106 }
1107
1108 // =======================================================================
1109 // function : generateShaderPrefix
1110 // purpose  : Generates shader prefix based on current ray-tracing options
1111 // =======================================================================
1112 TCollection_AsciiString OpenGl_View::generateShaderPrefix (const Handle(OpenGl_Context)& theGlContext) const
1113 {
1114   TCollection_AsciiString aPrefixString =
1115     TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
1116     TCollection_AsciiString ("#define NB_BOUNCES ") + TCollection_AsciiString (myRaytraceParameters.NbBounces);
1117
1118   if (myRaytraceParameters.TransparentShadows)
1119   {
1120     aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
1121   }
1122
1123   // If OpenGL driver supports bindless textures and texturing
1124   // is actually used, activate texturing in ray-tracing mode
1125   if (myRaytraceParameters.UseBindlessTextures && theGlContext->arbTexBindless != NULL)
1126   {
1127     aPrefixString += TCollection_AsciiString ("\n#define USE_TEXTURES") +
1128       TCollection_AsciiString ("\n#define MAX_TEX_NUMBER ") + TCollection_AsciiString (OpenGl_RaytraceGeometry::MAX_TEX_NUMBER);
1129   }
1130
1131   if (myRaytraceParameters.GlobalIllumination) // path tracing activated
1132   {
1133     aPrefixString += TCollection_AsciiString ("\n#define PATH_TRACING");
1134
1135     if (myRaytraceParameters.AdaptiveScreenSampling) // adaptive screen sampling requested
1136     {
1137       if (theGlContext->IsGlGreaterEqual (4, 4))
1138       {
1139         aPrefixString += TCollection_AsciiString ("\n#define ADAPTIVE_SAMPLING");
1140         if (myRaytraceParameters.AdaptiveScreenSamplingAtomic
1141          && theGlContext->CheckExtension ("GL_NV_shader_atomic_float"))
1142         {
1143           aPrefixString += TCollection_AsciiString ("\n#define ADAPTIVE_SAMPLING_ATOMIC");
1144         }
1145       }
1146     }
1147
1148     if (myRaytraceParameters.TwoSidedBsdfModels) // two-sided BSDFs requested
1149     {
1150       aPrefixString += TCollection_AsciiString ("\n#define TWO_SIDED_BXDF");
1151     }
1152
1153     switch (myRaytraceParameters.ToneMappingMethod)
1154     {
1155       case Graphic3d_ToneMappingMethod_Disabled:
1156         break;
1157       case Graphic3d_ToneMappingMethod_Filmic:
1158         aPrefixString += TCollection_AsciiString ("\n#define TONE_MAPPING_FILMIC");
1159         break;
1160     }
1161   }
1162
1163   if (myRaytraceParameters.DepthOfField)
1164   {
1165     aPrefixString += TCollection_AsciiString("\n#define DEPTH_OF_FIELD");
1166   }
1167
1168   return aPrefixString;
1169 }
1170
1171 // =======================================================================
1172 // function : safeFailBack
1173 // purpose  : Performs safe exit when shaders initialization fails
1174 // =======================================================================
1175 Standard_Boolean OpenGl_View::safeFailBack (const TCollection_ExtendedString& theMessage,
1176                                             const Handle(OpenGl_Context)&     theGlContext)
1177 {
1178   theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1179     GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, theMessage);
1180
1181   myRaytraceInitStatus = OpenGl_RT_FAIL;
1182
1183   releaseRaytraceResources (theGlContext);
1184
1185   return Standard_False;
1186 }
1187
1188 // =======================================================================
1189 // function : initShader
1190 // purpose  : Creates new shader object with specified source
1191 // =======================================================================
1192 Handle(OpenGl_ShaderObject) OpenGl_View::initShader (const GLenum                  theType,
1193                                                      const ShaderSource&           theSource,
1194                                                      const Handle(OpenGl_Context)& theGlContext)
1195 {
1196   Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (theType);
1197
1198   if (!aShader->Create (theGlContext))
1199   {
1200     const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to create ") +
1201       (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object";
1202
1203     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1204       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1205
1206     aShader->Release (theGlContext.operator->());
1207
1208     return Handle(OpenGl_ShaderObject)();
1209   }
1210
1211   if (!aShader->LoadSource (theGlContext, theSource.Source()))
1212   {
1213     const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to set ") +
1214       (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader source";
1215
1216     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1217       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1218
1219     aShader->Release (theGlContext.operator->());
1220
1221     return Handle(OpenGl_ShaderObject)();
1222   }
1223
1224   TCollection_AsciiString aBuildLog;
1225
1226   if (!aShader->Compile (theGlContext))
1227   {
1228     aShader->FetchInfoLog (theGlContext, aBuildLog);
1229
1230     const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to compile ") +
1231       (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object:\n" + aBuildLog;
1232
1233     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1234       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1235
1236     aShader->Release (theGlContext.operator->());
1237
1238 #ifdef RAY_TRACE_PRINT_INFO
1239     std::cout << "Shader build log:\n" << aBuildLog << "\n";
1240 #endif
1241
1242     return Handle(OpenGl_ShaderObject)();
1243   }
1244   else if (theGlContext->caps->glslWarnings)
1245   {
1246     aShader->FetchInfoLog (theGlContext, aBuildLog);
1247
1248     if (!aBuildLog.IsEmpty() && !aBuildLog.IsEqual ("No errors.\n"))
1249     {
1250       const TCollection_ExtendedString aMessage = TCollection_ExtendedString (theType == GL_VERTEX_SHADER ?
1251         "Vertex" : "Fragment") + " shader was compiled with following warnings:\n" + aBuildLog;
1252
1253       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1254         GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMessage);
1255     }
1256
1257 #ifdef RAY_TRACE_PRINT_INFO
1258     std::cout << "Shader build log:\n" << aBuildLog << "\n";
1259 #endif
1260   }
1261
1262   return aShader;
1263 }
1264
1265 // =======================================================================
1266 // function : initProgram
1267 // purpose  : Creates GLSL program from the given shader objects
1268 // =======================================================================
1269 Handle(OpenGl_ShaderProgram) OpenGl_View::initProgram (const Handle(OpenGl_Context)&      theGlContext,
1270                                                        const Handle(OpenGl_ShaderObject)& theVertShader,
1271                                                        const Handle(OpenGl_ShaderObject)& theFragShader,
1272                                                        const TCollection_AsciiString& theName)
1273 {
1274   const TCollection_AsciiString anId = TCollection_AsciiString("occt_rt_") + theName;
1275   Handle(OpenGl_ShaderProgram) aProgram = new OpenGl_ShaderProgram(Handle(Graphic3d_ShaderProgram)(), anId);
1276
1277   if (!aProgram->Create (theGlContext))
1278   {
1279     theVertShader->Release (theGlContext.operator->());
1280
1281     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1282       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Failed to create shader program");
1283
1284     return Handle(OpenGl_ShaderProgram)();
1285   }
1286
1287   if (!aProgram->AttachShader (theGlContext, theVertShader)
1288    || !aProgram->AttachShader (theGlContext, theFragShader))
1289   {
1290     theVertShader->Release (theGlContext.operator->());
1291
1292     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1293       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Failed to attach shader objects");
1294
1295     return Handle(OpenGl_ShaderProgram)();
1296   }
1297
1298   aProgram->SetAttributeName (theGlContext, Graphic3d_TOA_POS, "occVertex");
1299
1300   TCollection_AsciiString aLinkLog;
1301
1302   if (!aProgram->Link (theGlContext))
1303   {
1304     aProgram->FetchInfoLog (theGlContext, aLinkLog);
1305
1306     const TCollection_ExtendedString aMessage = TCollection_ExtendedString (
1307       "Failed to link shader program:\n") + aLinkLog;
1308
1309     theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1310       GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMessage);
1311
1312     return Handle(OpenGl_ShaderProgram)();
1313   }
1314   else if (theGlContext->caps->glslWarnings)
1315   {
1316     aProgram->FetchInfoLog (theGlContext, aLinkLog);
1317     if (!aLinkLog.IsEmpty() && !aLinkLog.IsEqual ("No errors.\n"))
1318     {
1319       const TCollection_ExtendedString aMessage = TCollection_ExtendedString (
1320         "Shader program was linked with following warnings:\n") + aLinkLog;
1321
1322       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1323         GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMessage);
1324     }
1325   }
1326
1327   return aProgram;
1328 }
1329
1330 // =======================================================================
1331 // function : initRaytraceResources
1332 // purpose  : Initializes OpenGL/GLSL shader programs
1333 // =======================================================================
1334 Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theSizeX,
1335                                                      const Standard_Integer theSizeY,
1336                                                      const Handle(OpenGl_Context)& theGlContext)
1337 {
1338   if (myRaytraceInitStatus == OpenGl_RT_FAIL)
1339   {
1340     return Standard_False;
1341   }
1342
1343   Standard_Boolean aToRebuildShaders = Standard_False;
1344
1345   if (myRenderParams.RebuildRayTracingShaders) // requires complete re-initialization
1346   {
1347     myRaytraceInitStatus = OpenGl_RT_NONE;
1348     releaseRaytraceResources (theGlContext, Standard_True);
1349     myRenderParams.RebuildRayTracingShaders = Standard_False; // clear rebuilding flag
1350   }
1351
1352   if (myRaytraceInitStatus == OpenGl_RT_INIT)
1353   {
1354     if (!myIsRaytraceDataValid)
1355     {
1356       return Standard_True;
1357     }
1358
1359     const Standard_Integer aRequiredStackSize =
1360       myRaytraceGeometry.TopLevelTreeDepth() + myRaytraceGeometry.BotLevelTreeDepth();
1361
1362     if (myRaytraceParameters.StackSize < aRequiredStackSize)
1363     {
1364       myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
1365
1366       aToRebuildShaders = Standard_True;
1367     }
1368     else
1369     {
1370       if (aRequiredStackSize < myRaytraceParameters.StackSize)
1371       {
1372         if (myRaytraceParameters.StackSize > THE_DEFAULT_STACK_SIZE)
1373         {
1374           myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
1375           aToRebuildShaders = Standard_True;
1376         }
1377       }
1378     }
1379
1380     if (myRenderParams.RaytracingDepth             != myRaytraceParameters.NbBounces
1381      || myRenderParams.IsTransparentShadowEnabled  != myRaytraceParameters.TransparentShadows
1382      || myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination
1383      || myRenderParams.TwoSidedBsdfModels          != myRaytraceParameters.TwoSidedBsdfModels
1384      || myRaytraceGeometry.HasTextures()           != myRaytraceParameters.UseBindlessTextures)
1385     {
1386       myRaytraceParameters.NbBounces           = myRenderParams.RaytracingDepth;
1387       myRaytraceParameters.TransparentShadows  = myRenderParams.IsTransparentShadowEnabled;
1388       myRaytraceParameters.GlobalIllumination  = myRenderParams.IsGlobalIlluminationEnabled;
1389       myRaytraceParameters.TwoSidedBsdfModels  = myRenderParams.TwoSidedBsdfModels;
1390       myRaytraceParameters.UseBindlessTextures = myRaytraceGeometry.HasTextures();
1391       aToRebuildShaders = Standard_True;
1392     }
1393
1394     if (myRenderParams.AdaptiveScreenSampling       != myRaytraceParameters.AdaptiveScreenSampling
1395      || myRenderParams.AdaptiveScreenSamplingAtomic != myRaytraceParameters.AdaptiveScreenSamplingAtomic)
1396     {
1397       myRaytraceParameters.AdaptiveScreenSampling       = myRenderParams.AdaptiveScreenSampling;
1398       myRaytraceParameters.AdaptiveScreenSamplingAtomic = myRenderParams.AdaptiveScreenSamplingAtomic;
1399       if (myRenderParams.AdaptiveScreenSampling) // adaptive sampling was requested
1400       {
1401         if (!theGlContext->HasRayTracingAdaptiveSampling())
1402         {
1403           // disable the feature if it is not supported
1404           myRaytraceParameters.AdaptiveScreenSampling = myRenderParams.AdaptiveScreenSampling = Standard_False;
1405           theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
1406                                      "Adaptive sampling is not supported (OpenGL 4.4 is missing)");
1407         }
1408         else if (myRaytraceParameters.AdaptiveScreenSamplingAtomic
1409              && !theGlContext->HasRayTracingAdaptiveSamplingAtomic())
1410         {
1411           // disable the feature if it is not supported
1412           myRaytraceParameters.AdaptiveScreenSamplingAtomic = myRenderParams.AdaptiveScreenSamplingAtomic = Standard_False;
1413           theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
1414                                      "Atomic adaptive sampling is not supported (GL_NV_shader_atomic_float is missing)");
1415         }
1416       }
1417
1418       aToRebuildShaders = Standard_True;
1419     }
1420     myTileSampler.SetSize (myRenderParams, myRaytraceParameters.AdaptiveScreenSampling ? Graphic3d_Vec2i (theSizeX, theSizeY) : Graphic3d_Vec2i (0, 0));
1421
1422     const bool toEnableDof = !myCamera->IsOrthographic() && myRaytraceParameters.GlobalIllumination;
1423     if (myRaytraceParameters.DepthOfField != toEnableDof)
1424     {
1425       myRaytraceParameters.DepthOfField = toEnableDof;
1426       aToRebuildShaders = Standard_True;
1427     }
1428
1429     if (myRenderParams.ToneMappingMethod != myRaytraceParameters.ToneMappingMethod)
1430     {
1431       myRaytraceParameters.ToneMappingMethod = myRenderParams.ToneMappingMethod;
1432       aToRebuildShaders = true;
1433     }
1434
1435     if (aToRebuildShaders)
1436     {
1437       // Reject accumulated frames
1438       myAccumFrames = 0;
1439
1440       // Environment map should be updated
1441       myToUpdateEnvironmentMap = Standard_True;
1442
1443       const TCollection_AsciiString aPrefixString = generateShaderPrefix (theGlContext);
1444
1445 #ifdef RAY_TRACE_PRINT_INFO
1446       std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
1447 #endif
1448
1449       myRaytraceShaderSource.SetPrefix (aPrefixString);
1450       myPostFSAAShaderSource.SetPrefix (aPrefixString);
1451       myOutImageShaderSource.SetPrefix (aPrefixString);
1452
1453       if (!myRaytraceShader->LoadAndCompile (theGlContext, myRaytraceShaderSource.Source())
1454        || !myPostFSAAShader->LoadAndCompile (theGlContext, myPostFSAAShaderSource.Source())
1455        || !myOutImageShader->LoadAndCompile (theGlContext, myOutImageShaderSource.Source()))
1456       {
1457         return safeFailBack ("Failed to compile ray-tracing fragment shaders", theGlContext);
1458       }
1459
1460       myRaytraceProgram->SetAttributeName (theGlContext, Graphic3d_TOA_POS, "occVertex");
1461       myPostFSAAProgram->SetAttributeName (theGlContext, Graphic3d_TOA_POS, "occVertex");
1462       myOutImageProgram->SetAttributeName (theGlContext, Graphic3d_TOA_POS, "occVertex");
1463
1464       if (!myRaytraceProgram->Link (theGlContext)
1465        || !myPostFSAAProgram->Link (theGlContext)
1466        || !myOutImageProgram->Link (theGlContext))
1467       {
1468         return safeFailBack ("Failed to initialize vertex attributes for ray-tracing program", theGlContext);
1469       }
1470     }
1471   }
1472
1473   if (myRaytraceInitStatus == OpenGl_RT_NONE)
1474   {
1475     myAccumFrames = 0; // accumulation should be restarted
1476
1477     if (!theGlContext->IsGlGreaterEqual (3, 1))
1478     {
1479       return safeFailBack ("Ray-tracing requires OpenGL 3.1 and higher", theGlContext);
1480     }
1481     else if (!theGlContext->arbTboRGB32)
1482     {
1483       return safeFailBack ("Ray-tracing requires OpenGL 4.0+ or GL_ARB_texture_buffer_object_rgb32 extension", theGlContext);
1484     }
1485     else if (!theGlContext->arbFBOBlit)
1486     {
1487       return safeFailBack ("Ray-tracing requires EXT_framebuffer_blit extension", theGlContext);
1488     }
1489
1490     myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth;
1491
1492     const TCollection_AsciiString aShaderFolder = Graphic3d_ShaderProgram::ShadersFolder();
1493     if (myIsRaytraceDataValid)
1494     {
1495       myRaytraceParameters.StackSize = Max (THE_DEFAULT_STACK_SIZE,
1496         myRaytraceGeometry.TopLevelTreeDepth() + myRaytraceGeometry.BotLevelTreeDepth());
1497     }
1498
1499     const TCollection_AsciiString aPrefixString  = generateShaderPrefix (theGlContext);
1500
1501 #ifdef RAY_TRACE_PRINT_INFO
1502     std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
1503 #endif
1504
1505     ShaderSource aBasicVertShaderSrc;
1506     {
1507       if (!aShaderFolder.IsEmpty())
1508       {
1509         const TCollection_AsciiString aFiles[] = { aShaderFolder + "/RaytraceBase.vs", "" };
1510         if (!aBasicVertShaderSrc.LoadFromFiles (aFiles))
1511         {
1512           return safeFailBack (aBasicVertShaderSrc.ErrorDescription(), theGlContext);
1513         }
1514       }
1515       else
1516       {
1517         const TCollection_AsciiString aSrcShaders[] = { Shaders_RaytraceBase_vs, "" };
1518         aBasicVertShaderSrc.LoadFromStrings (aSrcShaders);
1519       }
1520     }
1521
1522     {
1523       if (!aShaderFolder.IsEmpty())
1524       {
1525         const TCollection_AsciiString aFiles[] = { aShaderFolder + "/RaytraceBase.fs",
1526                                                    aShaderFolder + "/PathtraceBase.fs",
1527                                                    aShaderFolder + "/RaytraceRender.fs",
1528                                                    "" };
1529         if (!myRaytraceShaderSource.LoadFromFiles (aFiles, aPrefixString))
1530         {
1531           return safeFailBack (myRaytraceShaderSource.ErrorDescription(), theGlContext);
1532         }
1533       }
1534       else
1535       {
1536         const TCollection_AsciiString aSrcShaders[] = { Shaders_RaytraceBase_fs,
1537                                                         Shaders_PathtraceBase_fs,
1538                                                         Shaders_RaytraceRender_fs,
1539                                                         "" };
1540         myRaytraceShaderSource.LoadFromStrings (aSrcShaders, aPrefixString);
1541       }
1542
1543       Handle(OpenGl_ShaderObject) aBasicVertShader = initShader (GL_VERTEX_SHADER, aBasicVertShaderSrc, theGlContext);
1544       if (aBasicVertShader.IsNull())
1545       {
1546         return safeFailBack ("Failed to initialize ray-trace vertex shader", theGlContext);
1547       }
1548
1549       myRaytraceShader = initShader (GL_FRAGMENT_SHADER, myRaytraceShaderSource, theGlContext);
1550       if (myRaytraceShader.IsNull())
1551       {
1552         aBasicVertShader->Release (theGlContext.operator->());
1553         return safeFailBack ("Failed to initialize ray-trace fragment shader", theGlContext);
1554       }
1555
1556       myRaytraceProgram = initProgram (theGlContext, aBasicVertShader, myRaytraceShader, "main");
1557       if (myRaytraceProgram.IsNull())
1558       {
1559         return safeFailBack ("Failed to initialize ray-trace shader program", theGlContext);
1560       }
1561     }
1562
1563     {
1564       if (!aShaderFolder.IsEmpty())
1565       {
1566         const TCollection_AsciiString aFiles[] = { aShaderFolder + "/RaytraceBase.fs", aShaderFolder + "/RaytraceSmooth.fs", "" };
1567         if (!myPostFSAAShaderSource.LoadFromFiles (aFiles, aPrefixString))
1568         {
1569           return safeFailBack (myPostFSAAShaderSource.ErrorDescription(), theGlContext);
1570         }
1571       }
1572       else
1573       {
1574         const TCollection_AsciiString aSrcShaders[] = { Shaders_RaytraceBase_fs, Shaders_RaytraceSmooth_fs, "" };
1575         myPostFSAAShaderSource.LoadFromStrings (aSrcShaders, aPrefixString);
1576       }
1577
1578       Handle(OpenGl_ShaderObject) aBasicVertShader = initShader (GL_VERTEX_SHADER, aBasicVertShaderSrc, theGlContext);
1579       if (aBasicVertShader.IsNull())
1580       {
1581         return safeFailBack ("Failed to initialize FSAA vertex shader", theGlContext);
1582       }
1583
1584       myPostFSAAShader = initShader (GL_FRAGMENT_SHADER, myPostFSAAShaderSource, theGlContext);
1585       if (myPostFSAAShader.IsNull())
1586       {
1587         aBasicVertShader->Release (theGlContext.operator->());
1588         return safeFailBack ("Failed to initialize FSAA fragment shader", theGlContext);
1589       }
1590
1591       myPostFSAAProgram = initProgram (theGlContext, aBasicVertShader, myPostFSAAShader, "fsaa");
1592       if (myPostFSAAProgram.IsNull())
1593       {
1594         return safeFailBack ("Failed to initialize FSAA shader program", theGlContext);
1595       }
1596     }
1597
1598     {
1599       if (!aShaderFolder.IsEmpty())
1600       {
1601         const TCollection_AsciiString aFiles[] = { aShaderFolder + "/Display.fs", "" };
1602         if (!myOutImageShaderSource.LoadFromFiles (aFiles, aPrefixString))
1603         {
1604           return safeFailBack (myOutImageShaderSource.ErrorDescription(), theGlContext);
1605         }
1606       }
1607       else
1608       {
1609         const TCollection_AsciiString aSrcShaders[] = { Shaders_Display_fs, "" };
1610         myOutImageShaderSource.LoadFromStrings (aSrcShaders, aPrefixString);
1611       }
1612
1613       Handle(OpenGl_ShaderObject) aBasicVertShader = initShader (GL_VERTEX_SHADER, aBasicVertShaderSrc, theGlContext);
1614       if (aBasicVertShader.IsNull())
1615       {
1616         return safeFailBack ("Failed to set vertex shader source", theGlContext);
1617       }
1618
1619       myOutImageShader = initShader (GL_FRAGMENT_SHADER, myOutImageShaderSource, theGlContext);
1620       if (myOutImageShader.IsNull())
1621       {
1622         aBasicVertShader->Release (theGlContext.operator->());
1623         return safeFailBack ("Failed to set display fragment shader source", theGlContext);
1624       }
1625
1626       myOutImageProgram = initProgram (theGlContext, aBasicVertShader, myOutImageShader, "out");
1627       if (myOutImageProgram.IsNull())
1628       {
1629         return safeFailBack ("Failed to initialize display shader program", theGlContext);
1630       }
1631     }
1632   }
1633
1634   if (myRaytraceInitStatus == OpenGl_RT_NONE || aToRebuildShaders)
1635   {
1636     for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
1637     {
1638       Handle(OpenGl_ShaderProgram)& aShaderProgram =
1639         (anIndex == 0) ? myRaytraceProgram : myPostFSAAProgram;
1640
1641       theGlContext->BindProgram (aShaderProgram);
1642
1643       aShaderProgram->SetSampler (theGlContext,
1644         "uSceneMinPointTexture", OpenGl_RT_SceneMinPointTexture);
1645       aShaderProgram->SetSampler (theGlContext,
1646         "uSceneMaxPointTexture", OpenGl_RT_SceneMaxPointTexture);
1647       aShaderProgram->SetSampler (theGlContext,
1648         "uSceneNodeInfoTexture", OpenGl_RT_SceneNodeInfoTexture);
1649       aShaderProgram->SetSampler (theGlContext,
1650         "uGeometryVertexTexture", OpenGl_RT_GeometryVertexTexture);
1651       aShaderProgram->SetSampler (theGlContext,
1652         "uGeometryNormalTexture", OpenGl_RT_GeometryNormalTexture);
1653       aShaderProgram->SetSampler (theGlContext,
1654         "uGeometryTexCrdTexture", OpenGl_RT_GeometryTexCrdTexture);
1655       aShaderProgram->SetSampler (theGlContext,
1656         "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture);
1657       aShaderProgram->SetSampler (theGlContext, 
1658         "uSceneTransformTexture", OpenGl_RT_SceneTransformTexture);
1659       aShaderProgram->SetSampler (theGlContext,
1660         "uEnvironmentMapTexture", OpenGl_RT_EnvironmentMapTexture);
1661       aShaderProgram->SetSampler (theGlContext,
1662         "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
1663       aShaderProgram->SetSampler (theGlContext,
1664         "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
1665
1666       if (anIndex == 1)
1667       {
1668         aShaderProgram->SetSampler (theGlContext,
1669           "uFSAAInputTexture", OpenGl_RT_FsaaInputTexture);
1670       }
1671       else
1672       {
1673         aShaderProgram->SetSampler (theGlContext,
1674           "uAccumTexture", OpenGl_RT_PrevAccumTexture);
1675       }
1676
1677       myUniformLocations[anIndex][OpenGl_RT_aPosition] =
1678         aShaderProgram->GetAttributeLocation (theGlContext, "occVertex");
1679
1680       myUniformLocations[anIndex][OpenGl_RT_uOriginLB] =
1681         aShaderProgram->GetUniformLocation (theGlContext, "uOriginLB");
1682       myUniformLocations[anIndex][OpenGl_RT_uOriginRB] =
1683         aShaderProgram->GetUniformLocation (theGlContext, "uOriginRB");
1684       myUniformLocations[anIndex][OpenGl_RT_uOriginLT] =
1685         aShaderProgram->GetUniformLocation (theGlContext, "uOriginLT");
1686       myUniformLocations[anIndex][OpenGl_RT_uOriginRT] =
1687         aShaderProgram->GetUniformLocation (theGlContext, "uOriginRT");
1688       myUniformLocations[anIndex][OpenGl_RT_uDirectLB] =
1689         aShaderProgram->GetUniformLocation (theGlContext, "uDirectLB");
1690       myUniformLocations[anIndex][OpenGl_RT_uDirectRB] =
1691         aShaderProgram->GetUniformLocation (theGlContext, "uDirectRB");
1692       myUniformLocations[anIndex][OpenGl_RT_uDirectLT] =
1693         aShaderProgram->GetUniformLocation (theGlContext, "uDirectLT");
1694       myUniformLocations[anIndex][OpenGl_RT_uDirectRT] =
1695         aShaderProgram->GetUniformLocation (theGlContext, "uDirectRT");
1696       myUniformLocations[anIndex][OpenGl_RT_uViewPrMat] =
1697         aShaderProgram->GetUniformLocation (theGlContext, "uViewMat");
1698       myUniformLocations[anIndex][OpenGl_RT_uUnviewMat] =
1699         aShaderProgram->GetUniformLocation (theGlContext, "uUnviewMat");
1700
1701       myUniformLocations[anIndex][OpenGl_RT_uSceneRad] =
1702         aShaderProgram->GetUniformLocation (theGlContext, "uSceneRadius");
1703       myUniformLocations[anIndex][OpenGl_RT_uSceneEps] =
1704         aShaderProgram->GetUniformLocation (theGlContext, "uSceneEpsilon");
1705       myUniformLocations[anIndex][OpenGl_RT_uLightCount] =
1706         aShaderProgram->GetUniformLocation (theGlContext, "uLightCount");
1707       myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] =
1708         aShaderProgram->GetUniformLocation (theGlContext, "uGlobalAmbient");
1709
1710       myUniformLocations[anIndex][OpenGl_RT_uOffsetX] =
1711         aShaderProgram->GetUniformLocation (theGlContext, "uOffsetX");
1712       myUniformLocations[anIndex][OpenGl_RT_uOffsetY] =
1713         aShaderProgram->GetUniformLocation (theGlContext, "uOffsetY");
1714       myUniformLocations[anIndex][OpenGl_RT_uSamples] =
1715         aShaderProgram->GetUniformLocation (theGlContext, "uSamples");
1716
1717       myUniformLocations[anIndex][OpenGl_RT_uTexSamplersArray] =
1718         aShaderProgram->GetUniformLocation (theGlContext, "uTextureSamplers");
1719
1720       myUniformLocations[anIndex][OpenGl_RT_uShadowsEnabled] =
1721         aShaderProgram->GetUniformLocation (theGlContext, "uShadowsEnabled");
1722       myUniformLocations[anIndex][OpenGl_RT_uReflectEnabled] =
1723         aShaderProgram->GetUniformLocation (theGlContext, "uReflectEnabled");
1724       myUniformLocations[anIndex][OpenGl_RT_uSphereMapEnabled] =
1725         aShaderProgram->GetUniformLocation (theGlContext, "uSphereMapEnabled");
1726       myUniformLocations[anIndex][OpenGl_RT_uSphereMapForBack] =
1727         aShaderProgram->GetUniformLocation (theGlContext, "uSphereMapForBack");
1728       myUniformLocations[anIndex][OpenGl_RT_uBlockedRngEnabled] =
1729         aShaderProgram->GetUniformLocation (theGlContext, "uBlockedRngEnabled");
1730
1731       myUniformLocations[anIndex][OpenGl_RT_uWinSizeX] =
1732         aShaderProgram->GetUniformLocation (theGlContext, "uWinSizeX");
1733       myUniformLocations[anIndex][OpenGl_RT_uWinSizeY] =
1734         aShaderProgram->GetUniformLocation (theGlContext, "uWinSizeY");
1735
1736       myUniformLocations[anIndex][OpenGl_RT_uAccumSamples] =
1737         aShaderProgram->GetUniformLocation (theGlContext, "uAccumSamples");
1738       myUniformLocations[anIndex][OpenGl_RT_uFrameRndSeed] =
1739         aShaderProgram->GetUniformLocation (theGlContext, "uFrameRndSeed");
1740
1741       myUniformLocations[anIndex][OpenGl_RT_uRenderImage] =
1742         aShaderProgram->GetUniformLocation (theGlContext, "uRenderImage");
1743       myUniformLocations[anIndex][OpenGl_RT_uTilesImage] =
1744         aShaderProgram->GetUniformLocation (theGlContext, "uTilesImage");
1745       myUniformLocations[anIndex][OpenGl_RT_uOffsetImage] =
1746         aShaderProgram->GetUniformLocation (theGlContext, "uOffsetImage");
1747       myUniformLocations[anIndex][OpenGl_RT_uTileSize] =
1748         aShaderProgram->GetUniformLocation (theGlContext, "uTileSize");
1749       myUniformLocations[anIndex][OpenGl_RT_uVarianceScaleFactor] =
1750         aShaderProgram->GetUniformLocation (theGlContext, "uVarianceScaleFactor");
1751
1752       myUniformLocations[anIndex][OpenGl_RT_uBackColorTop] =
1753         aShaderProgram->GetUniformLocation (theGlContext, "uBackColorTop");
1754       myUniformLocations[anIndex][OpenGl_RT_uBackColorBot] =
1755         aShaderProgram->GetUniformLocation (theGlContext, "uBackColorBot");
1756
1757       myUniformLocations[anIndex][OpenGl_RT_uMaxRadiance] =
1758         aShaderProgram->GetUniformLocation (theGlContext, "uMaxRadiance");
1759     }
1760
1761     theGlContext->BindProgram (myOutImageProgram);
1762
1763     myOutImageProgram->SetSampler (theGlContext,
1764       "uInputTexture", OpenGl_RT_PrevAccumTexture);
1765
1766     myOutImageProgram->SetSampler (theGlContext,
1767       "uDepthTexture", OpenGl_RT_RaytraceDepthTexture);
1768
1769     theGlContext->BindProgram (NULL);
1770   }
1771
1772   if (myRaytraceInitStatus != OpenGl_RT_NONE)
1773   {
1774     return myRaytraceInitStatus == OpenGl_RT_INIT;
1775   }
1776
1777   const GLfloat aVertices[] = { -1.f, -1.f,  0.f,
1778                                 -1.f,  1.f,  0.f,
1779                                  1.f,  1.f,  0.f,
1780                                  1.f,  1.f,  0.f,
1781                                  1.f, -1.f,  0.f,
1782                                 -1.f, -1.f,  0.f };
1783
1784   myRaytraceScreenQuad.Init (theGlContext, 3, 6, aVertices);
1785
1786   myRaytraceInitStatus = OpenGl_RT_INIT; // initialized in normal way
1787
1788   return Standard_True;
1789 }
1790
1791 // =======================================================================
1792 // function : nullifyResource
1793 // purpose  : Releases OpenGL resource
1794 // =======================================================================
1795 template <class T>
1796 inline void nullifyResource (const Handle(OpenGl_Context)& theGlContext, Handle(T)& theResource)
1797 {
1798   if (!theResource.IsNull())
1799   {
1800     theResource->Release (theGlContext.operator->());
1801     theResource.Nullify();
1802   }
1803 }
1804
1805 // =======================================================================
1806 // function : releaseRaytraceResources
1807 // purpose  : Releases OpenGL/GLSL shader programs
1808 // =======================================================================
1809 void OpenGl_View::releaseRaytraceResources (const Handle(OpenGl_Context)& theGlContext, const Standard_Boolean theToRebuild)
1810 {
1811   // release shader resources
1812   nullifyResource (theGlContext, myRaytraceShader);
1813   nullifyResource (theGlContext, myPostFSAAShader);
1814
1815   nullifyResource (theGlContext, myRaytraceProgram);
1816   nullifyResource (theGlContext, myPostFSAAProgram);
1817   nullifyResource (theGlContext, myOutImageProgram);
1818
1819   if (!theToRebuild) // complete release
1820   {
1821     myRaytraceFBO1[0]->Release (theGlContext.operator->());
1822     myRaytraceFBO1[1]->Release (theGlContext.operator->());
1823     myRaytraceFBO2[0]->Release (theGlContext.operator->());
1824     myRaytraceFBO2[1]->Release (theGlContext.operator->());
1825
1826     nullifyResource (theGlContext, myRaytraceOutputTexture[0]);
1827     nullifyResource (theGlContext, myRaytraceOutputTexture[1]);
1828
1829     nullifyResource (theGlContext, myRaytraceTileOffsetsTexture[0]);
1830     nullifyResource (theGlContext, myRaytraceTileOffsetsTexture[1]);
1831     nullifyResource (theGlContext, myRaytraceVisualErrorTexture[0]);
1832     nullifyResource (theGlContext, myRaytraceVisualErrorTexture[1]);
1833     nullifyResource (theGlContext, myRaytraceTileSamplesTexture[0]);
1834     nullifyResource (theGlContext, myRaytraceTileSamplesTexture[1]);
1835
1836     nullifyResource (theGlContext, mySceneNodeInfoTexture);
1837     nullifyResource (theGlContext, mySceneMinPointTexture);
1838     nullifyResource (theGlContext, mySceneMaxPointTexture);
1839
1840     nullifyResource (theGlContext, myGeometryVertexTexture);
1841     nullifyResource (theGlContext, myGeometryNormalTexture);
1842     nullifyResource (theGlContext, myGeometryTexCrdTexture);
1843     nullifyResource (theGlContext, myGeometryTriangTexture);
1844     nullifyResource (theGlContext, mySceneTransformTexture);
1845
1846     nullifyResource (theGlContext, myRaytraceLightSrcTexture);
1847     nullifyResource (theGlContext, myRaytraceMaterialTexture);
1848
1849     myRaytraceGeometry.ReleaseResources (theGlContext);
1850
1851     if (myRaytraceScreenQuad.IsValid ())
1852     {
1853       myRaytraceScreenQuad.Release (theGlContext.operator->());
1854     }
1855   }
1856 }
1857
1858 // =======================================================================
1859 // function : updateRaytraceBuffers
1860 // purpose  : Updates auxiliary OpenGL frame buffers.
1861 // =======================================================================
1862 Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer        theSizeX,
1863                                                      const Standard_Integer        theSizeY,
1864                                                      const Handle(OpenGl_Context)& theGlContext)
1865 {
1866   // Auxiliary buffers are not used
1867   if (!myRaytraceParameters.GlobalIllumination && !myRenderParams.IsAntialiasingEnabled)
1868   {
1869     myRaytraceFBO1[0]->Release (theGlContext.operator->());
1870     myRaytraceFBO2[0]->Release (theGlContext.operator->());
1871     myRaytraceFBO1[1]->Release (theGlContext.operator->());
1872     myRaytraceFBO2[1]->Release (theGlContext.operator->());
1873
1874     return Standard_True;
1875   }
1876
1877   if (myRaytraceParameters.AdaptiveScreenSampling)
1878   {
1879     Graphic3d_Vec2i aMaxViewport = myTileSampler.OffsetTilesViewportMax().cwiseMax (Graphic3d_Vec2i (theSizeX, theSizeY));
1880     myRaytraceFBO1[0]->InitLazy (theGlContext, aMaxViewport.x(), aMaxViewport.y(), GL_RGBA32F, myFboDepthFormat);
1881     myRaytraceFBO2[0]->InitLazy (theGlContext, aMaxViewport.x(), aMaxViewport.y(), GL_RGBA32F, myFboDepthFormat);
1882     if (myRaytraceFBO1[1]->IsValid()) // second FBO not needed
1883     {
1884       myRaytraceFBO1[1]->Release (theGlContext.operator->());
1885       myRaytraceFBO2[1]->Release (theGlContext.operator->());
1886     }
1887   }
1888
1889   for (int aViewIter = 0; aViewIter < 2; ++aViewIter)
1890   {
1891     if (myRaytraceTileOffsetsTexture[aViewIter].IsNull())
1892     {
1893       myRaytraceOutputTexture[aViewIter] = new OpenGl_Texture();
1894       myRaytraceVisualErrorTexture[aViewIter] = new OpenGl_Texture();
1895       myRaytraceTileSamplesTexture[aViewIter] = new OpenGl_Texture();
1896       myRaytraceTileOffsetsTexture[aViewIter] = new OpenGl_Texture();
1897     }
1898
1899     if (aViewIter == 1
1900      && myCamera->ProjectionType() != Graphic3d_Camera::Projection_Stereo)
1901     {
1902       myRaytraceFBO1[1]->Release (theGlContext.operator->());
1903       myRaytraceFBO2[1]->Release (theGlContext.operator->());
1904       myRaytraceOutputTexture[1]->Release (theGlContext.operator->());
1905       myRaytraceVisualErrorTexture[1]->Release (theGlContext.operator->());
1906       myRaytraceTileOffsetsTexture[1]->Release (theGlContext.operator->());
1907       continue;
1908     }
1909
1910     if (myRaytraceParameters.AdaptiveScreenSampling)
1911     {
1912       if (myRaytraceOutputTexture[aViewIter]->SizeX() / 3 == theSizeX
1913        && myRaytraceOutputTexture[aViewIter]->SizeY() / 2 == theSizeY
1914        && myRaytraceVisualErrorTexture[aViewIter]->SizeX() == myTileSampler.NbTilesX()
1915        && myRaytraceVisualErrorTexture[aViewIter]->SizeY() == myTileSampler.NbTilesY())
1916       {
1917         if (myRaytraceParameters.AdaptiveScreenSamplingAtomic)
1918         {
1919           continue; // offsets texture is dynamically resized
1920         }
1921         else if (myRaytraceTileSamplesTexture[aViewIter]->SizeX() == myTileSampler.NbTilesX()
1922               && myRaytraceTileSamplesTexture[aViewIter]->SizeY() == myTileSampler.NbTilesY())
1923         {
1924           continue;
1925         }
1926       }
1927
1928       myAccumFrames = 0;
1929
1930       // Due to limitations of OpenGL image load-store extension
1931       // atomic operations are supported only for single-channel
1932       // images, so we define GL_R32F image. It is used as array
1933       // of 6D floating point vectors:
1934       // 0 - R color channel
1935       // 1 - G color channel
1936       // 2 - B color channel
1937       // 3 - hit time transformed into OpenGL NDC space
1938       // 4 - luminance accumulated for odd samples only
1939       myRaytraceOutputTexture[aViewIter]->InitRectangle (theGlContext, theSizeX * 3, theSizeY * 2, OpenGl_TextureFormat::Create<GLfloat, 1>());
1940
1941       // workaround for some NVIDIA drivers
1942       myRaytraceVisualErrorTexture[aViewIter]->Release (theGlContext.operator->());
1943       myRaytraceTileSamplesTexture[aViewIter]->Release (theGlContext.operator->());
1944       myRaytraceVisualErrorTexture[aViewIter]->Init (theGlContext, GL_R32I, GL_RED_INTEGER, GL_INT,
1945                                                      myTileSampler.NbTilesX(), myTileSampler.NbTilesY(), Graphic3d_TOT_2D);
1946       if (!myRaytraceParameters.AdaptiveScreenSamplingAtomic)
1947       {
1948         myRaytraceTileSamplesTexture[aViewIter]->Init (theGlContext, GL_R32I, GL_RED_INTEGER, GL_INT,
1949                                                        myTileSampler.NbTilesX(), myTileSampler.NbTilesY(), Graphic3d_TOT_2D);
1950       }
1951     }
1952     else // non-adaptive mode
1953     {
1954       if (myRaytraceFBO1[aViewIter]->GetSizeX() != theSizeX
1955        || myRaytraceFBO1[aViewIter]->GetSizeY() != theSizeY)
1956       {
1957         myAccumFrames = 0; // accumulation should be restarted
1958       }
1959
1960       myRaytraceFBO1[aViewIter]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
1961       myRaytraceFBO2[aViewIter]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
1962     }
1963   }
1964   return Standard_True;
1965 }
1966
1967 // =======================================================================
1968 // function : updateCamera
1969 // purpose  : Generates viewing rays for corners of screen quad
1970 // =======================================================================
1971 void OpenGl_View::updateCamera (const OpenGl_Mat4& theOrientation,
1972                                 const OpenGl_Mat4& theViewMapping,
1973                                 OpenGl_Vec3*       theOrigins,
1974                                 OpenGl_Vec3*       theDirects,
1975                                 OpenGl_Mat4&       theViewPr,
1976                                 OpenGl_Mat4&       theUnview)
1977 {
1978   // compute view-projection matrix
1979   theViewPr = theViewMapping * theOrientation;
1980
1981   // compute inverse view-projection matrix
1982   theViewPr.Inverted (theUnview);
1983
1984   Standard_Integer aOriginIndex = 0;
1985   Standard_Integer aDirectIndex = 0;
1986
1987   for (Standard_Integer aY = -1; aY <= 1; aY += 2)
1988   {
1989     for (Standard_Integer aX = -1; aX <= 1; aX += 2)
1990     {
1991       OpenGl_Vec4 aOrigin (GLfloat(aX),
1992                            GLfloat(aY),
1993                            -1.0f,
1994                            1.0f);
1995
1996       aOrigin = theUnview * aOrigin;
1997
1998       aOrigin.x() = aOrigin.x() / aOrigin.w();
1999       aOrigin.y() = aOrigin.y() / aOrigin.w();
2000       aOrigin.z() = aOrigin.z() / aOrigin.w();
2001
2002       OpenGl_Vec4 aDirect (GLfloat(aX),
2003                            GLfloat(aY),
2004                            1.0f,
2005                            1.0f);
2006
2007       aDirect = theUnview * aDirect;
2008
2009       aDirect.x() = aDirect.x() / aDirect.w();
2010       aDirect.y() = aDirect.y() / aDirect.w();
2011       aDirect.z() = aDirect.z() / aDirect.w();
2012
2013       aDirect = aDirect - aOrigin;
2014
2015       theOrigins[aOriginIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aOrigin.x()),
2016                                                 static_cast<GLfloat> (aOrigin.y()),
2017                                                 static_cast<GLfloat> (aOrigin.z()));
2018
2019       theDirects[aDirectIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aDirect.x()),
2020                                                 static_cast<GLfloat> (aDirect.y()),
2021                                                 static_cast<GLfloat> (aDirect.z()));
2022     }
2023   }
2024 }
2025
2026 // =======================================================================
2027 // function : updatePerspCameraPT
2028 // purpose  : Generates viewing rays (path tracing, perspective camera)
2029 // =======================================================================
2030 void OpenGl_View::updatePerspCameraPT (const OpenGl_Mat4&           theOrientation,
2031                                        const OpenGl_Mat4&           theViewMapping,
2032                                        Graphic3d_Camera::Projection theProjection,
2033                                        OpenGl_Mat4&                 theViewPr,
2034                                        OpenGl_Mat4&                 theUnview,
2035                                        const int                    theWinSizeX,
2036                                        const int                    theWinSizeY)
2037 {
2038   // compute view-projection matrix
2039   theViewPr = theViewMapping * theOrientation;
2040
2041   // compute inverse view-projection matrix
2042   theViewPr.Inverted(theUnview);
2043   
2044   // get camera stereo params
2045   float anIOD = myCamera->GetIODType() == Graphic3d_Camera::IODType_Relative
2046     ? static_cast<float> (myCamera->IOD() * myCamera->Distance())
2047     : static_cast<float> (myCamera->IOD());
2048
2049   float aZFocus = myCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
2050     ? static_cast<float> (myCamera->ZFocus() * myCamera->Distance())
2051     : static_cast<float> (myCamera->ZFocus());
2052
2053   // get camera view vectors
2054   const gp_Pnt anOrig = myCamera->Eye();
2055
2056   myEyeOrig = OpenGl_Vec3 (static_cast<float> (anOrig.X()),
2057                            static_cast<float> (anOrig.Y()),
2058                            static_cast<float> (anOrig.Z()));
2059
2060   const gp_Dir aView = myCamera->Direction();
2061
2062   OpenGl_Vec3 anEyeViewMono = OpenGl_Vec3 (static_cast<float> (aView.X()),
2063                                            static_cast<float> (aView.Y()),
2064                                            static_cast<float> (aView.Z()));
2065
2066   const gp_Dir anUp = myCamera->Up();
2067
2068   myEyeVert = OpenGl_Vec3 (static_cast<float> (anUp.X()),
2069                            static_cast<float> (anUp.Y()),
2070                            static_cast<float> (anUp.Z()));
2071
2072   myEyeSide = OpenGl_Vec3::Cross (anEyeViewMono, myEyeVert);
2073
2074   const double aScaleY = tan (myCamera->FOVy() / 360 * M_PI);
2075   const double aScaleX = theWinSizeX * aScaleY / theWinSizeY;
2076  
2077   myEyeSize = OpenGl_Vec2 (static_cast<float> (aScaleX),
2078                            static_cast<float> (aScaleY));
2079
2080   if (theProjection == Graphic3d_Camera::Projection_Perspective)
2081   {
2082     myEyeView = anEyeViewMono;
2083   }
2084   else // stereo camera
2085   {
2086     // compute z-focus point
2087     OpenGl_Vec3 aZFocusPoint = myEyeOrig + anEyeViewMono * aZFocus;
2088
2089     // compute stereo camera shift
2090     float aDx = theProjection == Graphic3d_Camera::Projection_MonoRightEye ? 0.5f * anIOD : -0.5f * anIOD;
2091     myEyeOrig += myEyeSide.Normalized() * aDx;
2092
2093     // estimate new camera direction vector and correct its length
2094     myEyeView = (aZFocusPoint - myEyeOrig).Normalized();
2095     myEyeView *= 1.f / anEyeViewMono.Dot (myEyeView);
2096   }
2097 }
2098
2099 // =======================================================================
2100 // function : uploadRaytraceData
2101 // purpose  : Uploads ray-trace data to the GPU
2102 // =======================================================================
2103 Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& theGlContext)
2104 {
2105   if (!theGlContext->IsGlGreaterEqual (3, 1))
2106   {
2107 #ifdef RAY_TRACE_PRINT_INFO
2108     std::cout << "Error: OpenGL version is less than 3.1" << std::endl;
2109 #endif
2110     return Standard_False;
2111   }
2112
2113   myAccumFrames = 0; // accumulation should be restarted
2114
2115   /////////////////////////////////////////////////////////////////////////////
2116   // Prepare OpenGL textures
2117
2118   if (theGlContext->arbTexBindless != NULL)
2119   {
2120     // If OpenGL driver supports bindless textures we need
2121     // to get unique 64- bit handles for using on the GPU
2122     if (!myRaytraceGeometry.UpdateTextureHandles (theGlContext))
2123     {
2124 #ifdef RAY_TRACE_PRINT_INFO
2125       std::cout << "Error: Failed to get OpenGL texture handles" << std::endl;
2126 #endif
2127       return Standard_False;
2128     }
2129   }
2130
2131   /////////////////////////////////////////////////////////////////////////////
2132   // Create OpenGL BVH buffers
2133
2134   if (mySceneNodeInfoTexture.IsNull()) // create scene BVH buffers
2135   {
2136     mySceneNodeInfoTexture  = new OpenGl_TextureBufferArb;
2137     mySceneMinPointTexture  = new OpenGl_TextureBufferArb;
2138     mySceneMaxPointTexture  = new OpenGl_TextureBufferArb;
2139     mySceneTransformTexture = new OpenGl_TextureBufferArb;
2140
2141     if (!mySceneNodeInfoTexture->Create  (theGlContext)
2142      || !mySceneMinPointTexture->Create  (theGlContext)
2143      || !mySceneMaxPointTexture->Create  (theGlContext)
2144      || !mySceneTransformTexture->Create (theGlContext))
2145     {
2146 #ifdef RAY_TRACE_PRINT_INFO
2147       std::cout << "Error: Failed to create scene BVH buffers" << std::endl;
2148 #endif
2149       return Standard_False;
2150     }
2151   }
2152
2153   if (myGeometryVertexTexture.IsNull()) // create geometry buffers
2154   {
2155     myGeometryVertexTexture = new OpenGl_TextureBufferArb;
2156     myGeometryNormalTexture = new OpenGl_TextureBufferArb;
2157     myGeometryTexCrdTexture = new OpenGl_TextureBufferArb;
2158     myGeometryTriangTexture = new OpenGl_TextureBufferArb;
2159
2160     if (!myGeometryVertexTexture->Create (theGlContext)
2161      || !myGeometryNormalTexture->Create (theGlContext)
2162      || !myGeometryTexCrdTexture->Create (theGlContext)
2163      || !myGeometryTriangTexture->Create (theGlContext))
2164     {
2165 #ifdef RAY_TRACE_PRINT_INFO
2166       std::cout << "Error: Failed to create buffers for triangulation data" << std::endl;
2167 #endif
2168       return Standard_False;
2169     }
2170   }
2171
2172   if (myRaytraceMaterialTexture.IsNull()) // create material buffer
2173   {
2174     myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
2175
2176     if (!myRaytraceMaterialTexture->Create (theGlContext))
2177     {
2178 #ifdef RAY_TRACE_PRINT_INFO
2179       std::cout << "Error: Failed to create buffers for material data" << std::endl;
2180 #endif
2181       return Standard_False;
2182     }
2183   }
2184   
2185   /////////////////////////////////////////////////////////////////////////////
2186   // Write transform buffer
2187
2188   BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()];
2189
2190   bool aResult = true;
2191
2192   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
2193   {
2194     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
2195       myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
2196
2197     const BVH_Transform<Standard_ShortReal, 4>* aTransform = dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (aTriangleSet->Properties().get());
2198     Standard_ASSERT_RETURN (aTransform != NULL,
2199       "OpenGl_TriangleSet does not contain transform", Standard_False);
2200
2201     aNodeTransforms[anElemIndex] = aTransform->Inversed();
2202   }
2203
2204   aResult &= mySceneTransformTexture->Init (theGlContext, 4,
2205     myRaytraceGeometry.Size() * 4, reinterpret_cast<const GLfloat*> (aNodeTransforms));
2206
2207   delete [] aNodeTransforms;
2208
2209   /////////////////////////////////////////////////////////////////////////////
2210   // Write geometry and bottom-level BVH buffers
2211
2212   Standard_Size aTotalVerticesNb = 0;
2213   Standard_Size aTotalElementsNb = 0;
2214   Standard_Size aTotalBVHNodesNb = 0;
2215
2216   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
2217   {
2218     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
2219       myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
2220
2221     Standard_ASSERT_RETURN (aTriangleSet != NULL,
2222       "Error: Failed to get triangulation of OpenGL element", Standard_False);
2223
2224     aTotalVerticesNb += aTriangleSet->Vertices.size();
2225     aTotalElementsNb += aTriangleSet->Elements.size();
2226
2227     Standard_ASSERT_RETURN (!aTriangleSet->QuadBVH().IsNull(),
2228       "Error: Failed to get bottom-level BVH of OpenGL element", Standard_False);
2229
2230     aTotalBVHNodesNb += aTriangleSet->QuadBVH()->NodeInfoBuffer().size();
2231   }
2232
2233   aTotalBVHNodesNb += myRaytraceGeometry.QuadBVH()->NodeInfoBuffer().size();
2234
2235   if (aTotalBVHNodesNb != 0)
2236   {
2237     aResult &= mySceneNodeInfoTexture->Init (
2238       theGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*>  (NULL));
2239     aResult &= mySceneMinPointTexture->Init (
2240       theGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
2241     aResult &= mySceneMaxPointTexture->Init (
2242       theGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
2243   }
2244
2245   if (!aResult)
2246   {
2247 #ifdef RAY_TRACE_PRINT_INFO
2248     std::cout << "Error: Failed to upload buffers for bottom-level scene BVH" << std::endl;
2249 #endif
2250     return Standard_False;
2251   }
2252
2253   if (aTotalElementsNb != 0)
2254   {
2255     aResult &= myGeometryTriangTexture->Init (
2256       theGlContext, 4, GLsizei (aTotalElementsNb), static_cast<const GLuint*> (NULL));
2257   }
2258
2259   if (aTotalVerticesNb != 0)
2260   {
2261     aResult &= myGeometryVertexTexture->Init (
2262       theGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
2263     aResult &= myGeometryNormalTexture->Init (
2264       theGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
2265     aResult &= myGeometryTexCrdTexture->Init (
2266       theGlContext, 2, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
2267   }
2268
2269   if (!aResult)
2270   {
2271 #ifdef RAY_TRACE_PRINT_INFO
2272     std::cout << "Error: Failed to upload buffers for scene geometry" << std::endl;
2273 #endif
2274     return Standard_False;
2275   }
2276
2277   const QuadBvhHandle& aBVH = myRaytraceGeometry.QuadBVH();
2278
2279   if (aBVH->Length() > 0)
2280   {
2281     aResult &= mySceneNodeInfoTexture->SubData (theGlContext, 0, aBVH->Length(),
2282       reinterpret_cast<const GLuint*> (&aBVH->NodeInfoBuffer().front()));
2283     aResult &= mySceneMinPointTexture->SubData (theGlContext, 0, aBVH->Length(),
2284       reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
2285     aResult &= mySceneMaxPointTexture->SubData (theGlContext, 0, aBVH->Length(),
2286       reinterpret_cast<const GLfloat*> (&aBVH->MaxPointBuffer().front()));
2287   }
2288
2289   for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
2290   {
2291     if (!aBVH->IsOuter (aNodeIdx))
2292       continue;
2293
2294     OpenGl_TriangleSet* aTriangleSet = myRaytraceGeometry.TriangleSet (aNodeIdx);
2295
2296     Standard_ASSERT_RETURN (aTriangleSet != NULL,
2297       "Error: Failed to get triangulation of OpenGL element", Standard_False);
2298
2299     Standard_Integer aBVHOffset = myRaytraceGeometry.AccelerationOffset (aNodeIdx);
2300
2301     Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
2302       "Error: Failed to get offset for bottom-level BVH", Standard_False);
2303
2304     const Standard_Integer aBvhBuffersSize = aTriangleSet->QuadBVH()->Length();
2305
2306     if (aBvhBuffersSize != 0)
2307     {
2308       aResult &= mySceneNodeInfoTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
2309         reinterpret_cast<const GLuint*> (&aTriangleSet->QuadBVH()->NodeInfoBuffer().front()));
2310       aResult &= mySceneMinPointTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
2311         reinterpret_cast<const GLfloat*> (&aTriangleSet->QuadBVH()->MinPointBuffer().front()));
2312       aResult &= mySceneMaxPointTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
2313         reinterpret_cast<const GLfloat*> (&aTriangleSet->QuadBVH()->MaxPointBuffer().front()));
2314
2315       if (!aResult)
2316       {
2317 #ifdef RAY_TRACE_PRINT_INFO
2318         std::cout << "Error: Failed to upload buffers for bottom-level scene BVHs" << std::endl;
2319 #endif
2320         return Standard_False;
2321       }
2322     }
2323
2324     const Standard_Integer aVerticesOffset = myRaytraceGeometry.VerticesOffset (aNodeIdx);
2325
2326     Standard_ASSERT_RETURN (aVerticesOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
2327       "Error: Failed to get offset for triangulation vertices of OpenGL element", Standard_False);
2328
2329     if (!aTriangleSet->Vertices.empty())
2330     {
2331       aResult &= myGeometryNormalTexture->SubData (theGlContext, aVerticesOffset,
2332         GLsizei (aTriangleSet->Normals.size()), reinterpret_cast<const GLfloat*> (&aTriangleSet->Normals.front()));
2333       aResult &= myGeometryTexCrdTexture->SubData (theGlContext, aVerticesOffset,
2334         GLsizei (aTriangleSet->TexCrds.size()), reinterpret_cast<const GLfloat*> (&aTriangleSet->TexCrds.front()));
2335       aResult &= myGeometryVertexTexture->SubData (theGlContext, aVerticesOffset,
2336         GLsizei (aTriangleSet->Vertices.size()), reinterpret_cast<const GLfloat*> (&aTriangleSet->Vertices.front()));
2337     }
2338
2339     const Standard_Integer anElementsOffset = myRaytraceGeometry.ElementsOffset (aNodeIdx);
2340
2341     Standard_ASSERT_RETURN (anElementsOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
2342       "Error: Failed to get offset for triangulation elements of OpenGL element", Standard_False);
2343
2344     if (!aTriangleSet->Elements.empty())
2345     {
2346       aResult &= myGeometryTriangTexture->SubData (theGlContext, anElementsOffset, GLsizei (aTriangleSet->Elements.size()),
2347                                                    reinterpret_cast<const GLuint*> (&aTriangleSet->Elements.front()));
2348     }
2349
2350     if (!aResult)
2351     {
2352 #ifdef RAY_TRACE_PRINT_INFO
2353       std::cout << "Error: Failed to upload triangulation buffers for OpenGL element" << std::endl;
2354 #endif
2355       return Standard_False;
2356     }
2357   }
2358
2359   /////////////////////////////////////////////////////////////////////////////
2360   // Write material buffer
2361
2362   if (myRaytraceGeometry.Materials.size() != 0)
2363   {
2364     aResult &= myRaytraceMaterialTexture->Init (theGlContext, 4,
2365       GLsizei (myRaytraceGeometry.Materials.size() * 19), myRaytraceGeometry.Materials.front().Packed());
2366
2367     if (!aResult)
2368     {
2369 #ifdef RAY_TRACE_PRINT_INFO
2370       std::cout << "Error: Failed to upload material buffer" << std::endl;
2371 #endif
2372       return Standard_False;
2373     }
2374   }
2375
2376   myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0;
2377
2378 #ifdef RAY_TRACE_PRINT_INFO
2379
2380   Standard_ShortReal aMemTrgUsed = 0.f;
2381   Standard_ShortReal aMemBvhUsed = 0.f;
2382
2383   for (Standard_Integer anElemIdx = 0; anElemIdx < myRaytraceGeometry.Size(); ++anElemIdx)
2384   {
2385     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (myRaytraceGeometry.Objects()(anElemIdx).get());
2386
2387     aMemTrgUsed += static_cast<Standard_ShortReal> (
2388       aTriangleSet->Vertices.size() * sizeof (BVH_Vec3f));
2389     aMemTrgUsed += static_cast<Standard_ShortReal> (
2390       aTriangleSet->Normals.size() * sizeof (BVH_Vec3f));
2391     aMemTrgUsed += static_cast<Standard_ShortReal> (
2392       aTriangleSet->TexCrds.size() * sizeof (BVH_Vec2f));
2393     aMemTrgUsed += static_cast<Standard_ShortReal> (
2394       aTriangleSet->Elements.size() * sizeof (BVH_Vec4i));
2395
2396     aMemBvhUsed += static_cast<Standard_ShortReal> (
2397       aTriangleSet->QuadBVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
2398     aMemBvhUsed += static_cast<Standard_ShortReal> (
2399       aTriangleSet->QuadBVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
2400     aMemBvhUsed += static_cast<Standard_ShortReal> (
2401       aTriangleSet->QuadBVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
2402   }
2403
2404   aMemBvhUsed += static_cast<Standard_ShortReal> (
2405     myRaytraceGeometry.QuadBVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
2406   aMemBvhUsed += static_cast<Standard_ShortReal> (
2407     myRaytraceGeometry.QuadBVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
2408   aMemBvhUsed += static_cast<Standard_ShortReal> (
2409     myRaytraceGeometry.QuadBVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
2410
2411   std::cout << "GPU Memory Used (Mb):\n"
2412     << "\tFor mesh: " << aMemTrgUsed / 1048576 << "\n"
2413     << "\tFor BVHs: " << aMemBvhUsed / 1048576 << "\n";
2414
2415 #endif
2416
2417   return aResult;
2418 }
2419
2420 // =======================================================================
2421 // function : updateRaytraceLightSources
2422 // purpose  : Updates 3D scene light sources for ray-tracing
2423 // =======================================================================
2424 Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& theInvModelView, const Handle(OpenGl_Context)& theGlContext)
2425 {
2426   std::vector<Handle(Graphic3d_CLight)> aLightSources;
2427   myRaytraceGeometry.Ambient = BVH_Vec4f (0.f, 0.f, 0.f, 0.f);
2428   if (myShadingModel != Graphic3d_TOSM_UNLIT
2429   && !myLights.IsNull())
2430   {
2431     const Graphic3d_Vec4& anAmbient = myLights->AmbientColor();
2432     myRaytraceGeometry.Ambient = BVH_Vec4f (anAmbient.r(), anAmbient.g(), anAmbient.b(), 0.0f);
2433
2434     // move positional light sources at the front of the list
2435     aLightSources.reserve (myLights->Extent());
2436     for (Graphic3d_LightSet::Iterator aLightIter (myLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
2437          aLightIter.More(); aLightIter.Next())
2438     {
2439       const Graphic3d_CLight& aLight = *aLightIter.Value();
2440       if (aLight.Type() != Graphic3d_TOLS_DIRECTIONAL)
2441       {
2442         aLightSources.push_back (aLightIter.Value());
2443       }
2444     }
2445
2446     for (Graphic3d_LightSet::Iterator aLightIter (myLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
2447          aLightIter.More(); aLightIter.Next())
2448     {
2449       if (aLightIter.Value()->Type() == Graphic3d_TOLS_DIRECTIONAL)
2450       {
2451         aLightSources.push_back (aLightIter.Value());
2452       }
2453     }
2454   }
2455
2456   // get number of 'real' (not ambient) light sources
2457   const size_t aNbLights = aLightSources.size();
2458   Standard_Boolean wasUpdated = myRaytraceGeometry.Sources.size () != aNbLights;
2459   if (wasUpdated)
2460   {
2461     myRaytraceGeometry.Sources.resize (aNbLights);
2462   }
2463
2464   for (size_t aLightIdx = 0, aRealIdx = 0; aLightIdx < aLightSources.size(); ++aLightIdx)
2465   {
2466     const Graphic3d_CLight& aLight = *aLightSources[aLightIdx];
2467     const Graphic3d_Vec4& aLightColor = aLight.PackedColor();
2468     BVH_Vec4f aEmission  (aLightColor.r() * aLight.Intensity(),
2469                           aLightColor.g() * aLight.Intensity(),
2470                           aLightColor.b() * aLight.Intensity(),
2471                           1.0f);
2472
2473     BVH_Vec4f aPosition (-aLight.PackedDirection().x(),
2474                          -aLight.PackedDirection().y(),
2475                          -aLight.PackedDirection().z(),
2476                          0.0f);
2477
2478     if (aLight.Type() != Graphic3d_TOLS_DIRECTIONAL)
2479     {
2480       aPosition = BVH_Vec4f (static_cast<float>(aLight.Position().X()),
2481                              static_cast<float>(aLight.Position().Y()),
2482                              static_cast<float>(aLight.Position().Z()),
2483                              1.0f);
2484
2485       // store smoothing radius in W-component
2486       aEmission.w() = Max (aLight.Smoothness(), 0.f);
2487     }
2488     else
2489     {
2490       // store cosine of smoothing angle in W-component
2491       aEmission.w() = cosf (Min (Max (aLight.Smoothness(), 0.f), static_cast<Standard_ShortReal> (M_PI / 2.0)));
2492     }
2493
2494     if (aLight.IsHeadlight())
2495     {
2496       aPosition = theInvModelView * aPosition;
2497     }
2498
2499     for (int aK = 0; aK < 4; ++aK)
2500     {
2501       wasUpdated |= (aEmission[aK] != myRaytraceGeometry.Sources[aRealIdx].Emission[aK])
2502                  || (aPosition[aK] != myRaytraceGeometry.Sources[aRealIdx].Position[aK]);
2503     }
2504
2505     if (wasUpdated)
2506     {
2507       myRaytraceGeometry.Sources[aRealIdx] = OpenGl_RaytraceLight (aEmission, aPosition);
2508     }
2509
2510     ++aRealIdx;
2511   }
2512
2513   if (myRaytraceLightSrcTexture.IsNull()) // create light source buffer
2514   {
2515     myRaytraceLightSrcTexture = new OpenGl_TextureBufferArb;
2516   }
2517
2518   if (myRaytraceGeometry.Sources.size() != 0 && wasUpdated)
2519   {
2520     const GLfloat* aDataPtr = myRaytraceGeometry.Sources.front().Packed();
2521     if (!myRaytraceLightSrcTexture->Init (theGlContext, 4, GLsizei (myRaytraceGeometry.Sources.size() * 2), aDataPtr))
2522     {
2523 #ifdef RAY_TRACE_PRINT_INFO
2524       std::cout << "Error: Failed to upload light source buffer" << std::endl;
2525 #endif
2526       return Standard_False;
2527     }
2528
2529     myAccumFrames = 0; // accumulation should be restarted
2530   }
2531
2532   return Standard_True;
2533 }
2534
2535 // =======================================================================
2536 // function : setUniformState
2537 // purpose  : Sets uniform state for the given ray-tracing shader program
2538 // =======================================================================
2539 Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        theProgramId,
2540                                                const Standard_Integer        theWinSizeX,
2541                                                const Standard_Integer        theWinSizeY,
2542                                                Graphic3d_Camera::Projection  theProjection,
2543                                                const Handle(OpenGl_Context)& theGlContext)
2544 {
2545   // Get projection state
2546   OpenGl_MatrixState<Standard_ShortReal>& aCntxProjectionState = theGlContext->ProjectionState;
2547
2548   OpenGl_Mat4 aViewPrjMat;
2549   OpenGl_Mat4 anUnviewMat;
2550   OpenGl_Vec3 aOrigins[4];
2551   OpenGl_Vec3 aDirects[4];
2552
2553   if (myCamera->IsOrthographic()
2554    || !myRenderParams.IsGlobalIlluminationEnabled)
2555   {
2556     updateCamera (myCamera->OrientationMatrixF(),
2557                   aCntxProjectionState.Current(),
2558                   aOrigins,
2559                   aDirects,
2560                   aViewPrjMat,
2561                   anUnviewMat);
2562   }
2563   else
2564   {
2565     updatePerspCameraPT (myCamera->OrientationMatrixF(),
2566                          aCntxProjectionState.Current(),
2567                          theProjection,
2568                          aViewPrjMat,
2569                          anUnviewMat,
2570                          theWinSizeX,
2571                          theWinSizeY);
2572   }
2573
2574   Handle(OpenGl_ShaderProgram)& theProgram = theProgramId == 0
2575                                            ? myRaytraceProgram
2576                                            : myPostFSAAProgram;
2577
2578   if (theProgram.IsNull())
2579   {
2580     return Standard_False;
2581   }
2582   
2583   theProgram->SetUniform(theGlContext, "uEyeOrig", myEyeOrig);
2584   theProgram->SetUniform(theGlContext, "uEyeView", myEyeView);
2585   theProgram->SetUniform(theGlContext, "uEyeVert", myEyeVert);
2586   theProgram->SetUniform(theGlContext, "uEyeSide", myEyeSide);
2587   theProgram->SetUniform(theGlContext, "uEyeSize", myEyeSize);
2588
2589   theProgram->SetUniform(theGlContext, "uApertureRadius", myRenderParams.CameraApertureRadius);
2590   theProgram->SetUniform(theGlContext, "uFocalPlaneDist", myRenderParams.CameraFocalPlaneDist);
2591   
2592   // Set camera state
2593   theProgram->SetUniform (theGlContext,
2594     myUniformLocations[theProgramId][OpenGl_RT_uOriginLB], aOrigins[0]);
2595   theProgram->SetUniform (theGlContext,
2596     myUniformLocations[theProgramId][OpenGl_RT_uOriginRB], aOrigins[1]);
2597   theProgram->SetUniform (theGlContext,
2598     myUniformLocations[theProgramId][OpenGl_RT_uOriginLT], aOrigins[2]);
2599   theProgram->SetUniform (theGlContext,
2600     myUniformLocations[theProgramId][OpenGl_RT_uOriginRT], aOrigins[3]);
2601   theProgram->SetUniform (theGlContext,
2602     myUniformLocations[theProgramId][OpenGl_RT_uDirectLB], aDirects[0]);
2603   theProgram->SetUniform (theGlContext,
2604     myUniformLocations[theProgramId][OpenGl_RT_uDirectRB], aDirects[1]);
2605   theProgram->SetUniform (theGlContext,
2606     myUniformLocations[theProgramId][OpenGl_RT_uDirectLT], aDirects[2]);
2607   theProgram->SetUniform (theGlContext,
2608     myUniformLocations[theProgramId][OpenGl_RT_uDirectRT], aDirects[3]);
2609   theProgram->SetUniform (theGlContext,
2610     myUniformLocations[theProgramId][OpenGl_RT_uViewPrMat], aViewPrjMat);
2611   theProgram->SetUniform (theGlContext,
2612     myUniformLocations[theProgramId][OpenGl_RT_uUnviewMat], anUnviewMat);
2613
2614   // Set screen dimensions
2615   myRaytraceProgram->SetUniform (theGlContext,
2616     myUniformLocations[theProgramId][OpenGl_RT_uWinSizeX], theWinSizeX);
2617   myRaytraceProgram->SetUniform (theGlContext,
2618     myUniformLocations[theProgramId][OpenGl_RT_uWinSizeY], theWinSizeY);
2619
2620   // Set 3D scene parameters
2621   theProgram->SetUniform (theGlContext,
2622     myUniformLocations[theProgramId][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
2623   theProgram->SetUniform (theGlContext,
2624     myUniformLocations[theProgramId][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
2625
2626   // Set light source parameters
2627   const Standard_Integer aLightSourceBufferSize =
2628     static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
2629   
2630   theProgram->SetUniform (theGlContext,
2631     myUniformLocations[theProgramId][OpenGl_RT_uLightCount], aLightSourceBufferSize);
2632
2633   // Set array of 64-bit texture handles
2634   if (theGlContext->arbTexBindless != NULL && myRaytraceGeometry.HasTextures())
2635   {
2636     const std::vector<GLuint64>& aTextures = myRaytraceGeometry.TextureHandles();
2637
2638     theProgram->SetUniform (theGlContext, myUniformLocations[theProgramId][OpenGl_RT_uTexSamplersArray],
2639       static_cast<GLsizei> (aTextures.size()), reinterpret_cast<const OpenGl_Vec2u*> (&aTextures.front()));
2640   }
2641
2642   // Set background colors (only gradient background supported)
2643   if (myBgGradientArray != NULL && myBgGradientArray->IsDefined())
2644   {
2645     theProgram->SetUniform (theGlContext,
2646       myUniformLocations[theProgramId][OpenGl_RT_uBackColorTop], myBgGradientArray->GradientColor (0));
2647     theProgram->SetUniform (theGlContext,
2648       myUniformLocations[theProgramId][OpenGl_RT_uBackColorBot], myBgGradientArray->GradientColor (1));
2649   }
2650   else
2651   {
2652     const OpenGl_Vec4& aBackColor = myBgColor;
2653
2654     theProgram->SetUniform (theGlContext,
2655       myUniformLocations[theProgramId][OpenGl_RT_uBackColorTop], aBackColor);
2656     theProgram->SetUniform (theGlContext,
2657       myUniformLocations[theProgramId][OpenGl_RT_uBackColorBot], aBackColor);
2658   }
2659
2660   // Set environment map parameters
2661   const Standard_Boolean toDisableEnvironmentMap = myTextureEnv.IsNull()
2662                                                ||  myTextureEnv->IsEmpty()
2663                                                || !myTextureEnv->First()->IsValid();
2664
2665   theProgram->SetUniform (theGlContext,
2666     myUniformLocations[theProgramId][OpenGl_RT_uSphereMapEnabled], toDisableEnvironmentMap ? 0 : 1);
2667
2668   theProgram->SetUniform (theGlContext,
2669     myUniformLocations[theProgramId][OpenGl_RT_uSphereMapForBack], myRenderParams.UseEnvironmentMapBackground ?  1 : 0);
2670
2671   if (myRenderParams.IsGlobalIlluminationEnabled) // GI parameters
2672   {
2673     theProgram->SetUniform (theGlContext,
2674       myUniformLocations[theProgramId][OpenGl_RT_uMaxRadiance], myRenderParams.RadianceClampingValue);
2675
2676     theProgram->SetUniform (theGlContext,
2677       myUniformLocations[theProgramId][OpenGl_RT_uBlockedRngEnabled], myRenderParams.CoherentPathTracingMode ? 1 : 0);
2678
2679     // Check whether we should restart accumulation for run-time parameters
2680     if (myRenderParams.RadianceClampingValue       != myRaytraceParameters.RadianceClampingValue
2681      || myRenderParams.UseEnvironmentMapBackground != myRaytraceParameters.UseEnvMapForBackground)
2682     {
2683       myAccumFrames = 0; // accumulation should be restarted
2684
2685       myRaytraceParameters.RadianceClampingValue  = myRenderParams.RadianceClampingValue;
2686       myRaytraceParameters.UseEnvMapForBackground = myRenderParams.UseEnvironmentMapBackground;
2687     }
2688   }
2689   else // RT parameters
2690   {
2691     // Set ambient light source
2692     theProgram->SetUniform (theGlContext,
2693       myUniformLocations[theProgramId][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
2694
2695     // Enable/disable run-time ray-tracing effects
2696     theProgram->SetUniform (theGlContext,
2697       myUniformLocations[theProgramId][OpenGl_RT_uShadowsEnabled], myRenderParams.IsShadowEnabled ?  1 : 0);
2698     theProgram->SetUniform (theGlContext,
2699       myUniformLocations[theProgramId][OpenGl_RT_uReflectEnabled], myRenderParams.IsReflectionEnabled ?  1 : 0);
2700   }
2701
2702   return Standard_True;
2703 }
2704
2705 // =======================================================================
2706 // function : bindRaytraceTextures
2707 // purpose  : Binds ray-trace textures to corresponding texture units
2708 // =======================================================================
2709 void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlContext,
2710                                         int theStereoView)
2711 {
2712   if (myRaytraceParameters.AdaptiveScreenSampling
2713    && myRaytraceParameters.GlobalIllumination)
2714   {
2715   #if !defined(GL_ES_VERSION_2_0)
2716     theGlContext->core42->glBindImageTexture (OpenGl_RT_OutputImage,
2717                                               myRaytraceOutputTexture[theStereoView]->TextureId(), 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32F);
2718     theGlContext->core42->glBindImageTexture (OpenGl_RT_VisualErrorImage,
2719                                               myRaytraceVisualErrorTexture[theStereoView]->TextureId(), 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32I);
2720     if (myRaytraceParameters.AdaptiveScreenSamplingAtomic)
2721     {
2722       theGlContext->core42->glBindImageTexture (OpenGl_RT_TileOffsetsImage,
2723                                                 myRaytraceTileOffsetsTexture[theStereoView]->TextureId(), 0, GL_TRUE, 0, GL_READ_ONLY, GL_RG32I);
2724     }
2725     else
2726     {
2727       theGlContext->core42->glBindImageTexture (OpenGl_RT_TileSamplesImage,
2728                                                 myRaytraceTileSamplesTexture[theStereoView]->TextureId(), 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32I);
2729     }
2730   #else
2731     (void )theStereoView;
2732   #endif
2733   }
2734
2735   if (!myTextureEnv.IsNull()
2736    && !myTextureEnv->IsEmpty()
2737    &&  myTextureEnv->First()->IsValid())
2738   {
2739     myTextureEnv->First()->Bind (theGlContext, OpenGl_RT_EnvironmentMapTexture);
2740   }
2741
2742   mySceneMinPointTexture   ->BindTexture (theGlContext, OpenGl_RT_SceneMinPointTexture);
2743   mySceneMaxPointTexture   ->BindTexture (theGlContext, OpenGl_RT_SceneMaxPointTexture);
2744   mySceneNodeInfoTexture   ->BindTexture (theGlContext, OpenGl_RT_SceneNodeInfoTexture);
2745   myGeometryVertexTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryVertexTexture);
2746   myGeometryNormalTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryNormalTexture);
2747   myGeometryTexCrdTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryTexCrdTexture);
2748   myGeometryTriangTexture  ->BindTexture (theGlContext, OpenGl_RT_GeometryTriangTexture);
2749   mySceneTransformTexture  ->BindTexture (theGlContext, OpenGl_RT_SceneTransformTexture);
2750   myRaytraceMaterialTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture);
2751   myRaytraceLightSrcTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture);
2752 }
2753
2754 // =======================================================================
2755 // function : unbindRaytraceTextures
2756 // purpose  : Unbinds ray-trace textures from corresponding texture units
2757 // =======================================================================
2758 void OpenGl_View::unbindRaytraceTextures (const Handle(OpenGl_Context)& theGlContext)
2759 {
2760   mySceneMinPointTexture   ->UnbindTexture (theGlContext, OpenGl_RT_SceneMinPointTexture);
2761   mySceneMaxPointTexture   ->UnbindTexture (theGlContext, OpenGl_RT_SceneMaxPointTexture);
2762   mySceneNodeInfoTexture   ->UnbindTexture (theGlContext, OpenGl_RT_SceneNodeInfoTexture);
2763   myGeometryVertexTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryVertexTexture);
2764   myGeometryNormalTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryNormalTexture);
2765   myGeometryTexCrdTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryTexCrdTexture);
2766   myGeometryTriangTexture  ->UnbindTexture (theGlContext, OpenGl_RT_GeometryTriangTexture);
2767   mySceneTransformTexture  ->UnbindTexture (theGlContext, OpenGl_RT_SceneTransformTexture);
2768   myRaytraceMaterialTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture);
2769   myRaytraceLightSrcTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture);
2770
2771   theGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
2772 }
2773
2774 // =======================================================================
2775 // function : runRaytraceShaders
2776 // purpose  : Runs ray-tracing shader programs
2777 // =======================================================================
2778 Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer        theSizeX,
2779                                                   const Standard_Integer        theSizeY,
2780                                                   Graphic3d_Camera::Projection  theProjection,
2781                                                   OpenGl_FrameBuffer*           theReadDrawFbo,
2782                                                   const Handle(OpenGl_Context)& theGlContext)
2783 {
2784   Standard_Boolean aResult = theGlContext->BindProgram (myRaytraceProgram);
2785
2786   aResult &= setUniformState (0,
2787                               theSizeX,
2788                               theSizeY,
2789                               theProjection,
2790                               theGlContext);
2791
2792   if (myRaytraceParameters.GlobalIllumination) // path tracing
2793   {
2794     aResult &= runPathtrace    (theSizeX, theSizeY, theProjection, theGlContext);
2795     aResult &= runPathtraceOut (theProjection, theReadDrawFbo, theGlContext);
2796   }
2797   else // Whitted-style ray-tracing
2798   {
2799     aResult &= runRaytrace (theSizeX, theSizeY, theProjection, theReadDrawFbo, theGlContext);
2800   }
2801
2802   return aResult;
2803 }
2804
2805 // =======================================================================
2806 // function : runRaytrace
2807 // purpose  : Runs Whitted-style ray-tracing
2808 // =======================================================================
2809 Standard_Boolean OpenGl_View::runRaytrace (const Standard_Integer        theSizeX,
2810                                            const Standard_Integer        theSizeY,
2811                                            Graphic3d_Camera::Projection  theProjection,
2812                                            OpenGl_FrameBuffer*           theReadDrawFbo,
2813                                            const Handle(OpenGl_Context)& theGlContext)
2814 {
2815   Standard_Boolean aResult = Standard_True;
2816
2817   // Choose proper set of frame buffers for stereo rendering
2818   const Standard_Integer aFBOIdx = (theProjection == Graphic3d_Camera::Projection_MonoRightEye) ? 1 : 0;
2819   bindRaytraceTextures (theGlContext, aFBOIdx);
2820
2821   if (myRenderParams.IsAntialiasingEnabled) // if second FSAA pass is used
2822   {
2823     myRaytraceFBO1[aFBOIdx]->BindBuffer (theGlContext);
2824
2825     glClear (GL_DEPTH_BUFFER_BIT); // render the image with depth
2826   }
2827
2828   theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
2829
2830   if (myRenderParams.IsAntialiasingEnabled)
2831   {
2832     glDisable (GL_DEPTH_TEST); // improve jagged edges without depth buffer
2833
2834     // bind ray-tracing output image as input
2835     myRaytraceFBO1[aFBOIdx]->ColorTexture()->Bind (theGlContext, OpenGl_RT_FsaaInputTexture);
2836
2837     aResult &= theGlContext->BindProgram (myPostFSAAProgram);
2838
2839     aResult &= setUniformState (1 /* FSAA ID */,
2840                                 theSizeX,
2841                                 theSizeY,
2842                                 theProjection,
2843                                 theGlContext);
2844
2845     // Perform multi-pass adaptive FSAA using ping-pong technique.
2846     // We use 'FLIPTRI' sampling pattern changing for every pixel
2847     // (3 additional samples per pixel, the 1st sample is already
2848     // available from initial ray-traced image).
2849     for (Standard_Integer anIt = 1; anIt < 4; ++anIt)
2850     {
2851       GLfloat aOffsetX = 1.f / theSizeX;
2852       GLfloat aOffsetY = 1.f / theSizeY;
2853
2854       if (anIt == 1)
2855       {
2856         aOffsetX *= -0.55f;
2857         aOffsetY *=  0.55f;
2858       }
2859       else if (anIt == 2)
2860       {
2861         aOffsetX *=  0.00f;
2862         aOffsetY *= -0.55f;
2863       }
2864       else if (anIt == 3)
2865       {
2866         aOffsetX *= 0.55f;
2867         aOffsetY *= 0.00f;
2868       }
2869
2870       aResult &= myPostFSAAProgram->SetUniform (theGlContext,
2871         myUniformLocations[1][OpenGl_RT_uSamples], anIt + 1);
2872       aResult &= myPostFSAAProgram->SetUniform (theGlContext,
2873         myUniformLocations[1][OpenGl_RT_uOffsetX], aOffsetX);
2874       aResult &= myPostFSAAProgram->SetUniform (theGlContext,
2875         myUniformLocations[1][OpenGl_RT_uOffsetY], aOffsetY);
2876
2877       Handle(OpenGl_FrameBuffer)& aFramebuffer = anIt % 2
2878                                                ? myRaytraceFBO2[aFBOIdx]
2879                                                : myRaytraceFBO1[aFBOIdx];
2880
2881       aFramebuffer->BindBuffer (theGlContext);
2882
2883       // perform adaptive FSAA pass
2884       theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
2885
2886       aFramebuffer->ColorTexture()->Bind (theGlContext, OpenGl_RT_FsaaInputTexture);
2887     }
2888
2889     const Handle(OpenGl_FrameBuffer)& aRenderImageFramebuffer = myRaytraceFBO2[aFBOIdx];
2890     const Handle(OpenGl_FrameBuffer)& aDepthSourceFramebuffer = myRaytraceFBO1[aFBOIdx];
2891
2892     glEnable (GL_DEPTH_TEST);
2893
2894     // Display filtered image
2895     theGlContext->BindProgram (myOutImageProgram);
2896
2897     if (theReadDrawFbo != NULL)
2898     {
2899       theReadDrawFbo->BindBuffer (theGlContext);
2900     }
2901     else
2902     {
2903       aRenderImageFramebuffer->UnbindBuffer (theGlContext);
2904     }
2905
2906     aRenderImageFramebuffer->ColorTexture()       ->Bind (theGlContext, OpenGl_RT_PrevAccumTexture);
2907     aDepthSourceFramebuffer->DepthStencilTexture()->Bind (theGlContext, OpenGl_RT_RaytraceDepthTexture);
2908
2909     // copy the output image with depth values
2910     theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
2911
2912     aDepthSourceFramebuffer->DepthStencilTexture()->Unbind (theGlContext, OpenGl_RT_RaytraceDepthTexture);
2913     aRenderImageFramebuffer->ColorTexture()       ->Unbind (theGlContext, OpenGl_RT_PrevAccumTexture);
2914   }
2915
2916   unbindRaytraceTextures (theGlContext);
2917
2918   theGlContext->BindProgram (NULL);
2919
2920   return aResult;
2921 }
2922
2923 // =======================================================================
2924 // function : runPathtrace
2925 // purpose  : Runs path tracing shader
2926 // =======================================================================
2927 Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer              theSizeX,
2928                                             const Standard_Integer              theSizeY,
2929                                             const Graphic3d_Camera::Projection  theProjection,
2930                                             const Handle(OpenGl_Context)&       theGlContext)
2931 {
2932   if (myToUpdateEnvironmentMap) // check whether the map was changed
2933   {
2934     myAccumFrames = myToUpdateEnvironmentMap = 0;
2935   }
2936   
2937   if (myRenderParams.CameraApertureRadius != myPrevCameraApertureRadius
2938    || myRenderParams.CameraFocalPlaneDist != myPrevCameraFocalPlaneDist)
2939   {
2940     myPrevCameraApertureRadius = myRenderParams.CameraApertureRadius;
2941     myPrevCameraFocalPlaneDist = myRenderParams.CameraFocalPlaneDist;
2942     myAccumFrames = 0;
2943   }
2944
2945   // Choose proper set of frame buffers for stereo rendering
2946   const Standard_Integer aFBOIdx = (theProjection == Graphic3d_Camera::Projection_MonoRightEye) ? 1 : 0;
2947
2948   if (myRaytraceParameters.AdaptiveScreenSampling)
2949   {
2950     if (myAccumFrames == 0)
2951     {
2952       myTileSampler.Reset(); // reset tile sampler to its initial state
2953
2954       // Adaptive sampling is starting at the second frame
2955       if (myRaytraceParameters.AdaptiveScreenSamplingAtomic)
2956       {
2957         myTileSampler.UploadOffsets (theGlContext, myRaytraceTileOffsetsTexture[aFBOIdx], false);
2958       }
2959       else
2960       {
2961         myTileSampler.UploadSamples (theGlContext, myRaytraceTileSamplesTexture[aFBOIdx], false);
2962       }
2963
2964     #if !defined(GL_ES_VERSION_2_0)
2965       theGlContext->core44->glClearTexImage (myRaytraceOutputTexture[aFBOIdx]->TextureId(), 0, GL_RED, GL_FLOAT, NULL);
2966     #endif
2967     }
2968
2969     // Clear adaptive screen sampling images
2970   #if !defined(GL_ES_VERSION_2_0)
2971     theGlContext->core44->glClearTexImage (myRaytraceVisualErrorTexture[aFBOIdx]->TextureId(), 0, GL_RED_INTEGER, GL_INT, NULL);
2972   #endif
2973   }
2974
2975   bindRaytraceTextures (theGlContext, aFBOIdx);
2976
2977   const Handle(OpenGl_FrameBuffer)& anAccumImageFramebuffer = myAccumFrames % 2 ? myRaytraceFBO2[aFBOIdx] : myRaytraceFBO1[aFBOIdx];
2978   anAccumImageFramebuffer->ColorTexture()->Bind (theGlContext, OpenGl_RT_PrevAccumTexture);
2979
2980   // Set frame accumulation weight
2981   myRaytraceProgram->SetUniform (theGlContext, myUniformLocations[0][OpenGl_RT_uAccumSamples], myAccumFrames);
2982
2983   // Set image uniforms for render program
2984   if (myRaytraceParameters.AdaptiveScreenSampling)
2985   {
2986     myRaytraceProgram->SetUniform (theGlContext, myUniformLocations[0][OpenGl_RT_uRenderImage], OpenGl_RT_OutputImage);
2987     myRaytraceProgram->SetUniform (theGlContext, myUniformLocations[0][OpenGl_RT_uTilesImage],  OpenGl_RT_TileSamplesImage);
2988     myRaytraceProgram->SetUniform (theGlContext, myUniformLocations[0][OpenGl_RT_uOffsetImage], OpenGl_RT_TileOffsetsImage);
2989     myRaytraceProgram->SetUniform (theGlContext, myUniformLocations[0][OpenGl_RT_uTileSize], myTileSampler.TileSize());
2990   }
2991
2992   const Handle(OpenGl_FrameBuffer)& aRenderImageFramebuffer = myAccumFrames % 2 ? myRaytraceFBO1[aFBOIdx] : myRaytraceFBO2[aFBOIdx];
2993   aRenderImageFramebuffer->BindBuffer (theGlContext);
2994   if (myRaytraceParameters.AdaptiveScreenSampling
2995    && myRaytraceParameters.AdaptiveScreenSamplingAtomic)
2996   {
2997     // extend viewport here, so that tiles at boundaries (cut tile size by target rendering viewport)
2998     // redirected to inner tiles (full tile size) are drawn entirely
2999     const Graphic3d_Vec2i anOffsetViewport = myTileSampler.OffsetTilesViewport (myAccumFrames > 1); // shrunk offsets texture will be uploaded since 3rd frame
3000     glViewport (0, 0, anOffsetViewport.x(), anOffsetViewport.y());
3001   }
3002
3003   // Generate for the given RNG seed
3004   glDisable (GL_DEPTH_TEST);
3005
3006   // Adaptive Screen Sampling computes the same overall amount of samples per frame redraw as normal Path Tracing,
3007   // but distributes them unequally across pixels (grouped in tiles), so that some pixels do not receive new samples at all.
3008   //
3009   // Offsets map (redirecting currently rendered tile to another tile) allows performing Adaptive Screen Sampling in single pass,
3010   // but current implementation relies on atomic float operations (AdaptiveScreenSamplingAtomic) for this.
3011   // So that when atomic floats are not supported by GPU, multi-pass rendering is used instead.
3012   //
3013   // Single-pass rendering is more optimal due to smaller amount of draw calls,
3014   // memory synchronization barriers, discarding most of the fragments and bad parallelization in case of very small amount of tiles requiring more samples.
3015   // However, atomic operations on float values still produces different result (close, but not bit exact) making non-regression testing not robust.
3016   // It should be possible following single-pass rendering approach but using extra accumulation buffer and resolving pass as possible improvement.
3017   const int aNbPasses = myRaytraceParameters.AdaptiveScreenSampling
3018                     && !myRaytraceParameters.AdaptiveScreenSamplingAtomic
3019                       ? myTileSampler.MaxTileSamples()
3020                       : 1;
3021   if (myAccumFrames == 0)
3022   {
3023     myRNG.SetSeed(); // start RNG from beginning
3024   }
3025   for (int aPassIter = 0; aPassIter < aNbPasses; ++aPassIter)
3026   {
3027     myRaytraceProgram->SetUniform (theGlContext, myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
3028     theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
3029     if (myRaytraceParameters.AdaptiveScreenSampling)
3030     {
3031     #if !defined(GL_ES_VERSION_2_0)
3032       theGlContext->core44->glMemoryBarrier (GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3033     #endif
3034     }
3035   }
3036   aRenderImageFramebuffer->UnbindBuffer (theGlContext);
3037
3038   if (myRaytraceParameters.AdaptiveScreenSampling
3039    && myRaytraceParameters.AdaptiveScreenSamplingAtomic)
3040   {
3041     glViewport (0, 0, theSizeX, theSizeY);
3042   }
3043   return true;
3044 }
3045
3046 // =======================================================================
3047 // function : runPathtraceOut
3048 // purpose  :
3049 // =======================================================================
3050 Standard_Boolean OpenGl_View::runPathtraceOut (const Graphic3d_Camera::Projection  theProjection,
3051                                                OpenGl_FrameBuffer*                 theReadDrawFbo,
3052                                                const Handle(OpenGl_Context)&       theGlContext)
3053 {
3054   // Output accumulated path traced image
3055   theGlContext->BindProgram (myOutImageProgram);
3056
3057   // Choose proper set of frame buffers for stereo rendering
3058   const Standard_Integer aFBOIdx = (theProjection == Graphic3d_Camera::Projection_MonoRightEye) ? 1 : 0;
3059
3060   if (myRaytraceParameters.AdaptiveScreenSampling)
3061   {
3062     // Set uniforms for display program
3063     myOutImageProgram->SetUniform (theGlContext, "uRenderImage",   OpenGl_RT_OutputImage);
3064     myOutImageProgram->SetUniform (theGlContext, "uAccumFrames",   myAccumFrames);
3065     myOutImageProgram->SetUniform (theGlContext, "uVarianceImage", OpenGl_RT_VisualErrorImage);
3066     myOutImageProgram->SetUniform (theGlContext, "uDebugAdaptive", myRenderParams.ShowSamplingTiles ?  1 : 0);
3067     myOutImageProgram->SetUniform (theGlContext, "uTileSize",      myTileSampler.TileSize());
3068     myOutImageProgram->SetUniform (theGlContext, "uVarianceScaleFactor", myTileSampler.VarianceScaleFactor());
3069   }
3070
3071   if (myRaytraceParameters.GlobalIllumination)
3072   {
3073     myOutImageProgram->SetUniform(theGlContext, "uExposure", myRenderParams.Exposure);
3074     switch (myRaytraceParameters.ToneMappingMethod)
3075     {
3076       case Graphic3d_ToneMappingMethod_Disabled:
3077         break;
3078       case Graphic3d_ToneMappingMethod_Filmic:
3079         myOutImageProgram->SetUniform (theGlContext, "uWhitePoint", myRenderParams.WhitePoint);
3080         break;
3081     }
3082   }
3083
3084   if (theReadDrawFbo != NULL)
3085   {
3086     theReadDrawFbo->BindBuffer (theGlContext);
3087   }
3088
3089   const Handle(OpenGl_FrameBuffer)& aRenderImageFramebuffer = myAccumFrames % 2 ? myRaytraceFBO1[aFBOIdx] : myRaytraceFBO2[aFBOIdx];
3090   aRenderImageFramebuffer->ColorTexture()->Bind (theGlContext, OpenGl_RT_PrevAccumTexture);
3091
3092   // Copy accumulated image with correct depth values
3093   glEnable (GL_DEPTH_TEST);
3094   theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
3095
3096   aRenderImageFramebuffer->ColorTexture()->Unbind (theGlContext, OpenGl_RT_PrevAccumTexture);
3097
3098   if (myRaytraceParameters.AdaptiveScreenSampling)
3099   {
3100     // Download visual error map from the GPU and build adjusted tile offsets for optimal image sampling
3101     myTileSampler.GrabVarianceMap (theGlContext, myRaytraceVisualErrorTexture[aFBOIdx]);
3102     if (myRaytraceParameters.AdaptiveScreenSamplingAtomic)
3103     {
3104       myTileSampler.UploadOffsets (theGlContext, myRaytraceTileOffsetsTexture[aFBOIdx], myAccumFrames != 0);
3105     }
3106     else
3107     {
3108       myTileSampler.UploadSamples (theGlContext, myRaytraceTileSamplesTexture[aFBOIdx], myAccumFrames != 0);
3109     }
3110   }
3111
3112   unbindRaytraceTextures (theGlContext);
3113   theGlContext->BindProgram (NULL);
3114   return true;
3115 }
3116
3117 // =======================================================================
3118 // function : raytrace
3119 // purpose  : Redraws the window using OpenGL/GLSL ray-tracing
3120 // =======================================================================
3121 Standard_Boolean OpenGl_View::raytrace (const Standard_Integer        theSizeX,
3122                                         const Standard_Integer        theSizeY,
3123                                         Graphic3d_Camera::Projection  theProjection,
3124                                         OpenGl_FrameBuffer*           theReadDrawFbo,
3125                                         const Handle(OpenGl_Context)& theGlContext)
3126 {
3127   if (!initRaytraceResources (theSizeX, theSizeY, theGlContext))
3128   {
3129     return Standard_False;
3130   }
3131
3132   if (!updateRaytraceBuffers (theSizeX, theSizeY, theGlContext))
3133   {
3134     return Standard_False;
3135   }
3136
3137   OpenGl_Mat4 aLightSourceMatrix;
3138
3139   // Get inversed model-view matrix for transforming lights
3140   myCamera->OrientationMatrixF().Inverted (aLightSourceMatrix);
3141
3142   if (!updateRaytraceLightSources (aLightSourceMatrix, theGlContext))
3143   {
3144     return Standard_False;
3145   }
3146
3147   // Generate image using Whitted-style ray-tracing or path tracing
3148   if (myIsRaytraceDataValid)
3149   {
3150     myRaytraceScreenQuad.BindVertexAttrib (theGlContext, Graphic3d_TOA_POS);
3151
3152     if (!myRaytraceGeometry.AcquireTextures (theGlContext))
3153     {
3154       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR,
3155         0, GL_DEBUG_SEVERITY_MEDIUM, "Error: Failed to acquire OpenGL image textures");
3156     }
3157
3158     glDisable (GL_BLEND);
3159
3160     const Standard_Boolean aResult = runRaytraceShaders (theSizeX,
3161                                                          theSizeY,
3162                                                          theProjection,
3163                                                          theReadDrawFbo,
3164                                                          theGlContext);
3165
3166     if (!aResult)
3167     {
3168       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR,
3169         0, GL_DEBUG_SEVERITY_MEDIUM, "Error: Failed to execute ray-tracing shaders");
3170     }
3171
3172     if (!myRaytraceGeometry.ReleaseTextures (theGlContext))
3173     {
3174       theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR,
3175         0, GL_DEBUG_SEVERITY_MEDIUM, "Error: Failed to release OpenGL image textures");
3176     }
3177
3178     myRaytraceScreenQuad.UnbindVertexAttrib (theGlContext, Graphic3d_TOA_POS);
3179   }
3180
3181   return Standard_True;
3182 }