diff --git a/zenovis/xinxinoptix/Light.cu b/zenovis/xinxinoptix/Light.cu index c908ca096..8d3f5cd56 100644 --- a/zenovis/xinxinoptix/Light.cu +++ b/zenovis/xinxinoptix/Light.cu @@ -124,26 +124,27 @@ extern "C" __global__ void __closesthit__radiance() const auto lightShape = light.shape; const auto shadingP = ray_orig + params.cam.eye; - const auto insideEllipse = [&]() -> bool { - - float3 _vertices_[3]; - optixGetTriangleVertexData( gas, optixGetPrimitiveIndex(), sbtGASIndex, 0, _vertices_ ); - - const float3& v0 = _vertices_[0]; - const float3& v1 = _vertices_[1]; - const float3& v2 = _vertices_[2]; - - float2 barys = optixGetTriangleBarycentrics(); - float3 P_Local = interp(barys, v0, v1, v2); - - auto delta = P_Local - light.rect.v; - - float2 uv = { dot(delta, light.rect.axisX) / light.rect.lenX, - dot(delta, light.rect.axisY) / light.rect.lenY }; - - auto uvd = uv - 0.5f; - return length(uvd) <= 0.5f; - }; + const auto rectUV = [&]() -> float2 { + float2 uv0, uv1, uv2; + if (primitiveIndex % 2 == 0) { + uv0 = float2{0, 0}; + uv1 = float2{1, 0}; + uv2 = float2{1, 1}; + } else { + uv0 = float2{0, 0}; + uv1 = float2{1, 1}; + uv2 = float2{0, 1}; + } + + float2 barys = optixGetTriangleBarycentrics(); + return interp(barys, uv0, uv1, uv2); + }; + + const auto insideEllipse = [&]() -> bool { + float2 uv = rectUV(); + auto uvd = uv - 0.5f; + return length(uvd) <= 0.5f; + }; if (prd->test_distance) { @@ -164,46 +165,50 @@ extern "C" __global__ void __closesthit__radiance() return; } - switch (lightShape) { - case zeno::LightShape::Plane: - case zeno::LightShape::Ellipse: { - - auto valid = true; - if (light.rect.isEllipse && !insideEllipse()) { - valid &= false; - prd->done = false; - prd->_tmin_ = optixGetRayTmax(); - } - // valid = light.rect.EvalAfterHit(&lsr, lightDirection, lightDistance, shadingP); - // if (!valid) { - // prd->done = false; - // prd->_tmin_ = optixGetRayTmax(); - // return; - // }; - if (!valid) { return; } - - auto rect = light.rect; - float2 uvScale, uvOffset; - valid &= SpreadClampRect(rect.v, rect.axisX, rect.lenX, rect.axisY, rect.lenY, - rect.normal, shadingP, - light.spreadMajor, uvScale, uvOffset); - - //if (!valid) { return; } - - SphericalRect squad; - SphericalRectInit(squad, shadingP, rect.v, rect.axisX, rect.lenX, rect.axisY, rect.lenY); - lsr.PDF = 1.0f / squad.S; - if ( !isfinite(lsr.PDF) ) { return; } - - lsr.n = light.N; - lsr.NoL = dot(light.N, -ray_dir); - lsr.uv = uvOffset + lsr.uv * uvScale; - - lsr.dir = lightDirection; - lsr.dist = lightDistance; - lsr.p = ray_orig + ray_dir * lightDistance; - break; - } + switch (lightShape) { + case zeno::LightShape::Ellipse: { + auto valid = true; + if (light.rect.isEllipse && !insideEllipse()) { + valid &= false; + } + if (!valid) { + prd->done = false; + prd->_tmin_ = optixGetRayTmax(); + return; + }; + } + case zeno::LightShape::Plane: { + + lsr.uv = rectUV(); + + if (prd->depth > 0) { + + auto rect = light.rect; + float2 uvScale, uvOffset; + bool valid = SpreadClampRect(rect.v, rect.axisX, rect.lenX, rect.axisY, + rect.lenY, rect.normal, shadingP, + light.spreadMajor, uvScale, uvOffset); + // if (!valid) { return; } + + SphericalRect squad; + SphericalRectInit(squad, shadingP, rect.v, rect.axisX, rect.lenX, + rect.axisY, rect.lenY); + lsr.PDF = 1.0f / squad.S; + if (!isfinite(lsr.PDF)) { + return; + } + + lsr.uv = uvOffset + lsr.uv * uvScale; + } + + lsr.n = light.N; + lsr.NoL = dot(light.N, -ray_dir); + + lsr.dir = lightDirection; + lsr.dist = lightDistance; + lsr.p = ray_orig + ray_dir * lightDistance; + break; + } case zeno::LightShape::Sphere: { light.sphere.EvalAfterHit(&lsr, lightDirection, lightDistance, shadingP); cihouSphereLightUV(lsr, light); break;