@@ -370,21 +370,49 @@ const float PathTracer::Rand()
370370 return dis (mRng );
371371}
372372
373- const bool PathTracer::IsSameSide (const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& a, const glm::vec3& b) const
373+ const glm::vec3 PathTracer::IntersectTriangle
374+ (
375+ const glm::vec3& ro, const glm::vec3& rd,
376+ const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2
377+ ) const
374378{
375- glm::vec3 ba = b - a;
376- glm::vec3 cp1 = glm::cross (ba, (p1 - a));
377- glm::vec3 cp2 = glm::cross (ba, (p2 - a));
379+ glm::vec3 edge1, edge2, h, s, q;
380+ float a, f, u, v;
378381
379- return (glm::dot (cp1, cp2) >= 0 );
380- }
382+ edge1 = v1 - v0;
383+ edge2 = v2 - v0;
384+ h = glm::cross (rd, edge2);
385+ a = glm::dot (edge1, h);
381386
382- const bool PathTracer::IntersectTriangle (const glm::vec3& p, const glm::vec3& a, const glm::vec3& b, const glm::vec3& c) const
383- {
384- return (IsSameSide (p, a, b, c) && IsSameSide (p, b, a, c) && IsSameSide (p, c, a, b));
387+ if (abs (a) < EPS)
388+ return glm::vec3 (0 .f );
389+
390+ f = 1 .0f / a;
391+ s = ro - v0;
392+ u = f * glm::dot (s, h);
393+
394+ if (u < 0 .0f || u > 1 .0f )
395+ return glm::vec3 (0 .f );
396+
397+ q = glm::cross (s, edge1);
398+ v = f * glm::dot (rd, q);
399+
400+ if (v < 0 .0f || u + v > 1 .0f )
401+ return glm::vec3 (0 .f );
402+
403+ float t = f * glm::dot (edge2, q);
404+
405+ if (t > EPS)
406+ return glm::vec3 (t, u, v);
407+
408+ return glm::vec3 (0 .f );
385409}
386410
387- const bool PathTracer::Hit (BVHNode* node, const glm::vec3& ro, const glm::vec3& rd, Triangle*& triangleOut, float & distOut)
411+ const bool PathTracer::Hit
412+ (
413+ BVHNode* node, const glm::vec3& ro, const glm::vec3& rd,
414+ Triangle*& triangleOut, float & distOut, glm::vec2& cOut
415+ )
388416{
389417 if (node->mLeft && node->mRight )
390418 {
@@ -393,32 +421,37 @@ const bool PathTracer::Hit(BVHNode* node, const glm::vec3& ro, const glm::vec3&
393421 Triangle* tLeft = 0 ;
394422 Triangle* tRight = 0 ;
395423 float dLeft, dRight;
396- bool hitLeft = Hit (node->mLeft , ro, rd, tLeft, dLeft);
397- bool hitRight = Hit (node->mRight , ro, rd, tRight, dRight);
424+ glm::vec2 cLeft, cRight;
425+ bool hitLeft = Hit (node->mLeft , ro, rd, tLeft, dLeft, cLeft);
426+ bool hitRight = Hit (node->mRight , ro, rd, tRight, dRight, cRight);
398427 if (hitLeft && hitRight)
399428 {
400429 if (dLeft < dRight)
401430 {
402431 triangleOut = tLeft;
403432 distOut = dLeft;
433+ cOut = cLeft;
404434 }
405435 else
406436 {
407437 triangleOut = tRight;
408438 distOut = dRight;
439+ cOut = cRight;
409440 }
410441 return true ;
411442 }
412443 else if (hitLeft)
413444 {
414445 triangleOut = tLeft;
415446 distOut = dLeft;
447+ cOut = cLeft;
416448 return true ;
417449 }
418450 else if (hitRight)
419451 {
420452 triangleOut = tRight;
421453 distOut = dRight;
454+ cOut = cRight;
422455 return true ;
423456 }
424457 else
@@ -429,28 +462,24 @@ const bool PathTracer::Hit(BVHNode* node, const glm::vec3& ro, const glm::vec3&
429462 }
430463 else if (node->mTriangle )
431464 {
432- if (glm::dot (rd, node->mTriangle ->normal ) == 0 .0f )
433- return false ;
434- distOut = glm::dot ((node->mTriangle ->v1 - ro), node->mTriangle ->normal ) / glm::dot (rd, node->mTriangle ->normal );
435- if (distOut < 0 )
436- return false ;
437- // update intersection point
438- glm::vec3 p = ro + rd * distOut;
439-
440- if (IntersectTriangle (p, node->mTriangle ->v1 , node->mTriangle ->v2 , node->mTriangle ->v3 ))
465+ glm::vec3 test = IntersectTriangle (ro, rd, node->mTriangle ->v1 , node->mTriangle ->v2 , node->mTriangle ->v3 );
466+ if (test.x > 0 .f )
441467 {
442468 bool result = true ;
443469 // Opacity
444470 if (node->mTriangle ->mat ->opacityTex )
445471 {
446- glm::vec2 uv = GetUV (p, node->mTriangle );
472+ glm::vec2 c = glm::vec2 (test.y , test.z );
473+ glm::vec2 uv = GetUV (c, node->mTriangle );
447474 float opacity = node->mTriangle ->mat ->opacityTex ->tex2D (uv).r ;
448475 result = Rand () < opacity;
449476 }
450477
451478 if (result)
452479 {
453480 triangleOut = node->mTriangle ;
481+ distOut = test.x ;
482+ cOut = glm::vec2 (test.y , test.z );
454483 return true ;
455484 }
456485 else
@@ -474,6 +503,8 @@ const glm::vec3 PathTracer::SampleTriangle(const glm::vec3& v0, const glm::vec3&
474503
475504const glm::vec3 PathTracer::DirectIllumimation (const glm::vec3& rd, const glm::vec3& p, const glm::vec3& n, const glm::vec3& diffuse)
476505{
506+ if (mLights .size () == 0 )
507+ return glm::vec3 (0 .f );
477508 // sample a light triangle
478509 int lightId = int (floor (Rand () * mLights .size ()));
479510 if (lightId == mLights .size () && lightId > 0 )
@@ -487,7 +518,8 @@ const glm::vec3 PathTracer::DirectIllumimation(const glm::vec3& rd, const glm::v
487518 return glm::vec3 (0 .f );
488519 float d = 0.0 ;
489520 Triangle* t = 0 ;
490- if (Hit (mBvh , p, l, t, d))
521+ glm::vec2 c;
522+ if (Hit (mBvh , p, l, t, d, c))
491523 {
492524 if (tLight != t)
493525 return glm::vec3 (0 .f );
@@ -498,32 +530,14 @@ const glm::vec3 PathTracer::DirectIllumimation(const glm::vec3& rd, const glm::v
498530 return lColor * diffuse * glm::dot (-n, -l);
499531}
500532
501- const glm::vec2 PathTracer::GetUV (const glm::vec3& p , Triangle* t) const
533+ const glm::vec2 PathTracer::GetUV (const glm::vec2& c , Triangle* t) const
502534{
503- glm::vec3 v2 = p - t->v1 ;
504- float d20 = glm::dot (v2, t->barycentricInfo .v0 );
505- float d21 = glm::dot (v2, t->barycentricInfo .v1 );
506-
507- float alpha = (t->barycentricInfo .d11 * d20 - t->barycentricInfo .d01 * d21) *
508- t->barycentricInfo .invDenom ;
509- float beta = (t->barycentricInfo .d00 * d21 - t->barycentricInfo .d01 * d20) *
510- t->barycentricInfo .invDenom ;
511-
512- return (1 .0f - alpha - beta) * t->uv1 + alpha * t->uv2 + beta * t->uv3 ;
535+ return (1 .0f - c.x - c.y ) * t->uv1 + c.x * t->uv2 + c.y * t->uv3 ;
513536}
514537
515- const glm::vec3 PathTracer::GetSmoothNormal (const glm::vec3& p , Triangle* t) const
538+ const glm::vec3 PathTracer::GetSmoothNormal (const glm::vec2& c , Triangle* t) const
516539{
517- glm::vec3 v2 = p - t->v1 ;
518- float d20 = glm::dot (v2, t->barycentricInfo .v0 );
519- float d21 = glm::dot (v2, t->barycentricInfo .v1 );
520-
521- float alpha = (t->barycentricInfo .d11 * d20 - t->barycentricInfo .d01 * d21) *
522- t->barycentricInfo .invDenom ;
523- float beta = (t->barycentricInfo .d00 * d21 - t->barycentricInfo .d01 * d20) *
524- t->barycentricInfo .invDenom ;
525-
526- glm::vec3 n = (1 .0f - alpha - beta) * t->n1 + alpha * t->n2 + beta * t->n3 ;
540+ glm::vec3 n = (1 .0f - c.x - c.y ) * t->n1 + c.x * t->n2 + c.y * t->n3 ;
527541 glm::vec3 res = glm::normalize (glm::vec3 (n.x , -n.y , n.z ));
528542 return glm::normalize (n);
529543}
@@ -532,14 +546,15 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
532546{
533547 float d = 0 .0f ;
534548 Triangle* t = 0 ;
535- if (Hit (mBvh , ro, rd, t, d))
549+ glm::vec2 c;
550+ if (Hit (mBvh , ro, rd, t, d, c))
536551 {
537552 Material& mat = mLoadedObjects [t->objectId ].elements [t->elementId ].material ;
538553 glm::vec3 p = ro + rd * d;
539- glm::vec2 uv = GetUV (p , t);
554+ glm::vec2 uv = GetUV (c , t);
540555 glm::vec3 n = t->normal ;
541556 if (t->smoothing )
542- n = GetSmoothNormal (p , t);
557+ n = GetSmoothNormal (c , t);
543558 if (mat.normalTex )
544559 {
545560 glm::mat3 TBN = glm::mat3 (t->tangent , t->bitangent , n);
@@ -659,7 +674,6 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
659674 refract = true ;
660675 }
661676
662- iter--;
663677 if (!refract)
664678 {
665679 if (roughness == 1 .0f )
@@ -684,6 +698,7 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
684698 reflectDir = w * cosf (2 .0f * M_PI * theta) * u + w * sinf (2 .0f * M_PI * theta) * v + sqrtf (1 .0f - w * w) * r;
685699 reflectDir = glm::normalize (reflectDir);
686700 }
701+ iter--;
687702 return emiss * mat.emissiveIntensity + Trace (p, reflectDir, depth, iter, inside) * mat.specular ;
688703 }
689704 else
@@ -693,6 +708,7 @@ const glm::vec3 PathTracer::Trace(const glm::vec3& ro, const glm::vec3& rd, int
693708 reflectDir = glm::normalize (eta * rd - (eta * glm::dot (n, rd) + sqrtf (k)) * refractN);
694709 p -= n * EPS * 2 .0f ;
695710 inside = !inside;
711+ iter--;
696712 return emiss * mat.emissiveIntensity + Trace (p, reflectDir, depth, iter, inside) * diffuse;
697713 }
698714 else
0 commit comments