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