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