From 25ef750e44acc0695242c0cb501b619e92deb853 Mon Sep 17 00:00:00 2001 From: dbp Date: Thu, 23 Oct 2014 14:09:23 +0400 Subject: [PATCH] 025306: Visualization, TKOpenGl - support texturing within RayTracing Fix bug with overlay OpenGL text. --- src/OpenGl/FILES | 4 + src/OpenGl/Handle_OpenGl_Sampler.hxx | 24 + src/OpenGl/OpenGl_ArbTexBindless.hxx | 47 ++ src/OpenGl/OpenGl_Context.cxx | 48 +- src/OpenGl/OpenGl_Context.hxx | 41 +- src/OpenGl/OpenGl_GlFunctions.hxx | 20 + src/OpenGl/OpenGl_Sampler.cxx | 133 +++++ src/OpenGl/OpenGl_Sampler.hxx | 84 +++ src/OpenGl/OpenGl_SceneGeometry.cxx | 193 ++++++- src/OpenGl/OpenGl_SceneGeometry.hxx | 100 ++-- src/OpenGl/OpenGl_ShaderProgram.cxx | 95 ++++ src/OpenGl/OpenGl_ShaderProgram.hxx | 36 ++ src/OpenGl/OpenGl_Text.cxx | 30 +- src/OpenGl/OpenGl_TextureBufferArb.cxx | 23 +- src/OpenGl/OpenGl_View.cxx | 17 +- src/OpenGl/OpenGl_View.hxx | 5 +- src/OpenGl/OpenGl_Workspace.cxx | 69 ++- src/OpenGl/OpenGl_Workspace.hxx | 77 ++- src/OpenGl/OpenGl_Workspace_Raytrace.cxx | 682 ++++++++++++++--------- src/Shaders/RaytraceBase.fs | 239 ++++---- tests/v3d/raytrace/textures | 75 +++ 21 files changed, 1542 insertions(+), 500 deletions(-) create mode 100644 src/OpenGl/Handle_OpenGl_Sampler.hxx create mode 100644 src/OpenGl/OpenGl_ArbTexBindless.hxx create mode 100644 src/OpenGl/OpenGl_Sampler.cxx create mode 100644 src/OpenGl/OpenGl_Sampler.hxx create mode 100644 tests/v3d/raytrace/textures diff --git a/src/OpenGl/FILES b/src/OpenGl/FILES index c68daee966..2afea24112 100755 --- a/src/OpenGl/FILES +++ b/src/OpenGl/FILES @@ -153,3 +153,7 @@ OpenGl_BVHTreeSelector.hxx OpenGl_BVHTreeSelector.cxx OpenGl_BVHClipPrimitiveSet.cxx OpenGl_BVHClipPrimitiveSet.hxx +OpenGl_ArbTexBindless.hxx +Handle_OpenGl_Sampler.hxx +OpenGl_Sampler.hxx +OpenGl_Sampler.cxx diff --git a/src/OpenGl/Handle_OpenGl_Sampler.hxx b/src/OpenGl/Handle_OpenGl_Sampler.hxx new file mode 100644 index 0000000000..623ae56708 --- /dev/null +++ b/src/OpenGl/Handle_OpenGl_Sampler.hxx @@ -0,0 +1,24 @@ +// Created on: 2014-10-17 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2013-2014 OPEN CASCADE SAS +// +// 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 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. + +#ifndef _Handle_OpenGl_Sampler_HeaderFile +#define _Handle_OpenGl_Sampler_HeaderFile + +#include + +class OpenGl_Sampler; +DEFINE_STANDARD_HANDLE(OpenGl_Sampler, OpenGl_Resource) + +#endif diff --git a/src/OpenGl/OpenGl_ArbTexBindless.hxx b/src/OpenGl/OpenGl_ArbTexBindless.hxx new file mode 100644 index 0000000000..482acaf937 --- /dev/null +++ b/src/OpenGl/OpenGl_ArbTexBindless.hxx @@ -0,0 +1,47 @@ +// Created on: 2014-10-07 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2014 OPEN CASCADE SAS +// +// 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 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. + +#ifndef _OpenGl_ArbTexBindless_H__ +#define _OpenGl_ArbTexBindless_H__ + +#include + +//! Provides bindless textures. +//! This extension allows OpenGL applications to access texture objects in +//! shaders without first binding each texture to one of a limited number of +//! texture image units. +struct OpenGl_ArbTexBindless : protected OpenGl_GlFunctions +{ +#if !defined(GL_ES_VERSION_2_0) + using OpenGl_GlFunctions::glGetTextureHandleARB; + using OpenGl_GlFunctions::glGetTextureSamplerHandleARB; + using OpenGl_GlFunctions::glMakeTextureHandleResidentARB; + using OpenGl_GlFunctions::glMakeTextureHandleNonResidentARB; + using OpenGl_GlFunctions::glGetImageHandleARB; + using OpenGl_GlFunctions::glMakeImageHandleResidentARB; + using OpenGl_GlFunctions::glMakeImageHandleNonResidentARB; + using OpenGl_GlFunctions::glUniformHandleui64ARB; + using OpenGl_GlFunctions::glUniformHandleui64vARB; + using OpenGl_GlFunctions::glProgramUniformHandleui64ARB; + using OpenGl_GlFunctions::glProgramUniformHandleui64vARB; + using OpenGl_GlFunctions::glIsTextureHandleResidentARB; + using OpenGl_GlFunctions::glIsImageHandleResidentARB; + using OpenGl_GlFunctions::glVertexAttribL1ui64ARB; + using OpenGl_GlFunctions::glVertexAttribL1ui64vARB; + using OpenGl_GlFunctions::glGetVertexAttribLui64vARB; +#endif +}; + +#endif // _OpenGl_ArbTexBindless_H__ diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 02e402a317..c9602a7707 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include #include #include @@ -79,6 +81,8 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) core20fwd (NULL), core32 (NULL), core32back (NULL), + core33 (NULL), + core33back (NULL), core41 (NULL), core41back (NULL), core42 (NULL), @@ -95,8 +99,11 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) hasHighp (Standard_True), hasTexRGBA8(Standard_True), #endif - arbNPTW(Standard_False), + arbNPTW (Standard_False), + arbTexRG (Standard_False), + arbTexBindless (NULL), arbTBO (NULL), + arbTboRGB32 (Standard_False), arbIns (NULL), arbDbg (NULL), arbFBO (NULL), @@ -170,6 +177,12 @@ OpenGl_Context::~OpenGl_Context() mySharedResources.Nullify(); myDelayed.Nullify(); + // release sampler object + if (!myTexSampler.IsNull()) + { + myTexSampler->Release (this); + } + #if !defined(GL_ES_VERSION_2_0) if (arbDbg != NULL && caps->contextDebug @@ -844,6 +857,8 @@ void OpenGl_Context::init() core20fwd = NULL; core32 = NULL; core32back = NULL; + core33 = NULL; + core33back = NULL; core41 = NULL; core41back = NULL; core42 = NULL; @@ -853,6 +868,7 @@ void OpenGl_Context::init() core44 = NULL; core44back = NULL; arbTBO = NULL; + arbTboRGB32 = Standard_False; arbIns = NULL; arbDbg = NULL; arbFBO = NULL; @@ -1723,6 +1739,7 @@ void OpenGl_Context::init() { arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs)); } + arbTboRGB32 = CheckExtension ("GL_ARB_texture_buffer_object_rgb32"); // initialize hardware instancing extension (ARB) if (!has31 @@ -1747,6 +1764,28 @@ void OpenGl_Context::init() extGS = (OpenGl_ExtGS* )(&(*myFuncs)); } + // initialize bindless texture extension (ARB) + if (CheckExtension ("GL_ARB_bindless_texture") + && FindProcShort (glGetTextureHandleARB) + && FindProcShort (glGetTextureSamplerHandleARB) + && FindProcShort (glMakeTextureHandleResidentARB) + && FindProcShort (glMakeTextureHandleNonResidentARB) + && FindProcShort (glGetImageHandleARB) + && FindProcShort (glMakeImageHandleResidentARB) + && FindProcShort (glMakeImageHandleNonResidentARB) + && FindProcShort (glUniformHandleui64ARB) + && FindProcShort (glUniformHandleui64vARB) + && FindProcShort (glProgramUniformHandleui64ARB) + && FindProcShort (glProgramUniformHandleui64vARB) + && FindProcShort (glIsTextureHandleResidentARB) + && FindProcShort (glIsImageHandleResidentARB) + && FindProcShort (glVertexAttribL1ui64ARB) + && FindProcShort (glVertexAttribL1ui64vARB) + && FindProcShort (glGetVertexAttribLui64vARB)) + { + arbTexBindless = (OpenGl_ArbTexBindless* )(&(*myFuncs)); + } + if (!has12) { myGlVerMajor = 1; @@ -1822,6 +1861,12 @@ void OpenGl_Context::init() myGlVerMinor = 2; return; } + core33 = (OpenGl_GlCore33* )(&(*myFuncs)); + core33back = (OpenGl_GlCore33Back* )(&(*myFuncs)); + + // initialize sampler object + myTexSampler = new OpenGl_Sampler(); + myTexSampler->Init (*this); if (!has40) { @@ -1829,6 +1874,7 @@ void OpenGl_Context::init() myGlVerMinor = 3; return; } + arbTboRGB32 = Standard_True; // in core since OpenGL 4.0 if (!has41) { diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index c41298ac61..c5140b7566 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ struct OpenGl_ArbIns; struct OpenGl_ArbDbg; struct OpenGl_ArbFBO; struct OpenGl_ExtGS; +struct OpenGl_ArbTexBindless; template struct OpenGl_TmplCore12; typedef OpenGl_TmplCore12 OpenGl_GlCore12; @@ -441,6 +443,12 @@ public: //! @name methods to alter or retrieve current state return myActiveProgram; } + //! @return OpenGL sampler object used to override default texture parameters + const Handle(OpenGl_Sampler)& TextureSampler() + { + return myTexSampler; + } + //! Bind specified program to current context, //! or unbind previous one when NULL specified. //! @return true if some program is bound to context @@ -473,6 +481,8 @@ public: //! @name core profiles OpenGl_GlCore20Fwd* core20fwd; //!< OpenGL 2.0 without deprecated entry points OpenGl_GlCore32* core32; //!< OpenGL 3.2 core profile OpenGl_GlCore32Back* core32back; //!< OpenGL 3.2 backward compatibility profile + OpenGl_GlCore33* core33; //!< OpenGL 3.3 core profile + OpenGl_GlCore33Back* core33back; //!< OpenGL 3.3 backward compatibility profile OpenGl_GlCore41* core41; //!< OpenGL 4.1 core profile OpenGl_GlCore41Back* core41back; //!< OpenGL 4.1 backward compatibility profile OpenGl_GlCore42* core42; //!< OpenGL 4.2 core profile @@ -486,20 +496,22 @@ public: //! @name core profiles public: //! @name extensions - Standard_Boolean hasHighp; //!< highp in GLSL ES fragment shader is supported - Standard_Boolean hasTexRGBA8; //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8 - Standard_Boolean arbNPTW; //!< GL_ARB_texture_non_power_of_two - Standard_Boolean arbTexRG; //!< GL_ARB_texture_rg - OpenGl_ArbTBO* arbTBO; //!< GL_ARB_texture_buffer_object - OpenGl_ArbIns* arbIns; //!< GL_ARB_draw_instanced - OpenGl_ArbDbg* arbDbg; //!< GL_ARB_debug_output - OpenGl_ArbFBO* arbFBO; //!< GL_ARB_framebuffer_object - OpenGl_ExtGS* extGS; //!< GL_EXT_geometry_shader4 - Standard_Boolean extBgra; //!< GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 on OpenGL ES - Standard_Boolean extAnis; //!< GL_EXT_texture_filter_anisotropic - Standard_Boolean extPDS; //!< GL_EXT_packed_depth_stencil - Standard_Boolean atiMem; //!< GL_ATI_meminfo - Standard_Boolean nvxMem; //!< GL_NVX_gpu_memory_info + Standard_Boolean hasHighp; //!< highp in GLSL ES fragment shader is supported + Standard_Boolean hasTexRGBA8; //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8 + Standard_Boolean arbNPTW; //!< GL_ARB_texture_non_power_of_two + Standard_Boolean arbTexRG; //!< GL_ARB_texture_rg + OpenGl_ArbTexBindless* arbTexBindless; //!< GL_ARB_bindless_texture + OpenGl_ArbTBO* arbTBO; //!< GL_ARB_texture_buffer_object + Standard_Boolean arbTboRGB32; //!< GL_ARB_texture_buffer_object_rgb32 (3-component TBO), in core since 4.0 + OpenGl_ArbIns* arbIns; //!< GL_ARB_draw_instanced + OpenGl_ArbDbg* arbDbg; //!< GL_ARB_debug_output + OpenGl_ArbFBO* arbFBO; //!< GL_ARB_framebuffer_object + OpenGl_ExtGS* extGS; //!< GL_EXT_geometry_shader4 + Standard_Boolean extBgra; //!< GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 on OpenGL ES + Standard_Boolean extAnis; //!< GL_EXT_texture_filter_anisotropic + Standard_Boolean extPDS; //!< GL_EXT_packed_depth_stencil + Standard_Boolean atiMem; //!< GL_ATI_meminfo + Standard_Boolean nvxMem; //!< GL_NVX_gpu_memory_info private: // system-dependent fields @@ -553,6 +565,7 @@ private: // context info private: //! @name fields tracking current state Handle(OpenGl_ShaderProgram) myActiveProgram; //!< currently active GLSL program + Handle(OpenGl_Sampler) myTexSampler; //!< currently active sampler object Standard_Integer myRenderMode; //!< value for active rendering mode Standard_Integer myDrawBuffer; //!< current draw buffer diff --git a/src/OpenGl/OpenGl_GlFunctions.hxx b/src/OpenGl/OpenGl_GlFunctions.hxx index 080c3e0d59..60e986646e 100644 --- a/src/OpenGl/OpenGl_GlFunctions.hxx +++ b/src/OpenGl/OpenGl_GlFunctions.hxx @@ -46,6 +46,7 @@ typedef double GLdouble; typedef double GLclampd; + typedef uint64_t GLuint64; #define GL_NONE 0 // OpenGL ES 3.0+ or GL_OES_element_index_uint extension @@ -1384,6 +1385,25 @@ public: //! @name GL_EXT_geometry_shader4 PFNGLPROGRAMPARAMETERIEXTPROC glProgramParameteriEXT; +public: //! @name GL_ARB_bindless_texture + + PFNGLGETTEXTUREHANDLEARBPROC glGetTextureHandleARB; + PFNGLGETTEXTURESAMPLERHANDLEARBPROC glGetTextureSamplerHandleARB; + PFNGLMAKETEXTUREHANDLERESIDENTARBPROC glMakeTextureHandleResidentARB; + PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC glMakeTextureHandleNonResidentARB; + PFNGLGETIMAGEHANDLEARBPROC glGetImageHandleARB; + PFNGLMAKEIMAGEHANDLERESIDENTARBPROC glMakeImageHandleResidentARB; + PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC glMakeImageHandleNonResidentARB; + PFNGLUNIFORMHANDLEUI64ARBPROC glUniformHandleui64ARB; + PFNGLUNIFORMHANDLEUI64VARBPROC glUniformHandleui64vARB; + PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC glProgramUniformHandleui64ARB; + PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC glProgramUniformHandleui64vARB; + PFNGLISTEXTUREHANDLERESIDENTARBPROC glIsTextureHandleResidentARB; + PFNGLISIMAGEHANDLERESIDENTARBPROC glIsImageHandleResidentARB; + PFNGLVERTEXATTRIBL1UI64ARBPROC glVertexAttribL1ui64ARB; + PFNGLVERTEXATTRIBL1UI64VARBPROC glVertexAttribL1ui64vARB; + PFNGLGETVERTEXATTRIBLUI64VARBPROC glGetVertexAttribLui64vARB; + #if defined(_WIN32) public: //! @name wgl extensions diff --git a/src/OpenGl/OpenGl_Sampler.cxx b/src/OpenGl/OpenGl_Sampler.cxx new file mode 100644 index 0000000000..0196a39ae1 --- /dev/null +++ b/src/OpenGl/OpenGl_Sampler.cxx @@ -0,0 +1,133 @@ +// Created on: 2014-10-08 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2014 OPEN CASCADE SAS +// +// 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 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. + +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE (OpenGl_Sampler, OpenGl_Resource) +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Sampler, OpenGl_Resource) + +// ======================================================================= +// function : OpenGl_Sampler +// purpose : +// ======================================================================= +OpenGl_Sampler::OpenGl_Sampler() +: mySamplerID (NO_SAMPLER) +{ + // +} + +// ======================================================================= +// function : ~OpenGl_Sampler +// purpose : +// ======================================================================= +OpenGl_Sampler::~OpenGl_Sampler() +{ + Release (NULL); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void OpenGl_Sampler::Release (OpenGl_Context* theContext) +{ + if (isValidSampler()) + { + // application can not handle this case by exception - this is bug in code + Standard_ASSERT_RETURN (theContext != NULL, + "OpenGl_Sampler destroyed without GL context! Possible GPU memory leakage...",); + + if (theContext->IsValid()) + { + #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) + theContext->core33->glDeleteSamplers (1, &mySamplerID); + #endif + } + + mySamplerID = NO_SAMPLER; + } +} + +// ======================================================================= +// function : Init +// purpose : Initializes sampler object +// ======================================================================= +Standard_Boolean OpenGl_Sampler::Init (OpenGl_Context& theContext) +{ + if (theContext.core33 == NULL) + { + return Standard_False; + } + + if (isValidSampler()) + { + Release (&theContext); + } + +#if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) + theContext.core33->glGenSamplers (1, &mySamplerID); + return Standard_True; +#else + return Standard_False; +#endif +} + +// ======================================================================= +// function : Bind +// purpose : Binds sampler object to the given texture unit +// ======================================================================= +void OpenGl_Sampler::Bind (OpenGl_Context& theContext, + const GLuint theUnit) +{ + if (isValidSampler()) + { + #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) + theContext.core33->glBindSampler (theUnit, mySamplerID); + #endif + } +} + +// ======================================================================= +// function : Unbind +// purpose : Unbinds sampler object from the given texture unit +// ======================================================================= +void OpenGl_Sampler::Unbind (OpenGl_Context& theContext, + const GLuint theUnit) +{ + if (isValidSampler()) + { + #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) + theContext.core33->glBindSampler (theUnit, NO_SAMPLER); + #endif + } +} + +// ======================================================================= +// function : SetParameter +// purpose : Sets sampler parameters +// ======================================================================= +void OpenGl_Sampler::SetParameter (OpenGl_Context& theContext, + const GLenum theParam, + const GLint theValue) +{ + if (isValidSampler()) + { + #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) + theContext.core33->glSamplerParameteri (mySamplerID, theParam, theValue); + #endif + } +} diff --git a/src/OpenGl/OpenGl_Sampler.hxx b/src/OpenGl/OpenGl_Sampler.hxx new file mode 100644 index 0000000000..dda1e3a7b8 --- /dev/null +++ b/src/OpenGl/OpenGl_Sampler.hxx @@ -0,0 +1,84 @@ +// Created on: 2014-10-08 +// Created by: Denis BOGOLEPOV +// Copyright (c) 2014 OPEN CASCADE SAS +// +// 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 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. + +#ifndef OPENGL_SAMPLER_H +#define OPENGL_SAMPLER_H + +#include +#include + +//! Class implements OpenGL sampler object resource that +//! stores the sampling parameters for a texture access. +class OpenGl_Sampler : public OpenGl_Resource +{ +public: + + //! Helpful constant defining invalid sampler identifier + static const GLuint NO_SAMPLER = 0; + +public: + + //! Creates new sampler object. + Standard_EXPORT OpenGl_Sampler(); + + //! Releases resources of sampler object. + Standard_EXPORT virtual ~OpenGl_Sampler(); + + //! Destroys object - will release GPU memory if any. + Standard_EXPORT virtual void Release (OpenGl_Context* theContext); + + //! Initializes sampler object. + Standard_EXPORT Standard_Boolean Init (OpenGl_Context& theContext); + + //! Returns true if current object was initialized. + Standard_Boolean IsValid() const + { + return isValidSampler(); + } + + //! Binds sampler object to the given texture unit. + Standard_EXPORT void Bind (OpenGl_Context& theContext, const GLuint theUnit = 0); + + //! Unbinds sampler object from the given texture unit. + Standard_EXPORT void Unbind (OpenGl_Context& theContext, const GLuint theUnit = 0); + + //! Sets specific sampler parameter. + Standard_EXPORT void SetParameter (OpenGl_Context& theContext, const GLenum theParam, const GLint theValue); + + //! Returns OpenGL sampler ID. + GLuint SamplerID() const + { + return mySamplerID; + } + +protected: + + //! Checks if sampler object is valid. + Standard_Boolean isValidSampler() const + { + return mySamplerID != NO_SAMPLER; + } + +protected: + + GLuint mySamplerID; //!< OpenGL sampler object ID + +public: + + DEFINE_STANDARD_RTTI(OpenGl_Sampler) + +}; + +#endif // OPENGL_SAMPLER_H diff --git a/src/OpenGl/OpenGl_SceneGeometry.cxx b/src/OpenGl/OpenGl_SceneGeometry.cxx index 0dcbb8a8fc..c618c299d9 100755 --- a/src/OpenGl/OpenGl_SceneGeometry.cxx +++ b/src/OpenGl/OpenGl_SceneGeometry.cxx @@ -13,8 +13,6 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#include - #ifdef HAVE_TBB // On Windows, function TryEnterCriticalSection has appeared in Windows NT // and is surrounded by #ifdef in MS VC++ 7.1 headers. @@ -29,21 +27,20 @@ #include +#include #include #include +#include +#include //! Use this macro to output BVH profiling info -//#define BVH_PRINT_INFO - -#ifdef BVH_PRINT_INFO - #include -#endif +// #define RAY_TRACE_PRINT_INFO namespace { //! Useful constant for null floating-point 4D vector. static const BVH_Vec4f ZERO_VEC_4F; -}; +} // ======================================================================= // function : OpenGl_RaytraceMaterial @@ -131,13 +128,51 @@ OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse, // } +// ======================================================================= +// function : Box +// purpose : Returns AABB of primitive set +// ======================================================================= +OpenGl_TriangleSet::BVH_BoxNt OpenGl_TriangleSet::Box() const +{ + const BVH_Transform* aTransform = + dynamic_cast* > (Properties().operator->()); + + BVH_BoxNt aBox = BVH_PrimitiveSet::Box(); + + if (aTransform != NULL) + { + BVH_BoxNt aTransformedBox; + + for (Standard_Integer aX = 0; aX <= 1; ++aX) + { + for (Standard_Integer aY = 0; aY <= 1; ++aY) + { + for (Standard_Integer aZ = 0; aZ <= 1; ++aZ) + { + BVH_Vec4f aCorner = aTransform->Transform() * BVH_Vec4f ( + aX == 0 ? aBox.CornerMin().x() : aBox.CornerMax().x(), + aY == 0 ? aBox.CornerMin().y() : aBox.CornerMax().y(), + aZ == 0 ? aBox.CornerMin().z() : aBox.CornerMax().z(), + 1.f); + + aTransformedBox.Add (reinterpret_cast (aCorner)); + } + } + } + + return aTransformedBox; + } + + return aBox; +} + // ======================================================================= // function : Clear // purpose : Clears ray-tracing geometry // ======================================================================= void OpenGl_RaytraceGeometry::Clear() { - BVH_Geometry::BVH_Geometry::Clear(); + BVH_Geometry::BVH_Geometry::Clear(); std::vector > anEmptySources; @@ -154,9 +189,9 @@ void OpenGl_RaytraceGeometry::Clear() struct OpenGL_BVHParallelBuilder { - BVH_ObjectSet* Set; + BVH_ObjectSet* Set; - OpenGL_BVHParallelBuilder (BVH_ObjectSet* theSet) + OpenGL_BVHParallelBuilder (BVH_ObjectSet* theSet) : Set (theSet) { // @@ -185,13 +220,13 @@ struct OpenGL_BVHParallelBuilder // ======================================================================= Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration() { -#ifdef BVH_PRINT_INFO +#ifdef RAY_TRACE_PRINT_INFO OSD_Timer aTimer; #endif MarkDirty(); // force BVH rebuilding -#ifdef BVH_PRINT_INFO +#ifdef RAY_TRACE_PRINT_INFO aTimer.Reset(); aTimer.Start(); #endif @@ -219,21 +254,21 @@ Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration() myBottomLevelTreeDepth = Max (myBottomLevelTreeDepth, aTriangleSet->BVH()->Depth()); } -#ifdef BVH_PRINT_INFO +#ifdef RAY_TRACE_PRINT_INFO aTimer.Stop(); std::cout << "Updating bottom-level BVHs (sec): " << aTimer.ElapsedTime() << std::endl; #endif -#ifdef BVH_PRINT_INFO +#ifdef RAY_TRACE_PRINT_INFO aTimer.Reset(); aTimer.Start(); #endif - NCollection_Handle > aBVH = BVH(); + NCollection_Handle > aBVH = BVH(); -#ifdef BVH_PRINT_INFO +#ifdef RAY_TRACE_PRINT_INFO aTimer.Stop(); std::cout << "Updating high-level BVH (sec): " << @@ -285,7 +320,7 @@ Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration() // ======================================================================= Standard_Integer OpenGl_RaytraceGeometry::AccelerationOffset (Standard_Integer theNodeIdx) { - const NCollection_Handle >& aBVH = BVH(); + const NCollection_Handle >& aBVH = BVH(); if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) return INVALID_OFFSET; @@ -299,7 +334,7 @@ Standard_Integer OpenGl_RaytraceGeometry::AccelerationOffset (Standard_Integer t // ======================================================================= Standard_Integer OpenGl_RaytraceGeometry::VerticesOffset (Standard_Integer theNodeIdx) { - const NCollection_Handle >& aBVH = BVH(); + const NCollection_Handle >& aBVH = BVH(); if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) return INVALID_OFFSET; @@ -313,7 +348,7 @@ Standard_Integer OpenGl_RaytraceGeometry::VerticesOffset (Standard_Integer theNo // ======================================================================= Standard_Integer OpenGl_RaytraceGeometry::ElementsOffset (Standard_Integer theNodeIdx) { - const NCollection_Handle >& aBVH = BVH(); + const NCollection_Handle >& aBVH = BVH(); if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) return INVALID_OFFSET; @@ -327,7 +362,7 @@ Standard_Integer OpenGl_RaytraceGeometry::ElementsOffset (Standard_Integer theNo // ======================================================================= OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNodeIdx) { - const NCollection_Handle >& aBVH = BVH(); + const NCollection_Handle >& aBVH = BVH(); if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) return NULL; @@ -339,6 +374,120 @@ OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNo aBVH->NodeInfoBuffer().at (theNodeIdx).x() - 1).operator->()); } +// ======================================================================= +// function : AcquireTextures +// purpose : Makes the OpenGL texture handles resident +// ======================================================================= +Standard_Boolean OpenGl_RaytraceGeometry::AcquireTextures (const Handle(OpenGl_Context)& theContext) const +{ + if (theContext->arbTexBindless == NULL) + { + return Standard_True; + } + +#if !defined(GL_ES_VERSION_2_0) + for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx) + { + theContext->arbTexBindless->glMakeTextureHandleResidentARB (myTextureHandles[anIdx]); + + if (glGetError() != GL_NO_ERROR) + { +#ifdef RAY_TRACE_PRINT_INFO + std::cout << "Error: Failed to make OpenGL texture resident" << std::endl; +#endif + return Standard_False; + } + } +#endif + + return Standard_True; +} + +// ======================================================================= +// function : ReleaseTextures +// purpose : Makes the OpenGL texture handles non-resident +// ======================================================================= +Standard_Boolean OpenGl_RaytraceGeometry::ReleaseTextures (const Handle(OpenGl_Context)& theContext) const +{ + if (theContext->arbTexBindless == NULL) + { + return Standard_True; + } + +#if !defined(GL_ES_VERSION_2_0) + for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx) + { + theContext->arbTexBindless->glMakeTextureHandleNonResidentARB (myTextureHandles[anIdx]); + + if (glGetError() != GL_NO_ERROR) + { +#ifdef RAY_TRACE_PRINT_INFO + std::cout << "Error: Failed to make OpenGL texture non-resident" << std::endl; +#endif + return Standard_False; + } + } +#endif + + return Standard_True; +} + +// ======================================================================= +// function : AddTexture +// purpose : Adds new OpenGL texture to the scene and returns its index +// ======================================================================= +Standard_Integer OpenGl_RaytraceGeometry::AddTexture (const Handle(OpenGl_Texture)& theTexture) +{ + NCollection_Vector::iterator anIter = + std::find (myTextures.begin(), myTextures.end(), theTexture); + + if (anIter == myTextures.end()) + { + if (myTextures.Size() >= MAX_TEX_NUMBER) + { + return -1; + } + + myTextures.Append (theTexture); + } + + return static_cast (anIter - myTextures.begin()); +} + +// ======================================================================= +// function : UpdateTextureHandles +// purpose : Updates unique 64-bit texture handles to use in shaders +// ======================================================================= +Standard_Boolean OpenGl_RaytraceGeometry::UpdateTextureHandles (const Handle(OpenGl_Context)& theContext) +{ + if (theContext->arbTexBindless == NULL) + { + return Standard_False; + } + + myTextureHandles.clear(); + +#if !defined(GL_ES_VERSION_2_0) + for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx) + { + const GLuint64 aHandle = theContext->arbTexBindless->glGetTextureHandleARB ( + myTextures.Value (anIdx)->TextureId()); + + if (glGetError() != GL_NO_ERROR) + { +#ifdef RAY_TRACE_PRINT_INFO + std::cout << "Error: Failed to get 64-bit handle of OpenGL texture" << std::endl; +#endif + return Standard_False; + } + + myTextureHandles.push_back (aHandle); + } +#endif + + return Standard_True; +} + namespace OpenGl_Raytrace { // ======================================================================= @@ -347,7 +496,7 @@ namespace OpenGl_Raytrace // ======================================================================= Standard_Boolean IsRaytracedElement (const OpenGl_ElementNode* theNode) { - OpenGl_PrimitiveArray* anArray = dynamic_cast< OpenGl_PrimitiveArray* > (theNode->elem); + OpenGl_PrimitiveArray* anArray = dynamic_cast (theNode->elem); return anArray != NULL && anArray->DrawMode() >= GL_TRIANGLES; } diff --git a/src/OpenGl/OpenGl_SceneGeometry.hxx b/src/OpenGl/OpenGl_SceneGeometry.hxx index 97390a706b..241e681e67 100755 --- a/src/OpenGl/OpenGl_SceneGeometry.hxx +++ b/src/OpenGl/OpenGl_SceneGeometry.hxx @@ -19,6 +19,8 @@ #include #include #include +#include +#include class OpenGl_Element; struct OpenGl_ElementNode; @@ -67,6 +69,9 @@ public: //! Material transparency. BVH_Vec4f Transparency; + //! Texture transformation matrix. + BVH_Mat4f TextureTransform; + public: //! Creates new default material. @@ -125,7 +130,7 @@ public: }; //! Triangulation of single OpenGL primitive array. -class OpenGl_TriangleSet : public BVH_Triangulation +class OpenGl_TriangleSet : public BVH_Triangulation { public: @@ -136,11 +141,11 @@ public: //! Creates new OpenGL element triangulation. OpenGl_TriangleSet (const Standard_Size theArrayID) - : BVH_Triangulation(), + : BVH_Triangulation (), myArrayID (theArrayID) - { - // - } + { + // + } //! Releases resources of OpenGL element triangulation. ~OpenGl_TriangleSet() @@ -158,38 +163,31 @@ public: Standard_Integer MaterialIndex() const { if (Elements.size() == 0) + { return INVALID_MATERIAL; + } return Elements.front().w(); } //! Sets material index for entire triangle set. - void SetMaterialIndex (Standard_Integer aMatID) + void SetMaterialIndex (Standard_Integer theMatID) { for (Standard_Size anIdx = 0; anIdx < Elements.size(); ++anIdx) - Elements[anIdx].w() = aMatID; - } - - //! Returns AABB of primitive set. - BVH_BoxNt Box() const - { - const BVH_Transform* aTransform = - dynamic_cast* > (Properties().operator->()); - - BVH_BoxNt aBox = BVH_PrimitiveSet::Box(); - - if (aTransform) { - return aTransform->Apply (aBox); + Elements[anIdx].w() = theMatID; } - - return aBox; } + //! Returns AABB of primitive set. + BVH_BoxNt Box() const; + public: - BVH_Array4f Normals; //!< Array of vertex normals. - + BVH_Array3f Normals; //!< Array of vertex normals. + + BVH_Array2f TexCrds; //!< Array of vertex UV coords. + private: Standard_Size myArrayID; //!< Id of associated primitive array. @@ -197,13 +195,19 @@ private: }; //! Stores geometry of ray-tracing scene. -class OpenGl_RaytraceGeometry : public BVH_Geometry +class OpenGl_RaytraceGeometry : public BVH_Geometry { public: //! Value of invalid offset to return in case of errors. static const Standard_Integer INVALID_OFFSET = -1; + //! Maximum number of textures used in ray-tracing shaders. + //! This is not restriction of the solution implemented, but + //! rather the reasonable limit of the number of textures in + //! various applications (can be increased if needed). + static const Standard_Integer MAX_TEX_NUMBER = 32; + public: //! Array of properties of light sources. @@ -221,7 +225,7 @@ public: //! Creates uninitialized ray-tracing geometry. OpenGl_RaytraceGeometry() - : BVH_Geometry(), + : BVH_Geometry(), myHighLevelTreeDepth (0), myBottomLevelTreeDepth (0) { @@ -234,19 +238,21 @@ public: // } - //! Clears ray-tracing geometry. - void Clear(); - //! Clears only ray-tracing materials. void ClearMaterials() { std::vector > anEmptyMaterials; - + Materials.swap (anEmptyMaterials); + + myTextures.Clear(); } -public: + //! Clears ray-tracing geometry. + void Clear(); + +public: //! @name methods related to acceleration structure //! Performs post-processing of high-level scene BVH. Standard_Boolean ProcessAcceleration(); @@ -271,6 +277,34 @@ public: //! @note Can be used after processing acceleration structure. OpenGl_TriangleSet* TriangleSet (Standard_Integer theNodeIdx); +public: //! @name methods related to texture management + + //! Adds new OpenGL texture to the scene and returns its index. + Standard_Integer AddTexture (const Handle(OpenGl_Texture)& theTexture); + + //! Updates unique 64-bit texture handles to use in shaders. + Standard_Boolean UpdateTextureHandles (const Handle(OpenGl_Context)& theContext); + + //! Makes the OpenGL texture handles resident (must be called before using). + Standard_Boolean AcquireTextures (const Handle(OpenGl_Context)& theContext) const; + + //! Makes the OpenGL texture handles non-resident (must be called after using). + Standard_Boolean ReleaseTextures (const Handle(OpenGl_Context)& theContext) const; + + //! Returns array of texture handles. + const std::vector& TextureHandles() const + { + return myTextureHandles; + } + + //! Checks if scene contains textured objects. + Standard_Integer HasTextures() const + { + return !myTextures.IsEmpty(); + } + +public: //! @name auxiliary methods + //! Returns depth of high-level scene BVH from last build. Standard_Integer HighLevelTreeDepth() const { @@ -285,8 +319,10 @@ public: protected: - Standard_Integer myHighLevelTreeDepth; //!< Depth of high-level scene BVH from last build - Standard_Integer myBottomLevelTreeDepth; //!< Maximum depth of bottom-level scene BVHs from last build + NCollection_Vector myTextures; //!< Array of texture maps shared between rendered objects + std::vector myTextureHandles; //!< Array of unique 64-bit texture handles obtained from OpenGL + Standard_Integer myHighLevelTreeDepth; //!< Depth of high-level scene BVH from last build + Standard_Integer myBottomLevelTreeDepth; //!< Maximum depth of bottom-level scene BVHs from last build }; diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index a0e027eabf..61cfaee97b 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -24,6 +24,7 @@ #include #include #include +#include IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource) IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource) @@ -784,6 +785,70 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& return Standard_True; } +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the 64-bit unsigned uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + GLuint64 theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the 64-bit unsigned uniform variable +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint64 theValue) +{ + if (theCtx->arbTexBindless == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + +#if !defined(GL_ES_VERSION_2_0) + theCtx->arbTexBindless->glUniformHandleui64ARB (theLocation, theValue); +#endif + + return Standard_True; +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the 64-bit unsigned uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const GLsizei theCount, + const GLuint64* theValue) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the 64-bit unsigned uniform array +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const GLsizei theCount, + const GLuint64* theValue) +{ + if (theCtx->arbTexBindless == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + +#if !defined(GL_ES_VERSION_2_0) + theCtx->arbTexBindless->glUniformHandleui64vARB (theLocation, theCount, theValue); +#endif + + return Standard_True; +} + // ======================================================================= // function : SetUniform // purpose : Specifies the value of the floating-point uniform variable @@ -980,6 +1045,36 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& return Standard_True; } +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4x4 matrix +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Mat4& theValue, + GLboolean theTranspose) +{ + return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose); +} + +// ======================================================================= +// function : SetUniform +// purpose : Specifies the value of the floating-point uniform 4x4 matrix +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Mat4& theValue, + GLboolean theTranspose) +{ + if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION) + { + return Standard_False; + } + + theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, theValue); + return Standard_True; +} + // ======================================================================= // function : SetUniform // purpose : Specifies the value of the floating-point uniform 4x4 matrix diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index c65124c1ac..b26cabbb9d 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -350,6 +350,30 @@ public: GLint theLocation, const OpenGl_Vec4i& theValue); +public: + + //! Specifies the value of the 64-bit unsigned integer uniform variable. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + GLuint64 theValue); + + //! Specifies the value of the 64-bit unsigned integer uniform variable. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + GLuint64 theValue); + + //! Specifies the value of the 64-bit unsigned integer uniform array. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const GLsizei theCount, + const GLuint64* theValue); + + //! Specifies the value of the 64-bit unsigned integer uniform array. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const GLsizei theCount, + const GLuint64* theValue); + public: //! Specifies the value of the float uniform variable. @@ -394,6 +418,18 @@ public: public: + //! Specifies the value of the float uniform 4x4 matrix. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + const GLchar* theName, + const OpenGl_Mat4& theValue, + GLboolean theTranspose = GL_FALSE); + + //! Specifies the value of the float uniform 4x4 matrix. + Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, + GLint theLocation, + const OpenGl_Mat4& theValue, + GLboolean theTranspose = GL_FALSE); + //! Specifies the value of the float uniform 4x4 matrix. Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, const GLchar* theName, diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index d991609fce..d4db2cec36 100755 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -377,10 +378,14 @@ void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx, // ======================================================================= void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const { - const OpenGl_AspectText* aTextAspect = theWorkspace->AspectText (Standard_True); - const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture(); - - const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); + const OpenGl_AspectText* aTextAspect = theWorkspace->AspectText (Standard_True); + const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture(); + const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); + const Handle(OpenGl_Sampler)& aSampler = aCtx->TextureSampler(); + if (!aSampler.IsNull()) + { + aSampler->Unbind (*aCtx); + } if (aCtx->IsGlGreaterEqual (2, 0)) { @@ -418,6 +423,10 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const } // restore aspects + if (!aSampler.IsNull()) + { + aSampler->Bind (*aCtx); + } if (!aPrevTexture.IsNull()) { theWorkspace->EnableTexture (aPrevTexture); @@ -722,6 +731,13 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx, theCtx->core15fwd->glActiveTexture (GL_TEXTURE0); } + // unbind current OpenGL sampler + const Handle(OpenGl_Sampler)& aSampler = theCtx->TextureSampler(); + if (!aSampler.IsNull() && aSampler->IsValid()) + { + aSampler->Unbind (*theCtx); + } + // extra drawings switch (theTextAspect.DisplayType()) { @@ -808,5 +824,11 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx, // revert OpenGL state glPopAttrib(); // enable bit glPopMatrix(); // model view matrix was modified + + // revert custom OpenGL sampler + if (!aSampler.IsNull() && aSampler->IsValid()) + { + aSampler->Bind (*theCtx); + } #endif } diff --git a/src/OpenGl/OpenGl_TextureBufferArb.cxx b/src/OpenGl/OpenGl_TextureBufferArb.cxx index f1d5aca292..af41da174f 100644 --- a/src/OpenGl/OpenGl_TextureBufferArb.cxx +++ b/src/OpenGl/OpenGl_TextureBufferArb.cxx @@ -99,13 +99,17 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx, const GLfloat* theData) { #if !defined(GL_ES_VERSION_2_0) - if (theComponentsNb != 1 - && theComponentsNb != 2 - && theComponentsNb != 4) + if (theComponentsNb < 1 + || theComponentsNb > 4) { // unsupported format return false; } + else if (theComponentsNb == 3 + && !theGlCtx->arbTboRGB32) + { + return false; + } else if (!Create (theGlCtx) || !OpenGl_VertexBuffer::Init (theGlCtx, theComponentsNb, theElemsNb, theData)) { @@ -116,7 +120,7 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx, { case 1: myTexFormat = GL_R32F; break; case 2: myTexFormat = GL_RG32F; break; - //case 3: myTexFormat = GL_RGB32F; break; // GL_ARB_texture_buffer_object_rgb32 + case 3: myTexFormat = GL_RGB32F; break; // GL_ARB_texture_buffer_object_rgb32 case 4: myTexFormat = GL_RGBA32F; break; } @@ -141,14 +145,17 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx, const GLuint* theData) { #if !defined(GL_ES_VERSION_2_0) - if (theComponentsNb != 1 - && theComponentsNb != 2 - && theComponentsNb != 3 - && theComponentsNb != 4) + if (theComponentsNb < 1 + || theComponentsNb > 4) { // unsupported format return false; } + else if (theComponentsNb == 3 + && !theGlCtx->arbTboRGB32) + { + return false; + } else if (!Create (theGlCtx) || !OpenGl_VertexBuffer::Init (theGlCtx, theComponentsNb, theElemsNb, theData)) { diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 56725e93b6..8762c5b54d 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -438,19 +438,10 @@ const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const H /*----------------------------------------------------------------------*/ -void OpenGl_View::GetMatrices (TColStd_Array2OfReal& theMatOrient, - TColStd_Array2OfReal& theMatMapping) const +void OpenGl_View::GetMatrices (OpenGl_Mat4& theOrientation, + OpenGl_Mat4& theViewMapping) const { - const Graphic3d_Mat4d& aProj = myCamera->ProjectionMatrix(); - const Graphic3d_Mat4d& aOrient = myCamera->OrientationMatrix(); - - for (Standard_Integer aRow = 0; aRow < 4; ++aRow) - { - for (Standard_Integer aCol = 0; aCol < 4; ++aCol) - { - theMatOrient (aRow, aCol) = aOrient.GetValue (aRow, aCol); - theMatMapping (aRow, aCol) = aProj .GetValue (aRow, aCol); - } - } + theViewMapping = myCamera->ProjectionMatrixF(); + theOrientation = myCamera->OrientationMatrixF(); } /*----------------------------------------------------------------------*/ diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index bbb90ca43e..35c0eef6bb 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -204,8 +204,9 @@ class OpenGl_View : public MMgt_TShared //! marks primitive set for rebuild. void InvalidateBVHData (const Standard_Integer theLayerId); - void GetMatrices (TColStd_Array2OfReal& theMatOrient, - TColStd_Array2OfReal& theMatMapping) const; + //! Returns view-mapping and orientation matrices. + void GetMatrices (OpenGl_Mat4& theOrientation, + OpenGl_Mat4& theViewMapping) const; //! Returns list of immediate structures rendered on top of main presentation const OpenGl_SequenceOfStructure& ImmediateStructures() const diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index 67799e2289..bf715d8790 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -144,6 +145,7 @@ OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDrive // myComputeInitStatus (OpenGl_RT_NONE), myIsRaytraceDataValid (Standard_False), + myIsRaytraceWarnTextures (Standard_False), myViewModificationStatus (0), myLayersModificationStatus (0), // @@ -435,6 +437,9 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& } #endif + // get active sampler object to override default texture parameters + const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); + // setup texture filtering and wrapping //if (theTexture->GetParams() != theParams) const GLenum aFilter = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR; @@ -444,9 +449,19 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& #if !defined(GL_ES_VERSION_2_0) case GL_TEXTURE_1D: { - glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter); - glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter); - glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode); + if (aSampler.IsNull() || !aSampler->IsValid()) + { + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter); + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter); + glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode); + } + else + { + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); + } + break; } #endif @@ -469,37 +484,58 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& { // setup degree of anisotropy filter const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy(); + GLint aDegree; switch (aParams->AnisoFilter()) { case Graphic3d_LOTA_QUALITY: { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aMaxDegree); + aDegree = aMaxDegree; break; } case Graphic3d_LOTA_MIDDLE: { - - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2)); + aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2); break; } case Graphic3d_LOTA_FAST: { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2); + aDegree = 2; break; } case Graphic3d_LOTA_OFF: default: { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + aDegree = 1; break; } } + + if (aSampler.IsNull() || !aSampler->IsValid()) + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); + } + else + { + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); + } } } - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode); + + if (aSampler.IsNull() || !aSampler->IsValid()) + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode); + } + else + { + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); + aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T, aWrapMode); + } + break; } default: break; @@ -563,6 +599,15 @@ Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Text myTextureBound->Bind (myGlContext); setTextureParams (myTextureBound, theParams); + // If custom sampler object is available it will be + // used for overriding default texture parameters + const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); + + if (!aSampler.IsNull() && aSampler->IsValid()) + { + aSampler->Bind (*myGlContext); + } + return aPrevTexture; } diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index c43f1deadf..805d577e09 100644 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -95,7 +95,7 @@ struct OpenGl_Material DEFINE_STANDARD_HANDLE (OpenGl_RaytraceFilter, OpenGl_RenderFilter) -//! Graphical raytracing filter. +//! Graphical ray-tracing filter. //! Filters out all raytracable structures. class OpenGl_RaytraceFilter : public OpenGl_RenderFilter { @@ -307,29 +307,26 @@ protected: OpenGl_RT_uOriginLB, OpenGl_RT_uOriginRT, OpenGl_RT_uOriginRB, - OpenGl_RT_uDirectLT, OpenGl_RT_uDirectLB, OpenGl_RT_uDirectRT, OpenGl_RT_uDirectRB, - OpenGl_RT_uInvModelProj, - + OpenGl_RT_uUnviewMat, + OpenGl_RT_uSceneRad, OpenGl_RT_uSceneEps, - OpenGl_RT_uLightAmbnt, OpenGl_RT_uLightCount, OpenGl_RT_uShadEnabled, OpenGl_RT_uReflEnabled, - - OpenGl_RT_uInputTexture, + OpenGl_RT_uEnvMapEnable, OpenGl_RT_uOffsetX, OpenGl_RT_uOffsetY, OpenGl_RT_uSamples, - OpenGl_RT_uEnvironmentEnable, + OpenGl_RT_uTextures, OpenGl_RT_NbVariables // special field }; @@ -347,19 +344,20 @@ protected: OpenGl_RT_GeometryVertexTexture = 6, OpenGl_RT_GeometryNormalTexture = 7, - OpenGl_RT_GeometryTriangTexture = 8, + OpenGl_RT_GeometryTexCrdTexture = 8, + OpenGl_RT_GeometryTriangTexture = 9, - OpenGl_RT_EnvironmentMapTexture = 9, + OpenGl_RT_EnvironmentMapTexture = 10, - OpenGl_RT_RaytraceMaterialTexture = 10, - OpenGl_RT_RaytraceLightSrcTexture = 11, + OpenGl_RT_RaytraceMaterialTexture = 11, + OpenGl_RT_RaytraceLightSrcTexture = 12, - OpenGl_RT_FSAAInputTexture = 12, + OpenGl_RT_FSAAInputTexture = 13, - OpenGl_RT_SceneTransformTexture = 13, + OpenGl_RT_SceneTransformTexture = 14, - OpenGl_RT_OpenGlColorTexture = 14, - OpenGl_RT_OpenGlDepthTexture = 15 + OpenGl_RT_OpenGlColorTexture = 15, + OpenGl_RT_OpenGlDepthTexture = 16 }; //! Tool class for management of shader sources. @@ -407,7 +405,7 @@ protected: }; //! Default ray-tracing depth. - static const Standard_Integer THE_DEFAULT_RAY_DEPTH = 3; + static const Standard_Integer THE_DEFAULT_NB_BOUNCES = 3; //! Default size of traversal stack. static const Standard_Integer THE_DEFAULT_STACK_SIZE = 24; @@ -419,7 +417,7 @@ protected: Standard_Integer StackSize; //! Actual ray-tracing depth (number of ray bounces). - Standard_Integer TraceDepth; + Standard_Integer NbBounces; //! Sets light propagation through transparent media. Standard_Boolean TransparentShadows; @@ -427,7 +425,7 @@ protected: //! Creates default compile-time ray-tracing parameters. RaytracingParams() : StackSize (THE_DEFAULT_STACK_SIZE), - TraceDepth (THE_DEFAULT_RAY_DEPTH), + NbBounces (THE_DEFAULT_NB_BOUNCES), TransparentShadows (Standard_False) { // @@ -442,8 +440,11 @@ protected: //! @name methods related to ray-tracing //! Checks to see if the structure is modified. Standard_Boolean CheckRaytraceStructure (const OpenGl_Structure* theStructure); + //! Creates ray-tracing material properties. + Standard_Boolean CreateMaterial (const OpenGl_AspectFace* theAspect, OpenGl_RaytraceMaterial& theMaterial); + //! Updates 3D scene light sources for ray-tracing. - Standard_Boolean UpdateRaytraceLightSources (const GLdouble theInvModelView[16]); + Standard_Boolean UpdateRaytraceLightSources (const OpenGl_Mat4& theInvModelView); //! Updates environment map for ray-tracing. Standard_Boolean UpdateRaytraceEnvironmentMap(); @@ -458,7 +459,7 @@ protected: //! @name methods related to ray-tracing //! Adds OpenGL primitive array to ray-traced scene geometry. OpenGl_TriangleSet* AddRaytracePrimitiveArray ( - const OpenGl_PrimitiveArray* theArray, int theMatID, const Standard_ShortReal* theTrans); + const OpenGl_PrimitiveArray* theArray, int theMatID, const OpenGl_Mat4* theTrans); //! Adds vertex indices from OpenGL primitive array to ray-traced scene geometry. Standard_Boolean AddRaytraceVertexIndices (OpenGl_TriangleSet& theSet, @@ -515,6 +516,9 @@ protected: //! @name methods related to ray-tracing //! Performs safe exit when shaders initialization fails. Standard_Boolean SafeFailBack (const TCollection_ExtendedString& theMessage); + //! Generates shader prefix based on current ray-tracing options. + TCollection_AsciiString GenerateShaderPrefix(); + //! Initializes OpenGL/GLSL shader programs. Standard_Boolean InitRaytraceResources (const Graphic3d_CView& theCView); @@ -529,11 +533,19 @@ protected: //! @name methods related to ray-tracing const Standard_Integer theSizeY); //! Generates viewing rays for corners of screen quad. - void UpdateCamera (const NCollection_Mat4& theOrientation, - const NCollection_Mat4& theViewMapping, - OpenGl_Vec3 theOrigins[4], - OpenGl_Vec3 theDirects[4], - NCollection_Mat4& theInvModelProj); + void UpdateCamera (const OpenGl_Mat4& theOrientation, + const OpenGl_Mat4& theViewMapping, + OpenGl_Vec3 theOrigins[4], + OpenGl_Vec3 theDirects[4], + OpenGl_Mat4& theInvModelProj); + + //! Sets uniform state for the given ray-tracing shader program. + Standard_Boolean SetUniformState (const Graphic3d_CView& theCView, + const OpenGl_Vec3* theOrigins, + const OpenGl_Vec3* theDirects, + const OpenGl_Mat4& theUnviewMat, + const Standard_Integer theProgramIndex, + Handle(OpenGl_ShaderProgram)& theRaytraceProgram); //! Runs ray-tracing shader programs. Standard_Boolean RunRaytraceShaders (const Graphic3d_CView& theCView, @@ -541,7 +553,7 @@ protected: //! @name methods related to ray-tracing const Standard_Integer theSizeY, const OpenGl_Vec3 theOrigins[4], const OpenGl_Vec3 theDirects[4], - const OpenGl_Matrix& theInvModelProj, + const OpenGl_Mat4& theUnviewMat, OpenGl_FrameBuffer* theFrameBuffer); //! Redraws the window using OpenGL/GLSL ray-tracing. @@ -561,6 +573,9 @@ protected: //! @name fields related to ray-tracing //! Is geometry data valid? Standard_Boolean myIsRaytraceDataValid; + //! Warning about missing extension GL_ARB_bindless_texture has been displayed? + Standard_Boolean myIsRaytraceWarnTextures; + //! 3D scene geometry data for ray-tracing. OpenGl_RaytraceGeometry myRaytraceGeometry; @@ -607,9 +622,11 @@ protected: //! @name fields related to ray-tracing Handle(OpenGl_TextureBufferArb) myGeometryVertexTexture; //! Texture buffer of vertex normals. Handle(OpenGl_TextureBufferArb) myGeometryNormalTexture; + //! Texture buffer of vertex UV coords. + Handle(OpenGl_TextureBufferArb) myGeometryTexCrdTexture; //! Texture buffer of triangle indices. Handle(OpenGl_TextureBufferArb) myGeometryTriangTexture; - + //! Texture buffer of material properties. Handle(OpenGl_TextureBufferArb) myRaytraceMaterialTexture; //! Texture buffer of light source properties. @@ -639,10 +656,10 @@ protected: //! @name fields related to ray-tracing //! Cached locations of frequently used uniform variables. Standard_Integer myUniformLocations[2][OpenGl_RT_NbVariables]; - //! Graphical raytracing filter to filter out all raytracable structures. + //! Graphical ray-tracing filter to filter out all raytracable structures. Handle(OpenGl_RaytraceFilter) myRaytraceFilter; - //! Redraw the scene using OpenGL rasterization or raytracing? + //! Redraw the scene using OpenGL rasterization or ray-tracing? Standard_Boolean myToRedrawGL; protected: //! @name protected fields diff --git a/src/OpenGl/OpenGl_Workspace_Raytrace.cxx b/src/OpenGl/OpenGl_Workspace_Raytrace.cxx index 9fc7898620..cd02fc43af 100644 --- a/src/OpenGl/OpenGl_Workspace_Raytrace.cxx +++ b/src/OpenGl/OpenGl_Workspace_Raytrace.cxx @@ -15,16 +15,13 @@ #include -#include -#include +#include #include #include -#include #include #include #include #include -#include using namespace OpenGl_Raytrace; @@ -35,24 +32,6 @@ using namespace OpenGl_Raytrace; #include #endif -// ======================================================================= -// function : MatVecMult -// purpose : Multiples 4x4 matrix by 4D vector -// ======================================================================= -template -BVH_Vec4f MatVecMult (const T m[16], const BVH_Vec4f& v) -{ - return BVH_Vec4f ( - static_cast (m[ 0] * v.x() + m[ 4] * v.y() + - m[ 8] * v.z() + m[12] * v.w()), - static_cast (m[ 1] * v.x() + m[ 5] * v.y() + - m[ 9] * v.z() + m[13] * v.w()), - static_cast (m[ 2] * v.x() + m[ 6] * v.y() + - m[10] * v.z() + m[14] * v.w()), - static_cast (m[ 3] * v.x() + m[ 7] * v.y() + - m[11] * v.z() + m[15] * v.w())); -} - // ======================================================================= // function : UpdateRaytraceGeometry // purpose : Updates 3D scene geometry for ray tracing @@ -148,7 +127,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod if (theMode == OpenGl_GUM_PREPARE) { - BVH_ObjectSet::BVH_ObjectList anUnchangedObjects; + BVH_ObjectSet::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. @@ -203,7 +182,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod myRaytraceSceneRadius = 2.f /* scale factor */ * Max (aMinRadius, aMaxRadius); - const BVH_Vec4f aSize = myRaytraceGeometry.Box().Size(); + const BVH_Vec3f aSize = myRaytraceGeometry.Box().Size(); myRaytraceSceneEpsilon = Max (1e-6f, 1e-4f * sqrtf ( aSize.x() * aSize.x() + aSize.y() * aSize.y() + aSize.z() * aSize.z())); @@ -241,54 +220,130 @@ Standard_Boolean OpenGl_Workspace::CheckRaytraceStructure (const OpenGl_Structur return Standard_True; } +// ======================================================================= +// function : BuildTexTransform +// purpose : Constructs texture transformation matrix +// ======================================================================= +void BuildTexTransform (const Handle(Graphic3d_TextureParams)& theParams, BVH_Mat4f& theMatrix) +{ + theMatrix.InitIdentity(); + + // Apply scaling + const Graphic3d_Vec2& aScale = theParams->Scale(); + + theMatrix.ChangeValue (0, 0) *= aScale.x(); + theMatrix.ChangeValue (1, 0) *= aScale.x(); + theMatrix.ChangeValue (2, 0) *= aScale.x(); + theMatrix.ChangeValue (3, 0) *= aScale.x(); + + theMatrix.ChangeValue (0, 1) *= aScale.y(); + theMatrix.ChangeValue (1, 1) *= aScale.y(); + theMatrix.ChangeValue (2, 1) *= aScale.y(); + theMatrix.ChangeValue (3, 1) *= aScale.y(); + + // Apply translation + const Graphic3d_Vec2 aTrans = -theParams->Translation(); + + theMatrix.ChangeValue (0, 3) = theMatrix.GetValue (0, 0) * aTrans.x() + + theMatrix.GetValue (0, 1) * aTrans.y(); + + theMatrix.ChangeValue (1, 3) = theMatrix.GetValue (1, 0) * aTrans.x() + + theMatrix.GetValue (1, 1) * aTrans.y(); + + theMatrix.ChangeValue (2, 3) = theMatrix.GetValue (2, 0) * aTrans.x() + + theMatrix.GetValue (2, 1) * aTrans.y(); + + // Apply rotation + const Standard_ShortReal aSin = std::sin ( + -theParams->Rotation() * static_cast (M_PI / 180.0)); + const Standard_ShortReal aCos = std::cos ( + -theParams->Rotation() * static_cast (M_PI / 180.0)); + + BVH_Mat4f aRotationMat; + aRotationMat.SetValue (0, 0, aCos); + aRotationMat.SetValue (1, 1, aCos); + aRotationMat.SetValue (0, 1, -aSin); + aRotationMat.SetValue (1, 0, aSin); + + theMatrix = theMatrix * aRotationMat; +} + // ======================================================================= // function : CreateMaterial // purpose : Creates ray-tracing material properties // ======================================================================= -void CreateMaterial (const OPENGL_SURF_PROP& theProp, OpenGl_RaytraceMaterial& theMaterial) +Standard_Boolean OpenGl_Workspace::CreateMaterial (const OpenGl_AspectFace* theAspect, OpenGl_RaytraceMaterial& theMaterial) { - const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb; - theMaterial.Ambient = BVH_Vec4f (aSrcAmb[0] * theProp.amb, - aSrcAmb[1] * theProp.amb, - aSrcAmb[2] * theProp.amb, - 1.0f); - - const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb; - theMaterial.Diffuse = BVH_Vec4f (aSrcDif[0] * theProp.diff, - aSrcDif[1] * theProp.diff, - aSrcDif[2] * theProp.diff, - 1.0f); - - const float aDefSpecCol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : aDefSpecCol; - theMaterial.Specular = BVH_Vec4f (aSrcSpe[0] * theProp.spec, - aSrcSpe[1] * theProp.spec, - aSrcSpe[2] * theProp.spec, - theProp.shine); - - const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb; - theMaterial.Emission = BVH_Vec4f (aSrcEms[0] * theProp.emsv, - aSrcEms[1] * theProp.emsv, - aSrcEms[2] * theProp.emsv, - 1.0f); + const OPENGL_SURF_PROP& aProperties = theAspect->IntFront(); + + const Standard_ShortReal* aSrcAmbient = + aProperties.isphysic ? aProperties.ambcol.rgb : aProperties.matcol.rgb; + + theMaterial.Ambient = BVH_Vec4f (aSrcAmbient[0] * aProperties.amb, + aSrcAmbient[1] * aProperties.amb, + aSrcAmbient[2] * aProperties.amb, + 1.f); + + const Standard_ShortReal* aSrcDiffuse = + aProperties.isphysic ? aProperties.difcol.rgb : aProperties.matcol.rgb; + + theMaterial.Diffuse = BVH_Vec4f (aSrcDiffuse[0] * aProperties.diff, + aSrcDiffuse[1] * aProperties.diff, + aSrcDiffuse[2] * aProperties.diff, + -1.f /* no texture */); + + theMaterial.Specular = BVH_Vec4f ( + (aProperties.isphysic ? aProperties.speccol.rgb[0] : 1.f) * aProperties.spec, + (aProperties.isphysic ? aProperties.speccol.rgb[1] : 1.f) * aProperties.spec, + (aProperties.isphysic ? aProperties.speccol.rgb[2] : 1.f) * aProperties.spec, + aProperties.shine); + + const Standard_ShortReal* aSrcEmission = + aProperties.isphysic ? aProperties.emscol.rgb : aProperties.matcol.rgb; + + theMaterial.Emission = BVH_Vec4f (aSrcEmission[0] * aProperties.emsv, + aSrcEmission[1] * aProperties.emsv, + aSrcEmission[2] * aProperties.emsv, + 1.f); // Note: Here we use sub-linear transparency function // to produce realistic-looking transparency effect - theMaterial.Transparency = BVH_Vec4f (powf (theProp.trans, 0.75f), - 1.f - theProp.trans, - theProp.index == 0 ? 1.f : theProp.index, - theProp.index == 0 ? 1.f : 1.f / theProp.index); + theMaterial.Transparency = BVH_Vec4f (powf (aProperties.trans, 0.75f), + 1.f - aProperties.trans, + aProperties.index == 0 ? 1.f : aProperties.index, + aProperties.index == 0 ? 1.f : 1.f / aProperties.index); - const float aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(), - Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(), - theMaterial.Diffuse.z() + theMaterial.Specular.z())); + const Standard_ShortReal aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(), + Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(), + theMaterial.Diffuse.z() + theMaterial.Specular.z())); - const float aReflectionScale = 0.75f / aMaxRefl; + const Standard_ShortReal aReflectionScale = 0.75f / aMaxRefl; + + theMaterial.Reflection = BVH_Vec4f ( + aProperties.speccol.rgb[0] * aProperties.spec * aReflectionScale, + aProperties.speccol.rgb[1] * aProperties.spec * aReflectionScale, + aProperties.speccol.rgb[2] * aProperties.spec * aReflectionScale, + 0.f); + + if (theAspect->DoTextureMap()) + { + if (myGlContext->arbTexBindless != NULL) + { + BuildTexTransform (theAspect->TextureParams(), theMaterial.TextureTransform); + theMaterial.Diffuse.w() = static_cast ( + myRaytraceGeometry.AddTexture (theAspect->TextureRes (myGlContext))); + } + else if (!myIsRaytraceWarnTextures) + { + myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, + "Warning: texturing in Ray-Trace requires GL_ARB_bindless_texture extension which is missing. " + "Textures will be ignored."); + myIsRaytraceWarnTextures = Standard_True; + } + } - 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); + return Standard_True; } // ======================================================================= @@ -313,7 +368,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceStructure (const OpenGl_Structure* aStructMatID = static_cast (myRaytraceGeometry.Materials.size()); OpenGl_RaytraceMaterial aStructMaterial; - CreateMaterial (theStructure->AspectFace()->IntFront(), aStructMaterial); + CreateMaterial (theStructure->AspectFace(), aStructMaterial); myRaytraceGeometry.Materials.push_back (aStructMaterial); } @@ -362,7 +417,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure* aGroupMatID = static_cast (myRaytraceGeometry.Materials.size()); OpenGl_RaytraceMaterial aGroupMaterial; - CreateMaterial (aGroupIter.Value()->AspectFace()->IntFront(), aGroupMaterial); + CreateMaterial (aGroupIter.Value()->AspectFace(), aGroupMaterial); myRaytraceGeometry.Materials.push_back (aGroupMaterial); } @@ -385,7 +440,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure* aMatID = static_cast (myRaytraceGeometry.Materials.size()); OpenGl_RaytraceMaterial aMaterial; - CreateMaterial (anAspect->IntFront(), aMaterial); + CreateMaterial (anAspect, aMaterial); myRaytraceGeometry.Materials.push_back (aMaterial); } @@ -400,7 +455,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure* if (aSetIter != myArrayToTrianglesMap.end()) { OpenGl_TriangleSet* aSet = aSetIter->second; - + BVH_Transform* aTransform = new BVH_Transform(); if (theTransform != NULL) @@ -410,14 +465,14 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure* aSet->SetProperties (aTransform); - if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID ) + if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID) { aSet->SetMaterialIndex (aMatID); } } else { - NCollection_Handle > aSet = + NCollection_Handle > aSet = AddRaytracePrimitiveArray (aPrimArray, aMatID, 0); if (!aSet.IsNull()) @@ -448,7 +503,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure* // ======================================================================= OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_PrimitiveArray* theArray, Standard_Integer theMatID, - const Standard_ShortReal* theTransform) + const OpenGl_Mat4* theTransform) { const Handle(Graphic3d_IndexBuffer)& anIndices = theArray->Indices(); const Handle(Graphic3d_Buffer)& anAttribs = theArray->Attributes(); @@ -478,10 +533,22 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr } #endif + OpenGl_Mat4 aNormalMatrix; + + if (theTransform != NULL) + { + Standard_ASSERT_RETURN (theTransform->Inverted (aNormalMatrix), + "Error: Failed to compute normal transformation matrix", NULL); + + aNormalMatrix.Transpose(); + } + OpenGl_TriangleSet* aSet = new OpenGl_TriangleSet (theArray->GetUID()); { aSet->Vertices.reserve (anAttribs->NbElements); aSet->Normals .reserve (anAttribs->NbElements); + aSet->TexCrds .reserve (anAttribs->NbElements); + const size_t aVertFrom = aSet->Vertices.size(); for (Standard_Integer anAttribIter = 0; anAttribIter < anAttribs->NbAttributes; ++anAttribIter) { @@ -494,8 +561,8 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr { for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) { - const Graphic3d_Vec3& aVert = *reinterpret_cast(anAttribs->value (aVertIter) + anOffset); - aSet->Vertices.push_back (BVH_Vec4f (aVert.x(), aVert.y(), aVert.z(), 1.0f)); + aSet->Vertices.push_back ( + *reinterpret_cast(anAttribs->value (aVertIter) + anOffset)); } } else if (anAttrib.DataType == Graphic3d_TOD_VEC2) @@ -503,7 +570,7 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) { const Graphic3d_Vec2& aVert = *reinterpret_cast(anAttribs->value (aVertIter) + anOffset); - aSet->Vertices.push_back (BVH_Vec4f (aVert.x(), aVert.y(), 0.0f, 1.0f)); + aSet->Vertices.push_back (BVH_Vec3f (aVert.x(), aVert.y(), 0.0f)); } } } @@ -514,8 +581,19 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr { for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) { - const Graphic3d_Vec3& aNorm = *reinterpret_cast(anAttribs->value (aVertIter) + anOffset); - aSet->Normals.push_back (BVH_Vec4f (aNorm.x(), aNorm.y(), aNorm.z(), 0.0f)); + aSet->Normals.push_back ( + *reinterpret_cast(anAttribs->value (aVertIter) + anOffset)); + } + } + } + else if (anAttrib.Id == Graphic3d_TOA_UV) + { + if (anAttrib.DataType == Graphic3d_TOD_VEC2) + { + for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) + { + aSet->TexCrds.push_back ( + *reinterpret_cast(anAttribs->value (aVertIter) + anOffset)); } } } @@ -525,21 +603,37 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr { for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) { - aSet->Normals.push_back (BVH_Vec4f()); + aSet->Normals.push_back (BVH_Vec3f()); + } + } + + if (aSet->TexCrds.size() != aSet->Vertices.size()) + { + for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) + { + aSet->TexCrds.push_back (BVH_Vec2f()); } } - if (theTransform) + if (theTransform != NULL) { for (size_t aVertIter = aVertFrom; aVertIter < aSet->Vertices.size(); ++aVertIter) { - BVH_Vec4f& aVertex = aSet->Vertices[aVertIter]; - aVertex = MatVecMult (theTransform, aVertex); + BVH_Vec3f& aVertex = aSet->Vertices[aVertIter]; + + BVH_Vec4f aTransVertex = + *theTransform * BVH_Vec4f (aVertex.x(), aVertex.y(), aVertex.z(), 1.f); + + aVertex = BVH_Vec3f (aTransVertex.x(), aTransVertex.y(), aTransVertex.z()); } for (size_t aVertIter = aVertFrom; aVertIter < aSet->Normals.size(); ++aVertIter) { - BVH_Vec4f& aNorm = aSet->Normals[aVertIter]; - aNorm = MatVecMult (theTransform, aNorm); + BVH_Vec3f& aNormal = aSet->Normals[aVertIter]; + + BVH_Vec4f aTransNormal = + aNormalMatrix * BVH_Vec4f (aNormal.x(), aNormal.y(), aNormal.z(), 0.f); + + aNormal = BVH_Vec3f (aTransNormal.x(), aTransNormal.y(), aTransNormal.z()); } } @@ -864,7 +958,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytracePolygonArray (OpenGl_TriangleSet& // function : UpdateRaytraceLightSources // purpose : Updates 3D scene light sources for ray-tracing // ======================================================================= -Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const GLdouble theInvModelView[16]) +Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const OpenGl_Mat4& theInvModelView) { myRaytraceGeometry.Sources.clear(); @@ -902,9 +996,10 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const GLdouble th } if (aLight.IsHeadlight) - aPosition = MatVecMult (theInvModelView, aPosition); + { + aPosition = theInvModelView * aPosition; + } - myRaytraceGeometry.Sources.push_back (OpenGl_RaytraceLight (aDiffuse, aPosition)); } @@ -963,12 +1058,12 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap() myGlContext, GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture); aProgram->SetUniform (myGlContext, - myUniformLocations[anIdx][OpenGl_RT_uEnvironmentEnable], 1); + myUniformLocations[anIdx][OpenGl_RT_uEnvMapEnable], 1); } else { aProgram->SetUniform (myGlContext, - myUniformLocations[anIdx][OpenGl_RT_uEnvironmentEnable], 0); + myUniformLocations[anIdx][OpenGl_RT_uEnvMapEnable], 0); } } } @@ -1115,6 +1210,32 @@ Standard_Boolean OpenGl_Workspace::SafeFailBack (const TCollection_ExtendedStrin return Standard_False; } +// ======================================================================= +// function : GenerateShaderPrefix +// purpose : Generates shader prefix based on current ray-tracing options +// ======================================================================= +TCollection_AsciiString OpenGl_Workspace::GenerateShaderPrefix() +{ + TCollection_AsciiString aPrefixString = + TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" + + TCollection_AsciiString ("#define NB_BOUNCES ") + TCollection_AsciiString (myRaytraceParameters.NbBounces); + + if (myRaytraceParameters.TransparentShadows) + { + aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS"); + } + + // If OpenGL driver supports bindless textures + // activate texturing in ray-tracing mode + if (myGlContext->arbTexBindless != NULL) + { + aPrefixString += TCollection_AsciiString ("\n#define USE_TEXTURES") + + TCollection_AsciiString ("\n#define MAX_TEX_NUMBER ") + TCollection_AsciiString (OpenGl_RaytraceGeometry::MAX_TEX_NUMBER); + } + + return aPrefixString; +} + // ======================================================================= // function : InitRaytraceResources // purpose : Initializes OpenGL/GLSL shader programs @@ -1149,9 +1270,9 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& } } - if (theCView.RenderParams.RaytracingDepth != myRaytraceParameters.TraceDepth) + if (theCView.RenderParams.RaytracingDepth != myRaytraceParameters.NbBounces) { - myRaytraceParameters.TraceDepth = theCView.RenderParams.RaytracingDepth; + myRaytraceParameters.NbBounces = theCView.RenderParams.RaytracingDepth; aToRebuildShaders = Standard_True; } @@ -1170,14 +1291,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& // Change state to force update all uniforms ++myViewModificationStatus; - TCollection_AsciiString aPrefixString = - TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" + - TCollection_AsciiString ("#define TRACE_DEPTH ") + TCollection_AsciiString (myRaytraceParameters.TraceDepth); - - if (myRaytraceParameters.TransparentShadows) - { - aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS"); - } + TCollection_AsciiString aPrefixString = GenerateShaderPrefix(); #ifdef RAY_TRACE_PRINT_INFO std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl; @@ -1212,15 +1326,20 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& { if (!myGlContext->IsGlGreaterEqual (3, 1)) { - const TCollection_ExtendedString aMessage = "Ray-tracing requires OpenGL 3.1 and higher"; - myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, - GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage); - + GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, + "Ray-tracing requires OpenGL 3.1 and higher"); + return Standard_False; + } + else if (!myGlContext->arbTboRGB32) + { + myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, + "Ray-tracing requires OpenGL 4.0+ or GL_ARB_texture_buffer_object_rgb32 extension"); return Standard_False; } - myRaytraceParameters.TraceDepth = theCView.RenderParams.RaytracingDepth; + myRaytraceParameters.NbBounces = theCView.RenderParams.RaytracingDepth; TCollection_AsciiString aFolder = Graphic3d_ShaderProgram::ShadersFolder(); @@ -1240,14 +1359,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth()); } - TCollection_AsciiString aPrefixString = - TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" + - TCollection_AsciiString ("#define TRACE_DEPTH ") + TCollection_AsciiString (myRaytraceParameters.TraceDepth); - - if (myRaytraceParameters.TransparentShadows) - { - aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS"); - } + TCollection_AsciiString aPrefixString = GenerateShaderPrefix(); #ifdef RAY_TRACE_PRINT_INFO std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl; @@ -1394,15 +1506,17 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& aShaderProgram->SetSampler (myGlContext, "uGeometryNormalTexture", OpenGl_RT_GeometryNormalTexture); aShaderProgram->SetSampler (myGlContext, - "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture); + "uGeometryTexCrdTexture", OpenGl_RT_GeometryTexCrdTexture); aShaderProgram->SetSampler (myGlContext, - "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture); - aShaderProgram->SetSampler (myGlContext, - "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture); + "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture); aShaderProgram->SetSampler (myGlContext, "uSceneTransformTexture", OpenGl_RT_SceneTransformTexture); aShaderProgram->SetSampler (myGlContext, "uEnvironmentMapTexture", OpenGl_RT_EnvironmentMapTexture); + aShaderProgram->SetSampler (myGlContext, + "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture); + aShaderProgram->SetSampler (myGlContext, + "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture); aShaderProgram->SetSampler (myGlContext, "uOpenGlColorTexture", OpenGl_RT_OpenGlColorTexture); @@ -1434,23 +1548,17 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& aShaderProgram->GetUniformLocation (myGlContext, "uDirectLT"); myUniformLocations[anIndex][OpenGl_RT_uDirectRT] = aShaderProgram->GetUniformLocation (myGlContext, "uDirectRT"); - myUniformLocations[anIndex][OpenGl_RT_uInvModelProj] = - aShaderProgram->GetUniformLocation (myGlContext, "uInvModelProj"); - - myUniformLocations[anIndex][OpenGl_RT_uLightCount] = - aShaderProgram->GetUniformLocation (myGlContext, "uLightCount"); - myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] = - aShaderProgram->GetUniformLocation (myGlContext, "uGlobalAmbient"); + myUniformLocations[anIndex][OpenGl_RT_uUnviewMat] = + aShaderProgram->GetUniformLocation (myGlContext, "uUnviewMat"); 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_uLightCount] = + aShaderProgram->GetUniformLocation (myGlContext, "uLightCount"); + myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] = + aShaderProgram->GetUniformLocation (myGlContext, "uGlobalAmbient"); myUniformLocations[anIndex][OpenGl_RT_uOffsetX] = aShaderProgram->GetUniformLocation (myGlContext, "uOffsetX"); @@ -1459,7 +1567,14 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& myUniformLocations[anIndex][OpenGl_RT_uSamples] = aShaderProgram->GetUniformLocation (myGlContext, "uSamples"); - myUniformLocations[anIndex][OpenGl_RT_uEnvironmentEnable] = + myUniformLocations[anIndex][OpenGl_RT_uTextures] = + aShaderProgram->GetUniformLocation (myGlContext, "uTextureSamplers"); + + myUniformLocations[anIndex][OpenGl_RT_uShadEnabled] = + aShaderProgram->GetUniformLocation (myGlContext, "uShadowsEnable"); + myUniformLocations[anIndex][OpenGl_RT_uReflEnabled] = + aShaderProgram->GetUniformLocation (myGlContext, "uReflectionsEnable"); + myUniformLocations[anIndex][OpenGl_RT_uEnvMapEnable] = aShaderProgram->GetUniformLocation (myGlContext, "uEnvironmentEnable"); } @@ -1535,6 +1650,7 @@ void OpenGl_Workspace::ReleaseRaytraceResources() NullifyResource (myGlContext, myGeometryVertexTexture); NullifyResource (myGlContext, myGeometryNormalTexture); + NullifyResource (myGlContext, myGeometryTexCrdTexture); NullifyResource (myGlContext, myGeometryTriangTexture); NullifyResource (myGlContext, mySceneTransformTexture); @@ -1559,6 +1675,22 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() return Standard_False; } + ///////////////////////////////////////////////////////////////////////////// + // Prepare OpenGL textures + + if (myGlContext->arbTexBindless != NULL) + { + // If OpenGL driver supports bindless textures we need + // to get unique 64- bit handles for using on the GPU + if (!myRaytraceGeometry.UpdateTextureHandles (myGlContext)) + { +#ifdef RAY_TRACE_PRINT_INFO + std::cout << "Error: Failed to get OpenGL texture handles" << std::endl; +#endif + return Standard_False; + } + } + ///////////////////////////////////////////////////////////////////////////// // Create OpenGL texture buffers @@ -1588,8 +1720,8 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() myObjectMaxPointTexture = new OpenGl_TextureBufferArb; if (!myObjectNodeInfoTexture->Create (myGlContext) - || !myObjectMinPointTexture->Create (myGlContext) - || !myObjectMaxPointTexture->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; @@ -1602,11 +1734,13 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() { myGeometryVertexTexture = new OpenGl_TextureBufferArb; myGeometryNormalTexture = new OpenGl_TextureBufferArb; + myGeometryTexCrdTexture = new OpenGl_TextureBufferArb; myGeometryTriangTexture = new OpenGl_TextureBufferArb; if (!myGeometryVertexTexture->Create (myGlContext) - || !myGeometryNormalTexture->Create (myGlContext) - || !myGeometryTriangTexture->Create (myGlContext)) + || !myGeometryNormalTexture->Create (myGlContext) + || !myGeometryTexCrdTexture->Create (myGlContext) + || !myGeometryTriangTexture->Create (myGlContext)) { #ifdef RAY_TRACE_PRINT_INFO std::cout << "Error: Failed to create buffers for triangulation data" << std::endl; @@ -1631,16 +1765,16 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() ///////////////////////////////////////////////////////////////////////////// // Write top-level BVH buffers - const NCollection_Handle >& aBVH = myRaytraceGeometry.BVH(); + const NCollection_Handle >& aBVH = myRaytraceGeometry.BVH(); bool aResult = true; if (!aBVH->NodeInfoBuffer().empty()) { aResult &= mySceneNodeInfoTexture->Init (myGlContext, 4, GLsizei (aBVH->NodeInfoBuffer().size()), reinterpret_cast (&aBVH->NodeInfoBuffer().front())); - aResult &= mySceneMinPointTexture->Init (myGlContext, 4, GLsizei (aBVH->MinPointBuffer().size()), + aResult &= mySceneMinPointTexture->Init (myGlContext, 3, GLsizei (aBVH->MinPointBuffer().size()), reinterpret_cast (&aBVH->MinPointBuffer().front())); - aResult &= mySceneMaxPointTexture->Init (myGlContext, 4, GLsizei (aBVH->MaxPointBuffer().size()), + aResult &= mySceneMaxPointTexture->Init (myGlContext, 3, GLsizei (aBVH->MaxPointBuffer().size()), reinterpret_cast (&aBVH->MaxPointBuffer().front())); } if (!aResult) @@ -1655,7 +1789,6 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() // Write transform buffer BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()]; - BVH_Mat4f anIdentity; for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex) { @@ -1669,13 +1802,12 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() "OpenGl_TriangleSet does not contain transform", Standard_False); aNodeTransforms[anElemIndex] = aTransform->Inversed(); - } aResult &= mySceneTransformTexture->Init (myGlContext, 4, myRaytraceGeometry.Size() * 4, reinterpret_cast (aNodeTransforms)); - delete[] aNodeTransforms; + delete [] aNodeTransforms; ///////////////////////////////////////////////////////////////////////////// // Write geometry and bottom-level BVH buffers @@ -1703,9 +1835,12 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() if (aTotalBVHNodesNb != 0) { - aResult &= myObjectNodeInfoTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast (NULL)); - aResult &= myObjectMinPointTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast (NULL)); - aResult &= myObjectMaxPointTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast (NULL)); + aResult &= myObjectNodeInfoTexture->Init ( + myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast (NULL)); + aResult &= myObjectMinPointTexture->Init ( + myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast (NULL)); + aResult &= myObjectMaxPointTexture->Init ( + myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast (NULL)); } if (!aResult) @@ -1718,13 +1853,18 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() if (aTotalElementsNb != 0) { - aResult &= myGeometryTriangTexture->Init (myGlContext, 4, GLsizei (aTotalElementsNb), static_cast (NULL)); + aResult &= myGeometryTriangTexture->Init ( + myGlContext, 4, GLsizei (aTotalElementsNb), static_cast (NULL)); } if (aTotalVerticesNb != 0) { - aResult &= myGeometryVertexTexture->Init (myGlContext, 4, GLsizei (aTotalVerticesNb), static_cast (NULL)); - aResult &= myGeometryNormalTexture->Init (myGlContext, 4, GLsizei (aTotalVerticesNb), static_cast (NULL)); + aResult &= myGeometryVertexTexture->Init ( + myGlContext, 3, GLsizei (aTotalVerticesNb), static_cast (NULL)); + aResult &= myGeometryNormalTexture->Init ( + myGlContext, 3, GLsizei (aTotalVerticesNb), static_cast (NULL)); + aResult &= myGeometryTexCrdTexture->Init ( + myGlContext, 2, GLsizei (aTotalVerticesNb), static_cast (NULL)); } if (!aResult) @@ -1778,6 +1918,8 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() { aResult &= myGeometryNormalTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Normals.size()), reinterpret_cast (&aTriangleSet->Normals.front())); + aResult &= myGeometryTexCrdTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->TexCrds.size()), + reinterpret_cast (&aTriangleSet->TexCrds.front())); aResult &= myGeometryVertexTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Vertices.size()), reinterpret_cast (&aTriangleSet->Vertices.front())); } @@ -1802,10 +1944,14 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() } } + ///////////////////////////////////////////////////////////////////////////// + // Write material buffer + if (myRaytraceGeometry.Materials.size() != 0) { - const GLfloat* aDataPtr = myRaytraceGeometry.Materials.front().Packed(); - aResult &= myRaytraceMaterialTexture->Init (myGlContext, 4, GLsizei (myRaytraceGeometry.Materials.size() * 7), aDataPtr); + aResult &= myRaytraceMaterialTexture->Init (myGlContext, 4, + GLsizei (myRaytraceGeometry.Materials.size() * 11), myRaytraceGeometry.Materials.front().Packed()); + if (!aResult) { #ifdef RAY_TRACE_PRINT_INFO @@ -1827,26 +1973,28 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData() myRaytraceGeometry.Objects().ChangeValue (anElemIdx).operator->()); aMemUsed += static_cast ( - aTriangleSet->Vertices.size() * sizeof (BVH_Vec4f)); + aTriangleSet->Vertices.size() * sizeof (BVH_Vec3f)); aMemUsed += static_cast ( - aTriangleSet->Normals.size() * sizeof (BVH_Vec4f)); + aTriangleSet->Normals.size() * sizeof (BVH_Vec3f)); + aMemUsed += static_cast ( + aTriangleSet->TexCrds.size() * sizeof (BVH_Vec2f)); aMemUsed += static_cast ( aTriangleSet->Elements.size() * sizeof (BVH_Vec4i)); aMemUsed += static_cast ( aTriangleSet->BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i)); aMemUsed += static_cast ( - aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f)); + aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f)); aMemUsed += static_cast ( - aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f)); + aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f)); } aMemUsed += static_cast ( myRaytraceGeometry.BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i)); aMemUsed += static_cast ( - myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f)); + myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f)); aMemUsed += static_cast ( - myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f)); + myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f)); std::cout << "GPU Memory Used (MB): ~" << aMemUsed / 1048576 << std::endl; @@ -1876,11 +2024,11 @@ Standard_Boolean OpenGl_Workspace::ResizeRaytraceBuffers (const Standard_Integer // function : UpdateCamera // purpose : Generates viewing rays for corners of screen quad // ======================================================================= -void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4& theOrientation, - const NCollection_Mat4& theViewMapping, - OpenGl_Vec3 theOrigins[4], - OpenGl_Vec3 theDirects[4], - NCollection_Mat4& theInvModelProj) +void OpenGl_Workspace::UpdateCamera (const OpenGl_Mat4& theOrientation, + const OpenGl_Mat4& theViewMapping, + OpenGl_Vec3 theOrigins[4], + OpenGl_Vec3 theDirects[4], + OpenGl_Mat4& theInvModelProj) { // compute inverse model-view-projection matrix (theViewMapping * theOrientation).Inverted (theInvModelProj); @@ -1892,10 +2040,10 @@ void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4& theOrient { for (Standard_Integer aX = -1; aX <= 1; aX += 2) { - OpenGl_Vec4d aOrigin (GLdouble(aX), - GLdouble(aY), - -1.0, - 1.0); + OpenGl_Vec4 aOrigin (GLfloat(aX), + GLfloat(aY), + -1.0f, + 1.0f); aOrigin = theInvModelProj * aOrigin; @@ -1903,10 +2051,10 @@ void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4& theOrient aOrigin.y() = aOrigin.y() / aOrigin.w(); aOrigin.z() = aOrigin.z() / aOrigin.w(); - OpenGl_Vec4d aDirect (GLdouble(aX), - GLdouble(aY), - 1.0, - 1.0); + OpenGl_Vec4 aDirect (GLfloat(aX), + GLfloat(aY), + 1.0f, + 1.0f); aDirect = theInvModelProj * aDirect; @@ -1931,6 +2079,80 @@ void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4& theOrient } } +// ======================================================================= +// function : SetUniformState +// purpose : Sets uniform state for the given ray-tracing shader program +// ======================================================================= +Standard_Boolean OpenGl_Workspace::SetUniformState (const Graphic3d_CView& theCView, + const OpenGl_Vec3* theOrigins, + const OpenGl_Vec3* theDirects, + const OpenGl_Mat4& theUnviewMat, + const Standard_Integer theProgramIndex, + Handle(OpenGl_ShaderProgram)& theRaytraceProgram) +{ + if (theRaytraceProgram.IsNull()) + { + return Standard_False; + } + + Standard_Integer aLightSourceBufferSize = + static_cast (myRaytraceGeometry.Sources.size()); + + Standard_Boolean aResult = Standard_True; + + // Set camera state + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uOriginLB], theOrigins[0]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uOriginRB], theOrigins[1]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uOriginLT], theOrigins[2]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uOriginRT], theOrigins[3]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uDirectLB], theDirects[0]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uDirectRB], theDirects[1]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uDirectLT], theDirects[2]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uDirectRT], theDirects[3]); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uUnviewMat], theUnviewMat); + + // Set scene parameters + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uSceneRad], myRaytraceSceneRadius); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uLightCount], aLightSourceBufferSize); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient); + + // Set rendering options + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uShadEnabled], theCView.RenderParams.IsShadowEnabled ? 1 : 0); + aResult &= theRaytraceProgram->SetUniform (myGlContext, + myUniformLocations[theProgramIndex][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0); + + // Set array of 64-bit texture handles + if (myGlContext->arbTexBindless != NULL && myRaytraceGeometry.HasTextures()) + { + aResult &= theRaytraceProgram->SetUniform (myGlContext, "uTextureSamplers", + static_cast (myRaytraceGeometry.TextureHandles().size()), &myRaytraceGeometry.TextureHandles()[0]); + } + + if (!aResult) + { +#ifdef RAY_TRACE_PRINT_INFO + std::cout << "Error: Failed to set uniform state for ray-tracing program" << theProgramIndex << std::endl; +#endif + } + + return aResult; +} + // ======================================================================= // function : RunRaytraceShaders // purpose : Runs ray-tracing shader programs @@ -1940,7 +2162,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th const Standard_Integer theSizeY, const OpenGl_Vec3 theOrigins[4], const OpenGl_Vec3 theDirects[4], - const OpenGl_Matrix& theInvModelProj, + const OpenGl_Mat4& theUnviewMat, OpenGl_FrameBuffer* theFrameBuffer) { mySceneMinPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture); @@ -1951,6 +2173,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th myObjectNodeInfoTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture); myGeometryVertexTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture); myGeometryNormalTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture); + myGeometryTexCrdTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture); myGeometryTriangTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture); mySceneTransformTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture); myRaytraceMaterialTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture); @@ -1968,39 +2191,12 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th myGlContext->BindProgram (myRaytraceProgram); - Standard_Integer aLightSourceBufferSize = - static_cast (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_uInvModelProj], theInvModelProj); - 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); + SetUniformState (theCView, + theOrigins, + theDirects, + theUnviewMat, + 0, // ID of RT program + myRaytraceProgram); myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS); { @@ -2008,7 +2204,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6); } myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS); - + if (!theCView.RenderParams.IsAntialiasingEnabled) { myGlContext->BindProgram (NULL); @@ -2023,10 +2219,11 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th myObjectNodeInfoTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture); myGeometryVertexTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture); myGeometryNormalTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture); + myGeometryTexCrdTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture); myGeometryTriangTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture); + mySceneTransformTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture); myRaytraceMaterialTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture); myRaytraceLightSrcTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture); - mySceneTransformTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture); myGlContext->core15fwd->glActiveTexture (GL_TEXTURE0); @@ -2037,36 +2234,12 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th myGlContext->BindProgram (myPostFSAAProgram); - 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]); - myRaytraceProgram->SetUniform (myGlContext, - myUniformLocations[1][OpenGl_RT_uInvModelProj], theInvModelProj); - 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); + SetUniformState (theCView, + theOrigins, + theDirects, + theUnviewMat, + 1, // ID of FSAA program + myPostFSAAProgram); const Standard_ShortReal aMaxOffset = 0.559017f; const Standard_ShortReal aMinOffset = 0.186339f; @@ -2136,10 +2309,11 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th myObjectNodeInfoTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture); myGeometryVertexTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture); myGeometryNormalTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture); + myGeometryTexCrdTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture); myGeometryTriangTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture); + mySceneTransformTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture); myRaytraceMaterialTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture); myRaytraceLightSrcTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture); - mySceneTransformTexture->UnbindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture); myGlContext->core15fwd->glActiveTexture (GL_TEXTURE0); @@ -2168,24 +2342,13 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView, return Standard_False; // Get model-view and projection matrices - TColStd_Array2OfReal theOrientation (0, 3, 0, 3); - TColStd_Array2OfReal theViewMapping (0, 3, 0, 3); + OpenGl_Mat4 aOrientationMatrix; + OpenGl_Mat4 aViewMappingMatrix; - myView->GetMatrices (theOrientation, theViewMapping); + myView->GetMatrices (aOrientationMatrix, + aViewMappingMatrix); - NCollection_Mat4 aOrientationMatrix; - NCollection_Mat4 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 aInvOrientationMatrix; + OpenGl_Mat4 aInvOrientationMatrix; aOrientationMatrix.Inverted (aInvOrientationMatrix); if (!UpdateRaytraceLightSources (aInvOrientationMatrix)) @@ -2193,22 +2356,13 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView, OpenGl_Vec3 aOrigins[4]; OpenGl_Vec3 aDirects[4]; - NCollection_Mat4 anInvModelProj; + OpenGl_Mat4 anUnviewMat; UpdateCamera (aOrientationMatrix, aViewMappingMatrix, aOrigins, aDirects, - anInvModelProj); - - OpenGl_Matrix anInvModelProjMatrix; - for (Standard_Integer j = 0; j < 4; ++j) - { - for (Standard_Integer i = 0; i < 4; ++i) - { - anInvModelProjMatrix.mat[j][i] = static_cast(anInvModelProj.GetValue(i,j)); - } - } + anUnviewMat); Standard_Boolean wasBlendingEnabled = glIsEnabled (GL_BLEND); Standard_Boolean wasDepthTestEnabled = glIsEnabled (GL_DEPTH_TEST); @@ -2256,14 +2410,30 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView, { myRaytraceScreenQuad.Bind (myGlContext); + if (!myRaytraceGeometry.AcquireTextures (myGlContext)) + { + const TCollection_ExtendedString aMessage = "Error: Failed to acquire OpenGL image textures"; + + myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_MEDIUM_ARB, aMessage); + } + RunRaytraceShaders (theCView, theSizeX, theSizeY, aOrigins, aDirects, - anInvModelProjMatrix, + anUnviewMat, theFrameBuffer); + if (!myRaytraceGeometry.ReleaseTextures (myGlContext)) + { + const TCollection_ExtendedString aMessage = "Error: Failed to release OpenGL image textures"; + + myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_MEDIUM_ARB, aMessage); + } + myRaytraceScreenQuad.Unbind (myGlContext); } diff --git a/src/Shaders/RaytraceBase.fs b/src/Shaders/RaytraceBase.fs index 1b860c30c6..d0c002e422 100644 --- a/src/Shaders/RaytraceBase.fs +++ b/src/Shaders/RaytraceBase.fs @@ -1,3 +1,7 @@ +#ifdef USE_TEXTURES + #extension GL_ARB_bindless_texture : require +#endif + //! Normalized pixel coordinates. in vec2 vPixel; @@ -20,7 +24,8 @@ uniform vec3 uDirectRT; uniform vec3 uDirectRB; //! Inverse model-view-projection matrix. -uniform mat4 uInvModelProj; +uniform mat4 uUnviewMat; + //! Texture buffer of data records of high-level BVH nodes. uniform isamplerBuffer uSceneNodeInfoTexture; //! Texture buffer of minimum points of high-level BVH nodes. @@ -41,6 +46,10 @@ uniform samplerBuffer uObjectMaxPointTexture; uniform samplerBuffer uGeometryVertexTexture; //! Texture buffer of vertex normals. uniform samplerBuffer uGeometryNormalTexture; +#ifdef USE_TEXTURES + //! Texture buffer of per-vertex UV-coordinates. + uniform samplerBuffer uGeometryTexCrdTexture; +#endif //! Texture buffer of triangle indices. uniform isamplerBuffer uGeometryTriangTexture; @@ -73,6 +82,11 @@ uniform float uSceneRadius; //! Scene epsilon to prevent self-intersections. uniform float uSceneEpsilon; +#ifdef USE_TEXTURES + //! Unique 64-bit handles of OpenGL textures. + uniform sampler2D uTextureSamplers[MAX_TEX_NUMBER]; +#endif + ///////////////////////////////////////////////////////////////////////////////////////// // Specific data types @@ -108,7 +122,6 @@ struct SIntersect #define AXIS_Y vec3 (0.0f, 1.0f, 0.0f) #define AXIS_Z vec3 (0.0f, 0.0f, 1.0f) - // ======================================================================= // function : MatrixRowMultiplyDir // purpose : Multiplies a vector by matrix @@ -171,7 +184,6 @@ SRay GenerateRay (in vec2 thePixel) vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y)); return SRay (mix (aP0, aP1, thePixel.y), aDirection); - } // ======================================================================= @@ -187,7 +199,7 @@ float ComputeOpenGlDepth (in SRay theRay) 2.0f * vPixel.y - 1.0f, 2.0f * anOpenGlDepth - 1.0f, 1.0f); - vec4 aFinal = uInvModelProj * aPoint; + vec4 aFinal = uUnviewMat * aPoint; aFinal.xyz *= 1.f / aFinal.w; return (anOpenGlDepth < 1.f) ? length (aFinal.xyz - theRay.Origin) : MAXFLOAT; @@ -334,7 +346,7 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO { if (aHead == theSentinel) return aTriIndex; - + aNode = Stack[aHead--]; } } @@ -377,13 +389,16 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO return aTriIndex; } -#define MATERIAL_AMBN(index) (7 * index + 0) -#define MATERIAL_DIFF(index) (7 * index + 1) -#define MATERIAL_SPEC(index) (7 * index + 2) -#define MATERIAL_EMIS(index) (7 * index + 3) -#define MATERIAL_REFL(index) (7 * index + 4) -#define MATERIAL_REFR(index) (7 * index + 5) -#define MATERIAL_TRAN(index) (7 * index + 6) +#define MATERIAL_AMBN(index) (11 * index + 0) +#define MATERIAL_DIFF(index) (11 * index + 1) +#define MATERIAL_SPEC(index) (11 * index + 2) +#define MATERIAL_EMIS(index) (11 * index + 3) +#define MATERIAL_REFL(index) (11 * index + 4) +#define MATERIAL_REFR(index) (11 * index + 5) +#define MATERIAL_TRAN(index) (11 * index + 6) +#define MATERIAL_TRS1(index) (11 * index + 7) +#define MATERIAL_TRS2(index) (11 * index + 8) +#define MATERIAL_TRS3(index) (11 * index + 9) // ======================================================================= // function : ObjectAnyHit @@ -408,7 +423,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse float aTimeOut; float aTimeLft; float aTimeRgh; - + aData.y += theBVHOffset; aData.z += theBVHOffset; @@ -469,7 +484,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse { vec3 aNormal; vec2 aParams; - + for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx) { ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset); @@ -495,7 +510,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse return 0.0f; #endif } - + #ifdef TRANSPARENT_SHADOWS if (aHead == theSentinel || aFactor < 0.1f) return aFactor; @@ -534,12 +549,12 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH { vec3 aNodeMin = texelFetch (uSceneMinPointTexture, aNode).xyz; vec3 aNodeMax = texelFetch (uSceneMaxPointTexture, aNode).xyz; - + vec3 aTime0 = (aNodeMin - theRay.Origin) * theInverse; vec3 aTime1 = (aNodeMax - theRay.Origin) * theInverse; - + vec3 aTimes = min (aTime0, aTime1); - + if (max (aTimes.x, max (aTimes.y, aTimes.z)) < theHit.Time) { // fetch object transformation @@ -576,7 +591,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH if (aHead < 0) return aHitObject; - + aNode = Stack[aHead--]; } else // if inner node @@ -684,11 +699,11 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) #else bool isShadow = 0.0f == ObjectAnyHit ( aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead); - + if (aHead < 0 || isShadow) return isShadow ? 0.0f : 1.0f; #endif - + aNode = Stack[aHead--]; } else // if inner node @@ -751,7 +766,7 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) } } } - + #ifdef TRANSPARENT_SHADOWS return aFactor; #else @@ -768,9 +783,9 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) vec2 Latlong (in vec3 thePoint, in float theRadius) { float aPsi = acos (-thePoint.z / theRadius); - + float aPhi = atan (thePoint.y, thePoint.x) + PI; - + return vec2 (aPhi * 0.1591549f, aPsi * 0.3183098f); } @@ -784,12 +799,29 @@ vec3 SmoothNormal (in vec2 theUV, in ivec4 theTriangle) vec3 aNormal0 = texelFetch (uGeometryNormalTexture, theTriangle.x).xyz; vec3 aNormal1 = texelFetch (uGeometryNormalTexture, theTriangle.y).xyz; vec3 aNormal2 = texelFetch (uGeometryNormalTexture, theTriangle.z).xyz; - + return normalize (aNormal1 * theUV.x + aNormal2 * theUV.y + aNormal0 * (1.0f - theUV.x - theUV.y)); } +// ======================================================================= +// function : SmoothUV +// purpose : Interpolates UV coordinates across the triangle +// ======================================================================= +#ifdef USE_TEXTURES +vec2 SmoothUV (in vec2 theUV, in ivec4 theTriangle) +{ + vec2 aTexCrd0 = texelFetch (uGeometryTexCrdTexture, theTriangle.x).st; + vec2 aTexCrd1 = texelFetch (uGeometryTexCrdTexture, theTriangle.y).st; + vec2 aTexCrd2 = texelFetch (uGeometryTexCrdTexture, theTriangle.z).st; + + return aTexCrd1 * theUV.x + + aTexCrd2 * theUV.y + + aTexCrd0 * (1.0f - theUV.x - theUV.y); +} +#endif + // ======================================================================= // function : Refract // purpose : Computes refraction ray (also handles TIR) @@ -799,21 +831,21 @@ vec3 Refract (in vec3 theInput, in float theRefractIndex, in float theInvRefractIndex) { - float aNdotI = dot (theInput, theNormal); - + float aNdotI = dot (theInput, theNormal); + float anIndex = aNdotI < 0.0f ? theInvRefractIndex : theRefractIndex; - + float aSquare = anIndex * anIndex * (1.0f - aNdotI * aNdotI); - + if (aSquare > 1.0f) { return reflect (theInput, theNormal); } - + float aNdotT = sqrt (1.0f - aSquare); - + return normalize (anIndex * theInput - (anIndex * aNdotI + (aNdotI < 0.0f ? aNdotT : -aNdotT)) * theNormal); } @@ -828,7 +860,7 @@ vec3 Refract (in vec3 theInput, // ======================================================================= // function : Radiance -// purpose : Computes color of specified ray +// purpose : Computes color along the given ray // ======================================================================= vec4 Radiance (in SRay theRay, in vec3 theInverse) { @@ -839,9 +871,7 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) float anOpenGlDepth = ComputeOpenGlDepth (theRay); - vec3 aViewDir = theRay.Direct; - - for (int aDepth = 0; aDepth < TRACE_DEPTH; ++aDepth) + for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth) { SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO); @@ -849,82 +879,81 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) if (aTriIndex.x == -1) { + vec4 aColor = vec4 (0.0f, 0.0f, 0.0f, 1.0f); + if (aWeight.w != 0.0f) { - if (anOpenGlDepth < MAXFLOAT) - { - vec4 anOpenGlColor = ComputeOpenGlColor (theRay); - aResult.xyz += aWeight.xyz * anOpenGlColor.xyz; - aWeight.w *= anOpenGlColor.w; - } - return vec4 (aResult.x, - aResult.y, - aResult.z, - aWeight.w); + if (anOpenGlDepth != MAXFLOAT) + aColor = ComputeOpenGlColor (theRay); } - - if (bool(uEnvironmentEnable)) + else if (bool(uEnvironmentEnable)) { float aTime = IntersectSphere (theRay, uSceneRadius); - - aResult.xyz += aWeight.xyz * textureLod (uEnvironmentMapTexture, - Latlong (theRay.Direct * aTime + theRay.Origin, uSceneRadius), 0.0f).xyz; + + aColor = textureLod (uEnvironmentMapTexture, Latlong ( + theRay.Direct * aTime + theRay.Origin, uSceneRadius), 0.0f); } - - return vec4 (aResult.x, - aResult.y, - aResult.z, - aWeight.w); + + return vec4 (aResult.xyz + aWeight.xyz * aColor.xyz, aWeight.w * aColor.w); } aHit.Normal = normalize (aHit.Normal); - - if (anOpenGlDepth != MAXFLOAT) - { - float aDepthSlope = dot (theRay.Direct, aHit.Normal); - - // For polygons that are parallel to the screen plane, the depth slope - // is equal to 1, resulting in small polygon offset. For polygons that - // that are at a large angle to the screen, the depth slope tends to 1, - // resulting in a larger polygon offset - float aPolygonOffset = uSceneEpsilon * EPS_SCALE / max (MIN_SLOPE, abs (aDepthSlope)); - if (anOpenGlDepth - aPolygonOffset < aHit.Time) - { - vec4 aColor = ComputeOpenGlColor (theRay); - - aResult.xyz += aWeight.xyz * aColor.xyz; - aWeight *= aColor.w; - - if (all (lessThanEqual (aWeight.xyz, THRESHOLD))) - { - return vec4 (aResult.x, - aResult.y, - aResult.z, - aWeight.w); - } - } + // For polygons that are parallel to the screen plane, the depth slope + // is equal to 1, resulting in small polygon offset. For polygons that + // that are at a large angle to the screen, the depth slope tends to 1, + // resulting in a larger polygon offset + float aPolygonOffset = uSceneEpsilon * min ( + EPS_SCALE / abs (dot (theRay.Direct, aHit.Normal)), EPS_SCALE / MIN_SLOPE); + + if (anOpenGlDepth - aPolygonOffset < aHit.Time) + { + vec4 aColor = ComputeOpenGlColor (theRay); + + aResult += aWeight.xyz * aColor.xyz; + aWeight *= aColor.w; } vec3 aPoint = theRay.Direct * aHit.Time + theRay.Origin; - + vec3 aAmbient = texelFetch ( uRaytraceMaterialTexture, MATERIAL_AMBN (aTriIndex.w)).rgb; - vec3 aDiffuse = texelFetch ( - uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w)).rgb; + vec4 aDiffuse = texelFetch ( + uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w)); vec4 aSpecular = texelFetch ( uRaytraceMaterialTexture, MATERIAL_SPEC (aTriIndex.w)); vec4 aOpacity = texelFetch ( uRaytraceMaterialTexture, MATERIAL_TRAN (aTriIndex.w)); vec3 aEmission = texelFetch ( uRaytraceMaterialTexture, MATERIAL_EMIS (aTriIndex.w)).rgb; - - vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex); + +#ifdef USE_TEXTURES + if (aDiffuse.w >= 0.f) + { + vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f); + + vec4 aTrsfRow1 = texelFetch ( + uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w)); + vec4 aTrsfRow2 = texelFetch ( + uRaytraceMaterialTexture, MATERIAL_TRS2 (aTriIndex.w)); + + aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord), + dot (aTrsfRow2, aTexCoord)); + + vec3 aTexColor = textureLod ( + uTextureSamplers[int(aDiffuse.w)], aTexCoord.st, 0.f).rgb; + + aDiffuse.rgb *= aTexColor; + aAmbient.rgb *= aTexColor; + } +#endif vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0); vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1); vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2); + vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex); + aNormal = normalize (MatrixRowMultiplyDir ( aNormal, aInvTransf0, aInvTransf1, aInvTransf2)); @@ -952,11 +981,11 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) if (bool(uShadowsEnable)) { vec3 aInverse = 1.0f / max (abs (aLight.xyz), SMALL); - + aInverse.x = aLight.x < 0.0f ? -aInverse.x : aInverse.x; aInverse.y = aLight.y < 0.0f ? -aInverse.y : aInverse.y; aInverse.z = aLight.z < 0.0f ? -aInverse.z : aInverse.z; - + aVisibility = SceneAnyHit (aShadow, aInverse, aDistance); } @@ -964,27 +993,25 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) { vec3 aIntensity = vec3 (texelFetch ( uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx))); - + float aLdotN = dot (aShadow.Direct, aNormal); - + if (aOpacity.y > 0.0f) // force two-sided lighting aLdotN = abs (aLdotN); // for transparent surfaces - + if (aLdotN > 0.0f) { float aRdotV = dot (reflect (aShadow.Direct, aNormal), theRay.Direct); - + aResult.xyz += aWeight.xyz * (aOpacity.x * aVisibility) * aIntensity * - (aDiffuse * aLdotN + aSpecular.xyz * pow (max (0.0f, aRdotV), aSpecular.w)); + (aDiffuse.rgb * aLdotN + aSpecular.xyz * pow (max (0.0f, aRdotV), aSpecular.w)); } } } - - aResult.xyz += aWeight.xyz * uGlobalAmbient.xyz * - aAmbient * aOpacity.x * max (abs (dot (aNormal, theRay.Direct)), 0.5f); - aResult.xyz += aWeight.xyz * aOpacity.x * aEmission; - + aResult.xyz += aWeight.xyz * aOpacity.x * (uGlobalAmbient.xyz * + aAmbient * max (abs (dot (aNormal, theRay.Direct)), 0.5f) + aEmission); + if (aOpacity.x != 1.0f) { aWeight *= aOpacity.y; @@ -994,13 +1021,13 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) theRay.Direct = Refract (theRay.Direct, aNormal, aOpacity.z, aOpacity.w); theInverse = 1.0f / max (abs (theRay.Direct), SMALL); - + theInverse.x = theRay.Direct.x < 0.0f ? -theInverse.x : theInverse.x; theInverse.y = theRay.Direct.y < 0.0f ? -theInverse.y : theInverse.y; theInverse.z = theRay.Direct.z < 0.0f ? -theInverse.z : theInverse.z; - + aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon); - + // Disable combining image with OpenGL output anOpenGlDepth = MAXFLOAT; } @@ -1013,26 +1040,26 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) { aWeight *= bool(uReflectionsEnable) ? texelFetch (uRaytraceMaterialTexture, MATERIAL_REFL (aTriIndex.w)) : vec4 (0.0f); - + theRay.Direct = reflect (theRay.Direct, aNormal); - + if (dot (theRay.Direct, aHit.Normal) < 0.0f) { theRay.Direct = reflect (theRay.Direct, aHit.Normal); } theInverse = 1.0f / max (abs (theRay.Direct), SMALL); - + theInverse.x = theRay.Direct.x < 0.0f ? -theInverse.x : theInverse.x; theInverse.y = theRay.Direct.y < 0.0f ? -theInverse.y : theInverse.y; theInverse.z = theRay.Direct.z < 0.0f ? -theInverse.z : theInverse.z; - + aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon); // Disable combining image with OpenGL output anOpenGlDepth = MAXFLOAT; } - + if (all (lessThanEqual (aWeight.xyz, THRESHOLD))) { return vec4 (aResult.x, @@ -1040,7 +1067,7 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) aResult.z, aWeight.w); } - + theRay.Origin = theRay.Direct * uSceneEpsilon + aPoint; } diff --git a/tests/v3d/raytrace/textures b/tests/v3d/raytrace/textures new file mode 100644 index 0000000000..f58f0729f3 --- /dev/null +++ b/tests/v3d/raytrace/textures @@ -0,0 +1,75 @@ +puts "========" +puts "Ray Tracing - check refraction" +puts "========" + +vinit View1 +vclear +vrenderparams -rasterization +vsetdispmode 1 +vsetgradientbg 180 200 255 180 180 180 2 + +box wall1 1 8 8 +box wall2 1 8 8 +box wall3 16 8 1 + +psphere S1 1.5 +psphere S2 1.5 +psphere S3 1.5 + +box B1 -1.5 -1.5 -1.5 2.5 2 3 +box B2 -1.5 -1.5 -1.5 2.5 2 3 +box B3 -1.5 -1.5 -1.5 2.5 2 3 + +vdisplay S1 +vdisplay S2 +vdisplay S3 + +vdisplay B1 +vdisplay B2 +vdisplay B3 + +vdisplay wall1 +vdisplay wall2 +vdisplay wall3 + +vtexture S1 8 +vtexture S2 2 +vtexture S3 3 + +vtexture B1 4 +vtexture B2 5 +vtexture B3 6 + +vsetlocation S1 2 2 4 +vsetlocation S2 -2 2 4 +vsetlocation S3 -6 2 4 + +vsetlocation B1 2 6 4 +vsetlocation B2 -2 6 4 +vsetlocation B3 -6 6 4 + +vsetlocation wall1 -10 0 0 +vsetlocation wall2 5 0 0 +vsetlocation wall3 -10 0 -1 + +vsetmaterial S1 gold +vsetmaterial S2 silver +vsetmaterial S3 copper + +vsetmaterial B1 steel +vsetmaterial B2 pewter +vsetmaterial B3 chrome + +vsetmaterial wall1 stone +vsetmaterial wall2 stone +vsetmaterial wall3 pewter + +vsetcolor wall1 red +vsetcolor wall2 green + +vright +vturnview 0 -0.3 0 +vfit +vlight change 0 pos 1 1 1 +vlight add directional +vrenderparams -raytrace -raydepth 3 -shadows on -reflections -fsaa -- 2.20.1