1 // Created on: 2013-08-27
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
22 #include <OpenGl_Cl.hxx>
29 #pragma comment (lib, "DelayImp.lib")
30 #pragma comment (lib, "OpenCL.lib")
32 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
33 #include <OpenGL/CGLCurrent.h>
38 #include <OpenGl_Context.hxx>
39 #include <OpenGl_Texture.hxx>
40 #include <OpenGl_View.hxx>
41 #include <OpenGl_Workspace.hxx>
43 using namespace OpenGl_Raytrace;
45 //! Use this macro to output ray-tracing debug info
46 //#define RAY_TRACE_PRINT_INFO
48 #ifdef RAY_TRACE_PRINT_INFO
49 #include <OSD_Timer.hxx>
52 //! OpenCL source of ray-tracing kernels.
53 extern const char THE_RAY_TRACE_OPENCL_SOURCE[];
55 // =======================================================================
56 // function : MatVecMult
57 // purpose : Multiples 4x4 matrix by 4D vector
58 // =======================================================================
59 template< typename T >
60 OpenGl_RTVec4f MatVecMult (const T m[16], const OpenGl_RTVec4f& v)
62 return OpenGl_RTVec4f (
63 static_cast<float> (m[ 0] * v.x() + m[ 4] * v.y() +
64 m[ 8] * v.z() + m[12] * v.w()),
65 static_cast<float> (m[ 1] * v.x() + m[ 5] * v.y() +
66 m[ 9] * v.z() + m[13] * v.w()),
67 static_cast<float> (m[ 2] * v.x() + m[ 6] * v.y() +
68 m[10] * v.z() + m[14] * v.w()),
69 static_cast<float> (m[ 3] * v.x() + m[ 7] * v.y() +
70 m[11] * v.z() + m[15] * v.w()));
73 // =======================================================================
74 // function : UpdateRaytraceEnvironmentMap
75 // purpose : Updates environment map for ray-tracing
76 // =======================================================================
77 Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
80 return Standard_False;
82 if (myViewModificationStatus == myView->ModificationState())
85 cl_int anError = CL_SUCCESS;
87 if (myRaytraceEnvironment != NULL)
88 clReleaseMemObject (myRaytraceEnvironment);
93 if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
95 aSizeX = (myView->TextureEnv()->SizeX() <= 0) ? 1 : myView->TextureEnv()->SizeX();
96 aSizeY = (myView->TextureEnv()->SizeY() <= 0) ? 1 : myView->TextureEnv()->SizeY();
99 cl_image_format aImageFormat;
101 aImageFormat.image_channel_order = CL_RGBA;
102 aImageFormat.image_channel_data_type = CL_FLOAT;
104 myRaytraceEnvironment = clCreateImage2D (myComputeContext, CL_MEM_READ_ONLY,
105 &aImageFormat, aSizeX, aSizeY, 0,
108 cl_float* aPixelData = new cl_float[aSizeX * aSizeY * 4];
110 // Note: texture format is not compatible with OpenCL image
111 // (it's not possible to create image directly from texture)
113 if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
115 myView->TextureEnv()->Bind (GetGlContext());
117 glGetTexImage (GL_TEXTURE_2D,
123 myView->TextureEnv()->Unbind (GetGlContext());
127 for (int aPixel = 0; aPixel < aSizeX * aSizeY * 4; ++aPixel)
128 aPixelData[aPixel] = 0.f;
131 size_t anImageOffset[] = { 0,
135 size_t anImageRegion[] = { aSizeX,
139 anError |= clEnqueueWriteImage (myRaytraceQueue, myRaytraceEnvironment, CL_TRUE,
140 anImageOffset, anImageRegion, 0, 0, aPixelData,
142 #ifdef RAY_TRACE_PRINT_INFO
143 if (anError != CL_SUCCESS)
144 std::cout << "Error! Failed to write environment map image!" << std::endl;
149 myViewModificationStatus = myView->ModificationState();
151 return (anError == CL_SUCCESS);
154 // =======================================================================
155 // function : UpdateRaytraceGeometry
156 // purpose : Updates 3D scene geometry for ray tracing
157 // =======================================================================
158 Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (Standard_Boolean theCheck)
161 return Standard_False;
163 // Note: In 'check' mode the scene geometry is analyzed for modifications
164 // This is light-weight procedure performed for each frame
168 myRaytraceSceneData.Clear();
170 myIsRaytraceDataValid = Standard_False;
174 if (myLayersModificationStatus != myView->LayerList().ModificationState())
176 return UpdateRaytraceGeometry (Standard_False);
180 float* aTransform (NULL);
182 // The set of processed structures (reflected to ray-tracing)
183 // This set is used to remove out-of-date records from the
184 // hash map of structures
185 std::set<const OpenGl_Structure*> anElements;
187 const OpenGl_LayerList& aList = myView->LayerList();
189 for (OpenGl_SequenceOfLayers::Iterator anLayerIt (aList.Layers()); anLayerIt.More(); anLayerIt.Next())
191 const OpenGl_PriorityList& aPriorityList = anLayerIt.Value();
193 if (aPriorityList.NbStructures() == 0)
196 const OpenGl_ArrayOfStructure& aStructArray = aPriorityList.ArrayOfStructures();
198 for (int anIndex = 0; anIndex < aStructArray.Length(); ++anIndex)
200 OpenGl_SequenceOfStructure::Iterator aStructIt;
202 for (aStructIt.Init (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next())
204 const OpenGl_Structure* aStructure = aStructIt.Value();
208 if (CheckRaytraceStructure (aStructure))
210 return UpdateRaytraceGeometry (Standard_False);
215 if (!aStructure->IsRaytracable())
218 if (aStructure->Transformation()->mat != NULL)
220 if (aTransform == NULL)
221 aTransform = new float[16];
223 for (int i = 0; i < 4; ++i)
224 for (int j = 0; j < 4; ++j)
226 aTransform[j * 4 + i] = aStructure->Transformation()->mat[i][j];
230 AddRaytraceStructure (aStructure, aTransform, anElements);
238 // Actualize the hash map of structures -- remove out-of-date records
239 std::map<const OpenGl_Structure*, Standard_Size>::iterator anIter = myStructureStates.begin();
241 while (anIter != myStructureStates.end())
243 if (anElements.find (anIter->first) == anElements.end())
245 myStructureStates.erase (anIter++);
253 // Actualize OpenGL layer list state
254 myLayersModificationStatus = myView->LayerList().ModificationState();
257 #ifdef RAY_TRACE_PRINT_INFO
262 myBVHBuilder.Build (myRaytraceSceneData);
264 #ifdef RAY_TRACE_PRINT_INFO
265 std::cout << " Build time: " << aTimer.ElapsedTime() << " for "
266 << myRaytraceSceneData.Triangles.size() / 1000 << "K triangles" << std::endl;
269 const float aScaleFactor = 1.5f;
271 myRaytraceSceneRadius = aScaleFactor *
272 Max ( Max (fabsf (myRaytraceSceneData.AABB.CornerMin().x()),
273 Max (fabsf (myRaytraceSceneData.AABB.CornerMin().y()),
274 fabsf (myRaytraceSceneData.AABB.CornerMin().z()))),
275 Max (fabsf (myRaytraceSceneData.AABB.CornerMax().x()),
276 Max (fabsf (myRaytraceSceneData.AABB.CornerMax().y()),
277 fabsf (myRaytraceSceneData.AABB.CornerMax().z()))) );
279 myRaytraceSceneEpsilon = Max (1e-4f, myRaytraceSceneRadius * 1e-4f);
281 return WriteRaytraceSceneToDevice();
284 delete [] aTransform;
286 return Standard_True;
289 // =======================================================================
290 // function : CheckRaytraceStructure
291 // purpose : Adds OpenGL structure to ray-traced scene geometry
292 // =======================================================================
293 Standard_Boolean OpenGl_Workspace::CheckRaytraceStructure (const OpenGl_Structure* theStructure)
295 if (!theStructure->IsRaytracable())
297 // Checks to see if all ray-tracable elements were
298 // removed from the structure
299 if (theStructure->ModificationState() > 0)
301 theStructure->ResetModificationState();
302 return Standard_True;
305 return Standard_False;
308 std::map<const OpenGl_Structure*, Standard_Size>::iterator aStructState = myStructureStates.find (theStructure);
310 if (aStructState != myStructureStates.end())
311 return aStructState->second != theStructure->ModificationState();
313 return Standard_True;
316 // =======================================================================
317 // function : CreateMaterial
318 // purpose : Creates ray-tracing material properties
319 // =======================================================================
320 void CreateMaterial (const OPENGL_SURF_PROP& theProp,
321 OpenGl_RaytraceMaterial& theMaterial)
323 const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
324 theMaterial.Ambient = OpenGl_RTVec4f (aSrcAmb[0] * theProp.amb,
325 aSrcAmb[1] * theProp.amb,
326 aSrcAmb[2] * theProp.amb,
329 const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
330 theMaterial.Diffuse = OpenGl_RTVec4f (aSrcDif[0] * theProp.diff,
331 aSrcDif[1] * theProp.diff,
332 aSrcDif[2] * theProp.diff,
335 const float aDefSpecCol[4] = {1.0f, 1.0f, 1.0f, 1.0f};
336 const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : aDefSpecCol;
337 theMaterial.Specular = OpenGl_RTVec4f (aSrcSpe[0] * theProp.spec,
338 aSrcSpe[1] * theProp.spec,
339 aSrcSpe[2] * theProp.spec,
342 const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
343 theMaterial.Emission = OpenGl_RTVec4f (aSrcEms[0] * theProp.emsv,
344 aSrcEms[1] * theProp.emsv,
345 aSrcEms[2] * theProp.emsv,
348 // Note: Here we use sub-linear transparency function
349 // to produce realistic-looking transparency effect
350 theMaterial.Transparency = OpenGl_RTVec4f (powf (theProp.trans, 0.75f),
355 const float aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
356 Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
357 theMaterial.Diffuse.z() + theMaterial.Specular.z()));
359 const float aReflectionScale = 0.75f / aMaxRefl;
361 theMaterial.Reflection = OpenGl_RTVec4f (theProp.speccol.rgb[0] * theProp.spec,
362 theProp.speccol.rgb[1] * theProp.spec,
363 theProp.speccol.rgb[2] * theProp.spec,
364 0.f) * aReflectionScale;
367 // =======================================================================
368 // function : AddRaytraceStructure
369 // purpose : Adds OpenGL structure to ray-traced scene geometry
370 // =======================================================================
371 Standard_Boolean OpenGl_Workspace::AddRaytraceStructure (const OpenGl_Structure* theStructure,
372 const float* theTransform,
373 std::set<const OpenGl_Structure*>& theElements)
375 #ifdef RAY_TRACE_PRINT_INFO
376 std::cout << "Add Structure" << std::endl;
379 theElements.insert (theStructure);
381 if (!theStructure->IsVisible())
383 myStructureStates[theStructure] = theStructure->ModificationState();
384 return Standard_True;
387 // Get structure material
388 int aStructMatID = -1;
390 if (theStructure->AspectFace() != NULL)
392 aStructMatID = static_cast<int> (myRaytraceSceneData.Materials.size());
394 OpenGl_RaytraceMaterial aStructMaterial;
395 CreateMaterial (theStructure->AspectFace()->IntFront(), aStructMaterial);
397 myRaytraceSceneData.Materials.push_back (aStructMaterial);
400 OpenGl_ListOfGroup::Iterator anItg (theStructure->Groups());
404 // Get group material
405 int aGroupMatID = -1;
407 if (anItg.Value()->AspectFace() != NULL)
409 aGroupMatID = static_cast<int> (myRaytraceSceneData.Materials.size());
411 OpenGl_RaytraceMaterial aGroupMaterial;
412 CreateMaterial (anItg.Value()->AspectFace()->IntFront(), aGroupMaterial);
414 myRaytraceSceneData.Materials.push_back (aGroupMaterial);
417 int aMatID = aGroupMatID < 0 ? aStructMatID : aGroupMatID;
419 if (aStructMatID < 0 && aGroupMatID < 0)
421 aMatID = static_cast<int> (myRaytraceSceneData.Materials.size());
423 myRaytraceSceneData.Materials.push_back (OpenGl_RaytraceMaterial());
426 // Add OpenGL elements from group (only arrays of primitives)
427 for (const OpenGl_ElementNode* aNode = anItg.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
429 if (TelNil == aNode->type)
431 OpenGl_AspectFace* anAspect = dynamic_cast<OpenGl_AspectFace*> (aNode->elem);
433 if (anAspect != NULL)
435 aMatID = static_cast<int> (myRaytraceSceneData.Materials.size());
437 OpenGl_RaytraceMaterial aMaterial;
438 CreateMaterial (anAspect->IntFront(), aMaterial);
440 myRaytraceSceneData.Materials.push_back (aMaterial);
443 else if (TelParray == aNode->type)
445 OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
447 if (aPrimArray != NULL)
449 AddRaytracePrimitiveArray (aPrimArray->PArray(), aMatID, theTransform);
457 float* aTransform (NULL);
459 // Process all connected OpenGL structures
460 OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures());
464 if (anIts.Value()->Transformation()->mat != NULL)
466 float* aTransform = new float[16];
468 for (int i = 0; i < 4; ++i)
469 for (int j = 0; j < 4; ++j)
471 aTransform[j * 4 + i] =
472 anIts.Value()->Transformation()->mat[i][j];
476 if (anIts.Value()->IsRaytracable())
477 AddRaytraceStructure (anIts.Value(), aTransform != NULL ? aTransform : theTransform, theElements);
484 myStructureStates[theStructure] = theStructure->ModificationState();
486 return Standard_True;
489 // =======================================================================
490 // function : AddRaytracePrimitiveArray
491 // purpose : Adds OpenGL primitive array to ray-traced scene geometry
492 // =======================================================================
493 Standard_Boolean OpenGl_Workspace::AddRaytracePrimitiveArray (const CALL_DEF_PARRAY* theArray,
495 const float* theTransform)
497 if (theArray->type != TelPolygonsArrayType &&
498 theArray->type != TelTrianglesArrayType &&
499 theArray->type != TelQuadranglesArrayType &&
500 theArray->type != TelTriangleFansArrayType &&
501 theArray->type != TelTriangleStripsArrayType &&
502 theArray->type != TelQuadrangleStripsArrayType)
504 return Standard_True;
507 if (theArray->vertices == NULL)
508 return Standard_False;
510 #ifdef RAY_TRACE_PRINT_INFO
511 switch (theArray->type)
513 case TelPolygonsArrayType:
514 std::cout << "\tTelPolygonsArrayType" << std::endl; break;
515 case TelTrianglesArrayType:
516 std::cout << "\tTelTrianglesArrayType" << std::endl; break;
517 case TelQuadranglesArrayType:
518 std::cout << "\tTelQuadranglesArrayType" << std::endl; break;
519 case TelTriangleFansArrayType:
520 std::cout << "\tTelTriangleFansArrayType" << std::endl; break;
521 case TelTriangleStripsArrayType:
522 std::cout << "\tTelTriangleStripsArrayType" << std::endl; break;
523 case TelQuadrangleStripsArrayType:
524 std::cout << "\tTelQuadrangleStripsArrayType" << std::endl; break;
528 // Simple optimization to eliminate possible memory allocations
529 // during processing of the primitive array vertices
530 myRaytraceSceneData.Vertices.reserve (
531 myRaytraceSceneData.Vertices.size() + theArray->num_vertexs);
533 const int aFirstVert = static_cast<int> (myRaytraceSceneData.Vertices.size());
535 for (int aVert = 0; aVert < theArray->num_vertexs; ++aVert)
537 OpenGl_RTVec4f aVertex (theArray->vertices[aVert].xyz[0],
538 theArray->vertices[aVert].xyz[1],
539 theArray->vertices[aVert].xyz[2],
543 aVertex = MatVecMult (theTransform, aVertex);
545 myRaytraceSceneData.Vertices.push_back (aVertex);
547 myRaytraceSceneData.AABB.Add (aVertex);
550 myRaytraceSceneData.Normals.reserve (
551 myRaytraceSceneData.Normals.size() + theArray->num_vertexs);
553 for (int aNorm = 0; aNorm < theArray->num_vertexs; ++aNorm)
555 OpenGl_RTVec4f aNormal;
557 // Note: In case of absence of normals, the visualizer
558 // will use generated geometric normals
560 if (theArray->vnormals != NULL)
562 aNormal = OpenGl_RTVec4f (theArray->vnormals[aNorm].xyz[0],
563 theArray->vnormals[aNorm].xyz[1],
564 theArray->vnormals[aNorm].xyz[2],
568 aNormal = MatVecMult (theTransform, aNormal);
571 myRaytraceSceneData.Normals.push_back (aNormal);
574 if (theArray->num_bounds > 0)
576 #ifdef RAY_TRACE_PRINT_INFO
577 std::cout << "\tNumber of bounds = " << theArray->num_bounds << std::endl;
582 for (int aBound = 0; aBound < theArray->num_bounds; ++aBound)
584 const int aVertNum = theArray->bounds[aBound];
586 #ifdef RAY_TRACE_PRINT_INFO
587 std::cout << "\tAdd indices from bound " << aBound << ": " <<
588 aVertOffset << ", " << aVertNum << std::endl;
591 if (!AddRaytraceVertexIndices (theArray, aFirstVert, aVertOffset, aVertNum, theMatID))
593 return Standard_False;
596 aVertOffset += aVertNum;
601 const int aVertNum = theArray->num_edges > 0 ? theArray->num_edges : theArray->num_vertexs;
603 #ifdef RAY_TRACE_PRINT_INFO
604 std::cout << "\tAdd indices: " << aVertNum << std::endl;
607 return AddRaytraceVertexIndices (theArray, aFirstVert, 0, aVertNum, theMatID);
610 return Standard_True;
613 // =======================================================================
614 // function : AddRaytraceVertexIndices
615 // purpose : Adds vertex indices to ray-traced scene geometry
616 // =======================================================================
617 Standard_Boolean OpenGl_Workspace::AddRaytraceVertexIndices (const CALL_DEF_PARRAY* theArray,
623 myRaytraceSceneData.Triangles.reserve (myRaytraceSceneData.Triangles.size() + theVertNum);
624 switch (theArray->type)
626 case TelTrianglesArrayType: return AddRaytraceTriangleArray (theArray, theFirstVert, theVertOffset, theVertNum, theMatID);
627 case TelQuadranglesArrayType: return AddRaytraceQuadrangleArray (theArray, theFirstVert, theVertOffset, theVertNum, theMatID);
628 case TelTriangleFansArrayType: return AddRaytraceTriangleFanArray (theArray, theFirstVert, theVertOffset, theVertNum, theMatID);
629 case TelTriangleStripsArrayType: return AddRaytraceTriangleStripArray (theArray, theFirstVert, theVertOffset, theVertNum, theMatID);
630 case TelQuadrangleStripsArrayType: return AddRaytraceQuadrangleStripArray (theArray, theFirstVert, theVertOffset, theVertNum, theMatID);
631 case TelPolygonsArrayType: return AddRaytracePolygonArray (theArray, theFirstVert, theVertOffset, theVertNum, theMatID);
632 default: return Standard_False;
636 // =======================================================================
637 // function : AddRaytraceTriangleArray
638 // purpose : Adds OpenGL triangle array to ray-traced scene geometry
639 // =======================================================================
640 Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleArray (const CALL_DEF_PARRAY* theArray,
647 return Standard_True;
649 if (theArray->num_edges > 0)
651 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 2; aVert += 3)
653 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theArray->edges[aVert + 0],
654 theFirstVert + theArray->edges[aVert + 1],
655 theFirstVert + theArray->edges[aVert + 2],
661 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 2; aVert += 3)
663 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + aVert + 0,
664 theFirstVert + aVert + 1,
665 theFirstVert + aVert + 2,
670 return Standard_True;
673 // =======================================================================
674 // function : AddRaytraceTriangleFanArray
675 // purpose : Adds OpenGL triangle fan array to ray-traced scene geometry
676 // =======================================================================
677 Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleFanArray (const CALL_DEF_PARRAY* theArray,
684 return Standard_True;
686 if (theArray->num_edges > 0)
688 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 2; ++aVert)
690 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theArray->edges[theVertOffset],
691 theFirstVert + theArray->edges[aVert + 1],
692 theFirstVert + theArray->edges[aVert + 2],
698 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 2; ++aVert)
700 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theVertOffset,
701 theFirstVert + aVert + 1,
702 theFirstVert + aVert + 2,
707 return Standard_True;
710 // =======================================================================
711 // function : AddRaytraceTriangleStripArray
712 // purpose : Adds OpenGL triangle strip array to ray-traced scene geometry
713 // =======================================================================
714 Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleStripArray (const CALL_DEF_PARRAY* theArray,
721 return Standard_True;
723 if (theArray->num_edges > 0)
725 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (
726 theFirstVert + theArray->edges[theVertOffset + 0],
727 theFirstVert + theArray->edges[theVertOffset + 1],
728 theFirstVert + theArray->edges[theVertOffset + 2],
731 for (int aVert = theVertOffset + 1, aTriNum = 1; aVert < theVertOffset + theVertNum - 2; ++aVert, ++aTriNum)
733 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (
734 theFirstVert + theArray->edges[aVert + (aTriNum % 2) ? 1 : 0],
735 theFirstVert + theArray->edges[aVert + (aTriNum % 2) ? 0 : 1],
736 theFirstVert + theArray->edges[aVert + 2],
742 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theVertOffset + 0,
743 theFirstVert + theVertOffset + 1,
744 theFirstVert + theVertOffset + 2,
747 for (int aVert = theVertOffset + 1, aTriNum = 1; aVert < theVertOffset + theVertNum - 2; ++aVert, ++aTriNum)
749 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + aVert + ( aTriNum % 2 ) ? 1 : 0,
750 theFirstVert + aVert + ( aTriNum % 2 ) ? 0 : 1,
751 theFirstVert + aVert + 2,
756 return Standard_True;
759 // =======================================================================
760 // function : AddRaytraceQuadrangleArray
761 // purpose : Adds OpenGL quad array to ray-traced scene geometry
762 // =======================================================================
763 Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleArray (const CALL_DEF_PARRAY* theArray,
770 return Standard_True;
772 if (theArray->num_edges > 0)
774 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 3; aVert += 4)
776 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theArray->edges[aVert + 0],
777 theFirstVert + theArray->edges[aVert + 1],
778 theFirstVert + theArray->edges[aVert + 2],
781 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theArray->edges[aVert + 0],
782 theFirstVert + theArray->edges[aVert + 2],
783 theFirstVert + theArray->edges[aVert + 3],
789 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 3; aVert += 4)
791 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + aVert + 0,
792 theFirstVert + aVert + 1,
793 theFirstVert + aVert + 2,
796 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + aVert + 0,
797 theFirstVert + aVert + 2,
798 theFirstVert + aVert + 3,
803 return Standard_True;
806 // =======================================================================
807 // function : AddRaytraceQuadrangleStripArray
808 // purpose : Adds OpenGL quad strip array to ray-traced scene geometry
809 // =======================================================================
810 Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleStripArray (const CALL_DEF_PARRAY* theArray,
817 return Standard_True;
819 if (theArray->num_edges > 0)
821 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (
822 theFirstVert + theArray->edges[theVertOffset + 0],
823 theFirstVert + theArray->edges[theVertOffset + 1],
824 theFirstVert + theArray->edges[theVertOffset + 2],
827 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (
828 theFirstVert + theArray->edges[theVertOffset + 1],
829 theFirstVert + theArray->edges[theVertOffset + 3],
830 theFirstVert + theArray->edges[theVertOffset + 2],
833 for (int aVert = theVertOffset + 2; aVert < theVertOffset + theVertNum - 3; aVert += 2)
835 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (
836 theFirstVert + theArray->edges[aVert + 0],
837 theFirstVert + theArray->edges[aVert + 1],
838 theFirstVert + theArray->edges[aVert + 2],
841 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (
842 theFirstVert + theArray->edges[aVert + 1],
843 theFirstVert + theArray->edges[aVert + 3],
844 theFirstVert + theArray->edges[aVert + 2],
850 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + 0,
855 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + 1,
860 for (int aVert = theVertOffset + 2; aVert < theVertOffset + theVertNum - 3; aVert += 2)
862 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + aVert + 0,
863 theFirstVert + aVert + 1,
864 theFirstVert + aVert + 2,
867 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + aVert + 1,
868 theFirstVert + aVert + 3,
869 theFirstVert + aVert + 2,
874 return Standard_True;
877 // =======================================================================
878 // function : AddRaytracePolygonArray
879 // purpose : Adds OpenGL polygon array to ray-traced scene geometry
880 // =======================================================================
881 Standard_Boolean OpenGl_Workspace::AddRaytracePolygonArray (const CALL_DEF_PARRAY* theArray,
887 if (theArray->num_vertexs < 3)
888 return Standard_True;
890 if (theArray->edges != NULL)
892 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 2; ++aVert)
894 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theArray->edges[theVertOffset],
895 theFirstVert + theArray->edges[aVert + 1],
896 theFirstVert + theArray->edges[aVert + 2],
902 for (int aVert = theVertOffset; aVert < theVertOffset + theVertNum - 2; ++aVert)
904 myRaytraceSceneData.Triangles.push_back (OpenGl_RTVec4i (theFirstVert + theVertOffset,
905 theFirstVert + aVert + 1,
906 theFirstVert + aVert + 2,
911 return Standard_True;
914 // =======================================================================
915 // function : UpdateRaytraceLightSources
916 // purpose : Updates 3D scene light sources for ray-tracing
917 // =======================================================================
918 Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const GLdouble theInvModelView[16])
920 myRaytraceSceneData.LightSources.clear();
922 OpenGl_RTVec4f anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
923 for (OpenGl_ListOfLight::Iterator anItl (myView->LightList());
924 anItl.More(); anItl.Next())
926 const OpenGl_Light& aLight = anItl.Value();
927 if (aLight.Type == Visual3d_TOLS_AMBIENT)
929 anAmbient += OpenGl_RTVec4f (aLight.Color.r(), aLight.Color.g(), aLight.Color.b(), 0.0f);
933 OpenGl_RTVec4f aDiffuse (aLight.Color.r(), aLight.Color.g(), aLight.Color.b(), 1.0f);
934 OpenGl_RTVec4f aPosition (-aLight.Direction.x(), -aLight.Direction.y(), -aLight.Direction.z(), 0.0f);
935 if (aLight.Type != Visual3d_TOLS_DIRECTIONAL)
937 aPosition = OpenGl_RTVec4f (aLight.Position.x(), aLight.Position.y(), aLight.Position.z(), 1.0f);
939 if (aLight.IsHeadlight)
941 aPosition = MatVecMult (theInvModelView, aPosition);
944 myRaytraceSceneData.LightSources.push_back (OpenGl_RaytraceLight (aDiffuse, aPosition));
947 if (myRaytraceSceneData.LightSources.size() > 0)
949 myRaytraceSceneData.LightSources.front().Ambient += anAmbient;
953 myRaytraceSceneData.LightSources.push_back (OpenGl_RaytraceLight (OpenGl_RTVec4f (anAmbient.rgb(), -1.0f)));
956 cl_int anError = CL_SUCCESS;
958 if (myRaytraceLightSourceBuffer != NULL)
959 clReleaseMemObject (myRaytraceLightSourceBuffer);
961 const size_t myLightBufferSize = myRaytraceSceneData.LightSources.size() > 0
962 ? myRaytraceSceneData.LightSources.size()
965 myRaytraceLightSourceBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
966 myLightBufferSize * sizeof(OpenGl_RaytraceLight),
969 if (myRaytraceSceneData.LightSources.size() > 0)
971 const void* aDataPtr = myRaytraceSceneData.LightSources.front().Packed();
972 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceLightSourceBuffer, CL_TRUE, 0,
973 myLightBufferSize * sizeof(OpenGl_RaytraceLight), aDataPtr,
977 #ifdef RAY_TRACE_PRINT_INFO
978 if (anError != CL_SUCCESS)
980 std::cout << "Error! Failed to set light sources!";
982 return Standard_False;
986 return Standard_True;
989 // =======================================================================
990 // function : CheckOpenCL
991 // purpose : Checks OpenCL dynamic library availability
992 // =======================================================================
993 Standard_Boolean CheckOpenCL()
995 #if defined ( _WIN32 )
999 cl_uint aNbPlatforms;
1000 clGetPlatformIDs (0, NULL, &aNbPlatforms);
1002 __except (EXCEPTION_EXECUTE_HANDLER)
1004 return Standard_False;
1009 return Standard_True;
1012 // =======================================================================
1013 // function : InitOpenCL
1014 // purpose : Initializes OpenCL objects
1015 // =======================================================================
1016 Standard_Boolean OpenGl_Workspace::InitOpenCL()
1018 if (myComputeInitStatus != OpenGl_CLIS_NONE)
1020 return myComputeInitStatus == OpenGl_CLIS_INIT;
1025 myComputeInitStatus = OpenGl_CLIS_FAIL; // fail to load OpenCL library
1026 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1027 GL_DEBUG_TYPE_ERROR_ARB,
1029 GL_DEBUG_SEVERITY_HIGH_ARB,
1030 "Failed to load OpenCL dynamic library!");
1031 return Standard_False;
1034 // Obtain the list of platforms available
1035 cl_uint aNbPlatforms = 0;
1036 cl_int anError = clGetPlatformIDs (0, NULL, &aNbPlatforms);
1037 cl_platform_id* aPlatforms = (cl_platform_id* )alloca (aNbPlatforms * sizeof(cl_platform_id));
1038 anError |= clGetPlatformIDs (aNbPlatforms, aPlatforms, NULL);
1039 if (anError != CL_SUCCESS
1040 || aNbPlatforms == 0)
1042 myComputeInitStatus = OpenGl_CLIS_FAIL;
1043 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1044 GL_DEBUG_TYPE_ERROR_ARB,
1046 GL_DEBUG_SEVERITY_HIGH_ARB,
1047 "No any OpenCL platform installed!");
1048 return Standard_False;
1051 // Note: We try to find NVIDIA or AMD platforms with GPU devices!
1052 cl_platform_id aPrefPlatform = NULL;
1053 for (cl_uint aPlatIter = 0; aPlatIter < aNbPlatforms; ++aPlatIter)
1056 anError = clGetPlatformInfo (aPlatforms[aPlatIter], CL_PLATFORM_NAME,
1057 sizeof(aName), aName, NULL);
1058 if (anError != CL_SUCCESS)
1063 if (strncmp (aName, "NVIDIA", strlen ("NVIDIA")) == 0)
1065 aPrefPlatform = aPlatforms[aPlatIter];
1067 // Use optimizations for NVIDIA GPUs
1068 myIsAmdComputePlatform = Standard_False;
1070 else if (strncmp (aName, "AMD", strlen ("AMD")) == 0)
1072 aPrefPlatform = (aPrefPlatform == NULL)
1073 ? aPlatforms[aPlatIter]
1076 // Use optimizations for ATI/AMD platform
1077 myIsAmdComputePlatform = Standard_True;
1081 if (aPrefPlatform == NULL)
1083 aPrefPlatform = aPlatforms[0];
1086 // Obtain the list of devices available in the selected platform
1087 cl_uint aNbDevices = 0;
1088 anError = clGetDeviceIDs (aPrefPlatform, CL_DEVICE_TYPE_GPU,
1089 0, NULL, &aNbDevices);
1091 cl_device_id* aDevices = (cl_device_id* )alloca (aNbDevices * sizeof(cl_device_id));
1092 anError |= clGetDeviceIDs (aPrefPlatform, CL_DEVICE_TYPE_GPU,
1093 aNbDevices, aDevices, NULL);
1094 if (anError != CL_SUCCESS)
1096 myComputeInitStatus = OpenGl_CLIS_FAIL;
1097 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1098 GL_DEBUG_TYPE_ERROR_ARB,
1100 GL_DEBUG_SEVERITY_HIGH_ARB,
1101 "Failed to get OpenCL GPU device!");
1102 return Standard_False;
1105 // Note: Simply get first available GPU
1106 cl_device_id aDevice = aDevices[0];
1108 // detect old contexts
1109 char aVerClStr[256];
1110 clGetDeviceInfo (aDevice, CL_DEVICE_VERSION,
1111 sizeof(aVerClStr), aVerClStr, NULL);
1112 aVerClStr[strlen ("OpenCL 1.0")] = '\0';
1113 const bool isVer10 = strncmp (aVerClStr, "OpenCL 1.0", strlen ("OpenCL 1.0")) == 0;
1115 // Create OpenCL context
1116 cl_context_properties aCtxProp[] =
1118 #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1119 CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
1120 (cl_context_properties )CGLGetShareGroup (CGLGetCurrentContext()),
1121 #elif defined(_WIN32)
1122 CL_CONTEXT_PLATFORM, (cl_context_properties )aPrefPlatform,
1123 CL_GL_CONTEXT_KHR, (cl_context_properties )wglGetCurrentContext(),
1124 CL_WGL_HDC_KHR, (cl_context_properties )wglGetCurrentDC(),
1126 CL_GL_CONTEXT_KHR, (cl_context_properties )glXGetCurrentContext(),
1127 CL_GLX_DISPLAY_KHR, (cl_context_properties )glXGetCurrentDisplay(),
1128 CL_CONTEXT_PLATFORM, (cl_context_properties )aPrefPlatform,
1133 myComputeContext = clCreateContext (aCtxProp,
1134 #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1135 0, NULL, // device will be taken from GL context
1139 NULL, NULL, &anError);
1140 if (anError != CL_SUCCESS)
1142 myComputeInitStatus = OpenGl_CLIS_FAIL;
1143 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1144 GL_DEBUG_TYPE_ERROR_ARB,
1146 GL_DEBUG_SEVERITY_HIGH_ARB,
1147 "Failed to initialize OpenCL context!");
1148 return Standard_False;
1151 // Create OpenCL program
1152 const char* aSources[] =
1154 isVer10 ? "#define M_PI_F ( float )( 3.14159265359f )\n" : "",
1155 THE_RAY_TRACE_OPENCL_SOURCE
1157 myRaytraceProgram = clCreateProgramWithSource (myComputeContext, 2,
1158 aSources, NULL, &anError);
1159 if (anError != CL_SUCCESS)
1161 myComputeInitStatus = OpenGl_CLIS_FAIL;
1162 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1163 GL_DEBUG_TYPE_ERROR_ARB,
1165 GL_DEBUG_SEVERITY_HIGH_ARB,
1166 "Failed to create OpenCL ray-tracing program!");
1167 return Standard_False;
1170 anError = clBuildProgram (myRaytraceProgram, 0,
1171 NULL, NULL, NULL, NULL);
1175 cl_int aResult = clGetProgramBuildInfo (myRaytraceProgram, aDevice,
1176 CL_PROGRAM_BUILD_LOG, 0, NULL, &aLogLen);
1178 char* aBuildLog = (char* )alloca (aLogLen);
1179 aResult |= clGetProgramBuildInfo (myRaytraceProgram, aDevice,
1180 CL_PROGRAM_BUILD_LOG, aLogLen, aBuildLog, NULL);
1181 if (aResult == CL_SUCCESS)
1183 if (anError != CL_SUCCESS)
1185 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1186 GL_DEBUG_TYPE_ERROR_ARB,
1188 GL_DEBUG_SEVERITY_HIGH_ARB,
1193 #ifdef RAY_TRACE_PRINT_INFO
1194 std::cout << aBuildLog << std::endl;
1200 if (anError != CL_SUCCESS)
1202 return Standard_False;
1205 // Create OpenCL ray tracing kernels
1206 myRaytraceRenderKernel = clCreateKernel (myRaytraceProgram, "Main", &anError);
1207 if (anError != CL_SUCCESS)
1209 myComputeInitStatus = OpenGl_CLIS_FAIL;
1210 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1211 GL_DEBUG_TYPE_ERROR_ARB,
1213 GL_DEBUG_SEVERITY_HIGH_ARB,
1214 "Failed to create OpenCL ray-tracing kernel!");
1215 return Standard_False;
1218 myRaytraceSmoothKernel = clCreateKernel (myRaytraceProgram, "MainAntialiased", &anError);
1219 if (anError != CL_SUCCESS)
1221 myComputeInitStatus = OpenGl_CLIS_FAIL;
1222 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1223 GL_DEBUG_TYPE_ERROR_ARB,
1225 GL_DEBUG_SEVERITY_HIGH_ARB,
1226 "Failed to create OpenCL ray-tracing kernel!");
1227 return Standard_False;
1230 // Create OpenCL command queue
1231 // Note: For profiling set CL_QUEUE_PROFILING_ENABLE
1232 cl_command_queue_properties aProps = CL_QUEUE_PROFILING_ENABLE;
1234 myRaytraceQueue = clCreateCommandQueue (myComputeContext, aDevice, aProps, &anError);
1235 if (anError != CL_SUCCESS)
1237 myComputeInitStatus = OpenGl_CLIS_FAIL;
1238 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1239 GL_DEBUG_TYPE_ERROR_ARB,
1241 GL_DEBUG_SEVERITY_HIGH_ARB,
1242 "Failed to create OpenCL command queue!");
1244 return Standard_False;
1247 myComputeInitStatus = OpenGl_CLIS_INIT; // initialized in normal way
1248 return Standard_True;
1251 // =======================================================================
1252 // function : GetOpenClDeviceInfo
1253 // purpose : Returns information about device used for computations
1254 // =======================================================================
1255 Standard_Boolean OpenGl_Workspace::GetOpenClDeviceInfo (NCollection_DataMap<TCollection_AsciiString,
1256 TCollection_AsciiString>& theInfo) const
1259 if (myComputeContext == NULL)
1261 return Standard_False;
1264 size_t aDevicesSize = 0;
1265 cl_int anError = clGetContextInfo (myComputeContext, CL_CONTEXT_DEVICES, 0, NULL, &aDevicesSize);
1266 cl_device_id* aDevices = (cl_device_id* )alloca (aDevicesSize);
1267 anError |= clGetContextInfo (myComputeContext, CL_CONTEXT_DEVICES, aDevicesSize, aDevices, NULL);
1268 if (anError != CL_SUCCESS)
1270 return Standard_False;
1273 char aDeviceName[256];
1274 anError |= clGetDeviceInfo (aDevices[0], CL_DEVICE_NAME, sizeof(aDeviceName), aDeviceName, NULL);
1275 theInfo.Bind ("Name", aDeviceName);
1277 char aDeviceVendor[256];
1278 anError |= clGetDeviceInfo (aDevices[0], CL_DEVICE_VENDOR, sizeof(aDeviceVendor), aDeviceVendor, NULL);
1279 theInfo.Bind ("Vendor", aDeviceVendor);
1281 cl_device_type aDeviceType;
1282 anError |= clGetDeviceInfo (aDevices[0], CL_DEVICE_TYPE, sizeof(aDeviceType), &aDeviceType, NULL);
1283 theInfo.Bind ("Type", aDeviceType == CL_DEVICE_TYPE_GPU ? "GPU" : "CPU");
1284 return Standard_True;
1287 // =======================================================================
1288 // function : ReleaseOpenCL
1289 // purpose : Releases resources of OpenCL objects
1290 // =======================================================================
1291 void OpenGl_Workspace::ReleaseOpenCL()
1293 clReleaseKernel (myRaytraceRenderKernel);
1294 clReleaseKernel (myRaytraceSmoothKernel);
1296 clReleaseProgram (myRaytraceProgram);
1297 clReleaseCommandQueue (myRaytraceQueue);
1299 clReleaseMemObject (myRaytraceOutputImage);
1300 clReleaseMemObject (myRaytraceEnvironment);
1301 clReleaseMemObject (myRaytraceOutputImageSmooth);
1303 clReleaseMemObject (myRaytraceVertexBuffer);
1304 clReleaseMemObject (myRaytraceNormalBuffer);
1305 clReleaseMemObject (myRaytraceTriangleBuffer);
1307 clReleaseMemObject (myRaytraceMaterialBuffer);
1308 clReleaseMemObject (myRaytraceLightSourceBuffer);
1310 clReleaseMemObject (myRaytraceNodeMinPointBuffer);
1311 clReleaseMemObject (myRaytraceNodeMaxPointBuffer);
1312 clReleaseMemObject (myRaytraceNodeDataRcrdBuffer);
1314 clReleaseContext (myComputeContext);
1316 if (glIsTexture (*myRaytraceOutputTexture))
1317 glDeleteTextures (2, myRaytraceOutputTexture);
1320 // =======================================================================
1321 // function : ResizeRaytraceOutputBuffer
1322 // purpose : Resizes OpenCL output image
1323 // =======================================================================
1324 Standard_Boolean OpenGl_Workspace::ResizeRaytraceOutputBuffer (const cl_int theSizeX,
1325 const cl_int theSizeY)
1327 if (myComputeContext == NULL)
1329 return Standard_False;
1332 bool toResize = true;
1335 if (*myRaytraceOutputTexture != 0)
1337 if (!myGlContext->IsGlGreaterEqual (2, 1))
1339 return Standard_False;
1342 glBindTexture (GL_TEXTURE_RECTANGLE, *myRaytraceOutputTexture);
1344 glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &aSizeX);
1345 glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aSizeY);
1347 toResize = (aSizeX != theSizeX) || (aSizeY != theSizeY);
1350 glDeleteTextures (2, myRaytraceOutputTexture);
1355 return Standard_True;
1358 glGenTextures (2, myRaytraceOutputTexture);
1359 for (int aTexIter = 0; aTexIter < 2; ++aTexIter)
1361 glBindTexture (GL_TEXTURE_RECTANGLE, myRaytraceOutputTexture[aTexIter]);
1363 glTexParameteri (GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
1364 glTexParameteri (GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
1365 glTexParameteri (GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_R, GL_CLAMP);
1367 glTexParameteri (GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1368 glTexParameteri (GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1370 glTexImage2D (GL_TEXTURE_RECTANGLE, 0, GL_RGBA32F,
1371 theSizeX, theSizeY, 0,
1372 GL_RGBA, GL_FLOAT, NULL);
1375 cl_int anError = CL_SUCCESS;
1377 if (myRaytraceOutputImage != NULL)
1379 clReleaseMemObject (myRaytraceOutputImage);
1381 if (myRaytraceOutputImageSmooth != NULL)
1383 clReleaseMemObject (myRaytraceOutputImageSmooth);
1386 myRaytraceOutputImage = clCreateFromGLTexture2D (myComputeContext, CL_MEM_READ_WRITE,
1387 GL_TEXTURE_RECTANGLE, 0,
1388 myRaytraceOutputTexture[0], &anError);
1389 if (anError != CL_SUCCESS)
1391 #ifdef RAY_TRACE_PRINT_INFO
1392 std::cout << "Error! Failed to create output image!" << std::endl;
1394 return Standard_False;
1397 myRaytraceOutputImageSmooth = clCreateFromGLTexture2D (myComputeContext, CL_MEM_READ_WRITE,
1398 GL_TEXTURE_RECTANGLE, 0,
1399 myRaytraceOutputTexture[1], &anError);
1400 if (anError != CL_SUCCESS)
1402 #ifdef RAY_TRACE_PRINT_INFO
1403 std::cout << "Error! Failed to create anti-aliased output image!" << std::endl;
1405 return Standard_False;
1408 return Standard_True;
1411 // =======================================================================
1412 // function : WriteRaytraceSceneToDevice
1413 // purpose : Writes scene geometry to OpenCl device
1414 // =======================================================================
1415 Standard_Boolean OpenGl_Workspace::WriteRaytraceSceneToDevice()
1417 if (myComputeContext == NULL)
1418 return Standard_False;
1420 cl_int anError = CL_SUCCESS;
1422 if (myRaytraceNormalBuffer != NULL)
1423 anError |= clReleaseMemObject (myRaytraceNormalBuffer);
1425 if (myRaytraceVertexBuffer != NULL)
1426 anError |= clReleaseMemObject (myRaytraceVertexBuffer);
1428 if (myRaytraceTriangleBuffer != NULL)
1429 anError |= clReleaseMemObject (myRaytraceTriangleBuffer);
1431 if (myRaytraceNodeMinPointBuffer != NULL)
1432 anError |= clReleaseMemObject (myRaytraceNodeMinPointBuffer);
1434 if (myRaytraceNodeMaxPointBuffer != NULL)
1435 anError |= clReleaseMemObject (myRaytraceNodeMaxPointBuffer);
1437 if (myRaytraceNodeDataRcrdBuffer != NULL)
1438 anError |= clReleaseMemObject (myRaytraceNodeDataRcrdBuffer);
1440 if (myRaytraceMaterialBuffer != NULL)
1441 anError |= clReleaseMemObject (myRaytraceMaterialBuffer);
1443 if (anError != CL_SUCCESS)
1445 #ifdef RAY_TRACE_PRINT_INFO
1446 std::cout << "Error! Failed to release OpenCL scene buffers!" << std::endl;
1448 return Standard_False;
1451 // Create geometry buffers
1452 cl_int anErrorTemp = CL_SUCCESS;
1453 const size_t myVertexBufferSize = myRaytraceSceneData.Vertices.size() > 0
1454 ? myRaytraceSceneData.Vertices.size() : 1;
1456 myRaytraceVertexBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
1457 myVertexBufferSize * sizeof(cl_float4), NULL, &anErrorTemp);
1458 anError |= anErrorTemp;
1460 const size_t myNormalBufferSize = myRaytraceSceneData.Normals.size() > 0
1461 ? myRaytraceSceneData.Normals.size() : 1;
1462 myRaytraceNormalBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
1463 myNormalBufferSize * sizeof(cl_float4), NULL, &anErrorTemp);
1464 anError |= anErrorTemp;
1466 const size_t myTriangleBufferSize = myRaytraceSceneData.Triangles.size() > 0
1467 ? myRaytraceSceneData.Triangles.size() : 1;
1468 myRaytraceTriangleBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
1469 myTriangleBufferSize * sizeof(cl_int4), NULL, &anErrorTemp);
1470 anError |= anErrorTemp;
1471 if (anError != CL_SUCCESS)
1473 #ifdef RAY_TRACE_PRINT_INFO
1474 std::cout << "Error! Failed to create OpenCL geometry buffers!" << std::endl;
1476 return Standard_False;
1479 // Create material buffer
1480 const size_t myMaterialBufferSize = myRaytraceSceneData.Materials.size() > 0
1481 ? myRaytraceSceneData.Materials.size() : 1;
1482 myRaytraceMaterialBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
1483 myMaterialBufferSize * sizeof(OpenGl_RaytraceMaterial), NULL,
1485 if (anErrorTemp != CL_SUCCESS)
1487 #ifdef RAY_TRACE_PRINT_INFO
1488 std::cout << "Error! Failed to create OpenCL material buffer!" << std::endl;
1490 return Standard_False;
1493 // Create BVH buffers
1494 OpenGl_BVH aTree = myBVHBuilder.Tree();
1495 const size_t myNodeMinPointBufferSize = aTree.MinPointBuffer().size() > 0
1496 ? aTree.MinPointBuffer().size() : 1;
1497 myRaytraceNodeMinPointBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
1498 myNodeMinPointBufferSize * sizeof(cl_float4), NULL,
1500 anError |= anErrorTemp;
1502 const size_t myNodeMaxPointBufferSize = aTree.MaxPointBuffer().size() > 0
1503 ? aTree.MaxPointBuffer().size() : 1;
1504 myRaytraceNodeMaxPointBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
1505 myNodeMaxPointBufferSize * sizeof(cl_float4), NULL,
1507 anError |= anErrorTemp;
1509 const size_t myNodeDataRecordBufferSize = aTree.DataRcrdBuffer().size() > 0
1510 ? aTree.DataRcrdBuffer().size() : 1;
1511 myRaytraceNodeDataRcrdBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
1512 myNodeDataRecordBufferSize * sizeof(cl_int4), NULL,
1514 anError |= anErrorTemp;
1515 if (anError != CL_SUCCESS)
1517 #ifdef RAY_TRACE_PRINT_INFO
1518 std::cout << "Error! Failed to create OpenCL BVH buffers!" << std::endl;
1520 return Standard_False;
1523 // Write scene geometry buffers
1524 if (myRaytraceSceneData.Triangles.size() > 0)
1526 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceVertexBuffer, CL_FALSE,
1527 0, myRaytraceSceneData.Vertices.size() * sizeof(cl_float4),
1528 &myRaytraceSceneData.Vertices.front(),
1530 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceNormalBuffer, CL_FALSE,
1531 0, myRaytraceSceneData.Normals.size() * sizeof(cl_float4),
1532 &myRaytraceSceneData.Normals.front(),
1534 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceTriangleBuffer, CL_FALSE,
1535 0, myRaytraceSceneData.Triangles.size() * sizeof(cl_int4),
1536 &myRaytraceSceneData.Triangles.front(),
1538 if (anError != CL_SUCCESS)
1540 #ifdef RAY_TRACE_PRINT_INFO
1541 std::cout << "Error! Failed to write OpenCL geometry buffers!" << std::endl;
1543 return Standard_False;
1547 // Write BVH buffers
1548 if (aTree.DataRcrdBuffer().size() > 0)
1550 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceNodeMinPointBuffer, CL_FALSE,
1551 0, aTree.MinPointBuffer().size() * sizeof(cl_float4),
1552 &aTree.MinPointBuffer().front(),
1554 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceNodeMaxPointBuffer, CL_FALSE,
1555 0, aTree.MaxPointBuffer().size() * sizeof(cl_float4),
1556 &aTree.MaxPointBuffer().front(),
1558 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceNodeDataRcrdBuffer, CL_FALSE,
1559 0, aTree.DataRcrdBuffer().size() * sizeof(cl_int4),
1560 &aTree.DataRcrdBuffer().front(),
1562 if (anError != CL_SUCCESS)
1564 #ifdef RAY_TRACE_PRINT_INFO
1565 std::cout << "Error! Failed to write OpenCL BVH buffers!" << std::endl;
1567 return Standard_False;
1571 // Write material buffers
1572 if (myRaytraceSceneData.Materials.size() > 0)
1574 const size_t aSize = myRaytraceSceneData.Materials.size();
1575 const void* aDataPtr = myRaytraceSceneData.Materials.front().Packed();
1577 anError |= clEnqueueWriteBuffer (myRaytraceQueue, myRaytraceMaterialBuffer, CL_FALSE,
1578 0, aSize * sizeof(OpenGl_RaytraceMaterial), aDataPtr,
1580 if (anError != CL_SUCCESS)
1582 #ifdef RAY_TRACE_PRINT_INFO
1583 std::cout << "Error! Failed to write OpenCL material buffer!" << std::endl;
1585 return Standard_False;
1589 anError |= clFinish (myRaytraceQueue);
1590 #ifdef RAY_TRACE_PRINT_INFO
1591 if (anError != CL_SUCCESS)
1592 std::cout << "Error! Failed to set scene data buffers!" << std::endl;
1595 if (anError == CL_SUCCESS)
1596 myIsRaytraceDataValid = myRaytraceSceneData.Triangles.size() > 0;
1598 #ifdef RAY_TRACE_PRINT_INFO
1600 float aMemUsed = static_cast<float> (
1601 myRaytraceSceneData.Materials.size()) * sizeof (OpenGl_RaytraceMaterial);
1603 aMemUsed += static_cast<float> (
1604 myRaytraceSceneData.Triangles.size() * sizeof (OpenGl_RTVec4i) +
1605 myRaytraceSceneData.Vertices.size() * sizeof (OpenGl_RTVec4f) +
1606 myRaytraceSceneData.Normals.size() * sizeof (OpenGl_RTVec4f));
1608 aMemUsed += static_cast<float> (
1609 aTree.MinPointBuffer().size() * sizeof (OpenGl_RTVec4f) +
1610 aTree.MaxPointBuffer().size() * sizeof (OpenGl_RTVec4f) +
1611 aTree.DataRcrdBuffer().size() * sizeof (OpenGl_RTVec4i));
1613 std::cout << "GPU memory used (Mb): " << aMemUsed / 1e6f << std::endl;
1617 myRaytraceSceneData.Clear();
1619 myBVHBuilder.CleanUp();
1621 return (CL_SUCCESS == anError);
1624 #define OPENCL_GROUP_SIZE_TEST_
1626 // =======================================================================
1627 // function : RunRaytraceOpenCLKernels
1628 // purpose : Runs OpenCL ray-tracing kernels
1629 // =======================================================================
1630 Standard_Boolean OpenGl_Workspace::RunRaytraceOpenCLKernels (const Graphic3d_CView& theCView,
1631 const GLfloat theOrigins[16],
1632 const GLfloat theDirects[16],
1636 if (myRaytraceRenderKernel == NULL || myRaytraceQueue == NULL)
1637 return Standard_False;
1639 ////////////////////////////////////////////////////////////
1640 // Set kernel arguments
1642 cl_uint anIndex = 0;
1645 anError = clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1646 sizeof(cl_mem), &myRaytraceOutputImage);
1647 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1648 sizeof(cl_mem), &myRaytraceEnvironment);
1649 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1650 sizeof(cl_mem), &myRaytraceNodeMinPointBuffer);
1651 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1652 sizeof(cl_mem), &myRaytraceNodeMaxPointBuffer);
1653 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1654 sizeof(cl_mem), &myRaytraceNodeDataRcrdBuffer);
1655 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1656 sizeof(cl_mem), &myRaytraceLightSourceBuffer);
1657 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1658 sizeof(cl_mem), &myRaytraceMaterialBuffer);
1659 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1660 sizeof(cl_mem), &myRaytraceVertexBuffer);
1661 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1662 sizeof(cl_mem), &myRaytraceNormalBuffer);
1663 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1664 sizeof(cl_mem), &myRaytraceTriangleBuffer);
1666 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1667 sizeof(cl_float16), theOrigins);
1668 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1669 sizeof(cl_float16), theDirects);
1671 cl_int aLightCount = static_cast<cl_int> (myRaytraceSceneData.LightSources.size());
1673 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1674 sizeof(cl_int), &aLightCount);
1675 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1676 sizeof(cl_float), &myRaytraceSceneEpsilon);
1677 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1678 sizeof(cl_float), &myRaytraceSceneRadius);
1679 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1680 sizeof(cl_int), &theCView.IsShadowsEnabled);
1681 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1682 sizeof(cl_int), &theCView.IsReflectionsEnabled);
1683 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1684 sizeof(cl_int), &theSizeX);
1685 anError |= clSetKernelArg (myRaytraceRenderKernel, anIndex++,
1686 sizeof(cl_int), &theSizeY);
1687 if (anError != CL_SUCCESS)
1689 const TCollection_ExtendedString aMsg = "Error! Failed to set arguments of ray-tracing kernel!";
1690 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1691 GL_DEBUG_TYPE_ERROR_ARB,
1693 GL_DEBUG_SEVERITY_HIGH_ARB,
1695 return Standard_False;
1698 // Note: second-pass 'smoothing' kernel runs only if anti-aliasing is enabled
1699 if (theCView.IsAntialiasingEnabled)
1702 anError = clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1703 sizeof(cl_mem), &myRaytraceOutputImage);
1704 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1705 sizeof(cl_mem), &myRaytraceOutputImageSmooth);
1706 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1707 sizeof(cl_mem), &myRaytraceEnvironment);
1708 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1709 sizeof(cl_mem), &myRaytraceNodeMinPointBuffer);
1710 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1711 sizeof(cl_mem), &myRaytraceNodeMaxPointBuffer);
1712 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1713 sizeof(cl_mem), &myRaytraceNodeDataRcrdBuffer);
1714 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1715 sizeof(cl_mem), &myRaytraceLightSourceBuffer);
1716 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1717 sizeof(cl_mem), &myRaytraceMaterialBuffer);
1718 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1719 sizeof(cl_mem), &myRaytraceVertexBuffer);
1720 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1721 sizeof(cl_mem), &myRaytraceNormalBuffer);
1722 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1723 sizeof(cl_mem), &myRaytraceTriangleBuffer);
1725 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1726 sizeof(cl_float16), theOrigins);
1727 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1728 sizeof(cl_float16), theDirects);
1730 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1731 sizeof(cl_int), &aLightCount);
1732 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1733 sizeof(cl_float), &myRaytraceSceneEpsilon);
1734 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1735 sizeof(cl_float), &myRaytraceSceneRadius);
1736 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1737 sizeof(cl_int), &theCView.IsShadowsEnabled);
1738 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1739 sizeof(cl_int), &theCView.IsReflectionsEnabled);
1740 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1741 sizeof(cl_int), &theSizeX);
1742 anError |= clSetKernelArg (myRaytraceSmoothKernel, anIndex++,
1743 sizeof(cl_int), &theSizeY);
1744 if (anError != CL_SUCCESS)
1746 const TCollection_ExtendedString aMsg = "Error! Failed to set arguments of 'smoothing' kernel!";
1747 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1748 GL_DEBUG_TYPE_ERROR_ARB,
1750 GL_DEBUG_SEVERITY_HIGH_ARB,
1752 return Standard_False;
1757 size_t aLocSizeRender[] = { myIsAmdComputePlatform ? 2 : 4, 32 };
1759 #ifdef OPENCL_GROUP_SIZE_TEST
1760 for (size_t aLocX = 2; aLocX <= 32; aLocX <<= 1 )
1761 for (size_t aLocY = 2; aLocY <= 32; aLocY <<= 1 )
1764 #ifdef OPENCL_GROUP_SIZE_TEST
1765 aLocSizeRender[0] = aLocX;
1766 aLocSizeRender[1] = aLocY;
1769 size_t aWorkSizeX = theSizeX;
1770 if (aWorkSizeX % aLocSizeRender[0] != 0)
1771 aWorkSizeX += aLocSizeRender[0] - aWorkSizeX % aLocSizeRender[0];
1773 size_t aWokrSizeY = theSizeY;
1774 if (aWokrSizeY % aLocSizeRender[1] != 0 )
1775 aWokrSizeY += aLocSizeRender[1] - aWokrSizeY % aLocSizeRender[1];
1777 size_t aGlbSizeRender[] = { aWorkSizeX, aWokrSizeY };
1780 cl_event anEvent (NULL), anEventSmooth (NULL);
1781 anError = clEnqueueNDRangeKernel (myRaytraceQueue, myRaytraceRenderKernel,
1782 2, NULL, aGlbSizeRender, aLocSizeRender,
1784 if (anError != CL_SUCCESS)
1786 const TCollection_ExtendedString aMsg = "Error! Failed to execute the ray-tracing kernel!";
1787 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1788 GL_DEBUG_TYPE_ERROR_ARB,
1790 GL_DEBUG_SEVERITY_HIGH_ARB,
1792 return Standard_False;
1794 clWaitForEvents (1, &anEvent);
1796 if (theCView.IsAntialiasingEnabled)
1798 size_t aLocSizeSmooth[] = { myIsAmdComputePlatform ? 8 : 4,
1799 myIsAmdComputePlatform ? 8 : 32 };
1801 #ifdef OPENCL_GROUP_SIZE_TEST
1802 aLocSizeSmooth[0] = aLocX;
1803 aLocSizeSmooth[1] = aLocY;
1806 aWorkSizeX = theSizeX;
1807 if (aWorkSizeX % aLocSizeSmooth[0] != 0)
1808 aWorkSizeX += aLocSizeSmooth[0] - aWorkSizeX % aLocSizeSmooth[0];
1810 size_t aWokrSizeY = theSizeY;
1811 if (aWokrSizeY % aLocSizeSmooth[1] != 0 )
1812 aWokrSizeY += aLocSizeSmooth[1] - aWokrSizeY % aLocSizeSmooth[1];
1814 size_t aGlbSizeSmooth [] = { aWorkSizeX, aWokrSizeY };
1815 anError = clEnqueueNDRangeKernel (myRaytraceQueue, myRaytraceSmoothKernel,
1816 2, NULL, aGlbSizeSmooth, aLocSizeSmooth,
1817 0, NULL, &anEventSmooth);
1818 clWaitForEvents (1, &anEventSmooth);
1820 if (anError != CL_SUCCESS)
1822 const TCollection_ExtendedString aMsg = "Error! Failed to execute the 'smoothing' kernel!";
1823 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1824 GL_DEBUG_TYPE_ERROR_ARB,
1826 GL_DEBUG_SEVERITY_HIGH_ARB,
1828 return Standard_False;
1832 // Get the profiling data
1833 #if defined (RAY_TRACE_PRINT_INFO) || defined(OPENCL_GROUP_SIZE_TEST)
1835 cl_ulong aTimeStart,
1838 clGetEventProfilingInfo (anEvent, CL_PROFILING_COMMAND_START,
1839 sizeof(aTimeStart), &aTimeStart, NULL);
1840 clGetEventProfilingInfo (anEvent, CL_PROFILING_COMMAND_END,
1841 sizeof(aTimeFinal), &aTimeFinal, NULL);
1842 std::cout << "\tRender time (ms): " << ( aTimeFinal - aTimeStart ) / 1e6f << std::endl;
1844 if (theCView.IsAntialiasingEnabled)
1846 clGetEventProfilingInfo (anEventSmooth, CL_PROFILING_COMMAND_START,
1847 sizeof(aTimeStart), &aTimeStart, NULL);
1848 clGetEventProfilingInfo (anEventSmooth, CL_PROFILING_COMMAND_END,
1849 sizeof(aTimeFinal), &aTimeFinal, NULL);
1850 std::cout << "\tSmoothing time (ms): " << ( aTimeFinal - aTimeStart ) / 1e6f << std::endl;
1854 if (anEvent != NULL)
1855 clReleaseEvent (anEvent);
1857 if (anEventSmooth != NULL)
1858 clReleaseEvent (anEventSmooth);
1861 return Standard_True;
1864 // =======================================================================
1865 // function : ComputeInverseMatrix
1866 // purpose : Computes inversion of 4x4 floating-point matrix
1867 // =======================================================================
1868 template <typename T>
1869 void ComputeInverseMatrix (const T m[16], T inv[16])
1871 inv[ 0] = m[ 5] * (m[10] * m[15] - m[11] * m[14]) -
1872 m[ 9] * (m[ 6] * m[15] - m[ 7] * m[14]) -
1873 m[13] * (m[ 7] * m[10] - m[ 6] * m[11]);
1875 inv[ 1] = m[ 1] * (m[11] * m[14] - m[10] * m[15]) -
1876 m[ 9] * (m[ 3] * m[14] - m[ 2] * m[15]) -
1877 m[13] * (m[ 2] * m[11] - m[ 3] * m[10]);
1879 inv[ 2] = m[ 1] * (m[ 6] * m[15] - m[ 7] * m[14]) -
1880 m[ 5] * (m[ 2] * m[15] - m[ 3] * m[14]) -
1881 m[13] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
1883 inv[ 3] = m[ 1] * (m[ 7] * m[10] - m[ 6] * m[11]) -
1884 m[ 5] * (m[ 3] * m[10] - m[ 2] * m[11]) -
1885 m[ 9] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
1887 inv[ 4] = m[ 4] * (m[11] * m[14] - m[10] * m[15]) -
1888 m[ 8] * (m[ 7] * m[14] - m[ 6] * m[15]) -
1889 m[12] * (m[ 6] * m[11] - m[ 7] * m[10]);
1891 inv[ 5] = m[ 0] * (m[10] * m[15] - m[11] * m[14]) -
1892 m[ 8] * (m[ 2] * m[15] - m[ 3] * m[14]) -
1893 m[12] * (m[ 3] * m[10] - m[ 2] * m[11]);
1895 inv[ 6] = m[ 0] * (m[ 7] * m[14] - m[ 6] * m[15]) -
1896 m[ 4] * (m[ 3] * m[14] - m[ 2] * m[15]) -
1897 m[12] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
1899 inv[ 7] = m[ 0] * (m[ 6] * m[11] - m[ 7] * m[10]) -
1900 m[ 4] * (m[ 2] * m[11] - m[ 3] * m[10]) -
1901 m[ 8] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
1903 inv[ 8] = m[ 4] * (m[ 9] * m[15] - m[11] * m[13]) -
1904 m[ 8] * (m[ 5] * m[15] - m[ 7] * m[13]) -
1905 m[12] * (m[ 7] * m[ 9] - m[ 5] * m[11]);
1907 inv[ 9] = m[ 0] * (m[11] * m[13] - m[ 9] * m[15]) -
1908 m[ 8] * (m[ 3] * m[13] - m[ 1] * m[15]) -
1909 m[12] * (m[ 1] * m[11] - m[ 3] * m[ 9]);
1911 inv[10] = m[ 0] * (m[ 5] * m[15] - m[ 7] * m[13]) -
1912 m[ 4] * (m[ 1] * m[15] - m[ 3] * m[13]) -
1913 m[12] * (m[ 3] * m[ 5] - m[ 1] * m[ 7]);
1915 inv[11] = m[ 0] * (m[ 7] * m[ 9] - m[ 5] * m[11]) -
1916 m[ 4] * (m[ 3] * m[ 9] - m[ 1] * m[11]) -
1917 m[ 8] * (m[ 1] * m[ 7] - m[ 3] * m[ 5]);
1919 inv[12] = m[ 4] * (m[10] * m[13] - m[ 9] * m[14]) -
1920 m[ 8] * (m[ 6] * m[13] - m[ 5] * m[14]) -
1921 m[12] * (m[ 5] * m[10] - m[ 6] * m[ 9]);
1923 inv[13] = m[ 0] * (m[ 9] * m[14] - m[10] * m[13]) -
1924 m[ 8] * (m[ 1] * m[14] - m[ 2] * m[13]) -
1925 m[12] * (m[ 2] * m[ 9] - m[ 1] * m[10]);
1927 inv[14] = m[ 0] * (m[ 6] * m[13] - m[ 5] * m[14]) -
1928 m[ 4] * (m[ 2] * m[13] - m[ 1] * m[14]) -
1929 m[12] * (m[ 1] * m[ 6] - m[ 2] * m[ 5]);
1931 inv[15] = m[ 0] * (m[ 5] * m[10] - m[ 6] * m[ 9]) -
1932 m[ 4] * (m[ 1] * m[10] - m[ 2] * m[ 9]) -
1933 m[ 8] * (m[ 2] * m[ 5] - m[ 1] * m[ 6]);
1935 T det = m[0] * inv[ 0] +
1940 if (det == T (0.0)) return;
1942 det = T (1.0) / det;
1944 for (int i = 0; i < 16; ++i)
1948 // =======================================================================
1949 // function : GenerateCornerRays
1950 // purpose : Generates primary rays for corners of screen quad
1951 // =======================================================================
1952 void GenerateCornerRays (const GLdouble theInvModelProj[16],
1953 float theOrigins[16],
1954 float theDirects[16])
1956 int aOriginIndex = 0;
1957 int aDirectIndex = 0;
1959 for (int y = -1; y <= 1; y += 2)
1961 for (int x = -1; x <= 1; x += 2)
1963 OpenGl_RTVec4f aOrigin (float(x),
1968 aOrigin = MatVecMult (theInvModelProj, aOrigin);
1970 OpenGl_RTVec4f aDirect (float(x),
1975 aDirect = MatVecMult (theInvModelProj, aDirect) - aOrigin;
1977 GLdouble aInvLen = 1.f / sqrt (aDirect.x() * aDirect.x() +
1978 aDirect.y() * aDirect.y() +
1979 aDirect.z() * aDirect.z());
1981 theOrigins [aOriginIndex++] = static_cast<GLfloat> (aOrigin.x());
1982 theOrigins [aOriginIndex++] = static_cast<GLfloat> (aOrigin.y());
1983 theOrigins [aOriginIndex++] = static_cast<GLfloat> (aOrigin.z());
1984 theOrigins [aOriginIndex++] = 1.f;
1986 theDirects [aDirectIndex++] = static_cast<GLfloat> (aDirect.x() * aInvLen);
1987 theDirects [aDirectIndex++] = static_cast<GLfloat> (aDirect.y() * aInvLen);
1988 theDirects [aDirectIndex++] = static_cast<GLfloat> (aDirect.z() * aInvLen);
1989 theDirects [aDirectIndex++] = 0.f;
1994 // =======================================================================
1995 // function : Raytrace
1996 // purpose : Redraws the window using OpenCL ray tracing
1997 // =======================================================================
1998 Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
2001 const Tint theToSwap)
2004 return Standard_False;
2006 if (!ResizeRaytraceOutputBuffer (theSizeX, theSizeY))
2007 return Standard_False;
2009 if (!UpdateRaytraceEnvironmentMap())
2010 return Standard_False;
2012 if (!UpdateRaytraceGeometry (Standard_True))
2013 return Standard_False;
2015 // Get model-view and projection matrices
2016 TColStd_Array2OfReal theOrientation (0, 3, 0, 3);
2017 TColStd_Array2OfReal theViewMapping (0, 3, 0, 3);
2019 myView->GetMatrices (theOrientation, theViewMapping, Standard_True);
2021 GLdouble aOrientationMatrix[16];
2022 GLdouble aViewMappingMatrix[16];
2023 GLdouble aOrientationInvers[16];
2025 for (int j = 0; j < 4; ++j)
2026 for (int i = 0; i < 4; ++i)
2028 aOrientationMatrix [4 * j + i] = theOrientation (i, j);
2029 aViewMappingMatrix [4 * j + i] = theViewMapping (i, j);
2032 ComputeInverseMatrix (aOrientationMatrix, aOrientationInvers);
2034 if (!UpdateRaytraceLightSources (aOrientationInvers))
2035 return Standard_False;
2037 // Generate primary rays for corners of the screen quad
2038 glMatrixMode (GL_MODELVIEW);
2040 glLoadMatrixd (aViewMappingMatrix);
2041 glMultMatrixd (aOrientationMatrix);
2043 GLdouble aModelProject[16];
2044 GLdouble aInvModelProj[16];
2046 glGetDoublev (GL_MODELVIEW_MATRIX, aModelProject);
2048 ComputeInverseMatrix (aModelProject, aInvModelProj);
2050 GLfloat aOrigins[16];
2051 GLfloat aDirects[16];
2053 GenerateCornerRays (aInvModelProj,
2057 // Compute ray-traced image using OpenCL kernel
2058 cl_mem anImages[] = { myRaytraceOutputImage, myRaytraceOutputImageSmooth };
2059 cl_int anError = clEnqueueAcquireGLObjects (myRaytraceQueue,
2062 clFinish (myRaytraceQueue);
2064 if (myIsRaytraceDataValid)
2066 RunRaytraceOpenCLKernels (theCView,
2073 anError |= clEnqueueReleaseGLObjects (myRaytraceQueue,
2076 clFinish (myRaytraceQueue);
2079 glPushAttrib (GL_ENABLE_BIT |
2081 GL_COLOR_BUFFER_BIT |
2082 GL_DEPTH_BUFFER_BIT);
2084 glDisable (GL_DEPTH_TEST);
2086 if (NamedStatus & OPENGL_NS_WHITEBACK)
2088 glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
2092 glClearColor (myBgColor.rgb[0],
2098 glClear (GL_COLOR_BUFFER_BIT);
2100 Handle(OpenGl_Workspace) aWorkspace (this);
2101 myView->DrawBackground (aWorkspace);
2103 // Draw dummy quad to show result image
2104 glEnable (GL_COLOR_MATERIAL);
2105 glEnable (GL_BLEND);
2107 glDisable (GL_DEPTH_TEST);
2109 glBlendFunc (GL_ONE, GL_SRC_ALPHA);
2111 glEnable (GL_TEXTURE_RECTANGLE);
2113 glMatrixMode (GL_PROJECTION);
2116 glMatrixMode (GL_MODELVIEW);
2119 glColor3f (1.0f, 1.0f, 1.0f);
2121 glBindTexture (GL_TEXTURE_RECTANGLE, myRaytraceOutputTexture[theCView.IsAntialiasingEnabled ? 1 : 0]);
2123 if (myIsRaytraceDataValid)
2127 glTexCoord2i ( 0, 0); glVertex2f (-1.f, -1.f);
2128 glTexCoord2i ( 0, theSizeY); glVertex2f (-1.f, 1.f);
2129 glTexCoord2i (theSizeX, theSizeY); glVertex2f ( 1.f, 1.f);
2130 glTexCoord2i (theSizeX, 0); glVertex2f ( 1.f, -1.f);
2140 GetGlContext()->SwapBuffers();
2141 myBackBufferRestored = Standard_False;
2146 return Standard_True;