<p>Multiplying <code>uv</code> by <code>K</code> scales it from a 0–1 range to a 0–K one. As you’re noting, the <code>fract</code> operation takes the result of that and removes the whole-number portion of the value, resulting in a [0 1) result. The values your shader outputs are never actually hitting 100% brightness in any channel (…within the limits of the 8-bit output, of course), because when the value becomes ≥ 1 it wraps around again. If you looked slightly off that top edge, say with <code>lv = fract((uv + vec2(0.0, 0.1)) * K)</code>, you’d see the black corner you’re looking for.</p>
<p><a href="https://i.sstatic.net/Scsj3.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Scsj3.png" alt="screenshot of the same 2×2 UV gradient, slightly shifted to show the pattern repeating past the top edge" /></a></p>
<p>Another way of looking at it would be to graph a 1-dimensional value. Here’s <code>y = x</code>:</p>
<p><a href="https://i.sstatic.net/gaH37.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/gaH37.png" alt="a graph of y = x, a diagonal line with 45° slope" /></a></p>
<p>…and here’s <code>y = fract(2x)</code>:</p>
<p><a href="https://i.sstatic.net/kuWU2.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/kuWU2.png" alt="a graph of y = fract(2x), a repeating diagonal line pattern with a steeper 63°ish slope" /></a></p>
<p>Just like the 2D color values you’re producing, the first extends indefinitely along that one line, and the second has a sawtooth pattern that repeats each time the value being fed into <code>fract</code> crosses a whole-number threshold.</p>

CC BY-SA 4.0
2024-04-18T18:28:28.930Z
2024-04-18T18:33:48.507Z
2024-04-18T18:33:48.507Z
Noah Witherspoon
<p>Here is a shader in GLSL that visualizes the normalized pixel coordinates (from 0 to 1):</p>
<pre><code>void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    
    
    vec2 lv = uv;
    
    vec3 col = vec3(lv,0.0);

    // Output to screen
    fragColor = vec4(col,1.0);
}
</code></pre>
<p>Output:</p>
<p><a href="https://i.sstatic.net/GjywQ.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/GjywQ.png" alt="enter image description here" /></a></p>
<p>So we have (0,0) at bottom left, (1,0) at top left, (1,1) at top right, and (1,0) at bottom right.</p>
<p>Pretty simple.</p>
<p>But now, if we change the line <code>vec2 lv = uv</code> to <code>vec2 lv = fract(uv*2.);</code>, we introduce a 2x2 grid:</p>
<p><a href="https://i.sstatic.net/BIKnP.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/BIKnP.png" alt="enter image description here" /></a></p>
<p>Why does that happen?</p>
<p>Previously, the top center was between green and yellow. When we had <code>uv = (0.5,1)</code>, but then we do <code>lv = fract((0.5,1)*2) = fract((1,2)) = (0,0)</code>, so it just becomes black? But there's no black at the top of the new image.</p>
<p><strong>TLDR:</strong> I don't understand why when we do <code>lv = fract(uv*K)</code> it introduces a KxK grid into the output.</p>

<shader><uv-mapping>
Why does lv = fract(uv*2) result in grid like pattern?
kyopa
# Why does lv = fract(uv*2) result in grid like pattern?

(Asked by: username_0 on 2024-04-18)

Here is a shader in GLSL that visualizes the normalized pixel coordinates (from 0 to 1):

```
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    
    
    vec2 lv = uv;
    
    vec3 col = vec3(lv,0.0);

    // Output to screen
    fragColor = vec4(col,1.0);
}

```

Output:

[![enter image description here](https://i.sstatic.net/GjywQ.png)](https://i.sstatic.net/GjywQ.png)

So we have (0,0) at bottom left, (1,0) at top left, (1,1) at top right, and (1,0) at bottom right.

Pretty simple.

But now, if we change the line `vec2 lv = uv` to `vec2 lv = fract(uv*2.);`, we introduce a 2x2 grid:

[![enter image description here](https://i.sstatic.net/BIKnP.png)](https://i.sstatic.net/BIKnP.png)

Why does that happen?

Previously, the top center was between green and yellow. When we had `uv = (0.5,1)`, but then we do `lv = fract((0.5,1)*2) = fract((1,2)) = (0,0)`, so it just becomes black? But there's no black at the top of the new image.

**TLDR:** I don't understand why when we do `lv = fract(uv*K)` it introduces a KxK grid into the output.

**Tags:** shader, uv-mapping


---

## 1 answers

### Answer by username_1 on 2024-04-18. Score: 3

Multiplying `uv` by `K` scales it from a 0–1 range to a 0–K one. As you’re noting, the `fract` operation takes the result of that and removes the whole-number portion of the value, resulting in a [0 1) result. The values your shader outputs are never actually hitting 100% brightness in any channel (…within the limits of the 8-bit output, of course), because when the value becomes ≥ 1 it wraps around again. If you looked slightly off that top edge, say with `lv = fract((uv + vec2(0.0, 0.1)) * K)`, you’d see the black corner you’re looking for.

[![screenshot of the same 2×2 UV gradient, slightly shifted to show the pattern repeating past the top edge](https://i.sstatic.net/Scsj3.png)](https://i.sstatic.net/Scsj3.png)

Another way of looking at it would be to graph a 1-dimensional value. Here’s `y = x`:

[![a graph of y = x, a diagonal line with 45° slope](https://i.sstatic.net/gaH37.png)](https://i.sstatic.net/gaH37.png)

…and here’s `y = fract(2x)`:

[![a graph of y = fract(2x), a repeating diagonal line pattern with a steeper 63°ish slope](https://i.sstatic.net/kuWU2.png)](https://i.sstatic.net/kuWU2.png)

Just like the 2D color values you’re producing, the first extends indefinitely along that one line, and the second has a sawtooth pattern that repeats each time the value being fed into `fract` crosses a whole-number threshold.


---

