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

<p>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.</p>

CC BY-SA 4.0
2018-05-31T10:56:45.740Z
2018-05-31T10:56:45.740Z
Pavlo Muratov
<p>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.</p>

<p>The option that's widely available is to use <a href="https://www.khronos.org/opengl/wiki/Cubemap_Array_Texture" rel="noreferrer">cubemap array textures</a>. 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.</p>

<p>The other option is to employ <a href="https://www.khronos.org/opengl/wiki/Bindless_Texture" rel="noreferrer">bindless textures</a>. 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.</p>

CC BY-SA 4.0
2018-05-09T13:40:23.407Z
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.
Pavlo Muratov
CC BY-SA 4.0
2018-05-09T13:41:37.773Z
Also, I’m considering 10x10x3bytes faces, which should fit
Pavlo Muratov
CC BY-SA 4.0
2018-05-09T13:42:36.907Z
@ПавелМуратов: "*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.
Nicol Bolas
CC BY-SA 4.0
2018-05-09T13:52:01.477Z
Hmm, how are 24bit depth values are stored then?
Pavlo Muratov
CC BY-SA 4.0
2018-05-09T13:54:23.073Z
@ПавелМуратов: With either 8-bits of stencil or 8-bits of wasted space.
Nicol Bolas
CC BY-SA 4.0
2018-05-09T13:23:02.783Z
2018-05-09T13:23:02.783Z
Nicol Bolas
<p>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. </p>

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

<p>Original mapping comes from Cigolle p.9
<a href="http://jcgt.org/published/0003/02/01/" rel="nofollow noreferrer">http://jcgt.org/published/0003/02/01/</a></p>

CC BY-SA 4.0
2018-06-01T08:36:36.413Z
Just wow, even reflections are supported.. It would also be nice if you incoporate this into your another answer https://computergraphics.stackexchange.com/a/7666/8541, since these are related.
Pavlo Muratov
CC BY-SA 4.0
2018-06-01T08:17:56.800Z
2018-06-01T08:17:56.800Z
Calvin
<p>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.</p>

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

CC BY-SA 4.0
2018-05-09T12:02:54.450Z
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?
Pavlo Muratov
CC BY-SA 4.0
2018-05-09T11:36:10.280Z
2018-05-09T11:36:10.280Z
ratchet freak
<p>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. </p>

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

<p>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..</p>

<opengl><shader><texture><glsl><lighting>
How to access several textures from huge amount of textures in a shader?
Pavlo Muratov
# How to access several textures from huge amount of textures in a shader?

(Asked by: username_0 on 2018-05-09)

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..

**Tags:** opengl, shader, texture, glsl, lighting


---

## 4 answers

### Answer by username_0 on 2018-05-31. Score: 2 | Accepted answer

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.


---

### Answer by username_1 on 2018-05-09. Score: 6

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](https://www.khronos.org/opengl/wiki/Cubemap_Array_Texture). 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](https://www.khronos.org/opengl/wiki/Bindless_Texture). 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.

> **Comments:**
> **username_0**: 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.  
> **username_0**: Also, I’m considering 10x10x3bytes faces, which should fit  
> **username_1**: @ПавелМуратов: "*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.  
> **username_0**: Hmm, how are 24bit depth values are stored then?  
> **username_1**: @ПавелМуратов: With either 8-bits of stencil or 8-bits of wasted space.  

---

### Answer by username_2 on 2018-06-01. Score: 1

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/>

> **Comments:**
> **username_0**: Just wow, even reflections are supported.. It would also be nice if you incoporate this into your another answer https://computergraphics.stackexchange.com/a/7666/8541, since these are related.  

---

### Answer by username_3 on 2018-05-09. Score: 0

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.

> **Comments:**
> **username_0**: 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?  

---

