0
\$\begingroup\$

In openGL, I have a 3D terrain composed of a grid of 255x255 vertices. The vertex of the lower left corner is at coordinates (-127;-127) and the one of the upper right corner is at coordinates (127;127). All the other points (vertices) are distributed evenly between these 2 points to form a square and regular grid.

I gathered in a sampler2Darray several textures (aerial photos, all having a resolution of 1024x1024) that I would like to display at different places of the mesh according to precise coordinates (i.e. 30.25; 23.37). The rest of the mesh (the one not covered in textures) would use a solid color (i.e. green).

I have 2 questions:

  • Is using a sampler2Darray the right thing to do?

  • How to pass the coordinates of each sampler2Darray texture and retrieve them in the fragment shader?

\$\endgroup\$
2
  • \$\begingroup\$ If the textures never overlap, you could do this with UV coordinates per vertex. If you have only a few textures, you could do this with a uniform array of position offsets. Is one route or the other more appropriate for your use case? \$\endgroup\$
    – DMGregory
    Commented Aug 13, 2023 at 12:05
  • \$\begingroup\$ Thanks @DMGregory for the quick reply. Yes the textures never overlap. Actually they perfectly fit together to form a tile puzzle. However there are dozens of textures. Could please you show me the way (it can be an article, a tutorial or a github project)? I can't figure out how to position each of the textures on the mesh from the sampler2Darray. Thank you very much. \$\endgroup\$
    – Greelings
    Commented Aug 13, 2023 at 13:26

1 Answer 1

1
\$\begingroup\$

I might solve this with an index texture, similar to this tilemap approach I presented earlier.

Set aside an extra texture that covers your whole terrain with a resolution of about 1 texel per aerial photo width - so it's very low res compared to the photos themselves.

For each of these index texels that overlaps a photo location, choose the closest photo, and encode the UV coordinates of its center point in the red and green components of the index texel, and the photo's array index in the blue component.

The center point can be stored as an offset from this texel's location, in units where 1.0 = 1 photo width, so even at 1 byte per channel, you can finely position photos within a precision of 1/256th of their width (4 pixels at 1024 resolution). You can bump up to larger texel formats for even higher precision if needed. You can use a special value like (1, 1, 1) to indicate "no photo nearby".

When drawing the terrain, sample the four closest texels in the index texture, with sample filtering set to point/nearest so they don't blend together. From this, you get the coordinates and array indices of the 4 closest aerial photos. Select the closest one to sample, or fall back on your default colour if none of them are close enough to overlap this fragment.

The advantage of this approach over sending coordinates as uniforms is that it scales up to large numbers of photos well: the work per fragment remains constant at 4 taps from the index texture and at most 1 tap from the photo array, and you don't have to iterate over a list of all photos.

The advantage of this approach over encoding the information in vertex attributes is that you can transition between photos in the middle of a polygon, rather than being restricted to the resolution of the mesh subdivision.

\$\endgroup\$
1
  • \$\begingroup\$ It's really clever. Thank you! \$\endgroup\$
    – Greelings
    Commented Aug 13, 2023 at 16:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .