SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLRay.cpp
Go to the documentation of this file.
1 /**
2  * \file SLRay.cpp
3  * \date July 2014
4  * \authors Marcus Hudritsch
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8 */
9 
10 #include <atomic>
11 #include <cmath>
12 #include <ctime>
13 #include <random>
14 
15 #include <SLRay.h>
16 #include <SLSceneView.h>
17 #include <SLSkybox.h>
18 
19 // init static variables
21 SLfloat SLRay::minContrib = 1.0 / 256.0;
35 
36 //-----------------------------------------------------------------------------
37 /*! Uniform random number generator for numbers between 0 and 1 that is used in
38 SLRay, SLLightRect and SLPathtracer.
39 \remarks The engine state is thread_local and must stay that way. The ray
40 tracer and the path tracer call rnd01 concurrently from all worker threads (see
41 SLPathtracer::render). A single shared std::mt19937 would be a data race on its
42 624 word state plus its position index. That is undefined behaviour, and in
43 practice the racing threads hand each other torn and repeated values, so their
44 samples are no longer independent and the noise no longer averages out with
45 1/sqrt(N).
46 Each thread seeds its own engine from the current time mixed with a shared
47 atomic counter, so that threads created within the same second still get
48 different sequences.
49 */
51 {
52  static std::atomic<SLuint> seedCounter{0};
53 
54  thread_local std::mt19937 engine((SLuint)std::time(nullptr) * 2654435761u +
55  seedCounter.fetch_add(1u) * 40503u + 1u);
56 
57  thread_local std::uniform_real_distribution<SLfloat> dist(0.0f, 1.0f);
58 
59  return dist(engine);
60 }
61 //-----------------------------------------------------------------------------
62 /*!
63 SLRay::SLRay default constructor
64 */
66 {
69  type = PRIMARY;
70  length = FLT_MAX;
71  depth = 1;
72  hitTriangle = -1;
76  hitAO = 1.0f;
77  hitNode = nullptr;
78  hitMesh = nullptr;
79  srcNode = nullptr;
80  srcMesh = nullptr;
81  srcTriangle = -1;
82  x = -1;
83  y = -1;
84  contrib = 1.0f;
85  isOutside = true;
86  isInsideVolume = false;
87  sv = sceneView;
88 }
89 //-----------------------------------------------------------------------------
90 /*!
91 SLRay::SLRay constructor for primary rays
92 */
93 SLRay::SLRay(const SLVec3f& Origin,
94  const SLVec3f& Dir,
95  SLfloat X,
96  SLfloat Y,
97  const SLCol4f& backColor,
98  SLSceneView* sceneView)
99 {
100  origin = Origin;
101  setDir(Dir);
102  type = PRIMARY;
103  length = FLT_MAX;
104  depth = 1;
105  hitTriangle = -1;
109  hitAO = 1.0f;
110  hitNode = nullptr;
111  hitMesh = nullptr;
112  srcNode = nullptr;
113  srcMesh = nullptr;
114  srcTriangle = -1;
115  x = (SLfloat)X;
116  y = (SLfloat)Y;
117  contrib = 1.0f;
118  isOutside = true;
119  isInsideVolume = false;
120  backgroundColor = backColor;
121  sv = sceneView;
122 }
123 //-----------------------------------------------------------------------------
124 /*!
125 SLRay::SLRay constructor for shadow rays
126 */
127 SLRay::SLRay(SLfloat distToLight,
128  const SLVec3f& dirToLight,
129  SLRay* rayFromHitPoint)
130 {
131  origin = rayFromHitPoint->hitPoint;
132  setDir(dirToLight);
133  type = SHADOW;
134  length = distToLight;
135  lightDist = distToLight;
136  depth = rayFromHitPoint->depth;
140  hitAO = 1.0f;
141  hitTriangle = -1;
142  hitNode = nullptr;
143  hitMesh = nullptr;
144  srcNode = rayFromHitPoint->hitNode;
145  srcMesh = rayFromHitPoint->hitMesh;
146  srcTriangle = rayFromHitPoint->hitTriangle;
147  x = rayFromHitPoint->x;
148  y = rayFromHitPoint->y;
149  backgroundColor = rayFromHitPoint->backgroundColor;
150  sv = rayFromHitPoint->sv;
151  contrib = 0.0f;
152  isOutside = rayFromHitPoint->isOutside;
153  shadowRays++;
154 }
155 //-----------------------------------------------------------------------------
156 /*!
157 SLRay::prints prints the rays origin (O), direction (D) and the length to the
158 intersection (L)
159 */
160 void SLRay::print() const
161 {
162  SL_LOG("Ray: O(%.2f, %.2f, %.2f), D(%.2f, %.2f, %.2f), L: %.2f",
163  origin.x,
164  origin.y,
165  origin.z,
166  dir.x,
167  dir.y,
168  dir.z,
169  length);
170 }
171 //-----------------------------------------------------------------------------
172 /*!
173 SLRay::reflect calculates a secondary ray reflected at the normal, starting at
174 the intersection point. All vectors must be normalized vectors.
175 R = 2(-I*N) N + I
176 */
177 void SLRay::reflect(SLRay* reflected) const
178 {
179 #ifdef DEBUG_RAY
180  for (SLint i = 0; i < depth; ++i)
181  cout << " ";
182  cout << "Reflect: " << hitMesh->name() << endl;
183 #endif
184 
185  SLVec3f R(dir - 2.0f * (dir * hitNormal) * hitNormal);
186 
187  reflected->setDir(R);
188  reflected->origin.set(hitPoint);
189  reflected->depth = depth + 1;
190  reflected->length = FLT_MAX;
191  reflected->contrib = contrib * hitMesh->mat()->kr();
192  reflected->srcNode = hitNode;
193  reflected->srcMesh = hitMesh;
194  reflected->srcTriangle = hitTriangle;
195  reflected->type = REFLECTED;
196  reflected->isOutside = isOutside;
197  reflected->x = x;
198  reflected->y = y;
199  reflected->sv = sv;
200  if (sv->s()->skybox())
201  reflected->backgroundColor = sv->s()->skybox()->colorAtDir(reflected->dir);
202  else
203  reflected->backgroundColor = backgroundColor;
204 
205  depthReached = reflected->depth;
206  ++reflectedRays;
207 }
208 //-----------------------------------------------------------------------------
209 /*!
210 SLRay::refract calculates a secondary refracted ray, starting at the
211 intersection point. All vectors must be normalized vectors, so the refracted
212 vector T will be a unit vector too. If total internal refraction occurs a
213 reflected ray is calculated instead.
214 Index of refraction eta = Kn_Source/Kn_Destination (Kn_Air = 1.0)
215 We are using a formula by Xavier Bec that is a little faster:
216 http://www.realtimerendering.com/resources/RTNews/html/rtnv10n1.html#art3
217 */
218 void SLRay::refract(SLRay* refracted)
219 {
220  assert(hitMesh && "hitMesh is null");
221 
222  SLVec3f T; // refracted direction
223  SLfloat eta; // refraction coefficient
224 
225  SLfloat c1 = hitNormal.dot(-dir);
226  SLbool hitFrontSide = c1 > 0.0f;
227 
228  SLMaterial* srcMat = srcMesh ? srcMesh->mat() : nullptr;
229  SLMaterial* hitMat = hitMesh ? hitMesh->mat() : nullptr;
230  SLMaterial* hitMatOut = hitMesh ? hitMesh->matOut() : nullptr;
231 
232 #ifdef DEBUG_RAY
233  for (SLint i = 0; i < depth; ++i)
234  cout << " ";
235  cout << "Refract: ";
236 #endif
237 
238  // Calculate index of refraction eta = Kn_Source/Kn_Destination
239  // Case 1: From air into a mesh
240  if (isOutside)
241  {
242  eta = 1.0f / hitMat->kn();
243  }
244  else
245  { // Case 2: From inside the same mesh
246  if (hitMesh == srcMesh)
247  {
248  if (hitMatOut) // Case 2a: into another material
249  eta = hitMat->kn() / hitMatOut->kn();
250  else // Case 2b: into air
251  eta = hitMat->kn(); // = hitMat / 1.0
252  }
253  else
254  { // Case 3: We hit inside another material from the front
255  if (hitFrontSide)
256  {
257  if (hitMatOut)
258  eta = hitMatOut->kn() / hitMat->kn();
259  else
260  { // Mesh hit without outside material before leaving another mesh.
261  // This should not happen, but can due to float inaccuracies
262  eta = srcMat->kn() / hitMat->kn();
263  }
264  }
265  else // Case 4: We hit inside another material from behind
266  {
267  if (hitMatOut) // Case 4a: into another material
268  eta = hitMat->kn() / hitMatOut->kn();
269  else // Case 4b: into air
270  eta = hitMat->kn(); // = hitMat / 1.0
271  }
272  }
273  }
274 
275  // Invert the hit normal if ray hit backside for correct refraction
276  if (!hitFrontSide)
277  {
278  c1 *= -1.0f;
279  hitNormal *= -1.0f;
280  }
281 
282  SLfloat w = eta * c1;
283  SLfloat c2 = 1.0f + (w - eta) * (w + eta);
284 
285  if (c2 >= 0.0f)
286  {
287  T = eta * dir + (w - sqrt(c2)) * hitNormal;
288  refracted->contrib = contrib * hitMat->kt();
289  refracted->type = REFRACTED;
290 
291  if (isOutside)
292  refracted->isOutside = false;
293  else // inside
294  {
295  if (srcMesh == hitMesh)
296  refracted->isOutside = !hitMatOut;
297  else
298  refracted->isOutside = !hitFrontSide;
299  }
300 
301  ++refractedRays;
302  }
303  else // total internal refraction results in a internal reflected ray
304  {
305  T = 2.0f * (-dir * hitNormal) * hitNormal + dir;
306  refracted->contrib = 1.0f;
307  refracted->type = REFLECTED;
308  refracted->isOutside = isOutside; // remain inside
309  ++tirRays;
310  }
311 
312  refracted->setDir(T);
313  refracted->origin.set(hitPoint);
314  refracted->length = FLT_MAX;
315  refracted->srcNode = hitNode;
316  refracted->srcMesh = hitMesh;
317  refracted->srcTriangle = hitTriangle;
318  refracted->depth = depth + 1;
319  refracted->x = x;
320  refracted->y = y;
321  refracted->sv = sv;
322  if (sv->s()->skybox())
323  refracted->backgroundColor = sv->s()->skybox()->colorAtDir(refracted->dir);
324  else
325  refracted->backgroundColor = backgroundColor;
326  depthReached = refracted->depth;
327 
328 #ifdef DEBUG_RAY
329  cout << hitMesh->name();
330  if (isOutside)
331  cout << ",out";
332  else
333  cout << ",in";
334  if (refracted->isOutside)
335  cout << ">out";
336  else
337  cout << ">in";
338  cout << ", dir: " << refracted->dir.toString();
339  cout << ", contrib: " << Utils::toString(refracted->contrib, 2);
340  cout << endl;
341 #endif
342 }
343 //-----------------------------------------------------------------------------
344 /*!
345 SLRay::lobeToWorld returns the rotation matrix that maps a direction sampled
346 around the +z axis onto lobeAxis. Its columns are an orthonormal basis whose
347 third vector is lobeAxis, so that rotMat * v = v.x*t + v.y*b + v.z*lobeAxis.
348 
349 This replaces the axis-angle construction that the scattering functions used to
350 do themselves:
351 
352  SLVec3f rotAxis((SLVec3f(0,0,1) ^ dir).normalize());
353  rotMat.rotation(acos(dir.z) * 180 * ONEOVERPI, rotAxis);
354 
355 which fails exactly where it is used most. The cross product is
356 (-dir.y, dir.x, 0) and its length is the sine of the angle, so it vanishes for
357 a lobe axis along +-z. SLVec3::normalize guards with if (L > 0) and therefore
358 returns the zero vector rather than a NaN, and the matrix built from a zero
359 axis is diag(cos a, cos a, cos a) - a uniform scale, not a rotation. It happens
360 to be usable at exactly +-z (identity and -I, and -I is fine for an
361 azimuthally symmetric lobe) but the axis loses its precision continuously as
362 the lobe approaches either pole, and acos(dir.z) additionally returns a NaN as
363 soon as rounding pushes |dir.z| past 1. In the Muttenzer Box the box is axis
364 aligned and the front and back walls face +-z, so this is the common case and
365 not a corner one.
366 
367 The basis is the branchless construction of Duff et al., "Building an
368 Orthonormal Basis, Revisited", JCGT 6(1), 2017. It is exact and orthonormal for
369 every unit vector including both poles, needs no trigonometry, and has no
370 branch on a tolerance that has to be tuned.
371 */
373 {
374  SLVec3f n(lobeAxis);
375  n.normalize();
376 
377  SLfloat sign = std::copysign(1.0f, n.z);
378  SLfloat a = -1.0f / (sign + n.z);
379  SLfloat b = n.x * n.y * a;
380 
381  SLVec3f t(1.0f + sign * n.x * n.x * a, sign * b, -sign * n.x);
382  SLVec3f u(b, sign + n.y * n.y * a, -n.y);
383 
384  // The SLMat3 constructor takes the components in row order and stores them
385  // column wise, so this sets the columns to t, u and n.
386  return SLMat3f(t.x, u.x, n.x, t.y, u.y, n.y, t.z, u.z, n.z);
387 }
388 //-----------------------------------------------------------------------------
389 /*!
390 SLRay::reflectMC scatters a ray around perfect specular direction according to
391 shininess (for higher shininess the ray is less scattered). This is used for
392 path tracing and distributed ray tracing as well as for photon scattering.
393 The direction is calculated according to MCCABE. The created direction is
394 along z-axis and then transformed to lie along specular direction with
395 rotationMatrix rotMat, which SLRay::lobeToWorld builds from the perfect
396 specular direction. The rotation matrix must be precalculated (stays the same
397 for each ray sample, needs to be calculated only once).
398 
399 reflected->dir must hold the perfect specular direction on entry, i.e. the
400 caller must have run SLRay::reflect first, because it is the reference against
401 which the sampled direction is tested.
402 
403 \return false if the sample landed on the far side of the surface. The Phong
404 lobe is a cone around the mirror direction and is not clipped to the
405 hemisphere, so a wide lobe at a grazing angle puts part of its samples below
406 the horizon. The normalised Phong BRDF is zero there, so such a sample carries
407 no energy and the caller must not trace it. Note that the test is a comparison
408 of signs and not "points along the normal": SLMesh::preShade does not flip the
409 hit normal towards the ray, so a back face hit has a perfect specular direction
410 with a negative dot product and every sample around it would otherwise be
411 rejected.
412 */
413 bool SLRay::reflectMC(SLRay* reflected, const SLMat3f& rotMat) const
414 {
415  SLfloat eta1, eta2;
416  SLVec3f randVec;
417  SLfloat shininess = hitMesh->mat()->shininess();
418 
419  // The side of the surface the perfect specular direction leaves on
420  SLfloat perfectCos = hitNormal.dot(reflected->dir);
421 
422  // scatter within specular lobe
423  eta1 = rnd01();
424  eta2 = Utils::TWOPI * rnd01();
425  SLfloat f1 = sqrt(1.0f - pow(eta1, 2.0f / (shininess + 1.0f)));
426 
427  // tranform to cartesian
428  randVec.set(f1 * cos(eta2),
429  f1 * sin(eta2),
430  pow(eta1, 1.0f / (shininess + 1.0f)));
431 
432  // ray needs to be reset if already hit a scene node
433  if (reflected->hitNode)
434  {
435  reflected->length = FLT_MAX;
436  reflected->hitNode = nullptr;
437  reflected->hitMesh = nullptr;
438  reflected->hitPoint = SLVec3f::ZERO;
439  reflected->hitNormal = SLVec3f::ZERO;
440  }
441 
442  // apply rotation
443  reflected->setDir(rotMat * randVec);
444 
445  // Set pixel and background
446  reflected->x = x;
447  reflected->y = y;
448  reflected->sv = sv;
449  if (sv->s()->skybox())
450  reflected->backgroundColor = sv->s()->skybox()->colorAtDir(reflected->dir);
451  else
452  reflected->backgroundColor = backgroundColor;
453 
454  // true if the sample stayed on the same side of the surface as the
455  // perfect specular direction it was scattered around
456  return (perfectCos * hitNormal.dot(reflected->dir) > 0.0f);
457 }
458 //-----------------------------------------------------------------------------
459 /*!
460 SLRay::refractMC scatters a ray around perfect transmissive direction according
461 to translucency (for higher translucency the ray is less scattered).
462 This is used for path tracing and distributed ray tracing as well as for photon
463 scattering. The direction is calculated the same as with specular scattering
464 (see reflectMC). The created direction is along z-axis and then transformed to
465 lie along transmissive direction with rotationMatrix rotMat, which
466 SLRay::lobeToWorld builds from the perfect transmissive direction. The rotation
467 matrix must be precalculated (stays the same for each ray sample, needs to be
468 calculated only once).
469 
470 refracted->dir must hold the perfect transmissive direction on entry, i.e. the
471 caller must have run SLRay::refract first.
472 
473 \return false if the sample landed on the near side of the surface, for the
474 same reason as in reflectMC. Testing against the sign of the perfect direction
475 rather than against the normal is what makes this work for total internal
476 reflection too, where SLRay::refract returns a direction on the incident side.
477 */
478 bool SLRay::refractMC(SLRay* refracted, const SLMat3f& rotMat) const
479 {
480  SLfloat eta1, eta2;
481  SLVec3f randVec;
482  SLfloat translucency = hitMesh->mat()->translucency();
483 
484  // The side of the surface the perfect transmissive direction leaves on
485  SLfloat perfectCos = hitNormal.dot(refracted->dir);
486 
487  // scatter within transmissive lobe
488  eta1 = rnd01();
489  eta2 = Utils::TWOPI * rnd01();
490  SLfloat f1 = sqrt(1.0f - pow(eta1, 2.0f / (translucency + 1.0f)));
491 
492  // transform to cartesian
493  randVec.set(f1 * cos(eta2),
494  f1 * sin(eta2),
495  pow(eta1, 1.0f / (translucency + 1.0f)));
496 
497  // ray needs to be reset if already hit a scene node
498  if (refracted->hitNode)
499  {
500  refracted->length = FLT_MAX;
501  refracted->hitNode = nullptr;
502  refracted->hitMesh = nullptr;
503  refracted->hitPoint = SLVec3f::ZERO;
504  refracted->hitNormal = SLVec3f::ZERO;
505  }
506 
507  // Apply rotation
508  refracted->setDir(rotMat * randVec);
509 
510  // Set pixel and background
511  refracted->x = x;
512  refracted->y = y;
513  refracted->sv = sv;
514  if (sv->s()->skybox())
515  refracted->backgroundColor = sv->s()->skybox()->colorAtDir(refracted->dir);
516  else
517  refracted->backgroundColor = backgroundColor;
518 
519  // true if the sample stayed on the same side of the surface as the
520  // perfect transmissive direction it was scattered around
521  return (perfectCos * hitNormal.dot(refracted->dir) > 0.0f);
522 }
523 //-----------------------------------------------------------------------------
524 /*!
525 SLRay::diffuseMC scatters a ray around the hit normal with a cosine
526 distribution, which is the importance sampling of the Lambertian BRDF: the
527 density is cos(theta)/PI, so it cancels the cosine of the rendering equation
528 and every sample carries the same weight. SLPathtracer::trace is its only
529 caller in this repository.
530 
531 The random direction lies around the z-Axis and is then transformed by a
532 rotation matrix to lie along the normal. The direction is calculated according
533 to MCCABE.
534 
535 \remarks The comment here used to read "This is only used for
536 photonmapping(russian roulette)". Both halves were wrong. Cosine distributed
537 scattering is importance sampling and has nothing to do with Russian roulette,
538 which is the unrelated technique that terminates the recursion in
539 SLPathtracer::trace (see plan point 13), and there is no photon mapper in this
540 repository.
541 */
542 void SLRay::diffuseMC(SLRay* scattered) const
543 {
544  SLVec3f randVec;
545  SLfloat eta1, eta2, eta1sqrt;
546 
547  scattered->setDir(hitNormal);
548  scattered->origin = hitPoint;
549  scattered->depth = depth + 1;
550  depthReached = scattered->depth;
551 
552  // for reflectance the start material stays the same
553  scattered->srcNode = hitNode;
554  scattered->srcMesh = hitMesh;
555  scattered->type = REFLECTED;
556 
557  // Rotation matrix that takes the +z lobe onto the hit normal. See
558  // SLRay::lobeToWorld for why this is not built from an axis and an angle.
559  SLMat3f rotMat = lobeToWorld(scattered->dir);
560 
561  // cosine distribution
562  eta1 = rnd01();
563  eta2 = Utils::TWOPI * rnd01();
564  eta1sqrt = sqrt(1 - eta1);
565 
566  // transform to cartesian
567  randVec.set(eta1sqrt * cos(eta2),
568  eta1sqrt * sin(eta2),
569  sqrt(eta1));
570 
571  // Apply rotation
572  scattered->setDir(rotMat * randVec);
573 
574  // Set pixel and background
575  scattered->x = x;
576  scattered->y = y;
577  scattered->sv = sv;
578  if (sv->s()->skybox())
579  scattered->backgroundColor = sv->s()->skybox()->colorAtDir(scattered->dir);
580  else
581  scattered->backgroundColor = backgroundColor;
582 }
583 //-----------------------------------------------------------------------------
float SLfloat
analog to GLfloat
Definition: SL.h:200
#define SL_LOG(...)
Some debugging and error handling macros.
Definition: SL.h:279
unsigned int SLuint
analog to GLuint
Definition: SL.h:198
bool SLbool
analog to GLbool
Definition: SL.h:202
int SLint
analog to GLint
Definition: SL.h:197
SLMat3< SLfloat > SLMat3f
Definition: SLMat3.h:746
SLfloat rnd01()
Definition: SLRay.cpp:50
@ SHADOW
Definition: SLRay.h:26
@ PRIMARY
Definition: SLRay.h:23
@ REFLECTED
Definition: SLRay.h:24
@ REFRACTED
Definition: SLRay.h:25
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
void translucency(SLfloat transl)
Definition: SLMaterial.h:176
void kt(SLfloat kt)
Definition: SLMaterial.h:190
void shininess(SLfloat shin)
Definition: SLMaterial.h:177
void kr(SLfloat kr)
Definition: SLMaterial.h:184
void kn(SLfloat kn)
Definition: SLMaterial.h:199
SLMaterial * matOut() const
Definition: SLMesh.h:178
SLMaterial * mat() const
Definition: SLMesh.h:177
void name(const SLstring &Name)
Definition: SLObject.h:34
Ray class with ray and intersection properties.
Definition: SLRay.h:40
static SLint maxDepth
Max. recursion depth.
Definition: SLRay.h:127
static SLuint shadowRays
NO. of shadow rays.
Definition: SLRay.h:133
SLint hitTriangle
Points to the intersected triangle.
Definition: SLRay.h:110
static SLuint tirRays
NO. of TIR refraction rays.
Definition: SLRay.h:134
SLVec3f origin
Vector to the origin of ray in WS.
Definition: SLRay.h:78
static SLuint primaryRays
NO. of primary rays shot.
Definition: SLRay.h:129
bool reflectMC(SLRay *reflected, const SLMat3f &rotMat) const
Definition: SLRay.cpp:413
SLfloat lightDist
Distance to light for shadow rays.
Definition: SLRay.h:96
SLRayType type
PRIMARY, REFLECTED, REFRACTED, SHADOW.
Definition: SLRay.h:95
SLint srcTriangle
Points to the triangle at ray origin.
Definition: SLRay.h:102
static SLuint intersections
NO. of intersection.
Definition: SLRay.h:136
SLCol4f backgroundColor
Background color at pixel x,y.
Definition: SLRay.h:103
static SLint depthReached
depth reached for a primary ray
Definition: SLRay.h:137
static SLfloat minContrib
Min. contibution to color (1/256)
Definition: SLRay.h:128
SLMesh * hitMesh
Points to the intersected mesh.
Definition: SLRay.h:109
SLbool isOutside
Flag if ray is inside of a material.
Definition: SLRay.h:98
static SLint maxDepthReached
max. depth reached for all rays
Definition: SLRay.h:138
SLint depth
Recursion depth for ray tracing.
Definition: SLRay.h:81
SLfloat hitAO
Ambient occlusion factor at intersection point.
Definition: SLRay.h:116
SLVec3f dir
Direction vector of ray in WS.
Definition: SLRay.h:79
SLMesh * srcMesh
Points to the mesh at ray origin.
Definition: SLRay.h:101
void refract(SLRay *refracted)
Definition: SLRay.cpp:218
static SLMat3f lobeToWorld(const SLVec3f &lobeAxis)
Rotation matrix that maps a sample drawn around +z onto lobeAxis.
Definition: SLRay.cpp:372
SLint sign[3]
Sign of invDir for fast AABB hit in WS.
Definition: SLRay.h:121
SLfloat length
length from origin to an intersection
Definition: SLRay.h:80
void print() const
Definition: SLRay.cpp:160
SLNode * hitNode
Points to the intersected node.
Definition: SLRay.h:108
static SLuint ignoredRays
NO. of ignore refraction rays.
Definition: SLRay.h:132
SLfloat contrib
Current contribution of ray to color.
Definition: SLRay.h:82
SLbool isInsideVolume
Flag if ray is in Volume.
Definition: SLRay.h:99
SLVec3f hitPoint
Point of intersection.
Definition: SLRay.h:113
void diffuseMC(SLRay *scattered) const
Definition: SLRay.cpp:542
static SLuint subsampledPixels
NO. of of subsampled pixels.
Definition: SLRay.h:141
SLNode * srcNode
Points to the node at ray origin.
Definition: SLRay.h:100
void setDir(const SLVec3f &Dir)
Setter for the rays direction in world space also setting the inverse direction.
Definition: SLRay.h:149
bool refractMC(SLRay *refracted, const SLMat3f &rotMat) const
Definition: SLRay.cpp:478
static SLuint tests
NO. of intersection tests.
Definition: SLRay.h:135
void reflect(SLRay *reflected) const
Definition: SLRay.cpp:177
static SLuint reflectedRays
NO. of reflected rays.
Definition: SLRay.h:130
SLCol4f hitTexColor
Color at intersection for texture or color attributes.
Definition: SLRay.h:115
SLfloat y
Pixel position for primary rays.
Definition: SLRay.h:97
SLfloat x
Definition: SLRay.h:97
SLVec3f hitNormal
Surface normal at intersection point.
Definition: SLRay.h:114
SLSceneView * sv
Pointer to the sceneview.
Definition: SLRay.h:104
static SLfloat avgDepth
average depth reached
Definition: SLRay.h:139
SLRay(SLSceneView *sv=nullptr)
default ctor
Definition: SLRay.cpp:65
static SLuint refractedRays
NO. of refracted rays.
Definition: SLRay.h:131
static SLuint subsampledRays
NO. of of subsampled rays.
Definition: SLRay.h:140
void skybox(SLSkybox *skybox)
Definition: SLScene.h:91
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
SLScene * s()
Definition: SLSceneView.h:171
SLstring toString(SLstring delimiter=", ", int decimals=2)
Conversion to string.
Definition: SLVec3.h:199
T y
Definition: SLVec3.h:43
T x
Definition: SLVec3.h:43
SLVec3 & normalize()
Definition: SLVec3.h:124
void set(const T X, const T Y, const T Z)
Definition: SLVec3.h:59
T dot(const SLVec3 &v) const
Definition: SLVec3.h:117
T z
Definition: SLVec3.h:43
static SLVec3 ZERO
Definition: SLVec3.h:285
static SLVec4 WHITE
Definition: SLVec4.h:215
static const float TWOPI
Definition: Utils.h:240
string toString(float f, int roundedDecimals)
Returns a string from a float with max. one trailing zero.
Definition: Utils.cpp:92