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