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