SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLRayMC.cpp
Go to the documentation of this file.
1 /**
2  * \file SLRay.cpp
3  * \date February 2013
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 <stdafx.h> // precompiled headers
11 
12 #include <SLRay.h"
13 
14 // init static variables
16 SLfloat SLRay::minContrib = 1.0 / 256.0;
28 
34 
36 
37 // init only once
38 TRanrotBGenerator* SLRay::random = new TRanrotBGenerator((unsigned)time(NULL));
39 
40 //-----------------------------------------------------------------------------
41 /*!
42 SLRay::SLRay default constructor
43 */
45 {
48  type = PRIMARY;
49  length = SL_FLOAT_MAX;
50  depth = 1;
51  hitTriangle = 0;
55  hitShape = 0;
56  hitMat = 0;
57  originTria = 0;
58  originMat = 0;
59  x = -1;
60  y = -1;
61  contrib = 1.0f;
62  isOutside = true;
63 }
64 //-----------------------------------------------------------------------------
65 /*!
66 SLRay::SLRay constructor for primary rays
67 */
69 {
70  origin = Origin;
71  setDir(Dir);
72  type = PRIMARY;
73  length = SL_FLOAT_MAX;
74  depth = 1;
75  hitTriangle = 0;
79  hitShape = 0;
80  hitMat = 0;
81  originTria = 0;
82  originMat = 0;
83  x = (SLfloat)X;
84  y = (SLfloat)Y;
85  contrib = 1.0f;
86  isOutside = true;
87 }
88 //-----------------------------------------------------------------------------
89 /*!
90 SLRay::SLRay constructor for shadow rays
91 */
92 SLRay::SLRay(SLfloat distToLight,
93  SLVec3f dirToLight,
94  SLRay* rayFromHitPoint)
95 {
96  origin = rayFromHitPoint->hitPoint;
97  setDir(dirToLight);
98  type = SHADOW;
99  length = distToLight;
100  lightDist = distToLight;
101  depth = rayFromHitPoint->depth;
105  hitTriangle = 0;
106  hitShape = 0;
107  hitMat = 0;
108  originTria = rayFromHitPoint->hitTriangle;
109  originMat = rayFromHitPoint->hitMat;
110  x = rayFromHitPoint->x;
111  y = rayFromHitPoint->y;
112  contrib = 0.0f;
113  isOutside = rayFromHitPoint->isOutside;
114  shadowRays++;
115 }
116 //-----------------------------------------------------------------------------
118  SLVec3f dir,
119  SLRayType type,
120  SLShape* originShape,
121  SLfloat length,
122  SLint depth)
123 {
124  origin = origin;
125  setDir(dir);
126  type = type;
127  length = length;
128  depth = depth;
129  hitShape = 0;
132  hitMat = 0;
134  originMat = 0;
135  x = y = -1;
136 
137  if (type == SHADOW)
138  {
139  ++shadowRays;
140  lightDist = length;
141  }
142 }
143 //-----------------------------------------------------------------------------
144 /*!
145 SLRay::prints prints the rays origin (O), direction (D) and the length to the
146 intersection (L)
147 */
149 {
150  SL_LOG("Ray: O(%.2f, %.2f, %.2f), D(%.2f, %.2f, %.2f), L: %.2f\n",
151  origin.x,
152  origin.y,
153  origin.z,
154  dir.x,
155  dir.y,
156  dir.z,
157  length);
158 }
159 //-----------------------------------------------------------------------------
160 /*!
161 SLRay::normalizeNormal does a careful normalization of the normal only when the
162 squared length is > 1.0+SL_EPSILON or < 1.0-SL_EPSILON.
163 */
165 {
166  SLfloat nLenSqr = hitNormal.lengthSqr();
167  if (nLenSqr > 1.0f + SL_EPSILON || nLenSqr < 1.0f - SL_EPSILON)
168  {
169  SLfloat len = sqrt(nLenSqr);
170  hitNormal /= len;
171  }
172 }
173 //-----------------------------------------------------------------------------
174 /*!
175 SLRay::reflect calculates a secondary ray reflected at the normal, starting at
176 the intersection point. All vectors must be normalized vectors.
177 R = 2(-I�N) N + I
178 */
179 void SLRay::reflect(SLRay* reflected)
180 {
181  SLVec3f R(dir - 2.0f * (dir * hitNormal) * hitNormal);
182 
183  reflected->setDir(R);
184  reflected->origin.set(hitPoint);
185  reflected->depth = depth + 1;
186  reflected->length = SL_FLOAT_MAX;
187  reflected->contrib = contrib * hitMat->kr();
188  reflected->originMat = hitMat;
189  reflected->originShape = hitShape;
190  reflected->originTria = hitTriangle;
191  reflected->type = REFLECTED;
192  reflected->isOutside = isOutside;
193  reflected->x = x;
194  reflected->y = y;
195  depthReached = reflected->depth;
196  ++reflectedRays;
197 }
198 //-----------------------------------------------------------------------------
199 /*!
200 SLRay::refract calculates a secondary refracted ray, starting at the
201 intersection point. All vectors must be normalized vectors, so the refracted
202 vector T will be a unit vector too. If total internal refraction occurs a
203 reflected ray is calculated instead.
204 Index of refraction eta = Kn_Source/Kn_Destination (Kn_Air = 1.0)
205 */
206 void SLRay::refract(SLRay* refracted)
207 {
208  SLVec3f T; // refracted direction
209  SLfloat eta; // refraction coefficient
210 
211  // Calculate index of refraction eta = Kn_Source/Kn_Destination
212  if (isOutside)
213  {
214  if (originMat == 0) // from air (outside) into a material
215  eta = 1 / hitMat->kn();
216  else // from another material into another one
217  eta = originMat->kn() / hitMat->kn();
218  }
219  else
220  {
221  if (originMat == hitMat) // from the inside a material into air
222  eta = hitMat->kn(); // hitMat / 1
223  else // from inside a material into another material
224  eta = originMat->kn() / hitMat->kn();
225  }
226 
227  // Bec's formula is a little faster (from Ray Tracing News)
228  SLfloat c1 = hitNormal * -dir;
229  SLfloat w = eta * c1;
230  SLfloat c2 = 1.0f + (w - eta) * (w + eta);
231 
232  if (c2 >= 0.0f)
233  {
234  T = eta * dir + (w - sqrt(c2)) * hitNormal;
235  refracted->contrib = contrib * hitMat->kt();
236  refracted->type = TRANSMITTED;
237  refracted->isOutside = !isOutside;
238  ++refractedRays;
239  }
240  else // total internal refraction results in a internal reflected ray
241  {
242  T = 2.0f * (-dir * hitNormal) * hitNormal + dir;
243  refracted->contrib = 1.0f;
244  refracted->type = REFLECTED;
245  refracted->isOutside = isOutside;
246  ++tirRays;
247  }
248 
249  refracted->setDir(T);
250  refracted->origin.set(hitPoint);
251  refracted->originMat = hitMat;
252  refracted->length = SL_FLOAT_MAX;
253  refracted->originShape = hitShape;
254  refracted->originTria = hitTriangle;
255  refracted->depth = depth + 1;
256  refracted->x = x;
257  refracted->y = y;
258  depthReached = refracted->depth;
259 }
260 //-----------------------------------------------------------------------------
261 /*!
262 SLRay::reflectMC scatters a ray around perfect specular direction according to
263 shininess (for higher shininess the ray is less scattered). This is used for
264 path tracing and distributed ray tracing as well as for photon scattering.
265 The direction is calculated according to MCCABE. The created direction is
266 along z-axis and then transformed to lie along specular direction with
267 rotationMatrix rotMat. The rotation matrix must be precalculated (stays the
268 same for each ray sample, needs to be be calculated only once)
269 */
270 bool SLRay::reflectMC(SLRay* reflected, SLMat3f rotMat)
271 {
272  SLfloat eta1, eta2;
273  SLVec3f randVec;
274  SLfloat shininess = hitMat->shininess();
275 
276  // scatter within specular lobe
277  eta1 = (SLfloat)random->Random();
278  eta2 = SL_2PI * (SLfloat)random->Random();
279  SLfloat f1 = sqrt(1.0f - pow(eta1, 2.0f / (shininess + 1.0f)));
280 
281  // tranform to cartesian
282  randVec.set(f1 * cos(eta2),
283  f1 * sin(eta2),
284  pow(eta1, 1.0f / (shininess + 1.0f)));
285 
286  // ray needs to be reset if already hit a shape
287  if (reflected->hitShape)
288  {
289  reflected->length = SL_FLOAT_MAX;
290  reflected->hitShape = 0;
291  reflected->hitPoint = SLVec3f::ZERO;
292  reflected->hitNormal = SLVec3f::ZERO;
293  }
294 
295  // apply rotation
296  reflected->setDir(rotMat * randVec);
297 
298  // true if in direction of normal
299  return (hitNormal * reflected->dir >= 0.0f);
300 }
301 //-----------------------------------------------------------------------------
302 /*!
303 SLRay::refractMC scatters a ray around perfect transmissive direction according
304 to translucency (for higher translucency the ray is less scattered).
305 This is used for path tracing and distributed ray tracing as well as for photon
306 scattering. The direction is calculated the same as with specular scattering
307 (see reflectMC). The created direction is along z-axis and then transformed to
308 lie along transmissive direction with rotationMatrix rotMat. The rotation
309 matrix must be precalculated (stays the same for each ray sample, needs to be
310 be calculated only once)
311 */
312 void SLRay::refractMC(SLRay* refracted, SLMat3f rotMat)
313 {
314  SLfloat eta1, eta2;
315  SLVec3f randVec;
316  SLfloat translucency = hitMat->translucency();
317 
318  // scatter within transmissive lobe
319  eta1 = (SLfloat)random->Random();
320  eta2 = SL_2PI * (SLfloat)random->Random();
321  SLfloat f1 = sqrt(1.0f - pow(eta1, 2.0f / (translucency + 1.0f)));
322 
323  // transform to cartesian
324  randVec.set(f1 * cos(eta2),
325  f1 * sin(eta2),
326  pow(eta1, 1.0f / (translucency + 1.0f)));
327 
328  // ray needs to be reset if already hit a shape
329  if (refracted->hitShape)
330  {
331  refracted->length = SL_FLOAT_MAX;
332  refracted->hitShape = 0;
333  refracted->hitPoint = SLVec3f::ZERO;
334  refracted->hitNormal = SLVec3f::ZERO;
335  }
336 
337  refracted->setDir(rotMat * randVec);
338 }
339 //-----------------------------------------------------------------------------
340 /*!
341 SLRay::diffuseMC scatters a ray around hit normal (cosine distribution).
342 This is only used for photonmapping(russian roulette).
343 The random direction lies around z-Axis and is then transformed by a rotation
344 matrix to lie along the normal. The direction is calculated according to MCCABE
345 */
346 void SLRay::diffuseMC(SLRay* scattered)
347 {
348  SLVec3f randVec;
349  SLfloat eta1, eta2, eta1sqrt;
350 
351  scattered->setDir(hitNormal);
352  scattered->origin = hitPoint;
353  scattered->depth = depth + 1;
354  depthReached = scattered->depth;
355 
356  // for reflectance the start material stays the same
357  scattered->originMat = hitMat;
358  scattered->originShape = hitShape;
359  scattered->type = REFLECTED;
360 
361  // calculate rotation matrix
362  SLMat3f rotMat;
363  SLVec3f rotAxis((SLVec3f(0.0, 0.0, 1.0) ^ scattered->dir).normalize());
364  SLfloat rotAngle = acos(scattered->dir.z); // z*scattered.dir()
365  rotMat.rotation(rotAngle * 180.0f / Utils::ONEPI, rotAxis);
366 
367  // cosine distribution
368  eta1 = (SLfloat)random->Random();
369  eta2 = SL_2PI * (SLfloat)random->Random();
370  eta1sqrt = sqrt(1 - eta1);
371  // transform to cartesian
372  randVec.set(eta1sqrt * cos(eta2),
373  eta1sqrt * sin(eta2),
374  sqrt(eta1));
375 
376  scattered->setDir(rotMat * randVec);
377 }
378 //-----------------------------------------------------------------------------
float SLfloat
Definition: SL.h:173
#define SL_LOG(...)
Definition: SL.h:233
unsigned int SLuint
Definition: SL.h:171
bool SLbool
Definition: SL.h:175
signed long SLlong
Definition: SL.h:164
int SLint
Definition: SL.h:170
SLRayType
SLRayType enumeration for specifying ray type in ray tracing.
Definition: SLRay.h:22
@ SHADOW
Definition: SLRay.h:26
@ PRIMARY
Definition: SLRay.h:23
@ REFLECTED
Definition: SLRay.h:24
@ TRANSMITTED
Definition: SLRayMC.h:25
SLVec3< SLfloat > SLVec3f
Definition: SLVec3.h:318
void rotation(const T angleDEG, const SLVec3< T > &axis)
Sets the rotation components
Definition: SLMat3.h:392
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
Ray class with ray and intersection properties.
Definition: SLRay.h:40
SLint hitTriangle
Points to the intersected triangle.
Definition: SLRay.h:107
SLVec3f origin
Vector to the origin of ray in WS.
Definition: SLRay.h:75
SLRay()
default ctor
Definition: SLRayMC.cpp:44
static SLint depthReached
depth reached for a primary ray
Definition: SLRay.h:134
static SLuint intersections
NO. of intersection.
Definition: SLRay.h:133
bool reflectMC(SLRay *reflected, const SLMat3f &rotMat) const
Definition: SLRay.cpp:332
SLfloat lightDist
Distance to light for shadow rays.
Definition: SLRay.h:93
static SLuint tirRays
NO. of TIR refraction rays.
Definition: SLRay.h:131
SLRayType type
PRIMARY, REFLECTED, REFRACTED, SHADOW.
Definition: SLRay.h:92
SLCol4f hitTexCol
Texture color at intersection point.
Definition: SLRayMC.h:121
static SLuint tests
NO. of intersection tests.
Definition: SLRay.h:132
SLbool isOutside
Flag if ray is inside of a material.
Definition: SLRay.h:95
SLFace * originTria
Points to the triangle at ray origin.
Definition: SLRayMC.h:109
static SLuint reflectedRays
NO. of reflected rays.
Definition: SLRay.h:127
SLint depth
Recursion depth for ray tracing.
Definition: SLRay.h:78
SLMaterial * hitMat
Points to material of intersected node.
Definition: SLRayMC.h:116
SLVec3f dir
Direction vector of ray in WS.
Definition: SLRay.h:76
SLShape * originShape
Points to the shape at ray origin.
Definition: SLRayMC.h:108
void normalizeNormal()
Definition: SLRay.h:175
void refract(SLRay *refracted)
Definition: SLRay.cpp:197
SLShape * hitShape
Points to the intersected shape.
Definition: SLRayMC.h:114
static SLint maxDepthReached
max. depth reached for all rays
Definition: SLRay.h:135
static SLuint refractedRays
NO. of refracted rays.
Definition: SLRay.h:128
static SLlong emittedPhotons
NO. of emitted photons from all lightsources.
Definition: SLRayMC.h:147
SLfloat length
length from origin to an intersection
Definition: SLRay.h:77
void print() const
Definition: SLRay.cpp:139
SLfloat contrib
Current contribution of ray to color.
Definition: SLRay.h:79
static SLuint subsampledPixels
NO. of of subsampled pixels.
Definition: SLRay.h:138
SLVec3f hitPoint
Point of intersection.
Definition: SLRay.h:110
void diffuseMC(SLRay *scattered) const
Definition: SLRay.cpp:429
static SLlong diffusePhotons
NO. of diffusely scattered photons on surfaces.
Definition: SLRayMC.h:148
void setDir(const SLVec3f &Dir)
Setter for the rays direction in world space also setting the inverse direction.
Definition: SLRay.h:146
static SLlong tirPhotons
NO. of total internal refraction photons.
Definition: SLRayMC.h:151
static SLlong refractedPhotons
NO. of refracted photons;.
Definition: SLRayMC.h:150
static SLfloat avgDepth
average depth reached
Definition: SLRay.h:136
static SLfloat minContrib
Min. contibution to color (1/256)
Definition: SLRay.h:125
void reflect(SLRay *reflected) const
Definition: SLRay.cpp:156
static SLuint subsampledRays
NO. of of subsampled rays.
Definition: SLRay.h:137
static SLbool ignoreLights
flag for gloss sampling
Definition: SLRayMC.h:152
SLfloat y
Pixel position for primary rays.
Definition: SLRay.h:94
static TRanrotBGenerator * random
Random generator.
Definition: SLRayMC.h:153
SLMaterial * originMat
Points to appearance at ray origin.
Definition: SLRayMC.h:110
SLfloat x
Definition: SLRay.h:94
void refractMC(SLRay *refracted, const SLMat3f &rotMat) const
Definition: SLRay.cpp:384
static SLuint shadowRays
NO. of shadow rays.
Definition: SLRay.h:130
SLVec3f hitNormal
Surface normal at intersection point.
Definition: SLRay.h:111
static SLlong reflectedPhotons
NO. of reflected photons;.
Definition: SLRayMC.h:149
static SLint maxDepth
Max. recursion depth.
Definition: SLRay.h:124
T y
Definition: SLVec3.h:43
T x
Definition: SLVec3.h:43
void set(const T X, const T Y, const T Z)
Definition: SLVec3.h:59
T z
Definition: SLVec3.h:43
static SLVec3 ZERO
Definition: SLVec3.h:285
T lengthSqr() const
Definition: SLVec3.h:123
static SLVec4 BLACK
Definition: SLVec4.h:213