# Why does lv = fract(uv*2) result in grid like pattern?

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:

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:

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.

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.
Another way of looking at it would be to graph a 1-dimensional value. Here’s y = x:
…and here’s y = fract(2x):
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.