//
// This file is part of Open CASCADE Technology software library.
//
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#ifdef HAVE_CONFIG_H
- #include <config.h>
-#endif
-
-#ifdef HAVE_OPENCL
-
-#include <OpenGl_Cl.hxx>
-
-#if defined(_WIN32)
-
- #include <windows.h>
- #include <wingdi.h>
-
- #pragma comment (lib, "DelayImp.lib")
- #pragma comment (lib, "OpenCL.lib")
-
-#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
- #include <OpenGL/CGLCurrent.h>
-#else
- #include <GL/glx.h>
-#endif
+#include <OpenGl_Workspace.hxx>
-#include <OpenGl_Context.hxx>
+#include <NCollection_Mat4.hxx>
+#include <OpenGl_ArbFBO.hxx>
+#include <OpenGl_FrameBuffer.hxx>
+#include <OpenGl_PrimitiveArray.hxx>
#include <OpenGl_Texture.hxx>
+#include <OpenGl_VertexBuffer.hxx>
#include <OpenGl_View.hxx>
-#include <OpenGl_Workspace.hxx>
+#include <OSD_File.hxx>
+#include <OSD_Protection.hxx>
#include <Standard_Assert.hxx>
using namespace OpenGl_Raytrace;
//! Use this macro to output ray-tracing debug info
-//#define RAY_TRACE_PRINT_INFO
+// #define RAY_TRACE_PRINT_INFO
#ifdef RAY_TRACE_PRINT_INFO
#include <OSD_Timer.hxx>
#endif
-//! OpenCL source of ray-tracing kernels.
-extern const char THE_RAY_TRACE_OPENCL_SOURCE[];
-
// =======================================================================
// function : MatVecMult
// purpose : Multiples 4x4 matrix by 4D vector
m[11] * v.z() + m[15] * v.w()));
}
-// =======================================================================
-// function : UpdateRaytraceEnvironmentMap
-// purpose : Updates environment map for ray-tracing
-// =======================================================================
-Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
-{
- if (myView.IsNull())
- return Standard_False;
-
- if (myViewModificationStatus == myView->ModificationState())
- return Standard_True;
-
- cl_int anError = CL_SUCCESS;
-
- if (myRaytraceEnvironment != NULL)
- clReleaseMemObject (myRaytraceEnvironment);
-
- Standard_Integer aSizeX = 1;
- Standard_Integer aSizeY = 1;
-
- if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
- {
- aSizeX = (myView->TextureEnv()->SizeX() <= 0) ? 1 : myView->TextureEnv()->SizeX();
- aSizeY = (myView->TextureEnv()->SizeY() <= 0) ? 1 : myView->TextureEnv()->SizeY();
- }
-
- cl_image_format anImageFormat;
-
- anImageFormat.image_channel_order = CL_RGBA;
- anImageFormat.image_channel_data_type = CL_FLOAT;
-
- myRaytraceEnvironment = clCreateImage2D (myComputeContext,
- CL_MEM_READ_ONLY, &anImageFormat, aSizeX, aSizeY, 0, NULL, &anError);
-
- cl_float* aPixelData = new cl_float[aSizeX * aSizeY * 4];
-
- // Note: texture format is not compatible with OpenCL image
- // (it's not possible to create image directly from texture)
-
- if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
- {
- myView->TextureEnv()->Bind (GetGlContext());
-
- glGetTexImage (GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- GL_FLOAT,
- aPixelData);
-
- myView->TextureEnv()->Unbind (GetGlContext());
- }
- else
- {
- for (Standard_Integer aPixel = 0; aPixel < aSizeX * aSizeY * 4; ++aPixel)
- aPixelData[aPixel] = 0.f;
- }
-
- size_t anImageOffset[] = { 0,
- 0,
- 0 };
-
- size_t anImageRegion[] = { aSizeX,
- aSizeY,
- 1 };
-
- anError |= clEnqueueWriteImage (myComputeQueue, myRaytraceEnvironment,
- CL_TRUE, anImageOffset, anImageRegion, 0, 0, aPixelData, 0, NULL, NULL);
-
-#ifdef RAY_TRACE_PRINT_INFO
- if (anError != CL_SUCCESS)
- std::cout << "Error! Failed to write environment map image!" << std::endl;
-#endif
-
- delete[] aPixelData;
-
- myViewModificationStatus = myView->ModificationState();
-
- return (anError == CL_SUCCESS);
-}
-
// =======================================================================
// function : UpdateRaytraceGeometry
// purpose : Updates 3D scene geometry for ray tracing
// =======================================================================
-Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (Standard_Boolean theCheck)
+Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMode)
{
if (myView.IsNull())
return Standard_False;
- // Note: In 'check' mode the scene geometry is analyzed for modifications
+ // Note: In 'check' mode (OpenGl_GUM_CHECK) the scene geometry is analyzed for modifications
// This is light-weight procedure performed for each frame
- if (!theCheck)
+ if (theMode == OpenGl_GUM_CHECK)
+ {
+ if (myLayersModificationStatus != myView->LayerList().ModificationState())
+ {
+ return UpdateRaytraceGeometry (OpenGl_GUM_PREPARE);
+ }
+ }
+ else if (theMode == OpenGl_GUM_PREPARE)
{
- myRaytraceGeometry.Clear();
+ myRaytraceGeometry.ClearMaterials();
+ myArrayToTrianglesMap.clear();
myIsRaytraceDataValid = Standard_False;
}
- else
- {
- if (myLayersModificationStatus != myView->LayerList().ModificationState())
- {
- return UpdateRaytraceGeometry (Standard_False);
- }
- }
-
- Standard_ShortReal* aTransform (NULL);
// The set of processed structures (reflected to ray-tracing)
// This set is used to remove out-of-date records from the
// hash map of structures
std::set<const OpenGl_Structure*> anElements;
+ // Set of all currently visible and "raytracable" primitive arrays.
+ std::set<const OpenGl_PrimitiveArray*> anArrays;
+
const OpenGl_LayerList& aList = myView->LayerList();
for (OpenGl_SequenceOfLayers::Iterator anLayerIt (aList.Layers()); anLayerIt.More(); anLayerIt.Next())
{
- const OpenGl_PriorityList& aPriorityList = anLayerIt.Value();
+ const OpenGl_PriorityList& aPriorityList = anLayerIt.Value().PriorityList();
if (aPriorityList.NbStructures() == 0)
continue;
for (aStructIt.Init (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next())
{
+ Standard_ShortReal* aTransform (NULL);
+
const OpenGl_Structure* aStructure = aStructIt.Value();
- if (theCheck)
+ if (theMode == OpenGl_GUM_CHECK)
{
if (CheckRaytraceStructure (aStructure))
{
- return UpdateRaytraceGeometry (Standard_False);
+ return UpdateRaytraceGeometry (OpenGl_GUM_PREPARE);
}
- }
- else
+ }
+ else if (theMode == OpenGl_GUM_PREPARE)
+ {
+ if (!aStructure->IsRaytracable()
+ || !aStructure->IsVisible())
+ continue;
+
+ for (OpenGl_Structure::GroupIterator aGroupIter (aStructure->DrawGroups()); aGroupIter.More(); aGroupIter.Next())
+ {
+ // OpenGL elements from group (extract primitives arrays)
+ for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
+ {
+ OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
+
+ if (aPrimArray != NULL)
+ {
+ // Collect all primitive arrays in scene.
+ anArrays.insert (aPrimArray);
+ }
+ }
+ }
+ }
+ else if (theMode == OpenGl_GUM_UPDATE)
{
if (!aStructure->IsRaytracable())
continue;
AddRaytraceStructure (aStructure, aTransform, anElements);
}
+
+ delete [] aTransform;
+ }
+ }
+ }
+
+ if (theMode == OpenGl_GUM_PREPARE)
+ {
+ BVH_ObjectSet<Standard_ShortReal, 4>::BVH_ObjectList anUnchangedObjects;
+
+ // Leave only unchanged objects in myRaytraceGeometry so only their transforms and materials will be updated
+ // Objects which not in myArrayToTrianglesMap will be built from scratch.
+ for (Standard_Integer anObjectIdx = 0; anObjectIdx < myRaytraceGeometry.Objects().Size(); ++anObjectIdx)
+ {
+ OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
+ myRaytraceGeometry.Objects().ChangeValue (anObjectIdx).operator->());
+
+ // If primitive array of object not in "anArrays" set then it was hided or deleted.
+ // If primitive array present in "anArrays" set but we don't have associated object yet, then
+ // the object is new and still has to be built.
+ if ((aTriangleSet != NULL) && ((anArrays.find (aTriangleSet->AssociatedPArray())) != anArrays.end()))
+ {
+ anUnchangedObjects.Append (myRaytraceGeometry.Objects().Value (anObjectIdx));
+
+ myArrayToTrianglesMap[aTriangleSet->AssociatedPArray()] = aTriangleSet;
}
}
+
+ myRaytraceGeometry.Objects() = anUnchangedObjects;
+
+ return UpdateRaytraceGeometry (OpenGl_GUM_UPDATE);
}
- if (!theCheck)
+ if (theMode == OpenGl_GUM_UPDATE)
{
// Actualize the hash map of structures -- remove out-of-date records
std::map<const OpenGl_Structure*, Standard_Size>::iterator anIter = myStructureStates.begin();
myRaytraceSceneRadius = 2.f /* scale factor */ * Max (aMinRadius, aMaxRadius);
- myRaytraceSceneEpsilon = Max (1e-4f,
- myRaytraceGeometry.Box().Size().Length() * 1e-4f);
+ const BVH_Vec4f aSize = myRaytraceGeometry.Box().Size();
- return WriteRaytraceSceneToDevice();
- }
+ myRaytraceSceneEpsilon = Max (1e-7f, 1e-4f * sqrtf (
+ aSize.x() * aSize.x() + aSize.y() * aSize.y() + aSize.z() * aSize.z()));
- delete [] aTransform;
+ return UploadRaytraceData();
+ }
return Standard_True;
}
// to produce realistic-looking transparency effect
theMaterial.Transparency = BVH_Vec4f (powf (theProp.trans, 0.75f),
1.f - theProp.trans,
- 1.f,
- 1.f);
+ theProp.index == 0 ? 1.f : theProp.index,
+ theProp.index == 0 ? 1.f : 1.f / theProp.index);
const float aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
const float aReflectionScale = 0.75f / aMaxRefl;
- theMaterial.Reflection = BVH_Vec4f (theProp.speccol.rgb[0] * theProp.spec,
- theProp.speccol.rgb[1] * theProp.spec,
- theProp.speccol.rgb[2] * theProp.spec,
- 0.f) * aReflectionScale;
+ theMaterial.Reflection = BVH_Vec4f (theProp.speccol.rgb[0] * theProp.spec * aReflectionScale,
+ theProp.speccol.rgb[1] * theProp.spec * aReflectionScale,
+ theProp.speccol.rgb[2] * theProp.spec * aReflectionScale,
+ 0.f);
}
// =======================================================================
myRaytraceGeometry.Materials.push_back (aStructMaterial);
}
- for (OpenGl_ListOfGroup::Iterator anItg (theStructure->Groups()); anItg.More(); anItg.Next())
+ for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->DrawGroups()); aGroupIter.More(); aGroupIter.Next())
{
// Get group material
Standard_Integer aGroupMatID = -1;
-
- if (anItg.Value()->AspectFace() != NULL)
+ if (aGroupIter.Value()->AspectFace() != NULL)
{
aGroupMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
OpenGl_RaytraceMaterial aGroupMaterial;
- CreateMaterial (anItg.Value()->AspectFace()->IntFront(), aGroupMaterial);
+ CreateMaterial (aGroupIter.Value()->AspectFace()->IntFront(), aGroupMaterial);
myRaytraceGeometry.Materials.push_back (aGroupMaterial);
}
}
// Add OpenGL elements from group (extract primitives arrays and aspects)
- for (const OpenGl_ElementNode* aNode = anItg.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
+ for (const OpenGl_ElementNode* aNode = aGroupIter.Value()->FirstNode(); aNode != NULL; aNode = aNode->next)
{
OpenGl_AspectFace* anAspect = dynamic_cast<OpenGl_AspectFace*> (aNode->elem);
if (anAspect != NULL)
else
{
OpenGl_PrimitiveArray* aPrimArray = dynamic_cast<OpenGl_PrimitiveArray*> (aNode->elem);
+
+ std::map<const OpenGl_PrimitiveArray*, OpenGl_TriangleSet*>::iterator aSetIter = myArrayToTrianglesMap.find (aPrimArray);
+
if (aPrimArray != NULL)
{
- NCollection_Handle<BVH_Object<Standard_ShortReal, 4> > aSet =
- AddRaytracePrimitiveArray (aPrimArray->PArray(), aMatID, theTransform);
+ if (aSetIter != myArrayToTrianglesMap.end())
+ {
+ OpenGl_TriangleSet* aSet = aSetIter->second;
+
+ BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>();
+
+ if (theTransform != NULL)
+ {
+ aTransform->SetTransform (*(reinterpret_cast<const BVH_Mat4f*> (theTransform)));
+ }
+
+ aSet->SetProperties (aTransform);
+
+ if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID )
+ {
+ aSet->SetMaterialIndex (aMatID);
+ }
+ }
+ else
+ {
+ NCollection_Handle<BVH_Object<Standard_ShortReal, 4> > aSet =
+ AddRaytracePrimitiveArray (aPrimArray, aMatID, 0);
+
+ if (!aSet.IsNull())
+ {
+ BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>;
+
+ if (theTransform != NULL)
+ {
+ aTransform->SetTransform (*(reinterpret_cast<const BVH_Mat4f*> (theTransform)));
+ }
- if (!aSet.IsNull())
- myRaytraceGeometry.Objects().Append (aSet);
+ aSet->SetProperties (aTransform);
+
+ myRaytraceGeometry.Objects().Append (aSet);
+ }
+ }
}
}
}
}
- Standard_ShortReal* aTransform (NULL);
+ Standard_ShortReal* aTransform = NULL;
// Process all connected OpenGL structures
for (OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures()); anIts.More(); anIts.Next())
{
if (anIts.Value()->Transformation()->mat != NULL)
{
- Standard_ShortReal* aTransform = new Standard_ShortReal[16];
+ if (aTransform == NULL)
+ aTransform = new Standard_ShortReal[16];
for (Standard_Integer i = 0; i < 4; ++i)
for (Standard_Integer j = 0; j < 4; ++j)
// function : AddRaytracePrimitiveArray
// purpose : Adds OpenGL primitive array to ray-traced scene geometry
// =======================================================================
-OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (
- const CALL_DEF_PARRAY* theArray, Standard_Integer theMatID, const Standard_ShortReal* theTransform)
+OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_PrimitiveArray* theArray,
+ Standard_Integer theMatID,
+ const Standard_ShortReal* theTransform)
{
- if (theArray->type != TelPolygonsArrayType &&
- theArray->type != TelTrianglesArrayType &&
- theArray->type != TelQuadranglesArrayType &&
- theArray->type != TelTriangleFansArrayType &&
- theArray->type != TelTriangleStripsArrayType &&
- theArray->type != TelQuadrangleStripsArrayType)
+ const Handle(Graphic3d_IndexBuffer)& anIndices = theArray->Indices();
+ const Handle(Graphic3d_Buffer)& anAttribs = theArray->Attributes();
+ const Handle(Graphic3d_BoundBuffer)& aBounds = theArray->Bounds();
+ if (theArray->DrawMode() < GL_TRIANGLES
+ || theArray->DrawMode() > GL_POLYGON
+ || anAttribs.IsNull())
{
return NULL;
}
- if (theArray->vertices == NULL)
- return NULL;
-
#ifdef RAY_TRACE_PRINT_INFO
- switch (theArray->type)
- {
- case TelPolygonsArrayType:
- std::cout << "\tAdding TelPolygonsArrayType" << std::endl; break;
- case TelTrianglesArrayType:
- std::cout << "\tAdding TelTrianglesArrayType" << std::endl; break;
- case TelQuadranglesArrayType:
- std::cout << "\tAdding TelQuadranglesArrayType" << std::endl; break;
- case TelTriangleFansArrayType:
- std::cout << "\tAdding TelTriangleFansArrayType" << std::endl; break;
- case TelTriangleStripsArrayType:
- std::cout << "\tAdding TelTriangleStripsArrayType" << std::endl; break;
- case TelQuadrangleStripsArrayType:
- std::cout << "\tAdding TelQuadrangleStripsArrayType" << std::endl; break;
+ switch (theArray->DrawMode())
+ {
+ case GL_POLYGON: std::cout << "\tAdding GL_POLYGON\n"; break;
+ case GL_TRIANGLES: std::cout << "\tAdding GL_TRIANGLES\n"; break;
+ case GL_QUADS: std::cout << "\tAdding GL_QUADS\n"; break;
+ case GL_TRIANGLE_FAN: std::cout << "\tAdding GL_TRIANGLE_FAN\n"; break;
+ case GL_TRIANGLE_STRIP: std::cout << "\tAdding GL_TRIANGLE_STRIP\n"; break;
+ case GL_QUAD_STRIP: std::cout << "\tAdding GL_QUAD_STRIP\n"; break;
}
#endif
- OpenGl_TriangleSet* aSet = new OpenGl_TriangleSet;
-
+ OpenGl_TriangleSet* aSet = new OpenGl_TriangleSet (theArray);
{
- aSet->Vertices.reserve (theArray->num_vertexs);
-
- for (Standard_Integer aVert = 0; aVert < theArray->num_vertexs; ++aVert)
+ aSet->Vertices.reserve (anAttribs->NbElements);
+ aSet->Normals .reserve (anAttribs->NbElements);
+ const size_t aVertFrom = aSet->Vertices.size();
+ for (Standard_Integer anAttribIter = 0; anAttribIter < anAttribs->NbAttributes; ++anAttribIter)
{
- BVH_Vec4f aVertex (theArray->vertices[aVert].xyz[0],
- theArray->vertices[aVert].xyz[1],
- theArray->vertices[aVert].xyz[2],
- 1.f);
- if (theTransform)
- aVertex = MatVecMult (theTransform, aVertex);
-
- aSet->Vertices.push_back (aVertex);
+ const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIter);
+ const size_t anOffset = anAttribs->AttributeOffset (anAttribIter);
+ if (anAttrib.Id == Graphic3d_TOA_POS)
+ {
+ if (anAttrib.DataType == Graphic3d_TOD_VEC3
+ || anAttrib.DataType == Graphic3d_TOD_VEC4)
+ {
+ for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
+ {
+ const Graphic3d_Vec3& aVert = *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset);
+ aSet->Vertices.push_back (BVH_Vec4f (aVert.x(), aVert.y(), aVert.z(), 1.0f));
+ }
+ }
+ else if (anAttrib.DataType == Graphic3d_TOD_VEC2)
+ {
+ for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
+ {
+ const Graphic3d_Vec2& aVert = *reinterpret_cast<const Graphic3d_Vec2* >(anAttribs->value (aVertIter) + anOffset);
+ aSet->Vertices.push_back (BVH_Vec4f (aVert.x(), aVert.y(), 0.0f, 1.0f));
+ }
+ }
+ }
+ else if (anAttrib.Id == Graphic3d_TOA_NORM)
+ {
+ if (anAttrib.DataType == Graphic3d_TOD_VEC3
+ || anAttrib.DataType == Graphic3d_TOD_VEC4)
+ {
+ for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
+ {
+ const Graphic3d_Vec3& aNorm = *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset);
+ aSet->Normals.push_back (BVH_Vec4f (aNorm.x(), aNorm.y(), aNorm.z(), 0.0f));
+ }
+ }
+ }
}
- aSet->Normals.reserve (theArray->num_vertexs);
-
- for (Standard_Integer aNorm = 0; aNorm < theArray->num_vertexs; ++aNorm)
+ if (aSet->Normals.size() != aSet->Vertices.size())
{
- BVH_Vec4f aNormal;
-
- // Note: In case of absence of normals, the
- // renderer uses generated geometric normals
-
- if (theArray->vnormals != NULL)
+ for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
{
- aNormal = BVH_Vec4f (theArray->vnormals[aNorm].xyz[0],
- theArray->vnormals[aNorm].xyz[1],
- theArray->vnormals[aNorm].xyz[2],
- 0.f);
-
- if (theTransform)
- aNormal = MatVecMult (theTransform, aNormal);
+ aSet->Normals.push_back (BVH_Vec4f());
}
+ }
- aSet->Normals.push_back (aNormal);
+ if (theTransform)
+ {
+ for (size_t aVertIter = aVertFrom; aVertIter < aSet->Vertices.size(); ++aVertIter)
+ {
+ BVH_Vec4f& aVertex = aSet->Vertices[aVertIter];
+ aVertex = MatVecMult (theTransform, aVertex);
+ }
+ for (size_t aVertIter = aVertFrom; aVertIter < aSet->Normals.size(); ++aVertIter)
+ {
+ BVH_Vec4f& aNorm = aSet->Normals[aVertIter];
+ aNorm = MatVecMult (theTransform, aNorm);
+ }
}
- if (theArray->num_bounds > 0)
+ if (!aBounds.IsNull())
{
#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "\tNumber of bounds = " << theArray->num_bounds << std::endl;
+ std::cout << "\tNumber of bounds = " << aBounds->NbBounds << std::endl;
#endif
Standard_Integer aBoundStart = 0;
-
- for (Standard_Integer aBound = 0; aBound < theArray->num_bounds; ++aBound)
+ for (Standard_Integer aBound = 0; aBound < aBounds->NbBounds; ++aBound)
{
- const Standard_Integer aVertNum = theArray->bounds[aBound];
+ const Standard_Integer aVertNum = aBounds->Bounds[aBound];
#ifdef RAY_TRACE_PRINT_INFO
std::cout << "\tAdding indices from bound " << aBound << ": " <<
aBoundStart << " .. " << aVertNum << std::endl;
#endif
- if (!AddRaytraceVertexIndices (aSet, theArray, aBoundStart, aVertNum, theMatID))
+ if (!AddRaytraceVertexIndices (*aSet, *theArray, aBoundStart, aVertNum, theMatID))
{
delete aSet;
return NULL;
}
else
{
- const Standard_Integer aVertNum = theArray->num_edges > 0 ? theArray->num_edges : theArray->num_vertexs;
+ const Standard_Integer aVertNum = !anIndices.IsNull() ? anIndices->NbElements : anAttribs->NbElements;
#ifdef RAY_TRACE_PRINT_INFO
std::cout << "\tAdding indices from array: " << aVertNum << std::endl;
#endif
- if (!AddRaytraceVertexIndices (aSet, theArray, 0, aVertNum, theMatID))
+ if (!AddRaytraceVertexIndices (*aSet, *theArray, 0, aVertNum, theMatID))
{
delete aSet;
return NULL;
// function : AddRaytraceVertexIndices
// purpose : Adds vertex indices to ray-traced scene geometry
// =======================================================================
-Standard_Boolean OpenGl_Workspace::AddRaytraceVertexIndices (OpenGl_TriangleSet* theSet,
- const CALL_DEF_PARRAY* theArray, Standard_Integer theOffset, Standard_Integer theCount, Standard_Integer theMatID)
+Standard_Boolean OpenGl_Workspace::AddRaytraceVertexIndices (OpenGl_TriangleSet& theSet,
+ const OpenGl_PrimitiveArray& theArray,
+ Standard_Integer theOffset,
+ Standard_Integer theCount,
+ Standard_Integer theMatID)
{
- switch (theArray->type)
+ switch (theArray.DrawMode())
{
- case TelTrianglesArrayType:
- return AddRaytraceTriangleArray (theSet, theArray, theOffset, theCount, theMatID);
-
- case TelQuadranglesArrayType:
- return AddRaytraceQuadrangleArray (theSet, theArray, theOffset, theCount, theMatID);
-
- case TelTriangleFansArrayType:
- return AddRaytraceTriangleFanArray (theSet, theArray, theOffset, theCount, theMatID);
-
- case TelTriangleStripsArrayType:
- return AddRaytraceTriangleStripArray (theSet, theArray, theOffset, theCount, theMatID);
-
- case TelQuadrangleStripsArrayType:
- return AddRaytraceQuadrangleStripArray (theSet, theArray, theOffset, theCount, theMatID);
-
- default:
- return AddRaytracePolygonArray (theSet, theArray, theOffset, theCount, theMatID);
+ case GL_TRIANGLES: return AddRaytraceTriangleArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
+ case GL_QUADS: return AddRaytraceQuadrangleArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
+ case GL_TRIANGLE_FAN: return AddRaytraceTriangleFanArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
+ case GL_TRIANGLE_STRIP: return AddRaytraceTriangleStripArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
+ case GL_QUAD_STRIP: return AddRaytraceQuadrangleStripArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
+ case GL_POLYGON: return AddRaytracePolygonArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
}
+ return Standard_False;
}
// =======================================================================
// function : AddRaytraceTriangleArray
// purpose : Adds OpenGL triangle array to ray-traced scene geometry
// =======================================================================
-Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleArray (OpenGl_TriangleSet* theSet,
- const CALL_DEF_PARRAY* theArray, Standard_Integer theOffset, Standard_Integer theCount, Standard_Integer theMatID)
+Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleArray (OpenGl_TriangleSet& theSet,
+ const Handle(Graphic3d_IndexBuffer)& theIndices,
+ Standard_Integer theOffset,
+ Standard_Integer theCount,
+ Standard_Integer theMatID)
{
if (theCount < 3)
return Standard_True;
- theSet->Elements.reserve (theSet->Elements.size() + theCount / 3);
+ theSet.Elements.reserve (theSet.Elements.size() + theCount / 3);
- if (theArray->num_edges > 0)
+ if (!theIndices.IsNull())
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
{
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[aVert + 0],
- theArray->edges[aVert + 1],
- theArray->edges[aVert + 2],
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
+ theIndices->Index (aVert + 1),
+ theIndices->Index (aVert + 2),
+ theMatID));
}
}
else
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; aVert += 3)
{
- theSet->Elements.push_back (BVH_Vec4i (aVert + 0,
- aVert + 1,
- aVert + 2,
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2,
+ theMatID));
}
}
// function : AddRaytraceTriangleFanArray
// purpose : Adds OpenGL triangle fan array to ray-traced scene geometry
// =======================================================================
-Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleFanArray (OpenGl_TriangleSet* theSet,
- const CALL_DEF_PARRAY* theArray, Standard_Integer theOffset, Standard_Integer theCount, Standard_Integer theMatID)
+Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleFanArray (OpenGl_TriangleSet& theSet,
+ const Handle(Graphic3d_IndexBuffer)& theIndices,
+ Standard_Integer theOffset,
+ Standard_Integer theCount,
+ Standard_Integer theMatID)
{
if (theCount < 3)
return Standard_True;
- theSet->Elements.reserve (theSet->Elements.size() + theCount - 2);
+ theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
- if (theArray->num_edges > 0)
+ if (!theIndices.IsNull())
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
{
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[theOffset],
- theArray->edges[aVert + 1],
- theArray->edges[aVert + 2],
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
+ theIndices->Index (aVert + 1),
+ theIndices->Index (aVert + 2),
+ theMatID));
}
}
else
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
{
- theSet->Elements.push_back (BVH_Vec4i (theOffset,
- aVert + 1,
- aVert + 2,
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theOffset,
+ aVert + 1,
+ aVert + 2,
+ theMatID));
}
}
// function : AddRaytraceTriangleStripArray
// purpose : Adds OpenGL triangle strip array to ray-traced scene geometry
// =======================================================================
-Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleStripArray (OpenGl_TriangleSet* theSet,
- const CALL_DEF_PARRAY* theArray, Standard_Integer theOffset, Standard_Integer theCount, Standard_Integer theMatID)
+Standard_Boolean OpenGl_Workspace::AddRaytraceTriangleStripArray (OpenGl_TriangleSet& theSet,
+ const Handle(Graphic3d_IndexBuffer)& theIndices,
+ Standard_Integer theOffset,
+ Standard_Integer theCount,
+ Standard_Integer theMatID)
{
if (theCount < 3)
return Standard_True;
- theSet->Elements.reserve (theSet->Elements.size() + theCount - 2);
+ theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
- if (theArray->num_edges > 0)
+ if (!theIndices.IsNull())
{
for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
{
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[aVert + aCW ? 1 : 0],
- theArray->edges[aVert + aCW ? 0 : 1],
- theArray->edges[aVert + 2],
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + aCW ? 1 : 0),
+ theIndices->Index (aVert + aCW ? 0 : 1),
+ theIndices->Index (aVert + 2),
+ theMatID));
}
}
else
{
for (Standard_Integer aVert = theOffset, aCW = 0; aVert < theOffset + theCount - 2; ++aVert, aCW = (aCW + 1) % 2)
{
- theSet->Elements.push_back (BVH_Vec4i (aVert + aCW ? 1 : 0,
- aVert + aCW ? 0 : 1,
- aVert + 2,
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (aVert + aCW ? 1 : 0,
+ aVert + aCW ? 0 : 1,
+ aVert + 2,
+ theMatID));
}
}
// function : AddRaytraceQuadrangleArray
// purpose : Adds OpenGL quad array to ray-traced scene geometry
// =======================================================================
-Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleArray (OpenGl_TriangleSet* theSet,
- const CALL_DEF_PARRAY* theArray, Standard_Integer theOffset, Standard_Integer theCount, Standard_Integer theMatID)
+Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleArray (OpenGl_TriangleSet& theSet,
+ const Handle(Graphic3d_IndexBuffer)& theIndices,
+ Standard_Integer theOffset,
+ Standard_Integer theCount,
+ Standard_Integer theMatID)
{
if (theCount < 4)
return Standard_True;
- theSet->Elements.reserve (theSet->Elements.size() + theCount / 2);
+ theSet.Elements.reserve (theSet.Elements.size() + theCount / 2);
- if (theArray->num_edges > 0)
+ if (!theIndices.IsNull())
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
{
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[aVert + 0],
- theArray->edges[aVert + 1],
- theArray->edges[aVert + 2],
- theMatID));
-
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[aVert + 0],
- theArray->edges[aVert + 2],
- theArray->edges[aVert + 3],
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
+ theIndices->Index (aVert + 1),
+ theIndices->Index (aVert + 2),
+ theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
+ theIndices->Index (aVert + 2),
+ theIndices->Index (aVert + 3),
+ theMatID));
}
}
else
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 4)
{
- theSet->Elements.push_back (BVH_Vec4i (aVert + 0,
- aVert + 1,
- aVert + 2,
- theMatID));
-
- theSet->Elements.push_back (BVH_Vec4i (aVert + 0,
- aVert + 2,
- aVert + 3,
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 1, aVert + 2,
+ theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (aVert + 0, aVert + 2, aVert + 3,
+ theMatID));
}
}
// function : AddRaytraceQuadrangleStripArray
// purpose : Adds OpenGL quad strip array to ray-traced scene geometry
// =======================================================================
-Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleStripArray (OpenGl_TriangleSet* theSet,
- const CALL_DEF_PARRAY* theArray, Standard_Integer theOffset, Standard_Integer theCount, Standard_Integer theMatID)
+Standard_Boolean OpenGl_Workspace::AddRaytraceQuadrangleStripArray (OpenGl_TriangleSet& theSet,
+ const Handle(Graphic3d_IndexBuffer)& theIndices,
+ Standard_Integer theOffset,
+ Standard_Integer theCount,
+ Standard_Integer theMatID)
{
if (theCount < 4)
return Standard_True;
- theSet->Elements.reserve (theSet->Elements.size() + 2 * theCount - 6);
+ theSet.Elements.reserve (theSet.Elements.size() + 2 * theCount - 6);
- if (theArray->num_edges > 0)
+ if (!theIndices.IsNull())
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
{
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[aVert + 0],
- theArray->edges[aVert + 1],
- theArray->edges[aVert + 2],
- theMatID));
-
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[aVert + 1],
- theArray->edges[aVert + 3],
- theArray->edges[aVert + 2],
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 0),
+ theIndices->Index (aVert + 1),
+ theIndices->Index (aVert + 2),
+ theMatID));
+
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (aVert + 1),
+ theIndices->Index (aVert + 3),
+ theIndices->Index (aVert + 2),
+ theMatID));
}
}
else
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 3; aVert += 2)
{
- theSet->Elements.push_back (BVH_Vec4i (aVert + 0,
- aVert + 1,
- aVert + 2,
- theMatID));
-
- theSet->Elements.push_back (BVH_Vec4i (aVert + 1,
- aVert + 3,
- aVert + 2,
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (aVert + 0,
+ aVert + 1,
+ aVert + 2,
+ theMatID));
+
+ theSet.Elements.push_back (BVH_Vec4i (aVert + 1,
+ aVert + 3,
+ aVert + 2,
+ theMatID));
}
}
// function : AddRaytracePolygonArray
// purpose : Adds OpenGL polygon array to ray-traced scene geometry
// =======================================================================
-Standard_Boolean OpenGl_Workspace::AddRaytracePolygonArray (OpenGl_TriangleSet* theSet,
- const CALL_DEF_PARRAY* theArray, Standard_Integer theOffset, Standard_Integer theCount, Standard_Integer theMatID)
+Standard_Boolean OpenGl_Workspace::AddRaytracePolygonArray (OpenGl_TriangleSet& theSet,
+ const Handle(Graphic3d_IndexBuffer)& theIndices,
+ Standard_Integer theOffset,
+ Standard_Integer theCount,
+ Standard_Integer theMatID)
{
if (theCount < 3)
return Standard_True;
- theSet->Elements.reserve (theSet->Elements.size() + theCount - 2);
+ theSet.Elements.reserve (theSet.Elements.size() + theCount - 2);
- if (theArray->num_edges > 0)
+ if (!theIndices.IsNull())
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
{
- theSet->Elements.push_back (BVH_Vec4i (theArray->edges[theOffset],
- theArray->edges[aVert + 1],
- theArray->edges[aVert + 2],
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theIndices->Index (theOffset),
+ theIndices->Index (aVert + 1),
+ theIndices->Index (aVert + 2),
+ theMatID));
}
}
else
{
for (Standard_Integer aVert = theOffset; aVert < theOffset + theCount - 2; ++aVert)
{
- theSet->Elements.push_back (BVH_Vec4i (theOffset,
- aVert + 1,
- aVert + 2,
- theMatID));
+ theSet.Elements.push_back (BVH_Vec4i (theOffset,
+ aVert + 1,
+ aVert + 2,
+ theMatID));
}
}
{
myRaytraceGeometry.Sources.clear();
- myRaytraceGeometry.GlobalAmbient = BVH_Vec4f (0.0f, 0.0f, 0.0f, 0.0f);
+ myRaytraceGeometry.Ambient = BVH_Vec4f (0.0f, 0.0f, 0.0f, 0.0f);
for (OpenGl_ListOfLight::Iterator anItl (myView->LightList()); anItl.More(); anItl.Next())
{
if (aLight.Type == Visual3d_TOLS_AMBIENT)
{
- myRaytraceGeometry.GlobalAmbient += BVH_Vec4f (aLight.Color.r(),
- aLight.Color.g(),
- aLight.Color.b(),
- 0.0f);
+ myRaytraceGeometry.Ambient += BVH_Vec4f (aLight.Color.r(),
+ aLight.Color.g(),
+ aLight.Color.b(),
+ 0.0f);
continue;
}
if (aLight.IsHeadlight)
aPosition = MatVecMult (theInvModelView, aPosition);
+
myRaytraceGeometry.Sources.push_back (OpenGl_RaytraceLight (aDiffuse, aPosition));
}
- cl_int anError = CL_SUCCESS;
-
- if (myRaytraceLightSourceBuffer != NULL)
- clReleaseMemObject (myRaytraceLightSourceBuffer);
-
- Standard_Integer aLightBufferSize = myRaytraceGeometry.Sources.size() != 0 ?
- static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size()) : 1;
-
- myRaytraceLightSourceBuffer = clCreateBuffer (myComputeContext, CL_MEM_READ_ONLY,
- aLightBufferSize * sizeof(OpenGl_RaytraceLight), NULL, &anError);
-
- if (myRaytraceGeometry.Sources.size() != 0)
+ if (myRaytraceLightSrcTexture.IsNull()) // create light source buffer
{
- const void* aDataPtr = myRaytraceGeometry.Sources.front().Packed();
-
- anError |= clEnqueueWriteBuffer (myComputeQueue, myRaytraceLightSourceBuffer, CL_TRUE, 0,
- aLightBufferSize * sizeof(OpenGl_RaytraceLight), aDataPtr, 0, NULL, NULL);
- }
+ myRaytraceLightSrcTexture = new OpenGl_TextureBufferArb;
+ if (!myRaytraceLightSrcTexture->Create (myGlContext))
+ {
#ifdef RAY_TRACE_PRINT_INFO
- if (anError != CL_SUCCESS)
- {
- std::cout << "Error! Failed to set light sources";
-
- return Standard_False;
- }
+ std::cout << "Error: Failed to create light source buffer" << std::endl;
#endif
-
- return Standard_True;
-}
-
-// =======================================================================
-// function : CheckOpenCL
-// purpose : Checks OpenCL dynamic library availability
-// =======================================================================
-Standard_Boolean CheckOpenCL()
-{
-#if defined ( _WIN32 )
-
- __try
- {
- cl_uint aNbPlatforms;
- clGetPlatformIDs (0, NULL, &aNbPlatforms);
+ return Standard_False;
+ }
}
- __except (EXCEPTION_EXECUTE_HANDLER)
+
+ if (myRaytraceGeometry.Sources.size() != 0)
{
- return Standard_False;
- }
-
+ const GLfloat* aDataPtr = myRaytraceGeometry.Sources.front().Packed();
+ if (!myRaytraceLightSrcTexture->Init (myGlContext, 4, GLsizei (myRaytraceGeometry.Sources.size() * 2), aDataPtr))
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to upload light source buffer" << std::endl;
#endif
+ return Standard_False;
+ }
+ }
return Standard_True;
}
// =======================================================================
-// function : InitOpenCL
-// purpose : Initializes OpenCL objects
+// function : UpdateRaytraceEnvironmentMap
+// purpose : Updates environment map for ray-tracing
// =======================================================================
-Standard_Boolean OpenGl_Workspace::InitOpenCL()
+Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
{
- if (myComputeInitStatus != OpenGl_CLIS_NONE)
- {
- return myComputeInitStatus == OpenGl_CLIS_INIT;
- }
-
- if (!CheckOpenCL())
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL; // fail to load OpenCL library
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "Failed to load OpenCL dynamic library!");
+ if (myView.IsNull())
return Standard_False;
- }
- // Obtain the list of platforms available
- cl_uint aNbPlatforms = 0;
- cl_int anError = clGetPlatformIDs (0, NULL, &aNbPlatforms);
- cl_platform_id* aPlatforms = (cl_platform_id* )alloca (aNbPlatforms * sizeof(cl_platform_id));
- anError |= clGetPlatformIDs (aNbPlatforms, aPlatforms, NULL);
- if (anError != CL_SUCCESS
- || aNbPlatforms == 0)
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "No any OpenCL platform installed!");
- return Standard_False;
- }
+ if (myViewModificationStatus == myView->ModificationState())
+ return Standard_True;
- // Note: We try to find NVIDIA or AMD platforms with GPU devices!
- cl_platform_id aPrefPlatform = NULL;
- for (cl_uint aPlatIter = 0; aPlatIter < aNbPlatforms; ++aPlatIter)
+ for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx)
{
- char aName[256];
- anError = clGetPlatformInfo (aPlatforms[aPlatIter], CL_PLATFORM_NAME,
- sizeof(aName), aName, NULL);
- if (anError != CL_SUCCESS)
- {
- continue;
- }
-
- if (strncmp (aName, "NVIDIA", strlen ("NVIDIA")) == 0)
- {
- aPrefPlatform = aPlatforms[aPlatIter];
+ const Handle(OpenGl_ShaderProgram)& aProgram =
+ anIdx == 0 ? myRaytraceProgram : myPostFSAAProgram;
- // Use optimizations for NVIDIA GPUs
- myIsAmdComputePlatform = Standard_False;
- }
- else if (strncmp (aName, "AMD", strlen ("AMD")) == 0)
+ if (!aProgram.IsNull())
{
- aPrefPlatform = (aPrefPlatform == NULL)
- ? aPlatforms[aPlatIter]
- : aPrefPlatform;
+ aProgram->Bind (myGlContext);
- // Use optimizations for ATI/AMD platform
- myIsAmdComputePlatform = Standard_True;
- }
- }
-
- if (aPrefPlatform == NULL)
- {
- aPrefPlatform = aPlatforms[0];
- }
-
- // Obtain the list of devices available in the selected platform
- cl_uint aNbDevices = 0;
- anError = clGetDeviceIDs (aPrefPlatform, CL_DEVICE_TYPE_GPU,
- 0, NULL, &aNbDevices);
-
- cl_device_id* aDevices = (cl_device_id* )alloca (aNbDevices * sizeof(cl_device_id));
- anError |= clGetDeviceIDs (aPrefPlatform, CL_DEVICE_TYPE_GPU,
- aNbDevices, aDevices, NULL);
- if (anError != CL_SUCCESS)
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "Failed to get OpenCL GPU device!");
- return Standard_False;
- }
-
- // Note: Simply get first available GPU
- cl_device_id aDevice = aDevices[0];
-
- // detect old contexts
- char aVerClStr[256];
- clGetDeviceInfo (aDevice, CL_DEVICE_VERSION,
- sizeof(aVerClStr), aVerClStr, NULL);
- aVerClStr[strlen ("OpenCL 1.0")] = '\0';
- const bool isVer10 = strncmp (aVerClStr, "OpenCL 1.0", strlen ("OpenCL 1.0")) == 0;
-
- // Create OpenCL context
- cl_context_properties aCtxProp[] =
- {
- #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
- CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
- (cl_context_properties )CGLGetShareGroup (CGLGetCurrentContext()),
- #elif defined(_WIN32)
- CL_CONTEXT_PLATFORM, (cl_context_properties )aPrefPlatform,
- CL_GL_CONTEXT_KHR, (cl_context_properties )wglGetCurrentContext(),
- CL_WGL_HDC_KHR, (cl_context_properties )wglGetCurrentDC(),
- #else
- CL_GL_CONTEXT_KHR, (cl_context_properties )glXGetCurrentContext(),
- CL_GLX_DISPLAY_KHR, (cl_context_properties )glXGetCurrentDisplay(),
- CL_CONTEXT_PLATFORM, (cl_context_properties )aPrefPlatform,
- #endif
- 0
- };
-
- myComputeContext = clCreateContext (aCtxProp,
- #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
- 0, NULL, // device will be taken from GL context
- #else
- 1, &aDevice,
- #endif
- NULL, NULL, &anError);
- if (anError != CL_SUCCESS)
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "Failed to initialize OpenCL context!");
- return Standard_False;
- }
-
- // Create OpenCL program
- const char* aSources[] =
- {
- isVer10 ? "#define M_PI_F ( float )( 3.14159265359f )\n" : "",
- THE_RAY_TRACE_OPENCL_SOURCE
- };
- myRaytraceProgram = clCreateProgramWithSource (myComputeContext, 2,
- aSources, NULL, &anError);
- if (anError != CL_SUCCESS)
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "Failed to create OpenCL ray-tracing program!");
- return Standard_False;
- }
-
- anError = clBuildProgram (myRaytraceProgram, 0,
- NULL, NULL, NULL, NULL);
- {
- // Fetch build log
- size_t aLogLen = 0;
- cl_int aResult = clGetProgramBuildInfo (myRaytraceProgram, aDevice,
- CL_PROGRAM_BUILD_LOG, 0, NULL, &aLogLen);
-
- char* aBuildLog = (char* )alloca (aLogLen);
- aResult |= clGetProgramBuildInfo (myRaytraceProgram, aDevice,
- CL_PROGRAM_BUILD_LOG, aLogLen, aBuildLog, NULL);
- if (aResult == CL_SUCCESS)
- {
- if (anError != CL_SUCCESS)
+ if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
{
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- aBuildLog);
+ myView->TextureEnv()->Bind (
+ myGlContext, GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
+
+ aProgram->SetUniform (myGlContext,
+ myUniformLocations[anIdx][OpenGl_RT_uEnvironmentEnable], 1);
}
else
{
- #ifdef RAY_TRACE_PRINT_INFO
- std::cout << aBuildLog << std::endl;
- #endif
+ aProgram->SetUniform (myGlContext,
+ myUniformLocations[anIdx][OpenGl_RT_uEnvironmentEnable], 0);
}
}
}
- if (anError != CL_SUCCESS)
- {
- return Standard_False;
- }
-
- // Create OpenCL ray tracing kernels
- myRaytraceRenderKernel = clCreateKernel (myRaytraceProgram, "RaytraceRender", &anError);
- if (anError != CL_SUCCESS)
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "Failed to create OpenCL ray-tracing kernel!");
- return Standard_False;
- }
-
- myRaytraceSmoothKernel = clCreateKernel (myRaytraceProgram, "RaytraceSmooth", &anError);
- if (anError != CL_SUCCESS)
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "Failed to create OpenCL ray-tracing kernel!");
- return Standard_False;
- }
-
- // Create OpenCL command queue
- // Note: For profiling set CL_QUEUE_PROFILING_ENABLE
- cl_command_queue_properties aProps = CL_QUEUE_PROFILING_ENABLE;
-
- myComputeQueue = clCreateCommandQueue (myComputeContext, aDevice, aProps, &anError);
- if (anError != CL_SUCCESS)
- {
- myComputeInitStatus = OpenGl_CLIS_FAIL;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- "Failed to create OpenCL command queue!");
+ OpenGl_ShaderProgram::Unbind (myGlContext);
- return Standard_False;
- }
+ myViewModificationStatus = myView->ModificationState();
- myComputeInitStatus = OpenGl_CLIS_INIT; // initialized in normal way
return Standard_True;
}
// =======================================================================
-// function : GetOpenClDeviceInfo
-// purpose : Returns information about device used for computations
+// function : Source
+// purpose : Returns shader source combined with prefix
// =======================================================================
-Standard_Boolean OpenGl_Workspace::GetOpenClDeviceInfo (NCollection_DataMap<TCollection_AsciiString,
- TCollection_AsciiString>& theInfo) const
+TCollection_AsciiString OpenGl_Workspace::ShaderSource::Source() const
{
- theInfo.Clear();
- if (myComputeContext == NULL)
- {
- return Standard_False;
- }
+ static const TCollection_AsciiString aVersion = "#version 140";
- size_t aDevicesSize = 0;
- cl_int anError = clGetContextInfo (myComputeContext, CL_CONTEXT_DEVICES, 0, NULL, &aDevicesSize);
- cl_device_id* aDevices = (cl_device_id* )alloca (aDevicesSize);
- anError |= clGetContextInfo (myComputeContext, CL_CONTEXT_DEVICES, aDevicesSize, aDevices, NULL);
- if (anError != CL_SUCCESS)
+ if (myPrefix.IsEmpty())
{
- return Standard_False;
+ return aVersion + "\n" + mySource;
}
- char aDeviceName[256];
- anError |= clGetDeviceInfo (aDevices[0], CL_DEVICE_NAME, sizeof(aDeviceName), aDeviceName, NULL);
- theInfo.Bind ("Name", aDeviceName);
-
- char aDeviceVendor[256];
- anError |= clGetDeviceInfo (aDevices[0], CL_DEVICE_VENDOR, sizeof(aDeviceVendor), aDeviceVendor, NULL);
- theInfo.Bind ("Vendor", aDeviceVendor);
-
- cl_device_type aDeviceType;
- anError |= clGetDeviceInfo (aDevices[0], CL_DEVICE_TYPE, sizeof(aDeviceType), &aDeviceType, NULL);
- theInfo.Bind ("Type", aDeviceType == CL_DEVICE_TYPE_GPU ? "GPU" : "CPU");
- return Standard_True;
+ return aVersion + "\n" + myPrefix + "\n" + mySource;
}
// =======================================================================
-// function : ReleaseOpenCL
-// purpose : Releases resources of OpenCL objects
+// function : Load
+// purpose : Loads shader source from specified files
// =======================================================================
-void OpenGl_Workspace::ReleaseOpenCL()
+void OpenGl_Workspace::ShaderSource::Load (
+ const TCollection_AsciiString* theFileNames, const Standard_Integer theCount)
{
- clReleaseKernel (myRaytraceRenderKernel);
- clReleaseKernel (myRaytraceSmoothKernel);
+ mySource.Clear();
- clReleaseProgram (myRaytraceProgram);
- clReleaseCommandQueue (myComputeQueue);
-
- clReleaseMemObject (myRaytraceOutputImage);
- clReleaseMemObject (myRaytraceEnvironment);
- clReleaseMemObject (myRaytraceOutputImageAA);
+ for (Standard_Integer anIndex = 0; anIndex < theCount; ++anIndex)
+ {
+ OSD_File aFile (theFileNames[anIndex]);
- clReleaseMemObject (myRaytraceMaterialBuffer);
- clReleaseMemObject (myRaytraceLightSourceBuffer);
+ Standard_ASSERT_RETURN (aFile.Exists(),
+ "Error: Failed to find shader source file", /* none */);
- clReleaseMemObject (mySceneNodeInfoBuffer);
- clReleaseMemObject (mySceneMinPointBuffer);
- clReleaseMemObject (mySceneMaxPointBuffer);
+ aFile.Open (OSD_ReadOnly, OSD_Protection());
- clReleaseMemObject (myObjectNodeInfoBuffer);
- clReleaseMemObject (myObjectMinPointBuffer);
- clReleaseMemObject (myObjectMaxPointBuffer);
+ TCollection_AsciiString aSource;
- clReleaseMemObject (myGeometryVertexBuffer);
- clReleaseMemObject (myGeometryNormalBuffer);
- clReleaseMemObject (myGeometryTriangBuffer);
+ Standard_ASSERT_RETURN (aFile.IsOpen(),
+ "Error: Failed to open shader source file", /* none */);
- clReleaseContext (myComputeContext);
+ aFile.Read (aSource, (Standard_Integer) aFile.Size());
- if (!myGlContext.IsNull())
- {
- if (!myRaytraceOutputTexture.IsNull())
- myGlContext->DelayedRelease (myRaytraceOutputTexture);
- myRaytraceOutputTexture.Nullify();
+ if (!aSource.IsEmpty())
+ {
+ mySource += TCollection_AsciiString ("\n") + aSource;
+ }
- if (!myRaytraceOutputTextureAA.IsNull())
- myGlContext->DelayedRelease (myRaytraceOutputTextureAA);
- myRaytraceOutputTextureAA.Nullify();
+ aFile.Close();
}
}
// =======================================================================
-// function : ResizeRaytraceOutputBuffer
-// purpose : Resizes OpenCL output image
+// function : LoadShader
+// purpose : Creates new shader object with specified source
// =======================================================================
-Standard_Boolean OpenGl_Workspace::ResizeRaytraceOutputBuffer (const cl_int theSizeX,
- const cl_int theSizeY)
+Handle(OpenGl_ShaderObject) OpenGl_Workspace::LoadShader (const ShaderSource& theSource, GLenum theType)
{
- if (myComputeContext == NULL)
- {
- return Standard_False;
- }
+ Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (theType);
- if (!myRaytraceOutputTexture.IsNull())
+ if (!aShader->Create (myGlContext))
{
- Standard_Boolean toResize = myRaytraceOutputTexture->SizeX() != theSizeX ||
- myRaytraceOutputTexture->SizeY() != theSizeY;
+ const TCollection_ExtendedString aMessage = "Error: Failed to create shader object";
+
+ myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
- if (!toResize)
- return Standard_True;
+ aShader->Release (myGlContext.operator->());
- if (!myGlContext.IsNull())
- {
- if (!myRaytraceOutputTexture.IsNull())
- myGlContext->DelayedRelease (myRaytraceOutputTexture);
- if (!myRaytraceOutputTextureAA.IsNull())
- myGlContext->DelayedRelease (myRaytraceOutputTextureAA);
- }
+ return Handle(OpenGl_ShaderObject)();
}
- myRaytraceOutputTexture = new OpenGl_Texture();
-
- myRaytraceOutputTexture->Create (myGlContext);
- myRaytraceOutputTexture->InitRectangle (myGlContext,
- theSizeX, theSizeY, OpenGl_TextureFormat::Create<GLfloat, 4>());
-
- myRaytraceOutputTextureAA = new OpenGl_Texture();
-
- myRaytraceOutputTextureAA->Create (myGlContext);
- myRaytraceOutputTextureAA->InitRectangle (myGlContext,
- theSizeX, theSizeY, OpenGl_TextureFormat::Create<GLfloat, 4>());
-
- if (myRaytraceOutputImage != NULL)
- clReleaseMemObject (myRaytraceOutputImage);
+ if (!aShader->LoadSource (myGlContext, theSource.Source()))
+ {
+ const TCollection_ExtendedString aMessage = "Error: Failed to set shader source";
+
+ myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
- if (myRaytraceOutputImageAA != NULL)
- clReleaseMemObject (myRaytraceOutputImageAA);
+ aShader->Release (myGlContext.operator->());
- cl_int anError = CL_SUCCESS;
+ return Handle(OpenGl_ShaderObject)();
+ }
- myRaytraceOutputImage = clCreateFromGLTexture2D (myComputeContext,
- CL_MEM_READ_WRITE, GL_TEXTURE_RECTANGLE, 0, myRaytraceOutputTexture->TextureId(), &anError);
+ TCollection_AsciiString aBuildLog;
- if (anError != CL_SUCCESS)
+ if (!aShader->Compile (myGlContext))
{
+ if (aShader->FetchInfoLog (myGlContext, aBuildLog))
+ {
+ const TCollection_ExtendedString aMessage =
+ TCollection_ExtendedString ("Error: Failed to compile shader object:\n") + aBuildLog;
+
#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to create output image!" << std::endl;
+ std::cout << aBuildLog << std::endl;
#endif
- return Standard_False;
- }
- myRaytraceOutputImageAA = clCreateFromGLTexture2D (myComputeContext,
- CL_MEM_READ_WRITE, GL_TEXTURE_RECTANGLE, 0, myRaytraceOutputTextureAA->TextureId(), &anError);
+ myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
+ }
+
+ aShader->Release (myGlContext.operator->());
+
+ return Handle(OpenGl_ShaderObject)();
+ }
- if (anError != CL_SUCCESS)
- {
#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to create anti-aliased output image!" << std::endl;
+ if (aShader->FetchInfoLog (myGlContext, aBuildLog))
+ {
+ if (!aBuildLog.IsEmpty())
+ {
+ std::cout << aBuildLog << std::endl;
+ }
+ else
+ {
+ std::cout << "Info: shader build log is empty" << std::endl;
+ }
+ }
#endif
- return Standard_False;
- }
- return Standard_True;
+ return aShader;
}
// =======================================================================
-// function : WriteRaytraceSceneToDevice
-// purpose : Writes scene geometry to OpenCL device
+// function : SafeFailBack
+// purpose : Performs safe exit when shaders initialization fails
// =======================================================================
-Standard_Boolean OpenGl_Workspace::WriteRaytraceSceneToDevice()
+Standard_Boolean OpenGl_Workspace::SafeFailBack (const TCollection_ExtendedString& theMessage)
{
- if (myComputeContext == NULL)
- return Standard_False;
-
- cl_int anErrorRes = CL_SUCCESS;
-
- if (mySceneNodeInfoBuffer != NULL)
- anErrorRes |= clReleaseMemObject (mySceneNodeInfoBuffer);
+ myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, theMessage);
- if (mySceneMinPointBuffer != NULL)
- anErrorRes |= clReleaseMemObject (mySceneMinPointBuffer);
+ myComputeInitStatus = OpenGl_RT_FAIL;
- if (mySceneMaxPointBuffer != NULL)
- anErrorRes |= clReleaseMemObject (mySceneMaxPointBuffer);
+ ReleaseRaytraceResources();
+
+ return Standard_False;
+}
- if (myObjectNodeInfoBuffer != NULL)
- anErrorRes |= clReleaseMemObject (myObjectNodeInfoBuffer);
+// =======================================================================
+// function : InitRaytraceResources
+// purpose : Initializes OpenGL/GLSL shader programs
+// =======================================================================
+Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& theCView)
+{
+ Standard_Boolean aToRebuildShaders = Standard_False;
- if (myObjectMinPointBuffer != NULL)
- anErrorRes |= clReleaseMemObject (myObjectMinPointBuffer);
+ if (myComputeInitStatus == OpenGl_RT_INIT)
+ {
+ if (!myIsRaytraceDataValid)
+ return Standard_True;
- if (myObjectMaxPointBuffer != NULL)
- anErrorRes |= clReleaseMemObject (myObjectMaxPointBuffer);
+ const Standard_Integer aRequiredStackSize =
+ myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth();
- if (myGeometryVertexBuffer != NULL)
- anErrorRes |= clReleaseMemObject (myGeometryVertexBuffer);
+ if (myRaytraceParameters.StackSize < aRequiredStackSize)
+ {
+ myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
- if (myGeometryNormalBuffer != NULL)
- anErrorRes |= clReleaseMemObject (myGeometryNormalBuffer);
+ aToRebuildShaders = Standard_True;
+ }
+ else
+ {
+ if (aRequiredStackSize < myRaytraceParameters.StackSize)
+ {
+ if (myRaytraceParameters.StackSize > THE_DEFAULT_STACK_SIZE)
+ {
+ myRaytraceParameters.StackSize = Max (aRequiredStackSize, THE_DEFAULT_STACK_SIZE);
+ aToRebuildShaders = Standard_True;
+ }
+ }
+ }
- if (myGeometryTriangBuffer != NULL)
- anErrorRes |= clReleaseMemObject (myGeometryTriangBuffer);
+ if (theCView.RenderParams.RaytracingDepth != myRaytraceParameters.TraceDepth)
+ {
+ myRaytraceParameters.TraceDepth = theCView.RenderParams.RaytracingDepth;
+ aToRebuildShaders = Standard_True;
+ }
- if (myRaytraceMaterialBuffer != NULL)
- anErrorRes |= clReleaseMemObject (myRaytraceMaterialBuffer);
+ if (theCView.RenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows)
+ {
+ myRaytraceParameters.TransparentShadows = theCView.RenderParams.IsTransparentShadowEnabled;
+ aToRebuildShaders = Standard_True;
+ }
- if (anErrorRes != CL_SUCCESS)
- {
+ if (aToRebuildShaders)
+ {
#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to release OpenCL buffers" << std::endl;
+ std::cout << "Info: Rebuild shaders with stack size: " << myRaytraceParameters.StackSize << std::endl;
#endif
- return Standard_False;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Create material buffer
+ // Change state to force update all uniforms
+ ++myViewModificationStatus;
- const size_t aMaterialBufferSize =
- myRaytraceGeometry.Materials.size() != 0 ? myRaytraceGeometry.Materials.size() : 1;
+ TCollection_AsciiString aPrefixString =
+ TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
+ TCollection_AsciiString ("#define TRACE_DEPTH ") + TCollection_AsciiString (myRaytraceParameters.TraceDepth);
- myRaytraceMaterialBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aMaterialBufferSize * sizeof(OpenGl_RaytraceMaterial), NULL, &anErrorRes);
+ if (myRaytraceParameters.TransparentShadows)
+ {
+ aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
+ }
- if (anErrorRes != CL_SUCCESS)
- {
#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to create OpenCL material buffer" << std::endl;
+ std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
#endif
- return Standard_False;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Create BVHs buffers
- cl_int anErrorTmp = CL_SUCCESS;
+ myRaytraceShaderSource.SetPrefix (aPrefixString);
+ myPostFSAAShaderSource.SetPrefix (aPrefixString);
- const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = myRaytraceGeometry.BVH();
-
- const size_t aSceneMinPointBufferSize =
- aBVH->MinPointBuffer().size() != 0 ? aBVH->MinPointBuffer().size() : 1;
-
- mySceneMinPointBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aSceneMinPointBufferSize * sizeof(cl_float4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
-
- const size_t aSceneMaxPointBufferSize =
- aBVH->MaxPointBuffer().size() != 0 ? aBVH->MaxPointBuffer().size() : 1;
-
- mySceneMaxPointBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aSceneMaxPointBufferSize * sizeof(cl_float4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
-
- const size_t aSceneNodeInfoBufferSize =
- aBVH->NodeInfoBuffer().size() != 0 ? aBVH->NodeInfoBuffer().size() : 1;
+ if (!myRaytraceShader->LoadSource (myGlContext, myRaytraceShaderSource.Source())
+ || !myPostFSAAShader->LoadSource (myGlContext, myPostFSAAShaderSource.Source()))
+ {
+ return Standard_False;
+ }
- mySceneNodeInfoBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aSceneNodeInfoBufferSize * sizeof(cl_int4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
+ if (!myRaytraceShader->Compile (myGlContext)
+ || !myPostFSAAShader->Compile (myGlContext))
+ {
+ return Standard_False;
+ }
- if (anErrorRes != CL_SUCCESS)
- {
-#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to create OpenCL buffers for high-level scene BVH" << std::endl;
-#endif
- return Standard_False;
+ if (!myRaytraceProgram->Link (myGlContext)
+ || !myPostFSAAProgram->Link (myGlContext))
+ {
+ return Standard_False;
+ }
+ }
}
- Standard_Integer aTotalVerticesNb = 0;
- Standard_Integer aTotalElementsNb = 0;
- Standard_Integer aTotalBVHNodesNb = 0;
-
- for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
+ if (myComputeInitStatus == OpenGl_RT_NONE)
{
- OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
- myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
+ if (!myGlContext->IsGlGreaterEqual (3, 1))
+ {
+ const TCollection_ExtendedString aMessage = "Ray-tracing requires OpenGL 3.1 and higher";
- Standard_ASSERT_RETURN (aTriangleSet != NULL,
- "Error! Failed to get triangulation of OpenGL element", Standard_False);
+ myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
- aTotalVerticesNb += aTriangleSet->Vertices.size();
- aTotalElementsNb += aTriangleSet->Elements.size();
+ return Standard_False;
+ }
- Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(),
- "Error! Failed to get bottom-level BVH of OpenGL element", Standard_False);
+ myRaytraceParameters.TraceDepth = theCView.RenderParams.RaytracingDepth;
- aTotalBVHNodesNb += aTriangleSet->BVH()->NodeInfoBuffer().size();
- }
+ TCollection_AsciiString aFolder = Graphic3d_ShaderProgram::ShadersFolder();
- aTotalBVHNodesNb = aTotalBVHNodesNb > 0 ? aTotalBVHNodesNb : 1;
+ if (aFolder.IsEmpty())
+ {
+ const TCollection_ExtendedString aMessage = "Failed to locate shaders directory";
+
+ myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
+
+ return Standard_False;
+ }
- myObjectNodeInfoBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aTotalBVHNodesNb * sizeof(cl_int4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
+ if (myIsRaytraceDataValid)
+ {
+ myRaytraceParameters.StackSize = Max (THE_DEFAULT_STACK_SIZE,
+ myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth());
+ }
- myObjectMinPointBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aTotalBVHNodesNb * sizeof(cl_float4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
+ TCollection_AsciiString aPrefixString =
+ TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
+ TCollection_AsciiString ("#define TRACE_DEPTH ") + TCollection_AsciiString (myRaytraceParameters.TraceDepth);
- myObjectMaxPointBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aTotalBVHNodesNb * sizeof(cl_float4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
+ if (myRaytraceParameters.TransparentShadows)
+ {
+ aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
+ }
- if (anErrorRes != CL_SUCCESS)
- {
#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to create OpenCL buffers for bottom-level scene BVHs" << std::endl;
+ std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
#endif
- return Standard_False;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Create geometry buffers
-
- aTotalVerticesNb = aTotalVerticesNb > 0 ? aTotalVerticesNb : 1;
- myGeometryVertexBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aTotalVerticesNb * sizeof(cl_float4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
+ {
+ Handle(OpenGl_ShaderObject) aBasicVertShader = LoadShader (
+ ShaderSource (aFolder + "/RaytraceBase.vs"), GL_VERTEX_SHADER);
- myGeometryNormalBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aTotalVerticesNb * sizeof(cl_float4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
+ if (aBasicVertShader.IsNull())
+ {
+ return SafeFailBack ("Failed to set vertex shader source");
+ }
- aTotalElementsNb = aTotalElementsNb > 0 ? aTotalElementsNb : 1;
+ TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs", aFolder + "/RaytraceRender.fs" };
- myGeometryTriangBuffer = clCreateBuffer (myComputeContext,
- CL_MEM_READ_ONLY, aTotalElementsNb * sizeof(cl_int4), NULL, &anErrorTmp);
- anErrorRes |= anErrorTmp;
+ myRaytraceShaderSource.Load (aFiles, 2);
- if (anErrorRes != CL_SUCCESS)
- {
-#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to create OpenCL geometry buffers" << std::endl;
-#endif
- return Standard_False;
- }
+ myRaytraceShaderSource.SetPrefix (aPrefixString);
- /////////////////////////////////////////////////////////////////////////////
- // Write BVH and geometry buffers
+ myRaytraceShader = LoadShader (myRaytraceShaderSource, GL_FRAGMENT_SHADER);
- if (aBVH->NodeInfoBuffer().size() != 0)
- {
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, mySceneNodeInfoBuffer, CL_FALSE, 0,
- aSceneNodeInfoBufferSize * sizeof(cl_int4), &aBVH->NodeInfoBuffer().front(), 0, NULL, NULL);
+ if (myRaytraceShader.IsNull())
+ {
+ aBasicVertShader->Release (myGlContext.operator->());
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, mySceneMinPointBuffer, CL_FALSE, 0,
- aSceneMinPointBufferSize * sizeof(cl_float4), &aBVH->MinPointBuffer().front(), 0, NULL, NULL);
+ return SafeFailBack ("Failed to set ray-trace fragment shader source");
+ }
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, mySceneMaxPointBuffer, CL_FALSE, 0,
- aSceneMaxPointBufferSize * sizeof(cl_float4), &aBVH->MaxPointBuffer().front(), 0, NULL, NULL);
+ myRaytraceProgram = new OpenGl_ShaderProgram;
- anErrorRes |= clFinish (myComputeQueue);
+ if (!myRaytraceProgram->Create (myGlContext))
+ {
+ aBasicVertShader->Release (myGlContext.operator->());
- if (anErrorRes != CL_SUCCESS)
- {
-#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to write OpenCL buffers for high-level scene BVH" << std::endl;
-#endif
- return Standard_False;
- }
+ return SafeFailBack ("Failed to create ray-trace shader program");
+ }
- for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
- {
- if (!aBVH->IsOuter (aNodeIdx))
- continue;
+ if (!myRaytraceProgram->AttachShader (myGlContext, aBasicVertShader)
+ || !myRaytraceProgram->AttachShader (myGlContext, myRaytraceShader))
+ {
+ aBasicVertShader->Release (myGlContext.operator->());
- OpenGl_TriangleSet* aTriangleSet = myRaytraceGeometry.TriangleSet (aNodeIdx);
+ return SafeFailBack ("Failed to attach ray-trace shader objects");
+ }
- Standard_ASSERT_RETURN (aTriangleSet != NULL,
- "Error! Failed to get triangulation of OpenGL element", Standard_False);
+ if (!myRaytraceProgram->Link (myGlContext))
+ {
+ TCollection_AsciiString aLinkLog;
- const size_t aBVHBuffserSize =
- aTriangleSet->BVH()->NodeInfoBuffer().size() != 0 ? aTriangleSet->BVH()->NodeInfoBuffer().size() : 1;
+ if (myRaytraceProgram->FetchInfoLog (myGlContext, aLinkLog))
+ {
+ #ifdef RAY_TRACE_PRINT_INFO
+ std::cout << aLinkLog << std::endl;
+ #endif
+ }
- const Standard_Integer aBVHOffset = myRaytraceGeometry.AccelerationOffset (aNodeIdx);
+ return SafeFailBack ("Failed to link ray-trace shader program");
+ }
+ }
- Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
- "Error! Failed to get offset for bottom-level BVH", Standard_False);
+ {
+ Handle(OpenGl_ShaderObject) aBasicVertShader = LoadShader (
+ ShaderSource (aFolder + "/RaytraceBase.vs"), GL_VERTEX_SHADER);
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, myObjectNodeInfoBuffer, CL_FALSE, aBVHOffset * sizeof(cl_int4),
- aBVHBuffserSize * sizeof(cl_int4), &aTriangleSet->BVH()->NodeInfoBuffer().front(), 0, NULL, NULL);
+ if (aBasicVertShader.IsNull())
+ {
+ return SafeFailBack ("Failed to set vertex shader source");
+ }
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, myObjectMinPointBuffer, CL_FALSE, aBVHOffset * sizeof(cl_float4),
- aBVHBuffserSize * sizeof(cl_float4), &aTriangleSet->BVH()->MinPointBuffer().front(), 0, NULL, NULL);
+ TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs", aFolder + "/RaytraceSmooth.fs" };
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, myObjectMaxPointBuffer, CL_FALSE, aBVHOffset * sizeof(cl_float4),
- aBVHBuffserSize * sizeof(cl_float4), &aTriangleSet->BVH()->MaxPointBuffer().front(), 0, NULL, NULL);
+ myPostFSAAShaderSource.Load (aFiles, 2);
- anErrorRes |= clFinish (myComputeQueue);
+ myPostFSAAShaderSource.SetPrefix (aPrefixString);
+
+ myPostFSAAShader = LoadShader (myPostFSAAShaderSource, GL_FRAGMENT_SHADER);
- if (anErrorRes != CL_SUCCESS)
+ if (myPostFSAAShader.IsNull())
{
-#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to write OpenCL buffers for bottom-level scene BVHs" << std::endl;
-#endif
- return Standard_False;
- }
+ aBasicVertShader->Release (myGlContext.operator->());
- const Standard_Integer aVerticesOffset = myRaytraceGeometry.VerticesOffset (aNodeIdx);
-
- Standard_ASSERT_RETURN (aVerticesOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
- "Error! Failed to get offset for triangulation vertices of OpenGL element", Standard_False);
-
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, myGeometryVertexBuffer, CL_FALSE, aVerticesOffset * sizeof(cl_float4),
- aTriangleSet->Vertices.size() * sizeof(cl_float4), &aTriangleSet->Vertices.front(), 0, NULL, NULL);
+ return SafeFailBack ("Failed to set FSAA fragment shader source");
+ }
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, myGeometryNormalBuffer, CL_FALSE, aVerticesOffset * sizeof(cl_float4),
- aTriangleSet->Normals.size() * sizeof(cl_float4), &aTriangleSet->Normals.front(), 0, NULL, NULL);
+ myPostFSAAProgram = new OpenGl_ShaderProgram;
- const Standard_Integer anElementsOffset = myRaytraceGeometry.ElementsOffset (aNodeIdx);
+ if (!myPostFSAAProgram->Create (myGlContext))
+ {
+ aBasicVertShader->Release (myGlContext.operator->());
- Standard_ASSERT_RETURN (anElementsOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
- "Error! Failed to get offset for triangulation elements of OpenGL element", Standard_False);
+ return SafeFailBack ("Failed to create FSAA shader program");
+ }
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, myGeometryTriangBuffer, CL_FALSE, anElementsOffset * sizeof(cl_int4),
- aTriangleSet->Elements.size() * sizeof(cl_int4), &aTriangleSet->Elements.front(), 0, NULL, NULL);
+ if (!myPostFSAAProgram->AttachShader (myGlContext, aBasicVertShader)
+ || !myPostFSAAProgram->AttachShader (myGlContext, myPostFSAAShader))
+ {
+ aBasicVertShader->Release (myGlContext.operator->());
- anErrorRes |= clFinish (myComputeQueue);
+ return SafeFailBack ("Failed to attach FSAA shader objects");
+ }
- if (anErrorRes != CL_SUCCESS)
+ if (!myPostFSAAProgram->Link (myGlContext))
{
-#ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to write OpenCL triangulation buffers for OpenGL element" << std::endl;
-#endif
- return Standard_False;
+ TCollection_AsciiString aLinkLog;
+
+ if (myPostFSAAProgram->FetchInfoLog (myGlContext, aLinkLog))
+ {
+ #ifdef RAY_TRACE_PRINT_INFO
+ std::cout << aLinkLog << std::endl;
+ #endif
+ }
+
+ return SafeFailBack ("Failed to link FSAA shader program");
}
}
}
- /////////////////////////////////////////////////////////////////////////////
- // Write material buffer
-
- if (myRaytraceGeometry.Materials.size() != 0)
+ if (myComputeInitStatus == OpenGl_RT_NONE || aToRebuildShaders)
{
- const void* aDataPtr = myRaytraceGeometry.Materials.front().Packed();
-
- anErrorRes |= clEnqueueWriteBuffer (myComputeQueue, myRaytraceMaterialBuffer,
- CL_FALSE, 0, aMaterialBufferSize * sizeof(OpenGl_RaytraceMaterial), aDataPtr, 0, NULL, NULL);
-
- if (anErrorRes != CL_SUCCESS)
+ for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
{
- #ifdef RAY_TRACE_PRINT_INFO
- std::cout << "Error! Failed to write OpenCL material buffer" << std::endl;
- #endif
- return Standard_False;
+ Handle(OpenGl_ShaderProgram)& aShaderProgram =
+ (anIndex == 0) ? myRaytraceProgram : myPostFSAAProgram;
+
+ aShaderProgram->Bind (myGlContext);
+
+ aShaderProgram->SetSampler (myGlContext,
+ "uSceneMinPointTexture", OpenGl_RT_SceneMinPointTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uSceneMaxPointTexture", OpenGl_RT_SceneMaxPointTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uSceneNodeInfoTexture", OpenGl_RT_SceneNodeInfoTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uObjectMinPointTexture", OpenGl_RT_ObjectMinPointTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uObjectMaxPointTexture", OpenGl_RT_ObjectMaxPointTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uObjectNodeInfoTexture", OpenGl_RT_ObjectNodeInfoTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uGeometryVertexTexture", OpenGl_RT_GeometryVertexTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uGeometryNormalTexture", OpenGl_RT_GeometryNormalTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uSceneTransformTexture", OpenGl_RT_SceneTransformTexture);
+ aShaderProgram->SetSampler (myGlContext,
+ "uEnvironmentMapTexture", OpenGl_RT_EnvironmentMapTexture);
+
+ if (anIndex == 1)
+ {
+ aShaderProgram->SetSampler (myGlContext,
+ "uFSAAInputTexture", OpenGl_RT_FSAAInputTexture);
+ }
+
+ myUniformLocations[anIndex][OpenGl_RT_aPosition] =
+ aShaderProgram->GetAttributeLocation (myGlContext, "aPosition");
+
+ myUniformLocations[anIndex][OpenGl_RT_uOriginLB] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uOriginLB");
+ myUniformLocations[anIndex][OpenGl_RT_uOriginRB] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uOriginRB");
+ myUniformLocations[anIndex][OpenGl_RT_uOriginLT] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uOriginLT");
+ myUniformLocations[anIndex][OpenGl_RT_uOriginRT] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uOriginRT");
+ myUniformLocations[anIndex][OpenGl_RT_uDirectLB] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uDirectLB");
+ myUniformLocations[anIndex][OpenGl_RT_uDirectRB] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uDirectRB");
+ myUniformLocations[anIndex][OpenGl_RT_uDirectLT] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uDirectLT");
+ myUniformLocations[anIndex][OpenGl_RT_uDirectRT] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uDirectRT");
+
+ myUniformLocations[anIndex][OpenGl_RT_uLightCount] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uLightCount");
+ myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uGlobalAmbient");
+
+ myUniformLocations[anIndex][OpenGl_RT_uSceneRad] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uSceneRadius");
+ myUniformLocations[anIndex][OpenGl_RT_uSceneEps] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uSceneEpsilon");
+
+ myUniformLocations[anIndex][OpenGl_RT_uShadEnabled] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uShadowsEnable");
+ myUniformLocations[anIndex][OpenGl_RT_uReflEnabled] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uReflectionsEnable");
+
+ myUniformLocations[anIndex][OpenGl_RT_uOffsetX] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uOffsetX");
+ myUniformLocations[anIndex][OpenGl_RT_uOffsetY] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uOffsetY");
+ myUniformLocations[anIndex][OpenGl_RT_uSamples] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uSamples");
+
+ myUniformLocations[anIndex][OpenGl_RT_uEnvironmentEnable] =
+ aShaderProgram->GetUniformLocation (myGlContext, "uEnvironmentEnable");
}
+
+ OpenGl_ShaderProgram::Unbind (myGlContext);
}
- anErrorRes |= clFinish (myComputeQueue);
+ if (myComputeInitStatus != OpenGl_RT_NONE)
+ {
+ return myComputeInitStatus == OpenGl_RT_INIT;
+ }
- if (anErrorRes == CL_SUCCESS)
+ if (myRaytraceFBO1.IsNull())
{
- myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0;
+ myRaytraceFBO1 = new OpenGl_FrameBuffer;
}
-#ifdef RAY_TRACE_PRINT_INFO
- else
+
+ if (myRaytraceFBO2.IsNull())
{
- std::cout << "Error! Failed to set scene data buffers" << std::endl;
+ myRaytraceFBO2 = new OpenGl_FrameBuffer;
}
-#endif
-#ifdef RAY_TRACE_PRINT_INFO
+ const GLfloat aVertices[] = { -1.f, -1.f, 0.f,
+ -1.f, 1.f, 0.f,
+ 1.f, 1.f, 0.f,
+ 1.f, 1.f, 0.f,
+ 1.f, -1.f, 0.f,
+ -1.f, -1.f, 0.f };
- Standard_ShortReal aMemUsed = 0.f;
+ myRaytraceScreenQuad.Init (myGlContext, 3, 6, aVertices);
- for (Standard_Integer anElemIdx = 0; anElemIdx < myRaytraceGeometry.Size(); ++anElemIdx)
+ myComputeInitStatus = OpenGl_RT_INIT; // initialized in normal way
+
+ return Standard_True;
+}
+
+// =======================================================================
+// function : NullifyResource
+// purpose :
+// =======================================================================
+inline void NullifyResource (const Handle(OpenGl_Context)& theContext,
+ Handle(OpenGl_Resource)& theResource)
+{
+ if (!theResource.IsNull())
{
- OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
- myRaytraceGeometry.Objects().ChangeValue (anElemIdx).operator->());
+ theResource->Release (theContext.operator->());
+ theResource.Nullify();
+ }
+}
- aMemUsed += static_cast<Standard_ShortReal> (
- aTriangleSet->Vertices.size() * sizeof (BVH_Vec4f));
- aMemUsed += static_cast<Standard_ShortReal> (
- aTriangleSet->Normals.size() * sizeof (BVH_Vec4f));
- aMemUsed += static_cast<Standard_ShortReal> (
- aTriangleSet->Elements.size() * sizeof (BVH_Vec4i));
+// =======================================================================
+// function : ReleaseRaytraceResources
+// purpose : Releases OpenGL/GLSL shader programs
+// =======================================================================
+void OpenGl_Workspace::ReleaseRaytraceResources()
+{
+ NullifyResource (myGlContext, myRaytraceFBO1);
+ NullifyResource (myGlContext, myRaytraceFBO2);
- aMemUsed += static_cast<Standard_ShortReal> (
- aTriangleSet->BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
- aMemUsed += static_cast<Standard_ShortReal> (
- aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f));
- aMemUsed += static_cast<Standard_ShortReal> (
- aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f));
- }
+ NullifyResource (myGlContext, myRaytraceShader);
+ NullifyResource (myGlContext, myPostFSAAShader);
- aMemUsed += static_cast<Standard_ShortReal> (
- myRaytraceGeometry.BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
- aMemUsed += static_cast<Standard_ShortReal> (
- myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f));
- aMemUsed += static_cast<Standard_ShortReal> (
- myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f));
+ NullifyResource (myGlContext, myRaytraceProgram);
+ NullifyResource (myGlContext, myPostFSAAProgram);
- std::cout << "GPU Memory Used (MB): ~" << aMemUsed / 1048576 << std::endl;
+ NullifyResource (myGlContext, mySceneNodeInfoTexture);
+ NullifyResource (myGlContext, mySceneMinPointTexture);
+ NullifyResource (myGlContext, mySceneMaxPointTexture);
-#endif
+ NullifyResource (myGlContext, myObjectNodeInfoTexture);
+ NullifyResource (myGlContext, myObjectMinPointTexture);
+ NullifyResource (myGlContext, myObjectMaxPointTexture);
- return (CL_SUCCESS == anErrorRes);
-}
+ NullifyResource (myGlContext, myGeometryVertexTexture);
+ NullifyResource (myGlContext, myGeometryNormalTexture);
+ NullifyResource (myGlContext, myGeometryTriangTexture);
+ NullifyResource (myGlContext, mySceneTransformTexture);
+
+ NullifyResource (myGlContext, myRaytraceLightSrcTexture);
+ NullifyResource (myGlContext, myRaytraceMaterialTexture);
-// Use it to estimate the optimal size of OpenCL work group
-// #define OPENCL_GROUP_SIZE_TEST
+ if (myRaytraceScreenQuad.IsValid())
+ myRaytraceScreenQuad.Release (myGlContext.operator->());
+}
// =======================================================================
-// function : RunRaytraceOpenCLKernels
-// purpose : Runs OpenCL ray-tracing kernels
+// function : UploadRaytraceData
+// purpose : Uploads ray-trace data to the GPU
// =======================================================================
-Standard_Boolean OpenGl_Workspace::RunRaytraceOpenCLKernels (const Graphic3d_CView& theCView,
- const Standard_ShortReal theOrigins[16],
- const Standard_ShortReal theDirects[16],
- const Standard_Integer theSizeX,
- const Standard_Integer theSizeY)
+Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
{
- if (myRaytraceRenderKernel == NULL || myComputeQueue == NULL)
+ if (!myGlContext->IsGlGreaterEqual (3, 1))
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: OpenGL version is less than 3.1" << std::endl;
+#endif
return Standard_False;
+ }
- ////////////////////////////////////////////////////////////////////////
- // Set kernel arguments
-
- cl_uint anIndex = 0;
- cl_int anError = 0;
-
- cl_int aLightSourceBufferSize = myRaytraceGeometry.Sources.size();
-
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_int), &theSizeX);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_int), &theSizeY);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_float16), theOrigins);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_float16), theDirects);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myRaytraceEnvironment);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myRaytraceOutputImage);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &mySceneNodeInfoBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &mySceneMinPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &mySceneMaxPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myObjectNodeInfoBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myObjectMinPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myObjectMaxPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myGeometryTriangBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myGeometryVertexBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myGeometryNormalBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myRaytraceLightSourceBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_mem), &myRaytraceMaterialBuffer);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_float4), &myRaytraceGeometry.GlobalAmbient);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_int), &aLightSourceBufferSize);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_int), &theCView.IsShadowsEnabled);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_int), &theCView.IsReflectionsEnabled);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_float), &myRaytraceSceneEpsilon);
- anError |= clSetKernelArg (
- myRaytraceRenderKernel, anIndex++, sizeof(cl_float), &myRaytraceSceneRadius);
-
- if (anError != CL_SUCCESS)
- {
- const TCollection_ExtendedString aMessage = "Error! Failed to set arguments of ray-tracing kernel!";
-
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
+ /////////////////////////////////////////////////////////////////////////////
+ // Create OpenGL texture buffers
- return Standard_False;
- }
+ if (mySceneNodeInfoTexture.IsNull()) // create hight-level BVH buffers
+ {
+ mySceneNodeInfoTexture = new OpenGl_TextureBufferArb;
+ mySceneMinPointTexture = new OpenGl_TextureBufferArb;
+ mySceneMaxPointTexture = new OpenGl_TextureBufferArb;
+ mySceneTransformTexture = new OpenGl_TextureBufferArb;
- // Second-pass 'smoothing' kernel runs only if anti-aliasing is enabled
- if (theCView.IsAntialiasingEnabled)
- {
- anIndex = 0;
-
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_int), &theSizeX);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_int), &theSizeY);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_float16), theOrigins);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_float16), theDirects);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myRaytraceOutputImage);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myRaytraceEnvironment);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myRaytraceOutputImageAA);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &mySceneNodeInfoBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &mySceneMinPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &mySceneMaxPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myObjectNodeInfoBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myObjectMinPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myObjectMaxPointBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myGeometryTriangBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myGeometryVertexBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myGeometryNormalBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myRaytraceLightSourceBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_mem), &myRaytraceMaterialBuffer);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_float4), &myRaytraceGeometry.GlobalAmbient);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_int), &aLightSourceBufferSize);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_int), &theCView.IsShadowsEnabled);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_int), &theCView.IsReflectionsEnabled);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_float), &myRaytraceSceneEpsilon);
- anError |= clSetKernelArg (
- myRaytraceSmoothKernel, anIndex++, sizeof(cl_float), &myRaytraceSceneRadius);
-
- if (anError != CL_SUCCESS)
+ if (!mySceneNodeInfoTexture->Create (myGlContext)
+ || !mySceneMinPointTexture->Create (myGlContext)
+ || !mySceneMaxPointTexture->Create (myGlContext)
+ || !mySceneTransformTexture->Create (myGlContext))
{
- const TCollection_ExtendedString aMessage = "Error! Failed to set arguments of smoothing kernel!";
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to create buffers for high-level scene BVH" << std::endl;
+#endif
+ return Standard_False;
+ }
+ }
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
+ if (myObjectNodeInfoTexture.IsNull()) // create bottom-level BVH buffers
+ {
+ myObjectNodeInfoTexture = new OpenGl_TextureBufferArb;
+ myObjectMinPointTexture = new OpenGl_TextureBufferArb;
+ myObjectMaxPointTexture = new OpenGl_TextureBufferArb;
+ if (!myObjectNodeInfoTexture->Create (myGlContext)
+ || !myObjectMinPointTexture->Create (myGlContext)
+ || !myObjectMaxPointTexture->Create (myGlContext))
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to create buffers for bottom-level scene BVH" << std::endl;
+#endif
return Standard_False;
}
}
- ////////////////////////////////////////////////////////////////////////
- // Set work size
+ if (myGeometryVertexTexture.IsNull()) // create geometry buffers
+ {
+ myGeometryVertexTexture = new OpenGl_TextureBufferArb;
+ myGeometryNormalTexture = new OpenGl_TextureBufferArb;
+ myGeometryTriangTexture = new OpenGl_TextureBufferArb;
- size_t aLocWorkSize[] = { myIsAmdComputePlatform ? 2 : 4, 32 };
+ if (!myGeometryVertexTexture->Create (myGlContext)
+ || !myGeometryNormalTexture->Create (myGlContext)
+ || !myGeometryTriangTexture->Create (myGlContext))
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to create buffers for triangulation data" << std::endl;
+#endif
+ return Standard_False;
+ }
+ }
-#ifdef OPENCL_GROUP_SIZE_TEST
- for (size_t aLocX = 2; aLocX <= 32; aLocX <<= 1)
- for (size_t aLocY = 2; aLocY <= 32; aLocY <<= 1)
+ if (myRaytraceMaterialTexture.IsNull()) // create material buffer
{
- aLocWorkSize[0] = aLocX;
- aLocWorkSize[1] = aLocY;
-#endif
+ myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
- size_t aWorkSizeX = theSizeX;
- if (aWorkSizeX % aLocWorkSize[0] != 0)
- aWorkSizeX += aLocWorkSize[0] - aWorkSizeX % aLocWorkSize[0];
+ if (!myRaytraceMaterialTexture->Create (myGlContext))
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to create buffers for material data" << std::endl;
+#endif
+ return Standard_False;
+ }
+ }
- size_t aWokrSizeY = theSizeY;
- if (aWokrSizeY % aLocWorkSize[1] != 0 )
- aWokrSizeY += aLocWorkSize[1] - aWokrSizeY % aLocWorkSize[1];
+ /////////////////////////////////////////////////////////////////////////////
+ // Write top-level BVH buffers
- size_t aTotWorkSize[] = { aWorkSizeX, aWokrSizeY };
+ const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = myRaytraceGeometry.BVH();
- cl_event anEvent = NULL, anEventSmooth = NULL;
+ bool aResult = true;
+ if (!aBVH->NodeInfoBuffer().empty())
+ {
+ aResult &= mySceneNodeInfoTexture->Init (myGlContext, 4, GLsizei (aBVH->NodeInfoBuffer().size()),
+ reinterpret_cast<const GLuint*> (&aBVH->NodeInfoBuffer().front()));
+ aResult &= mySceneMinPointTexture->Init (myGlContext, 4, GLsizei (aBVH->MinPointBuffer().size()),
+ reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
+ aResult &= mySceneMaxPointTexture->Init (myGlContext, 4, GLsizei (aBVH->MaxPointBuffer().size()),
+ reinterpret_cast<const GLfloat*> (&aBVH->MaxPointBuffer().front()));
+ }
+ if (!aResult)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to upload buffers for high-level scene BVH" << std::endl;
+#endif
+ return Standard_False;
+ }
- anError = clEnqueueNDRangeKernel (myComputeQueue,
- myRaytraceRenderKernel, 2, NULL, aTotWorkSize, aLocWorkSize, 0, NULL, &anEvent);
+ /////////////////////////////////////////////////////////////////////////////
+ // Write transform buffer
- if (anError != CL_SUCCESS)
- {
- const TCollection_ExtendedString aMessage = "Error! Failed to execute the ray-tracing kernel!";
+ BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()];
+ BVH_Mat4f anIdentity;
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
+ for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
+ {
+ OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
+ myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
- return Standard_False;
- }
+ const BVH_Transform<Standard_ShortReal, 4>* aTransform =
+ dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (aTriangleSet->Properties().operator->());
- clWaitForEvents (1, &anEvent);
+ Standard_ASSERT_RETURN (aTransform != NULL,
+ "OpenGl_TriangleSet does not contain transform", Standard_False);
- if (theCView.IsAntialiasingEnabled)
- {
- size_t aLocWorkSizeSmooth[] = { myIsAmdComputePlatform ? 8 : 4,
- myIsAmdComputePlatform ? 8 : 32 };
+ aNodeTransforms[anElemIndex] = aTransform->Inversed();
-#ifdef OPENCL_GROUP_SIZE_TEST
- aLocWorkSizeSmooth[0] = aLocX;
- aLocWorkSizeSmooth[1] = aLocY;
-#endif
+ }
- aWorkSizeX = theSizeX;
- if (aWorkSizeX % aLocWorkSizeSmooth[0] != 0)
- aWorkSizeX += aLocWorkSizeSmooth[0] - aWorkSizeX % aLocWorkSizeSmooth[0];
+ aResult &= mySceneTransformTexture->Init (myGlContext, 4,
+ myRaytraceGeometry.Size() * 4, reinterpret_cast<const GLfloat*> (aNodeTransforms));
- size_t aWokrSizeY = theSizeY;
- if (aWokrSizeY % aLocWorkSizeSmooth[1] != 0 )
- aWokrSizeY += aLocWorkSizeSmooth[1] - aWokrSizeY % aLocWorkSizeSmooth[1];
+ delete[] aNodeTransforms;
- size_t aTotWorkSizeSmooth [] = { aWorkSizeX, aWokrSizeY };
+ /////////////////////////////////////////////////////////////////////////////
+ // Write geometry and bottom-level BVH buffers
- anError = clEnqueueNDRangeKernel (myComputeQueue, myRaytraceSmoothKernel,
- 2, NULL, aTotWorkSizeSmooth, aLocWorkSizeSmooth, 0, NULL, &anEventSmooth);
+ Standard_Size aTotalVerticesNb = 0;
+ Standard_Size aTotalElementsNb = 0;
+ Standard_Size aTotalBVHNodesNb = 0;
- clWaitForEvents (1, &anEventSmooth);
+ for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
+ {
+ OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
+ myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
- if (anError != CL_SUCCESS)
- {
- const TCollection_ExtendedString aMessage = "Error! Failed to execute the smoothing kernel";
+ Standard_ASSERT_RETURN (aTriangleSet != NULL,
+ "Error: Failed to get triangulation of OpenGL element", Standard_False);
- myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
+ aTotalVerticesNb += aTriangleSet->Vertices.size();
+ aTotalElementsNb += aTriangleSet->Elements.size();
- return Standard_False;
- }
- }
+ Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(),
+ "Error: Failed to get bottom-level BVH of OpenGL element", Standard_False);
-#if defined (RAY_TRACE_PRINT_INFO) || defined (OPENCL_GROUP_SIZE_TEST)
+ aTotalBVHNodesNb += aTriangleSet->BVH()->NodeInfoBuffer().size();
+ }
- static cl_ulong ttt1 = 10000000000;
- static cl_ulong ttt2 = 10000000000;
+ if (aTotalBVHNodesNb != 0)
+ {
+ aResult &= myObjectNodeInfoTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*> (NULL));
+ aResult &= myObjectMinPointTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
+ aResult &= myObjectMaxPointTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
+ }
- cl_ulong aBegTime = 0;
- cl_ulong aEndTime = 0;
+ if (!aResult)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to upload buffers for bottom-level scene BVH" << std::endl;
+#endif
+ return Standard_False;
+ }
- clGetEventProfilingInfo (anEvent,
- CL_PROFILING_COMMAND_START, sizeof(aBegTime), &aBegTime, NULL);
- clGetEventProfilingInfo (anEvent,
- CL_PROFILING_COMMAND_END, sizeof(aEndTime), &aEndTime, NULL);
+ if (aTotalElementsNb != 0)
+ {
+ aResult &= myGeometryTriangTexture->Init (myGlContext, 4, GLsizei (aTotalElementsNb), static_cast<const GLuint*> (NULL));
+ }
- ttt1 = aEndTime - aBegTime < ttt1 ? aEndTime - aBegTime : ttt1;
+ if (aTotalVerticesNb != 0)
+ {
+ aResult &= myGeometryVertexTexture->Init (myGlContext, 4, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
+ aResult &= myGeometryNormalTexture->Init (myGlContext, 4, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
+ }
- std::cout << "\tRender time (ms): " << ttt1 / 1e6f << std::endl;
+ if (!aResult)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to upload buffers for scene geometry" << std::endl;
+#endif
+ return Standard_False;
+ }
- if (theCView.IsAntialiasingEnabled)
- {
- clGetEventProfilingInfo (anEventSmooth,
- CL_PROFILING_COMMAND_START, sizeof(aBegTime), &aBegTime, NULL);
- clGetEventProfilingInfo (anEventSmooth,
- CL_PROFILING_COMMAND_END, sizeof(aEndTime), &aEndTime, NULL);
+ for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
+ {
+ if (!aBVH->IsOuter (aNodeIdx))
+ continue;
- ttt2 = aEndTime - aBegTime < ttt2 ? aEndTime - aBegTime : ttt2;
+ OpenGl_TriangleSet* aTriangleSet = myRaytraceGeometry.TriangleSet (aNodeIdx);
- std::cout << "\tSmooth time (ms): " << ttt2 / 1e6f << std::endl;
- }
+ Standard_ASSERT_RETURN (aTriangleSet != NULL,
+ "Error: Failed to get triangulation of OpenGL element", Standard_False);
-#endif
+ const Standard_Integer aBVHOffset = myRaytraceGeometry.AccelerationOffset (aNodeIdx);
- if (anEvent != NULL)
- clReleaseEvent (anEvent);
+ Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
+ "Error: Failed to get offset for bottom-level BVH", Standard_False);
- if (anEventSmooth != NULL)
- clReleaseEvent (anEventSmooth);
+ const size_t aBVHBuffserSize = aTriangleSet->BVH()->NodeInfoBuffer().size();
-#ifdef OPENCL_GROUP_SIZE_TEST
- }
+ if (aBVHBuffserSize != 0)
+ {
+ aResult &= myObjectNodeInfoTexture->SubData (myGlContext, aBVHOffset, GLsizei (aBVHBuffserSize),
+ reinterpret_cast<const GLuint*> (&aTriangleSet->BVH()->NodeInfoBuffer().front()));
+ aResult &= myObjectMinPointTexture->SubData (myGlContext, aBVHOffset, GLsizei (aBVHBuffserSize),
+ reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MinPointBuffer().front()));
+ aResult &= myObjectMaxPointTexture->SubData (myGlContext, aBVHOffset, GLsizei (aBVHBuffserSize),
+ reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MaxPointBuffer().front()));
+ if (!aResult)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to upload buffers for bottom-level scene BVHs" << std::endl;
#endif
+ return Standard_False;
+ }
+ }
- return Standard_True;
-}
-
-// =======================================================================
-// function : ComputeInverseMatrix
-// purpose : Computes inversion of 4x4 floating-point matrix
-// =======================================================================
-template <typename T>
-void ComputeInverseMatrix (const T m[16], T inv[16])
-{
- inv[ 0] = m[ 5] * (m[10] * m[15] - m[11] * m[14]) -
- m[ 9] * (m[ 6] * m[15] - m[ 7] * m[14]) -
- m[13] * (m[ 7] * m[10] - m[ 6] * m[11]);
+ const Standard_Integer aVerticesOffset = myRaytraceGeometry.VerticesOffset (aNodeIdx);
- inv[ 1] = m[ 1] * (m[11] * m[14] - m[10] * m[15]) -
- m[ 9] * (m[ 3] * m[14] - m[ 2] * m[15]) -
- m[13] * (m[ 2] * m[11] - m[ 3] * m[10]);
+ Standard_ASSERT_RETURN (aVerticesOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
+ "Error: Failed to get offset for triangulation vertices of OpenGL element", Standard_False);
- inv[ 2] = m[ 1] * (m[ 6] * m[15] - m[ 7] * m[14]) -
- m[ 5] * (m[ 2] * m[15] - m[ 3] * m[14]) -
- m[13] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
+ if (!aTriangleSet->Vertices.empty())
+ {
+ aResult &= myGeometryNormalTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Normals.size()),
+ reinterpret_cast<const GLfloat*> (&aTriangleSet->Normals.front()));
+ aResult &= myGeometryVertexTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Vertices.size()),
+ reinterpret_cast<const GLfloat*> (&aTriangleSet->Vertices.front()));
+ }
- inv[ 3] = m[ 1] * (m[ 7] * m[10] - m[ 6] * m[11]) -
- m[ 5] * (m[ 3] * m[10] - m[ 2] * m[11]) -
- m[ 9] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
+ const Standard_Integer anElementsOffset = myRaytraceGeometry.ElementsOffset (aNodeIdx);
- inv[ 4] = m[ 4] * (m[11] * m[14] - m[10] * m[15]) -
- m[ 8] * (m[ 7] * m[14] - m[ 6] * m[15]) -
- m[12] * (m[ 6] * m[11] - m[ 7] * m[10]);
+ Standard_ASSERT_RETURN (anElementsOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
+ "Error: Failed to get offset for triangulation elements of OpenGL element", Standard_False);
- inv[ 5] = m[ 0] * (m[10] * m[15] - m[11] * m[14]) -
- m[ 8] * (m[ 2] * m[15] - m[ 3] * m[14]) -
- m[12] * (m[ 3] * m[10] - m[ 2] * m[11]);
+ if (!aTriangleSet->Elements.empty())
+ {
+ aResult &= myGeometryTriangTexture->SubData (myGlContext, anElementsOffset, GLsizei (aTriangleSet->Elements.size()),
+ reinterpret_cast<const GLuint*> (&aTriangleSet->Elements.front()));
+ }
- inv[ 6] = m[ 0] * (m[ 7] * m[14] - m[ 6] * m[15]) -
- m[ 4] * (m[ 3] * m[14] - m[ 2] * m[15]) -
- m[12] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
+ if (!aResult)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to upload triangulation buffers for OpenGL element" << std::endl;
+#endif
+ return Standard_False;
+ }
+ }
- inv[ 7] = m[ 0] * (m[ 6] * m[11] - m[ 7] * m[10]) -
- m[ 4] * (m[ 2] * m[11] - m[ 3] * m[10]) -
- m[ 8] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
+ if (myRaytraceGeometry.Materials.size() != 0)
+ {
+ const GLfloat* aDataPtr = myRaytraceGeometry.Materials.front().Packed();
+ aResult &= myRaytraceMaterialTexture->Init (myGlContext, 4, GLsizei (myRaytraceGeometry.Materials.size() * 7), aDataPtr);
+ if (!aResult)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to upload material buffer" << std::endl;
+#endif
+ return Standard_False;
+ }
+ }
- inv[ 8] = m[ 4] * (m[ 9] * m[15] - m[11] * m[13]) -
- m[ 8] * (m[ 5] * m[15] - m[ 7] * m[13]) -
- m[12] * (m[ 7] * m[ 9] - m[ 5] * m[11]);
+ myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0;
- inv[ 9] = m[ 0] * (m[11] * m[13] - m[ 9] * m[15]) -
- m[ 8] * (m[ 3] * m[13] - m[ 1] * m[15]) -
- m[12] * (m[ 1] * m[11] - m[ 3] * m[ 9]);
+#ifdef RAY_TRACE_PRINT_INFO
- inv[10] = m[ 0] * (m[ 5] * m[15] - m[ 7] * m[13]) -
- m[ 4] * (m[ 1] * m[15] - m[ 3] * m[13]) -
- m[12] * (m[ 3] * m[ 5] - m[ 1] * m[ 7]);
+ Standard_ShortReal aMemUsed = 0.f;
- inv[11] = m[ 0] * (m[ 7] * m[ 9] - m[ 5] * m[11]) -
- m[ 4] * (m[ 3] * m[ 9] - m[ 1] * m[11]) -
- m[ 8] * (m[ 1] * m[ 7] - m[ 3] * m[ 5]);
+ for (Standard_Integer anElemIdx = 0; anElemIdx < myRaytraceGeometry.Size(); ++anElemIdx)
+ {
+ OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
+ myRaytraceGeometry.Objects().ChangeValue (anElemIdx).operator->());
- inv[12] = m[ 4] * (m[10] * m[13] - m[ 9] * m[14]) -
- m[ 8] * (m[ 6] * m[13] - m[ 5] * m[14]) -
- m[12] * (m[ 5] * m[10] - m[ 6] * m[ 9]);
+ aMemUsed += static_cast<Standard_ShortReal> (
+ aTriangleSet->Vertices.size() * sizeof (BVH_Vec4f));
+ aMemUsed += static_cast<Standard_ShortReal> (
+ aTriangleSet->Normals.size() * sizeof (BVH_Vec4f));
+ aMemUsed += static_cast<Standard_ShortReal> (
+ aTriangleSet->Elements.size() * sizeof (BVH_Vec4i));
- inv[13] = m[ 0] * (m[ 9] * m[14] - m[10] * m[13]) -
- m[ 8] * (m[ 1] * m[14] - m[ 2] * m[13]) -
- m[12] * (m[ 2] * m[ 9] - m[ 1] * m[10]);
+ aMemUsed += static_cast<Standard_ShortReal> (
+ aTriangleSet->BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
+ aMemUsed += static_cast<Standard_ShortReal> (
+ aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f));
+ aMemUsed += static_cast<Standard_ShortReal> (
+ aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f));
+ }
- inv[14] = m[ 0] * (m[ 6] * m[13] - m[ 5] * m[14]) -
- m[ 4] * (m[ 2] * m[13] - m[ 1] * m[14]) -
- m[12] * (m[ 1] * m[ 6] - m[ 2] * m[ 5]);
+ aMemUsed += static_cast<Standard_ShortReal> (
+ myRaytraceGeometry.BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
+ aMemUsed += static_cast<Standard_ShortReal> (
+ myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f));
+ aMemUsed += static_cast<Standard_ShortReal> (
+ myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f));
- inv[15] = m[ 0] * (m[ 5] * m[10] - m[ 6] * m[ 9]) -
- m[ 4] * (m[ 1] * m[10] - m[ 2] * m[ 9]) -
- m[ 8] * (m[ 2] * m[ 5] - m[ 1] * m[ 6]);
+ std::cout << "GPU Memory Used (MB): ~" << aMemUsed / 1048576 << std::endl;
- T det = m[0] * inv[ 0] +
- m[1] * inv[ 4] +
- m[2] * inv[ 8] +
- m[3] * inv[12];
+#endif
- if (det == T (0.0)) return;
+ return aResult;
+}
- det = T (1.0) / det;
+// =======================================================================
+// function : ResizeRaytraceBuffers
+// purpose : Resizes OpenGL frame buffers
+// =======================================================================
+Standard_Boolean OpenGl_Workspace::ResizeRaytraceBuffers (const Standard_Integer theSizeX,
+ const Standard_Integer theSizeY)
+{
+ if (myRaytraceFBO1->GetVPSizeX() != theSizeX
+ || myRaytraceFBO1->GetVPSizeY() != theSizeY)
+ {
+ myRaytraceFBO1->Init (myGlContext, theSizeX, theSizeY);
+ myRaytraceFBO2->Init (myGlContext, theSizeX, theSizeY);
+ }
- for (Standard_Integer i = 0; i < 16; ++i)
- inv[i] *= det;
+ return Standard_True;
}
// =======================================================================
-// function : GenerateCornerRays
-// purpose : Generates primary rays for corners of screen quad
+// function : UpdateCamera
+// purpose : Generates viewing rays for corners of screen quad
// =======================================================================
-void GenerateCornerRays (const GLdouble theInvModelProj[16],
- cl_float theOrigins[16],
- cl_float theDirects[16])
+void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4<GLdouble>& theOrientation,
+ const NCollection_Mat4<GLdouble>& theViewMapping,
+ OpenGl_Vec3 theOrigins[4],
+ OpenGl_Vec3 theDirects[4])
{
+ NCollection_Mat4<GLdouble> aInvModelProj;
+
+ // compute inverse model-view-projection matrix
+ (theViewMapping * theOrientation).Inverted (aInvModelProj);
+
Standard_Integer aOriginIndex = 0;
Standard_Integer aDirectIndex = 0;
- for (Standard_Integer y = -1; y <= 1; y += 2)
+ for (Standard_Integer aY = -1; aY <= 1; aY += 2)
{
- for (Standard_Integer x = -1; x <= 1; x += 2)
+ for (Standard_Integer aX = -1; aX <= 1; aX += 2)
{
- BVH_Vec4f aOrigin (float(x),
- float(y),
- -1.f,
- 1.f);
+ OpenGl_Vec4d aOrigin (GLdouble(aX),
+ GLdouble(aY),
+ -1.0,
+ 1.0);
+
+ aOrigin = aInvModelProj * aOrigin;
- aOrigin = MatVecMult (theInvModelProj, aOrigin);
aOrigin.x() = aOrigin.x() / aOrigin.w();
aOrigin.y() = aOrigin.y() / aOrigin.w();
aOrigin.z() = aOrigin.z() / aOrigin.w();
- aOrigin.w() = 1.f;
- BVH_Vec4f aDirect (float(x),
- float(y),
- 1.f,
- 1.f);
+ OpenGl_Vec4d aDirect (GLdouble(aX),
+ GLdouble(aY),
+ 1.0,
+ 1.0);
+
+ aDirect = aInvModelProj * aDirect;
- aDirect = MatVecMult (theInvModelProj, aDirect);
aDirect.x() = aDirect.x() / aDirect.w();
aDirect.y() = aDirect.y() / aDirect.w();
aDirect.z() = aDirect.z() / aDirect.w();
- aDirect.w() = 1.f;
aDirect = aDirect - aOrigin;
- GLdouble aInvLen = 1.f / sqrt (aDirect.x() * aDirect.x() +
+ GLdouble aInvLen = 1.0 / sqrt (aDirect.x() * aDirect.x() +
aDirect.y() * aDirect.y() +
aDirect.z() * aDirect.z());
- theOrigins [aOriginIndex++] = static_cast<GLfloat> (aOrigin.x());
- theOrigins [aOriginIndex++] = static_cast<GLfloat> (aOrigin.y());
- theOrigins [aOriginIndex++] = static_cast<GLfloat> (aOrigin.z());
- theOrigins [aOriginIndex++] = 1.f;
+ theOrigins[aOriginIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aOrigin.x()),
+ static_cast<GLfloat> (aOrigin.y()),
+ static_cast<GLfloat> (aOrigin.z()));
- theDirects [aDirectIndex++] = static_cast<GLfloat> (aDirect.x() * aInvLen);
- theDirects [aDirectIndex++] = static_cast<GLfloat> (aDirect.y() * aInvLen);
- theDirects [aDirectIndex++] = static_cast<GLfloat> (aDirect.z() * aInvLen);
- theDirects [aDirectIndex++] = 0.f;
+ theDirects[aDirectIndex++] = OpenGl_Vec3 (static_cast<GLfloat> (aDirect.x() * aInvLen),
+ static_cast<GLfloat> (aDirect.y() * aInvLen),
+ static_cast<GLfloat> (aDirect.z() * aInvLen));
}
}
}
+// =======================================================================
+// function : RunRaytraceShaders
+// purpose : Runs ray-tracing shader programs
+// =======================================================================
+Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& theCView,
+ const Standard_Integer theSizeX,
+ const Standard_Integer theSizeY,
+ const OpenGl_Vec3 theOrigins[4],
+ const OpenGl_Vec3 theDirects[4],
+ OpenGl_FrameBuffer* theFrameBuffer)
+{
+ mySceneMinPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
+ mySceneMaxPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
+ mySceneNodeInfoTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
+ myObjectMinPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMinPointTexture);
+ myObjectMaxPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMaxPointTexture);
+ myObjectNodeInfoTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture);
+ myGeometryVertexTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
+ myGeometryNormalTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
+ myGeometryTriangTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
+ myRaytraceMaterialTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
+ myRaytraceLightSrcTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
+ mySceneTransformTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
+
+ if (theCView.RenderParams.IsAntialiasingEnabled) // render source image to FBO
+ {
+ myRaytraceFBO1->BindBuffer (myGlContext);
+
+ glDisable (GL_BLEND);
+ }
+
+ myRaytraceProgram->Bind (myGlContext);
+
+ Standard_Integer aLightSourceBufferSize =
+ static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
+
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uOriginLB], theOrigins[0]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uOriginRB], theOrigins[1]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uOriginLT], theOrigins[2]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uOriginRT], theOrigins[3]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uDirectLB], theDirects[0]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uDirectRB], theDirects[1]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uDirectLT], theDirects[2]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uDirectRT], theDirects[3]);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uLightCount], aLightSourceBufferSize);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uShadEnabled], theCView.RenderParams.IsShadowEnabled ? 1 : 0);
+ myRaytraceProgram->SetUniform (myGlContext,
+ myUniformLocations[0][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0);
+
+ myGlContext->core20fwd->glEnableVertexAttribArray (
+ myUniformLocations[0][OpenGl_RT_aPosition]);
+ {
+ myGlContext->core20fwd->glVertexAttribPointer (
+ myUniformLocations[0][OpenGl_RT_aPosition], 3, GL_FLOAT, GL_FALSE, 0, NULL);
+
+ myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
+ }
+ myGlContext->core20fwd->glDisableVertexAttribArray (
+ myUniformLocations[0][OpenGl_RT_aPosition]);
+
+ if (!theCView.RenderParams.IsAntialiasingEnabled)
+ {
+ myRaytraceProgram->Unbind (myGlContext);
+
+ return Standard_True;
+ }
+
+ myRaytraceFBO1->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
+
+ myPostFSAAProgram->Bind (myGlContext);
+
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uOriginLB], theOrigins[0]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uOriginRB], theOrigins[1]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uOriginLT], theOrigins[2]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uOriginRT], theOrigins[3]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uDirectLB], theDirects[0]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uDirectRB], theDirects[1]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uDirectLT], theDirects[2]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uDirectRT], theDirects[3]);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uLightCount], aLightSourceBufferSize);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uShadEnabled], theCView.RenderParams.IsShadowEnabled ? 1 : 0);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0);
+
+ const Standard_ShortReal aMaxOffset = 0.559017f;
+ const Standard_ShortReal aMinOffset = 0.186339f;
+
+ myGlContext->core20fwd->glEnableVertexAttribArray (
+ myUniformLocations[1][OpenGl_RT_aPosition]);
+
+ myGlContext->core20fwd->glVertexAttribPointer (
+ myUniformLocations[1][OpenGl_RT_aPosition], 3, GL_FLOAT, GL_FALSE, 0, NULL);
+
+ // Perform multi-pass adaptive FSAA using ping-pong technique
+ // rotated grid AA always uses 4 samples
+ for (Standard_Integer anIt = 0; anIt < 4; ++anIt)
+ {
+ GLfloat aOffsetX = 1.f / theSizeX;
+ GLfloat aOffsetY = 1.f / theSizeY;
+
+ if (anIt < 2)
+ {
+ aOffsetX *= anIt < 1 ? aMinOffset : -aMaxOffset;
+ aOffsetY *= anIt < 1 ? aMaxOffset : aMinOffset;
+ }
+ else
+ {
+ aOffsetX *= anIt > 2 ? aMaxOffset : -aMinOffset;
+ aOffsetY *= anIt > 2 ? -aMinOffset : -aMaxOffset;
+ }
+
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uSamples], anIt + 2);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uOffsetX], aOffsetX);
+ myPostFSAAProgram->SetUniform (myGlContext,
+ myUniformLocations[1][OpenGl_RT_uOffsetY], aOffsetY);
+
+ Handle(OpenGl_FrameBuffer)& aFramebuffer = anIt % 2 ? myRaytraceFBO1 : myRaytraceFBO2;
+
+ if (anIt == 3) // disable FBO on last iteration
+ {
+ glEnable (GL_BLEND);
+
+ if (theFrameBuffer != NULL)
+ theFrameBuffer->BindBuffer (myGlContext);
+ }
+ else
+ {
+ aFramebuffer->BindBuffer (myGlContext);
+ }
+
+ myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
+
+ if (anIt != 3) // set input for the next pass
+ {
+ aFramebuffer->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
+ aFramebuffer->UnbindBuffer (myGlContext);
+ }
+ }
+
+ myGlContext->core20fwd->glDisableVertexAttribArray (
+ myUniformLocations[1][OpenGl_RT_aPosition]);
+
+ myPostFSAAProgram->Unbind (myGlContext);
+
+ return Standard_True;
+}
+
// =======================================================================
// function : Raytrace
-// purpose : Redraws the window using OpenCL ray tracing
+// purpose : Redraws the window using OpenGL/GLSL ray-tracing
// =======================================================================
Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
const Standard_Integer theSizeX,
const Standard_Integer theSizeY,
- const Tint theToSwap)
+ const Standard_Boolean theToSwap,
+ OpenGl_FrameBuffer* theFrameBuffer)
{
- if (!InitOpenCL())
+ if (!UpdateRaytraceGeometry (OpenGl_GUM_CHECK))
return Standard_False;
- if (!ResizeRaytraceOutputBuffer (theSizeX, theSizeY))
+ if (!InitRaytraceResources (theCView))
return Standard_False;
- if (!UpdateRaytraceEnvironmentMap())
+ if (!ResizeRaytraceBuffers (theSizeX, theSizeY))
return Standard_False;
- if (!UpdateRaytraceGeometry (Standard_True))
+ if (!UpdateRaytraceEnvironmentMap())
return Standard_False;
// Get model-view and projection matrices
myView->GetMatrices (theOrientation, theViewMapping);
- GLdouble aOrientationMatrix[16];
- GLdouble aViewMappingMatrix[16];
- GLdouble aOrientationInvers[16];
+ NCollection_Mat4<GLdouble> aOrientationMatrix;
+ NCollection_Mat4<GLdouble> aViewMappingMatrix;
for (Standard_Integer j = 0; j < 4; ++j)
+ {
for (Standard_Integer i = 0; i < 4; ++i)
{
aOrientationMatrix [4 * j + i] = theOrientation (i, j);
aViewMappingMatrix [4 * j + i] = theViewMapping (i, j);
}
+ }
+
+ NCollection_Mat4<GLdouble> aInvOrientationMatrix;
+ aOrientationMatrix.Inverted (aInvOrientationMatrix);
- ComputeInverseMatrix (aOrientationMatrix, aOrientationInvers);
-
- if (!UpdateRaytraceLightSources (aOrientationInvers))
+ if (!UpdateRaytraceLightSources (aInvOrientationMatrix))
return Standard_False;
- // Generate primary rays for corners of the screen quad
- glMatrixMode (GL_MODELVIEW);
-
- glLoadMatrixd (aViewMappingMatrix);
- glMultMatrixd (aOrientationMatrix);
-
- GLdouble aModelProject[16];
- GLdouble aInvModelProj[16];
+ OpenGl_Vec3 aOrigins[4];
+ OpenGl_Vec3 aDirects[4];
- glGetDoublev (GL_MODELVIEW_MATRIX, aModelProject);
+ UpdateCamera (aOrientationMatrix,
+ aViewMappingMatrix,
+ aOrigins,
+ aDirects);
- ComputeInverseMatrix (aModelProject, aInvModelProj);
-
- GLfloat aOrigins[16];
- GLfloat aDirects[16];
-
- GenerateCornerRays (aInvModelProj,
- aOrigins,
- aDirects);
-
- // Compute ray-traced image using OpenCL kernel
- cl_mem anImages[] = { myRaytraceOutputImage, myRaytraceOutputImageAA };
- cl_int anError = clEnqueueAcquireGLObjects (myComputeQueue,
- 2, anImages,
- 0, NULL, NULL);
- clFinish (myComputeQueue);
-
- if (myIsRaytraceDataValid)
- {
- RunRaytraceOpenCLKernels (theCView,
- aOrigins,
- aDirects,
- theSizeX,
- theSizeY);
- }
-
- anError |= clEnqueueReleaseGLObjects (myComputeQueue,
- 2, anImages,
- 0, NULL, NULL);
- clFinish (myComputeQueue);
-
- // Draw background
- glPushAttrib (GL_ENABLE_BIT |
- GL_CURRENT_BIT |
- GL_COLOR_BUFFER_BIT |
- GL_DEPTH_BUFFER_BIT);
+ Standard_Boolean wasBlendingEnabled = glIsEnabled (GL_BLEND);
+ Standard_Boolean wasDepthTestEnabled = glIsEnabled (GL_DEPTH_TEST);
glDisable (GL_DEPTH_TEST);
glClear (GL_COLOR_BUFFER_BIT);
- Handle(OpenGl_Workspace) aWorkspace (this);
- myView->DrawBackground (aWorkspace);
-
- // Draw dummy quad to show result image
- glEnable (GL_COLOR_MATERIAL);
- glEnable (GL_BLEND);
-
- glDisable (GL_DEPTH_TEST);
-
- glBlendFunc (GL_ONE, GL_SRC_ALPHA);
+ if (theFrameBuffer != NULL)
+ theFrameBuffer->BindBuffer (myGlContext);
- glEnable (GL_TEXTURE_RECTANGLE);
+ myView->DrawBackground (*this);
+ // Generate ray-traced image
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
- glColor3f (1.0f, 1.0f, 1.0f);
-
- if (!theCView.IsAntialiasingEnabled)
- myRaytraceOutputTexture->Bind (myGlContext);
- else
- myRaytraceOutputTextureAA->Bind (myGlContext);
+ glEnable (GL_BLEND);
+ glBlendFunc (GL_ONE, GL_SRC_ALPHA);
if (myIsRaytraceDataValid)
{
- glBegin (GL_QUADS);
- {
- glTexCoord2i ( 0, 0); glVertex2f (-1.f, -1.f);
- glTexCoord2i ( 0, theSizeY); glVertex2f (-1.f, 1.f);
- glTexCoord2i (theSizeX, theSizeY); glVertex2f ( 1.f, 1.f);
- glTexCoord2i (theSizeX, 0); glVertex2f ( 1.f, -1.f);
- }
- glEnd();
+ myRaytraceScreenQuad.Bind (myGlContext);
+
+ RunRaytraceShaders (theCView,
+ theSizeX,
+ theSizeY,
+ aOrigins,
+ aDirects,
+ theFrameBuffer);
+
+ myRaytraceScreenQuad.Unbind (myGlContext);
}
- glPopAttrib();
+ if (!wasBlendingEnabled)
+ glDisable (GL_BLEND);
+
+ if (wasDepthTestEnabled)
+ glEnable (GL_DEPTH_TEST);
// Swap the buffers
if (theToSwap)
myBackBufferRestored = Standard_False;
}
else
+ {
glFlush();
+ }
return Standard_True;
}
-
-#endif