I'm developing a light probe based GI solution and currently dealing with light leaks due to interpolation between probes located on opposite sides of the walls. I want to tackle the problem by incorporating precomputed shadow maps assigned for each probe to determine which ones are occluded and therefore which probes need to be interpolated for the current fragment in the fragment shader.

The question is, how would I even store tens of thousands of shadow maps and access them in a fragment shader?

Maybe store them continuously in a huge buffer texture? Hmm, or maybe pack them to a huge texture atlas? That also makes me wonder which method would provide a better cache behavior..


Well, it's unlikely that 10,000 cubemaps could fit into memory at all (at 128x128x4-bytes-per-pixel, 10,000 cubemaps would require upwards of 4GB of RAM). But as far as the mechanism to use a large number of such textures, that's pretty easy. You have two options.

The option that's widely available is to use cubemap array textures. You allocate the storage for the array cubemap with the number of cubemaps you want * 6. Each set of 6 array layer-faces is a single cubemap. In your shader, you just provide an array index for the cubemap layer (not layer-face) that you want.

The other option is to employ bindless textures. You create however many cubemaps you want, then provide them to the shader as an SSBO array of 64-bit integer handles. You index this array as needed and convert the handle into a sampler value before fetching.

  • $\begingroup$ Thank you for a detailed answer. Unfortunately, bindles textures are not a thing on Mac, so I have to discard that option, unfortunately. A for the cubemap arrays, they won’t store thousands of layers, will they? Will have to ask OpenGL for particular numbers, but there is a limit of few hundred layers IIRC. What do you think about packing “cubemap faces” (no actual cubemaps are involved) as series of chunks of a large texture? Basically pack all shadow maps to a texture, making it an atlas, then, in fragment shader, compute offsets and transform direction vector into UV coords. $\endgroup$ – Pavlo Muratov May 9 '18 at 13:40
  • $\begingroup$ Also, I’m considering 10x10x3bytes faces, which should fit $\endgroup$ – Pavlo Muratov May 9 '18 at 13:41
  • $\begingroup$ @ПавелМуратов: "A for the cubemap arrays, they won’t store thousands of layers, will they?" That depends on the implementation. Also, there's no such thing as "3bytes" per pixel. You will get 4-bytes per pixel. $\endgroup$ – Nicol Bolas May 9 '18 at 13:42
  • $\begingroup$ Hmm, how are 24bit depth values are stored then? $\endgroup$ – Pavlo Muratov May 9 '18 at 13:52
  • $\begingroup$ @ПавелМуратов: With either 8-bits of stencil or 8-bits of wasted space. $\endgroup$ – Nicol Bolas May 9 '18 at 13:54

I'd like to add the approach that worked for me in this particular situation as an answer.

My "cubemaps" are small, face is only 10x10 pixels and because of that I was able to shove thousands of those cubemaps in one big 2D texture atlas. Faces were laid out sequentially and atlas offsets were computed in fragment shader on the fly.


I'll throw in another possibility. The Morgan Mcguire light fields probe paper uses a tetrahedron mapping to replace cube maps and claims a 4x bandwidth increase. Basically cubemaps are inefficient in the corners. They also used an atlas layout. Given that you faces are 10x10 though it might not make much of a difference in your case.

Mcguire "Real-Time Global Illumination using Precomputed Light Field Probes" p.2 (fig. 2) http://research.nvidia.com/sites/default/files/pubs/2017-02_Real-Time-Global-Illumination/light-field-probes-final.pdf

Original mapping comes from Cigolle p.9 http://jcgt.org/published/0003/02/01/


You can invert the shadow maps. Render a cube shadowmap at each probe. Then you can filter out any probes influence that would come from beyond a wall by comparing where the new point is in relation to the shadow map's depth in that direction.

Then if the point is beyond the wall you set the interpolation weight for that probe to 0.

  • $\begingroup$ I assume you mean pixel by “the new point”? Anyway, say, I have 10000 probes and therefore 10000 cubemaps and I determine 8 probe/cubemap indices for the current pixel in the fragment shader. How would I access these 8 cubemaps, or rather, how would I pass 10000 cubemaps to the shader to be able to pick the necessary 8 out of them? $\endgroup$ – Pavlo Muratov May 9 '18 at 12:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.