<p>I'm not sure if I understand your question correctly and don't know what you mean by &quot;counting&quot; and how you want to replace this by &quot;color&quot;. A simple photon mapper looks like this: 1) photon tracing: emit, scatter, store photons 2) path tracing: gather photons in a given radius and approximate radiance using this density.</p>
<p>To be more precise, in pseudocode (with russian roulette) this would look like:</p>
<p><code>xi</code> is the position, <code>wo</code> the outgoing direction, <code>W</code> the photon power. All three are vectors of length 3. <code>p</code> is the probability of the Russian roulette. A photon is a struct that stores the power, direction, and position.</p>
<pre><code>xi, wo, W = emitter.sample()
while(true)
   xi = traceRay(xi, wo)
   if(isDiffuse(xi))
      storePhoton(xi, wo, W)

   if(rand &lt; p)
      break
    W /= p;
    
    wo = bsdf.sample(xi)
    W *= bsdf(wo)/pdf(wo)*cos
</code></pre>
<p>You repeatedly call this function for a random emitter until you stored a predefined amount of photons (e.g. 500'000). After this, you <em>build</em> the photonmap, such as a k-d tree to make querying easy. As you can see, the &quot;color&quot; is stored in the power of the photon.</p>
<p>The next step is the gathering the photons, and it's normal path tracing but when you hit a diffuse surface, you gather all the photons in a fixed radius (other kernels can also be used). Here, <code>t</code> is the throughput, <code>wi</code> the incoming direction, the <code>photon_map</code> is the datastructure that we build before and populated with photons, and <code>total_photons</code> is the total amount of photons that we emitted.</p>
<pre><code>...

if(isDiffuse(xi))
   for photon: photon_map.get(xi, radius)
      radiance *= t*bsdf(xi, wi, photon.wo) * photon.power / (pi*radius^2 * total_photons)
   break
...

</code></pre>

CC BY-SA 4.0
2020-12-09T19:47:26.973Z
Ok, so you store photons with a vector-power each. I take it that this vector is the photon's power in R,G and B. Hence, you can think of it as the 'colour' of a photon?
Bram
CC BY-SA 4.0
2020-12-09T19:53:08.687Z
Yes, in this case it can be seen as RGB. As one commenter pointed out, you can read more about this in PBRT  [chapter 5](http://www.pbr-book.org/3ed-2018/Color_and_Radiometry/Spectral_Representation.html) . This could also be a spectrum with more components than just 3, but for most purposes this is enough.
lyinch
CC BY-SA 4.0
2020-12-17T19:48:22.113Z
If you use spectral rendering, wouldn't each photon just have a frequency, and that's it? The power of lightsources would just be achieved by emitting more or fewer photons, with each photon's power the same?
Bram
CC BY-SA 4.0
2020-12-09T18:46:43.253Z
2020-12-09T18:46:43.253Z
lyinch
<p>I wrote a rather elegant and compact <a href="https://en.wikipedia.org/wiki/Photon_mapping" rel="nofollow noreferrer">Photon Mapper</a> in <a href="https://en.wikipedia.org/wiki/CUDA" rel="nofollow noreferrer">CUDA</a>. But I treat all my photons they same, and ignore their colour.</p>
<p>This simplicity has some nice properties: e.g. I can just count them with one integer value for each little subdivision patch on the surface.</p>
<p>However, to properly model the global illumination, I should take into account the colour, after a photon bounces from a surface. (A red carpet, reflects red light onto a nearby wall, not white light.)</p>
<p>An obvious approach would be to replace the single integer count with three floating point counters, for R, G and B.</p>
<p>But I feel there must be a more elegant solution to this? Russian roulette on the R/G/B channels perhaps? Although this would create more noise? But it would mean fewer data per photon, and thus better use of the cache?</p>

CC BY-SA 4.0
2020-12-08T22:06:05.260Z
By color do you mean path throughput? There is no elegant way to handle "color" other than treating it as a vector, i.e. a spectrum over three channels (RGB). The photon count is different from the throughput weight. See [PBRT](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Stochastic_Progressive_Photon_Mapping.html) for an explanation on how to treat these particles to build your photon map.
Hubble
<global-illumination><photon-mapping>
How to count the photons when Photon Mapping
Bram
# How to count the photons when Photon Mapping

(Asked by: username_0 on 2020-12-07)

I wrote a rather elegant and compact [Photon Mapper](https://en.wikipedia.org/wiki/Photon_mapping) in [CUDA](https://en.wikipedia.org/wiki/CUDA). But I treat all my photons they same, and ignore their colour.

This simplicity has some nice properties: e.g. I can just count them with one integer value for each little subdivision patch on the surface.

However, to properly model the global illumination, I should take into account the colour, after a photon bounces from a surface. (A red carpet, reflects red light onto a nearby wall, not white light.)

An obvious approach would be to replace the single integer count with three floating point counters, for R, G and B.

But I feel there must be a more elegant solution to this? Russian roulette on the R/G/B channels perhaps? Although this would create more noise? But it would mean fewer data per photon, and thus better use of the cache?

**Tags:** global-illumination, photon-mapping

> **Comments:**
> **username_1**: By color do you mean path throughput? There is no elegant way to handle "color" other than treating it as a vector, i.e. a spectrum over three channels (RGB). The photon count is different from the throughput weight. See [PBRT](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Stochastic_Progressive_Photon_Mapping.html) for an explanation on how to treat these particles to build your photon map.  

---

## 1 answers

### Answer by username_2 on 2020-12-09. Score: 2

I'm not sure if I understand your question correctly and don't know what you mean by "counting" and how you want to replace this by "color". A simple photon mapper looks like this: 1) photon tracing: emit, scatter, store photons 2) path tracing: gather photons in a given radius and approximate radiance using this density.

To be more precise, in pseudocode (with russian roulette) this would look like:

`xi` is the position, `wo` the outgoing direction, `W` the photon power. All three are vectors of length 3. `p` is the probability of the Russian roulette. A photon is a struct that stores the power, direction, and position.

```
xi, wo, W = emitter.sample()
while(true)
   xi = traceRay(xi, wo)
   if(isDiffuse(xi))
      storePhoton(xi, wo, W)

   if(rand < p)
      break
    W /= p;
    
    wo = bsdf.sample(xi)
    W *= bsdf(wo)/pdf(wo)*cos

```

You repeatedly call this function for a random emitter until you stored a predefined amount of photons (e.g. 500'000). After this, you *build* the photonmap, such as a k-d tree to make querying easy. As you can see, the "color" is stored in the power of the photon.

The next step is the gathering the photons, and it's normal path tracing but when you hit a diffuse surface, you gather all the photons in a fixed radius (other kernels can also be used). Here, `t` is the throughput, `wi` the incoming direction, the `photon_map` is the datastructure that we build before and populated with photons, and `total_photons` is the total amount of photons that we emitted.

```
...

if(isDiffuse(xi))
   for photon: photon_map.get(xi, radius)
      radiance *= t*bsdf(xi, wi, photon.wo) * photon.power / (pi*radius^2 * total_photons)
   break
...

```

> **Comments:**
> **username_0**: Ok, so you store photons with a vector-power each. I take it that this vector is the photon's power in R,G and B. Hence, you can think of it as the 'colour' of a photon?  
> **username_2**: Yes, in this case it can be seen as RGB. As one commenter pointed out, you can read more about this in PBRT  [chapter 5](http://www.pbr-book.org/3ed-2018/Color_and_Radiometry/Spectral_Representation.html) . This could also be a spectrum with more components than just 3, but for most purposes this is enough.  
> **username_0**: If you use spectral rendering, wouldn't each photon just have a frequency, and that's it? The power of lightsources would just be achieved by emitting more or fewer photons, with each photon's power the same?  

---

