Implement normal perturbation materials on raytracing

This commit is contained in:
Mario Luzeiro 2016-10-01 00:59:51 +01:00 committed by Wayne Stambaugh
parent 89bb47ede6
commit ee71875b4b
12 changed files with 263 additions and 3 deletions

View File

@ -54,6 +54,10 @@
void C3D_RENDER_RAYTRACING::setupMaterials() 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 // http://devernay.free.fr/cours/opengl/materials.html
// Copper // Copper
@ -76,6 +80,8 @@ void C3D_RENDER_RAYTRACING::setupMaterials()
0.0f, // transparency 0.0f, // transparency
0.0f ); 0.0f );
m_materials.m_Copper.SetNormalPerturbator( &m_copper_normal_perturbator );
m_materials.m_Paste = CBLINN_PHONG_MATERIAL( m_materials.m_Paste = CBLINN_PHONG_MATERIAL(
(SFVEC3F)m_settings.m_SolderPasteColor * (SFVEC3F)m_settings.m_SolderPasteColor *
(SFVEC3F)m_settings.m_SolderPasteColor, // ambient (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.SetCastShadows( true );
m_materials.m_SolderMask.SetNormalPerturbator( &m_solder_mask_normal_perturbator );
m_materials.m_EpoxyBoard = CBLINN_PHONG_MATERIAL( m_materials.m_EpoxyBoard = CBLINN_PHONG_MATERIAL(
SFVEC3F( 16.0f / 255.0f, SFVEC3F( 16.0f / 255.0f,
14.0f / 255.0f, 14.0f / 255.0f,
@ -123,6 +131,8 @@ void C3D_RENDER_RAYTRACING::setupMaterials()
0.10f, // transparency 0.10f, // transparency
0.0f ); // reflection 0.0f ); // reflection
m_materials.m_EpoxyBoard.SetNormalPerturbator( &m_board_normal_perturbator );
SFVEC3F bgTop = (SFVEC3F)m_settings.m_BgColorTop; SFVEC3F bgTop = (SFVEC3F)m_settings.m_BgColorTop;
//SFVEC3F bgBot = (SFVEC3F)m_settings.m_BgColorBot; //SFVEC3F bgBot = (SFVEC3F)m_settings.m_BgColorBot;

View File

@ -1346,7 +1346,7 @@ void C3D_RENDER_RAYTRACING::rt_render_post_process_blur_finish( GLubyte *ptrPBO,
#pragma omp barrier #pragma omp barrier
// Debug code // Debug code
m_postshader_ssao.DebugBuffersOutputAsImages(); //m_postshader_ssao.DebugBuffersOutputAsImages();
} }
// End rendering // End rendering

View File

@ -96,6 +96,10 @@ private:
CBLINN_PHONG_MATERIAL m_Floor; CBLINN_PHONG_MATERIAL m_Floor;
}m_materials; }m_materials;
CBOARDNORMAL m_board_normal_perturbator;
CCOPPERNORMAL m_copper_normal_perturbator;
CSOLDERMASKNORMAL m_solder_mask_normal_perturbator;
bool m_isPreview; bool m_isPreview;
SFVEC3F shadeHit( const SFVEC3F &aBgColor, SFVEC3F shadeHit( const SFVEC3F &aBgColor,

View File

@ -28,6 +28,7 @@
*/ */
#include "cmaterial.h" #include "cmaterial.h"
#include <3d_math.h>
#include <wx/debug.h> #include <wx/debug.h>
@ -40,6 +41,8 @@ CMATERIAL::CMATERIAL()
m_transparency = 0.0f; // completely opaque m_transparency = 0.0f; // completely opaque
m_cast_shadows = true; m_cast_shadows = true;
m_reflection = 0.0f; m_reflection = 0.0f;
m_normal_perturbator = NULL;
} }
@ -66,6 +69,8 @@ CMATERIAL::CMATERIAL( const SFVEC3F &aAmbient,
m_transparency = aTransparency; m_transparency = aTransparency;
m_reflection = aReflection; m_reflection = aReflection;
m_cast_shadows = true; m_cast_shadows = true;
m_normal_perturbator = NULL;
} }
@ -117,3 +122,62 @@ SFVEC3F CBLINN_PHONG_MATERIAL::Shade( const RAY &aRay,
return m_ambientColor * ambientFactor; return m_ambientColor * ambientFactor;
} }
CPROCEDURALGENERATOR::CPROCEDURALGENERATOR()
{
}
CBOARDNORMAL::CBOARDNORMAL( float aScale ) : CPROCEDURALGENERATOR()
{
m_scale = (2.0f * glm::pi<float>()) / 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);
}

View File

