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