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