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