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