<p>It's hard to say without seeing the shader in question. My guess is that every animation frame in the atlas has the same size. This fixed size allows mapping any UV coordinates to the proper animation frame's UV extents.</p>

<p>For example, with 16 frames in a texture:</p>

<pre><code>0 0.25 0.5 0.75 1.0
\  \   |   /  _/
 +--+--+--+--+
 | 0| 1| 2| 3|
 +--+--+--+--+ 0.25
 | 4| 5| 6| 7|
 +--+--+--+--+ 0.5
 | 8| 9|10|11|
 +--+--+--+--+ 0.75
 |12|13|14|15|
 +--+--+--+--+ 1.0
</code></pre>

<p>This code should do the trick to convert UV coordinates (range [0, 1]) to a given frame's UV extents:</p>

<pre><code>vec2 uv = ...
uint frameId = ... // [0, 15]
const uint rowFrameCount = 4; // implies frameUVWidth = 1 / 4 = 0.25
const vec2 frameUVSize = vec2(1.0 / rowFrameCount, 0.25);

// Find the column and row offset
uvec2 frameOffset = uvec2(frameId % rowFrameCount, frameId / rowFrameCount);

// Offset to the proper column
uv += frameOffset;

// Scale the coordinates in the range of a single frame (here [f_0, f_0 + 0.25])
uv *= frameUVSize;
</code></pre>

<p>Some results:</p>

<pre><code>uv = vec2(0, 1); frameId = 0; uv_out = vec2(0, 0.25);
uv = vec2(0, 0.5); frameId = 3; uv_out = vec2(0.75, 0.125);
uv = vec2(0.5, 0.5); frameId = 14; uv_out = vec2(0.625, 0.875);
</code></pre>

<p>In truth however, this kind of texture trickery is less useful these days since <a href="https://www.khronos.org/opengl/wiki/Array_Texture" rel="nofollow noreferrer">array textures</a> are now widely available with better results and simpler indexing.</p>

CC BY-SA 4.0
2019-01-09T08:39:49.520Z
2019-01-09T08:39:49.520Z
bernie
<p>I am working with an atlas shader that steps through various sprite tiles within a single png atlas page to playback an animation with sampler2D.  Looking at the shader code, I would expect to have to define a lower left and upper right point for each image area on the atlas image that I want to use for that frame.  However, it simply uses a Vec2 which is just a single x,y value.  How is this possible?  How is a single vec2 defining both position and range of the sampled area?  In a more broad sense how are these UV vec2s from varying UVs being interpreted in GLSL in general?  To me, you can't define an image area from just a vec2 so I am really confused???</p>

<shader><glsl><uv-mapping><image><tile-based-rendering>
How does a GLSL Sampler2D read a Vec2 UV coordinate to determine UV range
Daniel E
# How does a GLSL Sampler2D read a Vec2 UV coordinate to determine UV range

(Asked by: username_0 on 2019-01-08)

I am working with an atlas shader that steps through various sprite tiles within a single png atlas page to playback an animation with sampler2D. Looking at the shader code, I would expect to have to define a lower left and upper right point for each image area on the atlas image that I want to use for that frame. However, it simply uses a Vec2 which is just a single x,y value. How is this possible? How is a single vec2 defining both position and range of the sampled area? In a more broad sense how are these UV vec2s from varying UVs being interpreted in GLSL in general? To me, you can't define an image area from just a vec2 so I am really confused???

**Tags:** shader, glsl, uv-mapping, image, tile-based-rendering


---

## 1 answers

### Answer by username_1 on 2019-01-09. Score: 1

It's hard to say without seeing the shader in question. My guess is that every animation frame in the atlas has the same size. This fixed size allows mapping any UV coordinates to the proper animation frame's UV extents.

For example, with 16 frames in a texture:

```
0 0.25 0.5 0.75 1.0
\  \   |   /  _/
 +--+--+--+--+
 | 0| 1| 2| 3|
 +--+--+--+--+ 0.25
 | 4| 5| 6| 7|
 +--+--+--+--+ 0.5
 | 8| 9|10|11|
 +--+--+--+--+ 0.75
 |12|13|14|15|
 +--+--+--+--+ 1.0

```

This code should do the trick to convert UV coordinates (range [0, 1]) to a given frame's UV extents:

```
vec2 uv = ...
uint frameId = ... // [0, 15]
const uint rowFrameCount = 4; // implies frameUVWidth = 1 / 4 = 0.25
const vec2 frameUVSize = vec2(1.0 / rowFrameCount, 0.25);

// Find the column and row offset
uvec2 frameOffset = uvec2(frameId % rowFrameCount, frameId / rowFrameCount);

// Offset to the proper column
uv += frameOffset;

// Scale the coordinates in the range of a single frame (here [f_0, f_0 + 0.25])
uv *= frameUVSize;

```

Some results:

```
uv = vec2(0, 1); frameId = 0; uv_out = vec2(0, 0.25);
uv = vec2(0, 0.5); frameId = 3; uv_out = vec2(0.75, 0.125);
uv = vec2(0.5, 0.5); frameId = 14; uv_out = vec2(0.625, 0.875);

```

In truth however, this kind of texture trickery is less useful these days since [array textures](https://www.khronos.org/opengl/wiki/Array_Texture) are now widely available with better results and simpler indexing.


---

