Skip to content

Commit 4b60055

Browse files
committed
fix self shadowing in gaussian GI mode
1 parent 09a3072 commit 4b60055

6 files changed

Lines changed: 27 additions & 10 deletions

File tree

assets/tests/hotel_old_mill_realistic.nrscene

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
"objects": [
33
{
44
"type": "camera",
5-
"name": "Canon Automotive Fisheye",
5+
"name": "Samy & Gao 220deg",
66
"position": [0.0, 2.0, 5.0],
77
"rotation_euler": [0.0, 0.0, 0.0],
88
"scale": [1.0, 1.0, 1.0],
99
"camera": {
1010
"projection": "realistic",
1111
"active": true,
1212
"focus_distance_cm": 500.0,
13-
"exposure": 3.5,
13+
"exposure": 4.0,
1414
"resolution": [1928, 1088],
15-
"lens": "/home/marcel/GitRepositories/NoorRay/external/ROSS/resources/lenses/canon_automotive_fisheye/canon_automotive_fisheye.zmx",
15+
"lens": "/home/marcel/GitRepositories/ROSS/resources/lenses/samy_gao/Samy&Gao-1(220deg).zmx",
1616
"sensor": "/home/marcel/GitRepositories/NoorRay/external/ROSS/resources/sensors/onsemi_AR0237.json",
1717
"glass_catalogs": "/home/marcel/GitRepositories/NoorRay/external/ROSS/resources/glasscatalogs/ohara.AGF;/home/marcel/GitRepositories/NoorRay/external/ROSS/resources/glasscatalogs/schott.AGF"
1818
}

src/libnoorray/Kernels/Connect.cu

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ NR_GPU inline bool shadowOccluded(
3131
const uint32_t gaussianSampleIndex = gaussianEnabled ? randomUint(rng) : 0;
3232
const RayHit hit = intersectRay(params.scene.tlasHandle, shadow.origin,
3333
shadow.direction, rayMin, shadow.tMax, gaussianSampleIndex,
34-
gaussianEnabled, meshVisibilityBoundEnabled);
34+
gaussianEnabled, meshVisibilityBoundEnabled,
35+
shadow.excludedGaussianId);
3536
if (hit.instanceIndex == InvalidIndex)
3637
return false;
3738

src/libnoorray/Kernels/GaussianHit.cu

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ extern "C" __global__ void __anyhit__gaussian()
1616
const uint32_t instanceId = optixGetInstanceId();
1717
const uint32_t globalGaussianId = instanceId;
1818

19+
// Shadow rays start inside the Gaussian that produced the scattering
20+
// event. Exclude that exact instance instead of relying on a world-space
21+
// epsilon, which cannot cover differently scaled Gaussians robustly.
22+
if (globalGaussianId == optixGetPayload_2())
23+
{
24+
optixIgnoreIntersection();
25+
return;
26+
}
27+
1928
const float opacity = params.scene.gaussianOpacities[globalGaussianId];
2029
if (opacity <= 0.0f)
2130
{

src/libnoorray/Kernels/Shade.cu

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ NR_GPU_KERNEL void shadeKernel(const KernelParams params)
142142
ShadowWorkItem shadow{};
143143
shadow.tMin = 1.0f;
144144
shadow.tMax = 0.0f;
145+
shadow.excludedGaussianId = InvalidIndex;
145146
if (mayWriteShadowQueue)
146147
params.queues.shadowQueue[index].tMax = 0.0f;
147148
PathState state = params.queues.pathStates[hit.sampleIndex];
@@ -269,6 +270,7 @@ NR_GPU_KERNEL void shadeKernel(const KernelParams params)
269270
state.throughput * brdf * lightSample.radiance;
270271
shadow.rngState = shadowRng;
271272
shadow.sampleIndex = hit.sampleIndex;
273+
shadow.excludedGaussianId = gaussianId;
272274
params.queues.shadowQueue[index] = shadow;
273275
}
274276
}

src/libnoorray/Raytracing/RayTraversal.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ NR_GPU inline RayHit intersectRay(
5353
const float tMax,
5454
const uint32_t sampleIndex = 0,
5555
const bool gaussianEnabled = true,
56-
const bool meshVisibilityBoundEnabled = true)
56+
const bool meshVisibilityBoundEnabled = true,
57+
const uint32_t excludedGaussianId = InvalidIndex)
5758
{
5859
RayHit hit{};
5960
#if defined(NR_GPU_DEVICE_COMPILE)
@@ -90,7 +91,10 @@ NR_GPU inline RayHit intersectRay(
9091
const float gaussianTMax = meshHit.instanceIndex != InvalidIndex ? meshHit.t : tMax;
9192
uint32_t payload0 = sampleIndex;
9293
uint32_t payload1 = __float_as_uint(gaussianTMax);
93-
uint32_t payload2 = InvalidIndex;
94+
// Before acceptance payload 2 identifies a Gaussian that must not
95+
// intersect this ray. Any-hit overwrites it only when another
96+
// Gaussian is accepted.
97+
uint32_t payload2 = excludedGaussianId;
9498
optixTraverse(
9599
accel,
96100
make_float3(origin.x, origin.y, origin.z),
@@ -105,12 +109,12 @@ NR_GPU inline RayHit intersectRay(
105109
0,
106110
payload0, payload1, payload2);
107111

108-
const uint32_t gaussianId = payload2;
109-
if (gaussianId != InvalidIndex)
112+
const float gaussianT = __uint_as_float(payload1);
113+
if (gaussianT < gaussianTMax)
110114
{
111115
// Gaussian accepted via Russian roulette.
112-
hit.instanceIndex = gaussianId;
113-
hit.t = __uint_as_float(payload1);
116+
hit.instanceIndex = payload2;
117+
hit.t = gaussianT;
114118
}
115119
else if (meshHit.instanceIndex != InvalidIndex)
116120
{

src/libnoorray/Raytracing/Types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct alignas(16) ShadowWorkItem
8585
SampledSpectrum contribution;
8686
RandomState rngState;
8787
uint32_t sampleIndex;
88+
uint32_t excludedGaussianId;
8889
};
8990

9091
struct WavefrontQueues

0 commit comments

Comments
 (0)