@@ -422,6 +422,20 @@ _SampleCylinder(GfMatrix4f const& xf, GfMatrix3f const& normalXform,
422
422
};
423
423
}
424
424
425
+ _ShapeSample
426
+ _IntersectAreaLight (HdEmbree_LightData const & light, RTCRayHit const & rayHit)
427
+ {
428
+ // XXX: just rect lights at the moment, need to do the others
429
+ auto const & rect = std::get<HdEmbree_Rect>(light.lightVariant );
430
+
431
+ return _ShapeSample {
432
+ _CalculateHitPosition (rayHit),
433
+ GfVec3f (rayHit.hit .Ng_x , rayHit.hit .Ng_y , rayHit.hit .Ng_z ),
434
+ GfVec2f (1 .0f - rayHit.hit .u , rayHit.hit .v ),
435
+ _AreaRect (light.xformLightToWorld , rect.width , rect.height )
436
+ };
437
+ }
438
+
425
439
GfVec3f
426
440
_EvalLightBasic (HdEmbree_LightData const & light)
427
441
{
@@ -1275,6 +1289,43 @@ _CosineWeightedDirection(GfVec2f const& uniform_float)
1275
1289
return dir;
1276
1290
}
1277
1291
1292
+ bool
1293
+ HdEmbreeRenderer::_RayShouldContinue (RTCRayHit const & rayHit) const {
1294
+ if (rayHit.hit .geomID == RTC_INVALID_GEOMETRY_ID) {
1295
+ // missed, don't continue
1296
+ return false ;
1297
+ }
1298
+
1299
+ if (rayHit.hit .instID [0 ] == RTC_INVALID_GEOMETRY_ID) {
1300
+ // not hit an instance, but a "raw" geometry. This should be a light
1301
+ const HdEmbreeInstanceContext *instanceContext =
1302
+ static_cast <HdEmbreeInstanceContext*>(
1303
+ rtcGetGeometryUserData (rtcGetGeometry (_scene,
1304
+ rayHit.hit .geomID )));
1305
+
1306
+ if (instanceContext->light == nullptr ) {
1307
+ // if this isn't a light, don't know what this is
1308
+ return false ;
1309
+ }
1310
+
1311
+ auto const & light = instanceContext->light ->LightData ();
1312
+
1313
+ if ((rayHit.ray .mask & HdEmbree_RayMask::Camera)
1314
+ && !light.visible_camera ) {
1315
+ return true ;
1316
+ } else if ((rayHit.ray .mask & HdEmbree_RayMask::Shadow)
1317
+ && !light.visible_shadow ) {
1318
+ return true ;
1319
+ } else {
1320
+ return false ;
1321
+ }
1322
+ }
1323
+
1324
+ // XXX: otherwise this is a regular geo. we should handle visibility here
1325
+ // too eventually
1326
+ return false ;
1327
+ }
1328
+
1278
1329
void
1279
1330
HdEmbreeRenderer::_TraceRay (unsigned int x, unsigned int y,
1280
1331
GfVec3f const &origin, GfVec3f const &dir,
@@ -1306,6 +1357,13 @@ HdEmbreeRenderer::_TraceRay(unsigned int x, unsigned int y,
1306
1357
rayHit.hit .Ng_z = -rayHit.hit .Ng_z ;
1307
1358
}
1308
1359
1360
+ if (_RayShouldContinue (rayHit)) {
1361
+ GfVec3f hitPos = _CalculateHitPosition (rayHit);
1362
+
1363
+ _TraceRay (x, y, hitPos + dir * _rayHitContinueBias, dir, random );
1364
+ return ;
1365
+ }
1366
+
1309
1367
// Write AOVs to attachments that aren't converged.
1310
1368
for (size_t i = 0 ; i < _aovBindings.size (); ++i) {
1311
1369
HdEmbreeRenderBuffer *renderBuffer =
@@ -1361,6 +1419,11 @@ HdEmbreeRenderer::_ComputeId(RTCRayHit const& rayHit, TfToken const& idType,
1361
1419
return false ;
1362
1420
}
1363
1421
1422
+ if (rayHit.hit .instID [0 ] == RTC_INVALID_GEOMETRY_ID) {
1423
+ // not hit an instance, but a "raw" geometry. This should be a light
1424
+ return false ;
1425
+ }
1426
+
1364
1427
// Get the instance and prototype context structures for the hit prim.
1365
1428
// We don't use embree's multi-level instancing; we
1366
1429
// flatten everything in hydra. So instID[0] should always be correct.
@@ -1401,6 +1464,11 @@ HdEmbreeRenderer::_ComputeDepth(RTCRayHit const& rayHit,
1401
1464
return false ;
1402
1465
}
1403
1466
1467
+ if (rayHit.hit .instID [0 ] == RTC_INVALID_GEOMETRY_ID) {
1468
+ // not hit an instance, but a "raw" geometry. This should be a light
1469
+ return false ;
1470
+ }
1471
+
1404
1472
if (clip) {
1405
1473
GfVec3f hitPos = _CalculateHitPosition (rayHit);
1406
1474
@@ -1424,6 +1492,11 @@ HdEmbreeRenderer::_ComputeNormal(RTCRayHit const& rayHit,
1424
1492
return false ;
1425
1493
}
1426
1494
1495
+ if (rayHit.hit .instID [0 ] == RTC_INVALID_GEOMETRY_ID) {
1496
+ // not hit an instance, but a "raw" geometry. This should be a light
1497
+ return false ;
1498
+ }
1499
+
1427
1500
// We don't use embree's multi-level instancing; we
1428
1501
// flatten everything in hydra. So instID[0] should always be correct.
1429
1502
const HdEmbreeInstanceContext *instanceContext =
@@ -1462,6 +1535,11 @@ HdEmbreeRenderer::_ComputePrimvar(RTCRayHit const& rayHit,
1462
1535
return false ;
1463
1536
}
1464
1537
1538
+ if (rayHit.hit .instID [0 ] == RTC_INVALID_GEOMETRY_ID) {
1539
+ // not hit an instance, but a "raw" geometry. This should be a light
1540
+ return false ;
1541
+ }
1542
+
1465
1543
// We don't use embree's multi-level instancing; we
1466
1544
// flatten everything in hydra. So instID[0] should always be correct.
1467
1545
const HdEmbreeInstanceContext *instanceContext =
@@ -1548,6 +1626,30 @@ HdEmbreeRenderer::_ComputeColor(RTCRayHit const& rayHit,
1548
1626
return domeColor;
1549
1627
}
1550
1628
1629
+ if (rayHit.hit .instID [0 ] == RTC_INVALID_GEOMETRY_ID) {
1630
+ // if it's not an instance then it's almost certainly a light
1631
+ const HdEmbreeInstanceContext *instanceContext =
1632
+ static_cast <HdEmbreeInstanceContext*>(
1633
+ rtcGetGeometryUserData (rtcGetGeometry (_scene,
1634
+ rayHit.hit .geomID )));
1635
+
1636
+ // if we hit a light, just evaluate the light directly
1637
+ if (instanceContext->light != nullptr ) {
1638
+ auto const & light = instanceContext->light ->LightData ();
1639
+ _ShapeSample ss = _IntersectAreaLight (light, rayHit);
1640
+ _LightSample ls = _EvalAreaLight (light, ss,
1641
+ GfVec3f (rayHit.ray .org_x , rayHit.ray .org_y , rayHit.ray .org_z ));
1642
+
1643
+ return GfVec4f (ls.Li [0 ], ls.Li [1 ], ls.Li [2 ], 1 .0f );
1644
+ } else {
1645
+ // should never get here. magenta warning!
1646
+ TF_WARN (" Unexpected runtime state - hit an an embree instance "
1647
+ " that wasn't a geo or light" );
1648
+ return GfVec4f (1 .0f , 0 .0f , 1 .0f , 1 .0f );
1649
+ }
1650
+
1651
+ }
1652
+
1551
1653
// Get the instance and prototype context structures for the hit prim.
1552
1654
// We don't use embree's multi-level instancing; we
1553
1655
// flatten everything in hydra. So instID[0] should always be correct.
0 commit comments