From ee71875b4b450fac217641badbd9d4c407a4c125 Mon Sep 17 00:00:00 2001 From: Mario Luzeiro Date: Sat, 1 Oct 2016 00:59:51 +0100 Subject: [PATCH] Implement normal perturbation materials on raytracing --- .../c3d_render_createscene.cpp | 10 +++ .../c3d_render_raytracing.cpp | 2 +- .../c3d_render_raytracing.h | 4 ++ .../3d_render_raytracing/cmaterial.cpp | 64 ++++++++++++++++++ .../3d_render_raytracing/cmaterial.h | 67 +++++++++++++++++++ .../shapes3D/ccylinder.cpp | 8 +++ .../shapes3D/cdummyblock.cpp | 8 +++ .../shapes3D/clayeritem.cpp | 53 ++++++++++++++- .../3d_render_raytracing/shapes3D/cobject.h | 1 + .../3d_render_raytracing/shapes3D/cplane.cpp | 7 ++ .../shapes3D/croundseg.cpp | 35 ++++++++++ .../shapes3D/ctriangle.cpp | 7 ++ 12 files changed, 263 insertions(+), 3 deletions(-) diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp index 87521e5838..1b0c27d5e8 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp @@ -54,6 +54,10 @@ void C3D_RENDER_RAYTRACING::setupMaterials() { + m_board_normal_perturbator = CBOARDNORMAL( 1.25f * IU_PER_MM * m_settings.BiuTo3Dunits() ); + m_copper_normal_perturbator = CCOPPERNORMAL( &m_board_normal_perturbator ); + m_solder_mask_normal_perturbator = CSOLDERMASKNORMAL( &m_copper_normal_perturbator ); + // http://devernay.free.fr/cours/opengl/materials.html // Copper @@ -76,6 +80,8 @@ void C3D_RENDER_RAYTRACING::setupMaterials() 0.0f, // transparency 0.0f ); + m_materials.m_Copper.SetNormalPerturbator( &m_copper_normal_perturbator ); + m_materials.m_Paste = CBLINN_PHONG_MATERIAL( (SFVEC3F)m_settings.m_SolderPasteColor * (SFVEC3F)m_settings.m_SolderPasteColor, // ambient @@ -111,6 +117,8 @@ void C3D_RENDER_RAYTRACING::setupMaterials() m_materials.m_SolderMask.SetCastShadows( true ); + m_materials.m_SolderMask.SetNormalPerturbator( &m_solder_mask_normal_perturbator ); + m_materials.m_EpoxyBoard = CBLINN_PHONG_MATERIAL( SFVEC3F( 16.0f / 255.0f, 14.0f / 255.0f, @@ -123,6 +131,8 @@ void C3D_RENDER_RAYTRACING::setupMaterials() 0.10f, // transparency 0.0f ); // reflection + m_materials.m_EpoxyBoard.SetNormalPerturbator( &m_board_normal_perturbator ); + SFVEC3F bgTop = (SFVEC3F)m_settings.m_BgColorTop; //SFVEC3F bgBot = (SFVEC3F)m_settings.m_BgColorBot; diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp index 4ffd2df22c..579c2fe445 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp @@ -1346,7 +1346,7 @@ void C3D_RENDER_RAYTRACING::rt_render_post_process_blur_finish( GLubyte *ptrPBO, #pragma omp barrier // Debug code - m_postshader_ssao.DebugBuffersOutputAsImages(); + //m_postshader_ssao.DebugBuffersOutputAsImages(); } // End rendering diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h index b5af57c4bf..934e2f4bb6 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h +++ b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h @@ -96,6 +96,10 @@ private: CBLINN_PHONG_MATERIAL m_Floor; }m_materials; + CBOARDNORMAL m_board_normal_perturbator; + CCOPPERNORMAL m_copper_normal_perturbator; + CSOLDERMASKNORMAL m_solder_mask_normal_perturbator; + bool m_isPreview; SFVEC3F shadeHit( const SFVEC3F &aBgColor, diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.cpp index a0425f9bce..d63e5723ff 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.cpp @@ -28,6 +28,7 @@ */ #include "cmaterial.h" +#include <3d_math.h> #include @@ -40,6 +41,8 @@ CMATERIAL::CMATERIAL() m_transparency = 0.0f; // completely opaque m_cast_shadows = true; m_reflection = 0.0f; + + m_normal_perturbator = NULL; } @@ -66,6 +69,8 @@ CMATERIAL::CMATERIAL( const SFVEC3F &aAmbient, m_transparency = aTransparency; m_reflection = aReflection; m_cast_shadows = true; + + m_normal_perturbator = NULL; } @@ -117,3 +122,62 @@ SFVEC3F CBLINN_PHONG_MATERIAL::Shade( const RAY &aRay, return m_ambientColor * ambientFactor; } + + +CPROCEDURALGENERATOR::CPROCEDURALGENERATOR() +{ +} + + +CBOARDNORMAL::CBOARDNORMAL( float aScale ) : CPROCEDURALGENERATOR() +{ + m_scale = (2.0f * glm::pi()) / aScale; +} + + +SFVEC3F CBOARDNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const +{ + const SFVEC3F hitPos = aRay.at( aHitInfo.m_tHit ); + + // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJzaW4oc2luKHgpKjEuNykrMSIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi0wLjk2MjEwNTcwODA3ODUyNjIiLCI3Ljk3MTQyNjI2NzYwMTQzIiwiLTIuNTE3NjIwMzUxNDgyNDQ5IiwiMi45Nzk5Mzc3ODczOTc1MzAzIl0sInNpemUiOls2NDgsMzk4XX1d + + return SFVEC3F( ((float)glm::sin( glm::sin(hitPos.x * m_scale ) ) + 1.0f) * 0.15f, + ((float)glm::sin( glm::sin(hitPos.y * m_scale ) ) + 1.0f) * 0.07f, + 0.0f ); +} + + +CCOPPERNORMAL::CCOPPERNORMAL( const CBOARDNORMAL *aBoardNormalGenerator ) +{ + m_board_normal_generator = aBoardNormalGenerator; +} + + +SFVEC3F CCOPPERNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const +{ + if( m_board_normal_generator ) + { + const SFVEC3F boardNormal = m_board_normal_generator->Generate( aRay, aHitInfo ); + + return boardNormal * SFVEC3F(0.75f); + } + else + return SFVEC3F(0.0f); +} + +CSOLDERMASKNORMAL::CSOLDERMASKNORMAL( const CCOPPERNORMAL *aCopperNormalGenerator ) +{ + m_copper_normal_generator = aCopperNormalGenerator; +} + +SFVEC3F CSOLDERMASKNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const +{ + if( m_copper_normal_generator ) + { + const SFVEC3F copperNormal = m_copper_normal_generator->Generate( aRay, aHitInfo ); + + return copperNormal * SFVEC3F(0.40f); + } + else + return SFVEC3F(0.0f); +} diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.h b/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.h index 630ec89b2a..18eb1dc1d1 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.h +++ b/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.h @@ -33,6 +33,68 @@ #include "ray.h" #include "hitinfo.h" +/// A base class that can be used to derive a procedural generator implementation +class CPROCEDURALGENERATOR +{ +public: + CPROCEDURALGENERATOR(); + + /** + * @brief Generate - Generates a 3D vector based on the ray and + * hit information depending on the implementation + * @param aRay: the camera ray that hits the object + * @param aHitInfo: the hit information + * @return the result of the procedural + */ + virtual SFVEC3F Generate( const RAY &aRay, + const HITINFO &aHitInfo ) const = 0; + +protected: + +}; + + +// Procedural generation of the board normals +class CBOARDNORMAL : public CPROCEDURALGENERATOR +{ +public: + CBOARDNORMAL() : CPROCEDURALGENERATOR() { m_scale = 1.0f; } + CBOARDNORMAL( float aScale ); + + // Imported from CPROCEDURALGENERATOR + SFVEC3F Generate( const RAY &aRay, + const HITINFO &aHitInfo ) const override; +private: + float m_scale; +}; + +// Procedural generation of the copper normals +class CCOPPERNORMAL : public CPROCEDURALGENERATOR +{ +public: + CCOPPERNORMAL() : CPROCEDURALGENERATOR() { m_board_normal_generator = NULL; } + CCOPPERNORMAL( const CBOARDNORMAL *aBoardNormalGenerator ); + + // Imported from CPROCEDURALGENERATOR + SFVEC3F Generate( const RAY &aRay, + const HITINFO &aHitInfo ) const override; +private: + const CBOARDNORMAL *m_board_normal_generator; +}; + +// Procedural generation of the solder mask +class CSOLDERMASKNORMAL : public CPROCEDURALGENERATOR +{ +public: + CSOLDERMASKNORMAL() : CPROCEDURALGENERATOR() { m_copper_normal_generator = NULL; } + CSOLDERMASKNORMAL( const CCOPPERNORMAL *aCopperNormalGenerator ); + + // Imported from CPROCEDURALGENERATOR + SFVEC3F Generate( const RAY &aRay, + const HITINFO &aHitInfo ) const override; +private: + const CCOPPERNORMAL *m_copper_normal_generator; +}; /// A base material class that can be used to derive a material implementation class CMATERIAL @@ -81,6 +143,9 @@ public: const SFVEC3F &aLightColor, float aShadowAttenuationFactor ) const = 0; + void SetNormalPerturbator( const CPROCEDURALGENERATOR *aPerturbator ) { m_normal_perturbator = aPerturbator; } + const CPROCEDURALGENERATOR *GetNormalPerturbator() const { return m_normal_perturbator; } + protected: SFVEC3F m_ambientColor; @@ -94,6 +159,8 @@ protected: float m_transparency; ///< 1.0 is completely transparent, 0.0 completely opaque float m_reflection; ///< 1.0 completely reflective, 0.0 no reflective bool m_cast_shadows; ///< true if this object will block the light + + const CPROCEDURALGENERATOR *m_normal_perturbator; }; diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ccylinder.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ccylinder.cpp index eac6411d57..83b12ca64e 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ccylinder.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ccylinder.cpp @@ -114,6 +114,14 @@ bool CVCYLINDER::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( -(hitPoint2D.x - m_center.x) * m_inv_radius, -(hitPoint2D.y - m_center.y) * m_inv_radius, 0.0f ); + + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + aHitInfo.pHitObject = this; } diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cdummyblock.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cdummyblock.cpp index d1392f3ba0..63ecce1c11 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cdummyblock.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cdummyblock.cpp @@ -53,6 +53,14 @@ bool CDUMMYBLOCK::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f ); else aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f,-1.0f ); + + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + aHitInfo.pHitObject = this; return true; diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/clayeritem.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/clayeritem.cpp index 8562aa1afd..bec1e601c4 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/clayeritem.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/clayeritem.cpp @@ -66,7 +66,7 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const if( fabs(tBBoxStart - tBBoxEnd) < FLT_EPSILON ) return false; - bool startedInside = m_bbox.Inside( aRay.m_Origin ); + const bool startedInside = m_bbox.Inside( aRay.m_Origin ); if( !startedInside ) { @@ -122,6 +122,13 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -139,6 +146,13 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -161,6 +175,13 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -183,6 +204,13 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -228,6 +256,13 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( outNormal.x, outNormal.y, 0.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } } @@ -259,13 +294,19 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const if( tBBoxEnd < aHitInfo.m_tHit ) { aHitInfo.m_tHit = tBBoxEnd; + aHitInfo.pHitObject = this; if( aRay.m_Dir.z > 0.0f ) aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f ); else aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f ); - aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } return true; } @@ -279,6 +320,7 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const // and calculate the real hitT of the ray. const SFVEC3F hitPoint = boxHitPointStart + (boxHitPointEnd - boxHitPointStart) * tOut; + const float t = glm::length( hitPoint - aRay.m_Origin ); if( t < aHitInfo.m_tHit ) @@ -288,6 +330,13 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aHitInfo.m_HitNormal = SFVEC3F( outNormal.x, outNormal.y, 0.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } } diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h index 3a7b24c948..0a9d13262b 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h @@ -46,6 +46,7 @@ enum OBJECT3D_TYPE OBJ3D_MAX }; + class COBJECT { protected: diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cplane.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cplane.cpp index 730ec7f308..e16465cd41 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cplane.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cplane.cpp @@ -90,6 +90,13 @@ bool CXYPLANE::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const else aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f,-1.0f ); + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/croundseg.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/croundseg.cpp index 91b305c894..268941b341 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/croundseg.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/croundseg.cpp @@ -89,6 +89,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const aRay.m_dirIsNeg[2]? 1.0f: -1.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -125,6 +132,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const 0.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -162,6 +176,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const 0.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -212,6 +233,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const 0.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } @@ -252,6 +280,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const 0.0f ); aHitInfo.pHitObject = this; + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + return true; } diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ctriangle.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ctriangle.cpp index 630d59c82c..19d2e63167 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ctriangle.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/ctriangle.cpp @@ -259,6 +259,13 @@ bool CTRIANGLE::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const u * m_normal[1] + v * m_normal[2] ); + if (m_material->GetNormalPerturbator()) + { + aHitInfo.m_HitNormal = aHitInfo.m_HitNormal + + m_material->GetNormalPerturbator()->Generate( aRay, aHitInfo ); + aHitInfo.m_HitNormal = glm::normalize( aHitInfo.m_HitNormal ); + } + aHitInfo.pHitObject = this; return true;