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