KiCad PCB EDA Suite
material.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2020 Mario Luzeiro <[email protected]>
5  * Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include "material.h"
26 #include <3d_math.h>
27 #include <wx/debug.h>
28 
33 
34 // This may be a good value if based on nr of lights
35 // that contribute to the illumination of that point
36 #define AMBIENT_FACTOR (1.0f / 6.0f)
37 #define SPECULAR_FACTOR 1.0f
38 
39 
41 {
42  m_ambientColor = SFVEC3F( 0.2f, 0.2f, 0.2f );
43  m_emissiveColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
44  m_specularColor = SFVEC3F( 1.0f, 1.0f, 1.0f );
45  m_reflectivity = 50.2f;
46  m_transparency = 0.0f; // completely opaque
47  m_castShadows = true;
48  m_reflection = 0.0f;
49  m_absorbance = 1.0f;
54 
55  m_generator = nullptr;
56 }
57 
58 
59 MATERIAL::MATERIAL( const SFVEC3F& aAmbient, const SFVEC3F& aEmissive, const SFVEC3F& aSpecular,
60  float aShinness, float aTransparency, float aReflection )
61 {
62  wxASSERT( aReflection >= 0.0f );
63  wxASSERT( aReflection <= 1.0f );
64 
65  wxASSERT( aTransparency >= 0.0f );
66  wxASSERT( aTransparency <= 1.0f );
67 
68  wxASSERT( aShinness >= 0.0f );
69  wxASSERT( aShinness <= 180.0f );
70 
72 
73  m_emissiveColor = aEmissive;
74  m_specularColor = aSpecular;
75  m_reflectivity = aShinness;
76  m_transparency = glm::clamp( aTransparency, 0.0f, 1.0f );
77  m_absorbance = 1.0f;
78  m_reflection = aReflection;
79  m_castShadows = true;
84 
85  m_generator = nullptr;
86 }
87 
88 
89 void MATERIAL::Generate( SFVEC3F& aNormal, const RAY& aRay, const HITINFO& aHitInfo ) const
90 {
91  if( m_generator )
92  {
93  aNormal = aNormal + m_generator->Generate( aRay, aHitInfo );
94  aNormal = glm::normalize( aNormal );
95  }
96 }
97 
98 
99 // https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model
100 SFVEC3F BLINN_PHONG_MATERIAL::Shade( const RAY& aRay, const HITINFO& aHitInfo, float NdotL,
101  const SFVEC3F& aDiffuseObjColor, const SFVEC3F& aDirToLight,
102  const SFVEC3F& aLightColor,
103  float aShadowAttenuationFactor ) const
104 {
105  wxASSERT( NdotL >= FLT_EPSILON );
106 
107  // This is a hack to get some kind of fake ambient illumination
108  // There is no logic behind this, just pure artistic experimentation
109  if( aShadowAttenuationFactor > FLT_EPSILON )
110  {
111  // Calculate the diffuse light factoring in light color,
112  // power and the attenuation
113  const SFVEC3F diffuse = NdotL * aLightColor;
114 
115  // Calculate the half vector between the light vector and the view vector.
116  const SFVEC3F H = glm::normalize( aDirToLight - aRay.m_Dir );
117 
118  //Intensity of the specular light
119  const float NdotH = glm::dot( H, aHitInfo.m_HitNormal );
120  const float intensitySpecular = glm::pow( glm::max( NdotH, 0.0f ), m_reflectivity );
121 
122  return m_ambientColor +
123  aShadowAttenuationFactor * ( diffuse * aDiffuseObjColor + SPECULAR_FACTOR *
124  aLightColor * intensitySpecular * m_specularColor );
125  }
126 
127  return m_ambientColor;
128 }
129 
130 
132 {
133 }
134 
135 
137 
138 
140 {
141  m_scale = ( 2.0f * glm::pi<float>() ) / aScale;
142 }
143 
144 
145 SFVEC3F BOARD_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
146 {
147  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
148 
149  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJzaW4oc2luKHNpbih4KSoxLjkpKjEuNSkiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjEwMDAsIndpbmRvdyI6WyItMC45NjIxMDU3MDgwNzg1MjYyIiwiNy45NzE0MjYyNjc2MDE0MyIsIi0yLjUxNzYyMDM1MTQ4MjQ0OSIsIjIuOTc5OTM3Nzg3Mzk3NTMwMyJdLCJzaXplIjpbNjQ2LDM5Nl19XQ--
150 
151  // Implement a texture as the "measling crazing blistering" method of FR4
152  const float x = glm::sin( glm::sin( hitPos.x ) * 1.5f ) * 0.06f;
153  const float y = glm::sin( glm::sin( hitPos.y ) * 1.5f ) * 0.03f;
154  const float z = -(x + y) + glm::sin( hitPos.z ) * 0.06f;
155 
156  const float noise1 = s_perlinNoise.noise( hitPos.x * 1.0f, hitPos.y * 0.7f ) - 0.5f;
157  const float noise2 = s_perlinNoise.noise( hitPos.x * 0.7f, hitPos.y * 1.0f ) - 0.5f;
158  const float noise3 = s_perlinNoise.noise( hitPos.x * 0.3f, hitPos.z * 1.0f ) - 0.5f;
159 
160  return ( SFVEC3F( noise1, noise2, -( noise3 ) ) * 0.3f + SFVEC3F( x, y, z ) );
161 }
162 
163 
164 COPPER_NORMAL::COPPER_NORMAL( float aScale, const MATERIAL_GENERATOR* aBoardNormalGenerator )
165 {
166  m_board_normal_generator = aBoardNormalGenerator;
167  m_scale = 1.0f / aScale;
168 }
169 
170 
171 SFVEC3F COPPER_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
172 {
174  {
175  const SFVEC3F boardNormal = m_board_normal_generator->Generate( aRay, aHitInfo );
176 
177  SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
178 
179  const float noise =
180  ( s_perlinNoise.noise( hitPos.x + boardNormal.y + aRay.m_Origin.x * 0.2f,
181  hitPos.y + boardNormal.x ) - 0.5f ) * 2.0f;
182 
183  float scratchPattern =
184  ( s_perlinNoise.noise( noise + hitPos.x / 100.0f, hitPos.y * 100.0f ) - 0.5f );
185 
186  const float x = scratchPattern * 0.14f;
187  const float y = (noise + noise * scratchPattern) * 0.14f;
188 
189  return SFVEC3F( x, y, - ( x + y ) ) + boardNormal * 0.25f;
190  }
191  else
192  {
193  return SFVEC3F( 0.0f );
194  }
195 }
196 
197 
199 {
200  m_copper_normal_generator = aCopperNormalGenerator;
201 }
202 
203 
204 SFVEC3F SOLDER_MASK_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
205 {
207  {
208  const SFVEC3F copperNormal = m_copper_normal_generator->Generate( aRay, aHitInfo );
209 
210  return copperNormal * 0.05f;
211  }
212  else
213  {
214  return SFVEC3F( 0.0f );
215  }
216 }
217 
218 
219 SFVEC3F PLATED_COPPER_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
220 {
221  SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
222 
223  const float noise1 = ( s_perlinNoise.noise( hitPos.x, hitPos.y ) - 0.5f );
224  const float noise2 = ( s_perlinNoise.noise( hitPos.y, hitPos.x ) - 0.5f );
225 
226  return SFVEC3F( noise1, noise2, -( noise1 + noise2 ) ) * 0.02f;
227 }
228 
229 
231 {
232  m_scale = 1.0f / aScale;
233 }
234 
235 
236 SFVEC3F PLASTIC_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
237 {
238  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
239 
240  const float noise1 = s_perlinNoise.noise( hitPos.x * 1.0f, hitPos.y * 1.1f,
241  hitPos.z * 1.2f ) - 0.5f;
242 
243  const float noise2 = s_perlinNoise.noise( hitPos.x * 1.3f, hitPos.y * 1.0f,
244  hitPos.z * 1.5f ) - 0.5f;
245 
246  const float noise3 = s_perlinNoise.noise( hitPos.x * 1.0f, hitPos.y * 1.0f,
247  hitPos.z * 1.8f ) - 0.5f;
248 
249  const float distanceReduction = 1.0f / ( aHitInfo.m_tHit + 0.5f );
250 
251  return SFVEC3F( noise1, noise2, noise3 ) * SFVEC3F( distanceReduction );
252 }
253 
254 
256 {
257  m_scale = 1.0f / aScale;
258 }
259 
260 
261 SFVEC3F PLASTIC_SHINE_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
262 {
263  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
264 
265  const float noise1 = s_perlinNoise.noise( hitPos.x * 0.01f, hitPos.y * 0.01f,
266  hitPos.z * 0.01f ) - 0.5f;
267 
268  const float noise2 = s_perlinNoise.noise( hitPos.x * 1.0f, hitPos.y * 1.0f,
269  hitPos.z * 1.6f ) - 0.5f;
270 
271  float noise3 = s_perlinNoise.noise( hitPos.x * 1.5f, hitPos.y * 1.5f,
272  hitPos.z * 1.0f ) - 0.5f;
273  noise3 = noise3 * noise3 * noise3;
274 
275  return SFVEC3F( noise1, noise2, noise3 ) * SFVEC3F( 0.1f, 0.2f, 1.0f );
276 }
277 
278 
280 {
281  m_scale = 1.0f / aScale;
282 }
283 
284 
285 SFVEC3F BRUSHED_METAL_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
286 {
287  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
288 
289  const float noise1 = s_perlinNoise.noise( hitPos.x * 1.0f, hitPos.y * 1.1f,
290  hitPos.z * 1.2f ) - 0.5f;
291 
292  const float noise2 = s_perlinNoise.noise( hitPos.x * 1.3f, hitPos.y * 1.4f,
293  hitPos.z * 1.5f ) - 0.5f;
294 
295  const float noise3 = s_perlinNoise.noise( hitPos.x * 0.1f, hitPos.y * 0.1f,
296  hitPos.z * 1.0f ) - 0.5f;
297 
298  return SFVEC3F( noise1 * 0.15f + noise3 * 0.35f, noise2 * 0.25f, noise1 * noise2 * noise3 );
299 }
300 
301 
303 {
304  m_scale = 1.0f / aScale;
305 }
306 
307 
308 SFVEC3F SILK_SCREEN_NORMAL::Generate( const RAY& aRay, const HITINFO& aHitInfo ) const
309 {
310  const SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale;
311 
312  const float noise1 = s_perlinNoise.noise( hitPos.x * 2.0f, hitPos.y * 2.0f, hitPos.z );
313 
314  const float noise2 = s_perlinNoise.noise( hitPos.x * 0.6f, hitPos.y * 0.6f, hitPos.z );
315 
316  SFVEC3F t = SFVEC3F( noise1, noise2, 0.0f ) - 0.5f;
317 
318  SFVEC3F tt = t * t;
319 
320  t = t * tt * tt * 100.0f; // this factor controls the intensity of the effect
321 
322  t.z = 0.0f; // this will keep untouch the original z component of the normal
323 
324  return t;
325 }
float m_reflection
1.0 completely reflective, 0.0 no reflective.
Definition: material.h:351
#define SPECULAR_FACTOR
Definition: material.cpp:37
bool m_castShadows
true if this object will block the light.
Definition: material.h:352
void Generate(SFVEC3F &aNormal, const RAY &aRay, const HITINFO &aHitInfo) const
Definition: material.cpp:89
static int m_defaultReflectionRayCount
Definition: material.h:370
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:145
SFVEC3F m_emissiveColor
Definition: material.h:344
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:261
SFVEC3F m_ambientColor
Definition: material.h:338
float m_scale
Definition: material.h:162
float m_scale
Definition: material.h:94
Definition: ray.h:62
float m_tHit
( 4) distance
Definition: hitinfo.h:38
float m_transparency
Definition: material.h:349
static int m_defaultFeflectionRecursionCount
Definition: material.h:372
SFVEC3F m_HitPoint
(12) hit position
Definition: hitinfo.h:44
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:285
unsigned int m_reflectionRecursionCount
Definition: material.h:364
unsigned int m_refractionRayCount
Number of rays that will be interpolated for this material if it is reflective.
Definition: material.h:355
A base class that can be used to derive procedurally generated materials.
Definition: material.h:35
unsigned int m_reflectionRayCount
Number of levels it allows for refraction recursiveness.
Definition: material.h:358
unsigned int m_refractionRecursionCount
Number of levels it allows for reflection recursiveness.
Definition: material.h:361
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:308
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:236
const MATERIAL_GENERATOR * m_generator
Definition: material.h:366
static int m_defaultRefractionRecursionCount
Definition: material.h:371
SFVEC3F m_Dir
Definition: ray.h:67
#define H(x, y, z)
Definition: md5_hash.cpp:17
static PerlinNoise s_perlinNoise
Definition: material.cpp:136
SFVEC3F m_specularColor
Definition: material.h:345
SFVEC3F m_Origin
Definition: ray.h:64
const MATERIAL_GENERATOR * m_copper_normal_generator
Definition: material.h:138
static int m_defaultRefractionRayCount
Definition: material.h:369
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:35
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
SFVEC3F Shade(const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, float aShadowAttenuationFactor) const override
Shade an intersection point.
Definition: material.cpp:100
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:204
const MATERIAL_GENERATOR * m_board_normal_generator
Definition: material.h:93
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:171
SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const override
Generate a 3D vector based on the ray and hit information depending on the implementation.
Definition: material.cpp:219
Defines math related functions.
float m_absorbance
absorbance factor for the transparent material.
Definition: material.h:350
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition: hitinfo.h:37
MATERIAL()
Definition: material.cpp:40
BOARD_NORMAL()
Definition: material.h:58
float m_reflectivity
1.0 is completely transparent, 0.0 completely opaque.
Definition: material.h:346
float noise(float x, float y, float z) const
float m_scale
Definition: material.h:68
virtual SFVEC3F Generate(const RAY &aRay, const HITINFO &aHitInfo) const =0
Generate a 3D vector based on the ray and hit information depending on the implementation.
#define AMBIENT_FACTOR
Definition: material.cpp:36