Loops - Shader Basics - Shader Learning

Shader Basics

Loops

Task

The starter has two arrays:

  • rects - 4 rectangles in uv coordinates. Each is a vec4 (HLSL: float4): x and y are its bottom-left corner, z and w its top-right corner;
  • colors - the color of each rectangle: colors[i] belongs to rects[i].

Use a loop to draw all four rectangles on a black background. They overlap: draw them in order, so a later rectangle covers the earlier ones, like sheets of paper put on a table one after another.

Hint 1

One pass of the loop handles one rectangle, rects[i]. A pixel is inside it when its uv is to the right of and above the bottom-left corner and to the left of and below the top-right corner.

Hint 2

Create the color variable before the loop (black). Inside the loop, change it only when the pixel is inside the current rectangle. Because the loop goes from the first rectangle to the last, the last one that covers the pixel wins.

Hint 3

Write the result to the output after the loop, not inside it.

Theory

A loop runs the same code several times. Instead of writing the code for 5 rectangles 5 times, you write it once and repeat it.


The for loop

for (int i = 0; i < 5; i++) {
    // this code runs 5 times: with i = 0, 1, 2, 3, 4
}

The brackets after for have three parts, separated by ;:

  1. int i = 0 - runs once, before the loop: creates the counter i;
  2. i < 5 - checked before every repeat: the loop goes on while it's true;
  3. i++ - runs after every repeat: adds 1 to i (the same as i = i + 1).

Collecting a result


A loop usually builds up a value step by step. Create the variable before the loop and update it inside:

float sum = 0.0;
for (int i = 0; i < 4; i++) {
    sum += 0.25; // the same as sum = sum + 0.25
}
// sum is 1.0

Besides += there are -=, *= and /=.


Loops and arrays


The counter is an int, so it's a ready-made array index:

for (int i = 0; i < 3; i++) {
    vec3 c = palette[i]; // palette[0], palette[1], palette[2]
}

If you need the counter in a calculation with floats, convert it: float(i).


Leaving early


break stops the loop right away; continue skips the rest of the current repeat and goes to the next one:

for (int i = 0; i < 100; i++) {
    if (sum > 1.0) {
        break;
    }
    sum += 0.3;
}

There's also a while (condition) { ... } loop, but for is the one you'll see in shaders most of the time.


Loops on the GPU


Remember that the shader runs for every pixel: a loop of 100 repeats on a Full HD screen is 200 million repeats per frame. Keep loops short, and prefer a fixed number of repeats (a number or a const, not a value that changes from pixel to pixel), so the compiler can plan them.


HLSL


The for loop, break, continue, += and int(...) / float(...) look exactly the same in HLSL.