Overweighting certain lights with ray tracing

I'm just getting started with ray tracing with DXR and I'm building some simple lighting with it. I've run into a slight issue; namely, that my game is set in space. Therefore the vast majority of all light rays miss regardless of the number of bounces. Currently I'm just using cosine weighting as I haven't implemented any reflections, specular, etc. When I place my spaceship even quite near the sun, then it looks pretty dark; even though I'm emitting pure white light, most samples miss.

I've experimented a bit with more of a shadow ray solution; sample the sun directly. Whilst this works well and produces some results that feel more appealing, if I imagine trying to scale this solution up further with 1 ray per light source, per bounce, it seems like it's going to be unmanagably slow, and I'm not totally sure how to combine the direct shadow ray result with the bounce result. So I could do this for dominant light sources, like 1-3 suns, but it won't apply for most light-emitting geometry.

I've looked at trying to crank the light emitted by the light source above 1, but this creates an enormous amount of noise and only works at quite limited distances. I'm hoping to achieve a solution that can works regardless of the distance to the light source.

I've considered using something like changing the sampling distribution, but I'm not sure if this resolves the issue as the maximum light you can receive from any given source is still capped by the sampling frequency as far as I understand it, so if I randomly sample the sun 50% of the time, it can't produce a brightness above 0.5.

Any suggestions for forcing objects to appear brighter than they otherwise should?

1. You basically answered your own questions. By deterministically connecting a vertex on your "light path", you are implementing a technique called "Next-Event Estimation". Be sure to account for the probabilities of selecting the various light sources and weigh the directions towards them. An excellent guide on how to do this can be found in the PBRT book by Matt Pharr et al.

2. Recently, techniques like ReSTIR can significantly help with framerates. However, please note that a fully ray-traced game might become unfeasible very, very quickly (just to give some context, Lumen, the global illumination solution in Unreal, has a ray budget of half a ray per pixel to keep frame rates above 60 FPS). Sadly RT ray tracing with all the fancy stuff simply isn't something that can be done on current consumer-grade hardware (and to be honest it probably won't for a few more years at least in my opinion).

3. "...the maximum light you can receive from any given source is still capped by the sampling frequency as far as I understand it, so if I randomly sample the sun 50% of the time, it can't produce a brightness above 0.5." This is not "entirely" correct. Techniques like multiple importance sampling allow you to for example, sample both the sun and another direction, combine the results and weigh them appropriately. Yes this does require more computing for a specific light ray but can significantly reduce variance in the final Monte Carlo radiance estimate. For more information, you can try to search for "Multiple Importance Sampling".

• OK, so taking a little time to think about this, the first issue is that I'm not weighting the rays very well, because most cosine rays miss, so all the non-sun rays are not importance weighted at all. And the second issue is that I'm not explicitly calculating and mixing the weights correctly so that I'm not weighting the sun ray high enough? So what I should do is explicitly calculate the weights of all my geometry and then fire the ray at something by weight, and then make sure to mix the weights properly at the end? Commented Jul 7 at 10:48

• "Next-Event Estimation" indeed require you to call the any-hit shader at least one more time, per bounce. Yet this speed up convergence significantly, especially when the emitter is hard to be hit. The amount of extra overhead is definitely worthy.
• But how to speed NEE up? Uniformly sampling an emitter is not a good solution (implementation of PBRT-v3) since different emitters can have pretty different power. One simple solution is to sample the emitter by their power. Note that power is also influenced by the distance to the emitter. This will importance-sample the emitters to help you reduce variance. The better solution, will be LightBVHm especially when you have multiple emitters (like, in space). You can check out Falcor for power and LightBVH emitter sampling methods.
• Regarding:

...the maximum light you can receive from any given source is still capped by the sampling frequency as far as I understand it, so if I randomly sample the sun 50% of the time, it can't produce a brightness above 0.5.

As pointed out by Matthias K., MIS is indeed a good solution to weighting different NEE / bounce samples (the best explanation is here, the original thesis of Eric Veach) but the fact that radiance can go higher than 50% has nothing to do with it. Even if you don't use MIS, you can still get radiance that is higher than 50%:

• Unbiased: for unbiased Monte Carlo estimator, let's say you are using NEE and there are two emitters sun_1 and sun_2. Unbiased Monte Carlo estimator will always account for sampling PDF, so that: $$\mathbb{E}(L_{\text{NEE}})= \frac{1}{N_1}\sum_{i = 1}^{N_1}\frac{L_1(\omega_i)p_{1}(\omega_i)}{p_{1}(\omega_i)}+ \frac{1}{N_2}\sum_{j = 1}^{N_2}\frac{L_2(\omega_j)p_{2}(\omega_i)}{p_{2}(\omega_i)} \approx \\ \int_{\Omega_1} \frac{L_1(\omega)p_{1}(\omega)}{p_{1}(\omega)}d\omega + \int_{\Omega_1} \frac{L_2(\omega)p_{2}(\omega)}{p_{2}(\omega)}d\omega = \int_{\Omega_1} L_1(\omega) d\omega + \int_{\Omega_2} L_2(\omega) d\omega$$ $$L_i$$ denotes the direct radiance of sun_i, p_i denotes the sampling probability of that emitter direction. Our estimator is always chosen to be $$L / p$$, so when we compute the expectation, the sampling PDF in the denominator will be cancelled out (the cancelled out PDF includes your 50% chance). However, unbiasedness require you to use the exact PDF of the sampling distribution. So no matter what distribution you choose, if the method is unbiased, they will look the same eventually. It is just the matter of how fast different method converges.

• Biased: if you don't care about the physical correctness, you can choose a PDF that is not equivalent to the PDF of your sampling distribution. For example: $$L / (p \times 0.1)$$ increases the contribution of the current sample by 10x. Since you are creating a game, introducing bias won't be a problem unless you opt for extreme realness. Bias can help you get better convergence (for example, the biased branch of ReSTIR).

• Extra thanks for the last section, I implemented MIS but couldn't quite get the bias right until I came back and double-checked here! Commented Aug 31 at 13:38