@ -33,6 +33,68 @@
#include "ray.h" #include "ray.h"
#include "hitinfo.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 /// A base material class that can be used to derive a material implementation
class CMATERIAL class CMATERIAL
@ -81,6 +143,9 @@ public:
const SFVEC3F &aLightColor, const SFVEC3F &aLightColor,
float aShadowAttenuationFactor ) const = 0; float aShadowAttenuationFactor ) const = 0;
void SetNormalPerturbator( const CPROCEDURALGENERATOR *aPerturbator ) { m_normal_perturbator = aPerturbator; }
const CPROCEDURALGENERATOR *GetNormalPerturbator() const { return m_normal_perturbator; }
protected: protected:
SFVEC3F m_ambientColor; SFVEC3F m_ambientColor;
@ -94,6 +159,8 @@ protected:
float m_transparency; ///< 1.0 is completely transparent, 0.0 completely opaque float m_transparency; ///< 1.0 is completely transparent, 0.0 completely opaque
float m_reflection; ///< 1.0 completely reflective, 0.0 no reflective float m_reflection; ///< 1.0 completely reflective, 0.0 no reflective
bool m_cast_shadows; ///< true if this object will block the light bool m_cast_shadows; ///< true if this object will block the light
const CPROCEDURALGENERATOR *m_normal_perturbator;
}; };

View File

@ -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, aHitInfo.m_HitNormal = SFVEC3F( -(hitPoint2D.x - m_center.x) * m_inv_radius,
-(hitPoint2D.y - m_center.y) * m_inv_radius, -(hitPoint2D.y - m_center.y) * m_inv_radius,
0.0f ); 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; aHitInfo.pHitObject = this;
} }

View File

@ -53,6 +53,14 @@ bool CDUMMYBLOCK::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f ); aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
else else
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f,-1.0f ); 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; aHitInfo.pHitObject = this;
return true; return true;

View File

@ -66,7 +66,7 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
if( fabs(tBBoxStart - tBBoxEnd) < FLT_EPSILON ) if( fabs(tBBoxStart - tBBoxEnd) < FLT_EPSILON )
return false; return false;
bool startedInside = m_bbox.Inside( aRay.m_Origin ); const bool startedInside = m_bbox.Inside( aRay.m_Origin );
if( !startedInside ) 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.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
aHitInfo.pHitObject = this; 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; 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.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
aHitInfo.pHitObject = this; 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; 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.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
aHitInfo.pHitObject = this; 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; 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.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
aHitInfo.pHitObject = this; 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; 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.m_HitNormal = SFVEC3F( outNormal.x, outNormal.y, 0.0f );
aHitInfo.pHitObject = this; 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; return true;
} }
} }
@ -259,13 +294,19 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
if( tBBoxEnd < aHitInfo.m_tHit ) if( tBBoxEnd < aHitInfo.m_tHit )
{ {
aHitInfo.m_tHit = tBBoxEnd; aHitInfo.m_tHit = tBBoxEnd;
aHitInfo.pHitObject = this;
if( aRay.m_Dir.z > 0.0f ) if( aRay.m_Dir.z > 0.0f )
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f ); aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
else else
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f ); 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; return true;
} }
@ -279,6 +320,7 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
// and calculate the real hitT of the ray. // and calculate the real hitT of the ray.
const SFVEC3F hitPoint = boxHitPointStart + const SFVEC3F hitPoint = boxHitPointStart +
(boxHitPointEnd - boxHitPointStart) * tOut; (boxHitPointEnd - boxHitPointStart) * tOut;
const float t = glm::length( hitPoint - aRay.m_Origin ); const float t = glm::length( hitPoint - aRay.m_Origin );
if( t < aHitInfo.m_tHit ) 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.m_HitNormal = SFVEC3F( outNormal.x, outNormal.y, 0.0f );
aHitInfo.pHitObject = this; 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; return true;
} }
} }

View File

@ -46,6 +46,7 @@ enum OBJECT3D_TYPE
OBJ3D_MAX OBJ3D_MAX
}; };
class COBJECT class COBJECT
{ {
protected: protected:

View File

@ -90,6 +90,13 @@ bool CXYPLANE::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
else else
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f,-1.0f ); 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; return true;
} }

View File

@ -89,6 +89,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
aRay.m_dirIsNeg[2]? 1.0f: -1.0f ); aRay.m_dirIsNeg[2]? 1.0f: -1.0f );
aHitInfo.pHitObject = this; 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; return true;
} }
@ -125,6 +132,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
0.0f ); 0.0f );
aHitInfo.pHitObject = this; 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; return true;
} }
@ -162,6 +176,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
0.0f ); 0.0f );
aHitInfo.pHitObject = this; 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; return true;
} }
@ -212,6 +233,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
0.0f ); 0.0f );
aHitInfo.pHitObject = this; 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; return true;
} }
@ -252,6 +280,13 @@ bool CROUNDSEG::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
0.0f ); 0.0f );
aHitInfo.pHitObject = this; 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; return true;
} }

View File

@ -259,6 +259,13 @@ bool CTRIANGLE::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
u * m_normal[1] + u * m_normal[1] +
v * m_normal[2] ); 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; aHitInfo.pHitObject = this;
return true; return true;