# OPENRNDR & Processing - Loops, shades and randomness

**URL:** <https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80>\
**Category:** Tutorials\
**Created:** [April 8, 2020, 2:01pm UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80 "2020-04-08T14:01:45Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [April 8, 2020, 2:01pm UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/1 "2020-04-08T14:01:45Z")

</div>

# Loops, shades and randomness

Create a grid of circle pairs. In each position in the grid there is a larger circle and maybe (50% chance) a smaller circle. The larger circle has a shade of pink (either brighter or darker). The smaller circle fill color is picked randomly from a set of 4 colors. That set contains white twice to make it more frequent.

 ![p5.P06_loopsrandom-2020-04-08-22.48.57](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/4828edb7b0190d2431bc2cb02bbfc129f959fc00.png)

### Processing / Java

```auto
import java.util.Arrays;
int seed = 1111;
int PINK = #FFC0CB;
int WHITE = #FFFFFF;
int BLACK = #000000;
ArrayList<Integer> colors = new ArrayList<Integer>(Arrays.asList(
  PINK, WHITE, WHITE, color(PINK, 128)));

void setup() {
  size(900, 450);
}

void draw() {
  randomSeed(seed);
  background(WHITE);
  for (int x=0; x<=15; x++) {
    for (int y=0; y<=5; y++) {
      PVector pos = new PVector(
        map(x, 0, 15, 100, width - 100), 
        map(y, 0, 5, 100, height - 100)
        );
      stroke(PINK, 102);
      float amount = noise(pos.x * 0.007, pos.y * 0.004) * 3 - 0.7;
      fill(amount > 1 ? lerpColor(PINK, WHITE, amount-1) : 
                        lerpColor(PINK, BLACK, 1-amount));
      circle(pos.x, pos.y, 40);
      if (random(1) < 0.5) {
        fill(colors.get((int)random(colors.size())));
        circle(pos.x, pos.y, 20);
      }
    }
  }
}

```

### OPENRNDR / Kotlin

> **Imports**
>
> ```auto
> // imports are added automatically by the IDE
> import org.openrndr.application
> import org.openrndr.color.ColorRGBa
> import org.openrndr.extra.noise.Random
> import org.openrndr.math.Vector2
> import org.openrndr.math.map
> 
> ```

```auto
fun main() = application {
    configure {
        width = 900
        height = 450
    }
    program {
        val colors = listOf(ColorRGBa.PINK, ColorRGBa.WHITE,
                            ColorRGBa.WHITE, ColorRGBa.PINK.shade(0.5))
        extend {
            Random.resetState()
            drawer.background(ColorRGBa.WHITE)
            for (x in 0..15) {
                for (y in 0..5) {
                    val pos = Vector2(
                        map(0.0, 15.0, 100.0, width - 100.0, x * 1.0),
                        map(0.0, 5.0, 100.0, height - 100.0, y * 1.0)
                    )
                    drawer.stroke = ColorRGBa.PINK.opacify(0.4)
                    val amount = Random.simplex(pos.x * 0.004, pos.y * 0.003) + 0.5
                    drawer.fill = ColorRGBa.PINK.shade(amount)
                    drawer.circle(pos, 20.0)
                    if (Random.bool()) {
                        drawer.fill = Random.pick(colors)
                        drawer.circle(pos, 10.0)
                    }
                }
            }
        }
    }
}

```

| Concept | Processing | OPENRNDR |
| --- | --- | --- |
| flip a coin | `random(1) < 0.5` | `Random.bool()` |
| pick a random item from a list | `colors.get( (int)random(colors.size()))` | `Random.pick(colors)` |
| reset the random number generator | `randomSeed(value); //noiseSeed(value);` | `Random.resetState()` or `Random.seed = "capybara"` |
| get a random noise value | `noise(x, y)` | `Random.perlin(x, y)` or `Random.simplex(x, y)` or `Random.value(x, y)` and [even more](https://github.com/openrndr/orx/tree/master/orx-noise) |
| count from 0 to 15 | `for(int x=0; x<=15; x++)`   
 `for(int x=0; x<16; x++)`   
. | `for(x in 0..15)`   
 `for(x in 0 until 16)`   
 `(0..15).foreach` |
| get a translucent variation of a color | `fill(PINK, alpha)` | `ColorRGBa.PINK.opacify(0.4)` |
| get brighter or darker variation of a color | `if(amount > 1) lerpColorPINK, WHITE, amount-1) else lerpColor(BLACK, PINK, amount)` | `ColorRGBa.PINK.shade(amount)` |

Notes:

Different noise values are used to achieve similar color shades in both programs. Noise functions and their arguments produce different aesthetics, so you just need to play with the values to get what you want.

By resetting the random seed I avoid a flickering animation, because I obtain the same sequence of random numbers on each frame. But if you want it to flicker remove the `randomSeed()` / `Random.resetState()` 🙂

👇 Share your questions and comments below | 🔎 [Find other OPENRNDR & Processing posts](https://openrndr.discourse.group/search?q=Processing%20%23openrndr%3Atutorials)

---

<div class="post-metadata">

**Author:** ![ricardo](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/ricardo/32/8_2.png) [@ricardo](https://openrndr.discourse.group/u/ricardo)\
**Post date:** [April 9, 2020, 7:14am UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/2 "2020-04-09T07:14:58Z")

</div>

Looking good! `Random.resetState()` should be called automatically by the `init` block, were you having a different behavior?

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [April 9, 2020, 7:16am UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/3 "2020-04-09T07:16:51Z")

</div>

Resetting it avoids animation. I didn’t want to get new values on every frame. I’ll mention that.

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [April 9, 2020, 8:25am UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/5 "2020-04-09T08:25:30Z")

</div>

There was a discussion in slack about which one of these to use:

- A. `for(x in 0 until 10) { ... }`
- B. `for(x in 0..9) { ... }`
- C. `(0..9).forEach { ... }`

Case A, not including the top value (`x < 10` in Java), is more common than including it (case B, `x <= 10` in Java). The reason I chose B is because I find it less confusing when mapping the looped variable.

For example, if I wanted to map the previous ranges to the range (100.0, 400.0), I would use

- `map(0.0, 9.0, 100.0, 400.0, x * 1.0)`

In case A, we have 10 in the loop but 9.0 in the map (because we count from 0 up to - but not including - 10). In cases B and C we have 9 both in the loop and in the map, which I think helps avoid errors.

Note: `forEach` can also be used to loop but, unlike `for` and `while`, it does not provide `break` nor `continue`.

---

<div class="post-metadata">

**Author:** ![MarkWebster](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/markwebster/32/79_2.png) [@MarkWebster](https://openrndr.discourse.group/u/MarkWebster)\
**Post date:** [April 12, 2020, 12:27pm UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/6 "2020-04-12T12:27:51Z")

</div>

Hi Abe,

I’ve been playing a little with your above example. The loop idiom you use takes a little time to understand coming from Processing but that is just a matter of getting accustomed to it. I have however a few questions:

- Regarding the noise functions, I’m not getting the same behaviour between the two.
- I’ve added a little harmonic motion, but again I’m not getting the same motion.
- Is there a rectMode in OPENRNDR? I haven’t found one and I’m wondering about translations such as rotations for rectangles…

Here’s my P5 code

```auto
float xGridMax = 100.0;
float yGridMax = 15.0;

void setup() {
  size(800, 460);
}

void draw() {

  background(255);
  noStroke();
  for (int x=0; x<=xGridMax; x++) {
    for (int y=0; y<=yGridMax; y++) {
      PVector pos = new PVector(
        map(x, 0, xGridMax, 100, width - 100), 
        map(y, 0, yGridMax, 100, height - 100)
      );

      float amount = noise(pos.x * 0.015, pos.y * 0.015);
      float alpha = map(amount, 0, 1, 0, 255);
      fill(0, 0, 255, alpha);
      float rectH = map(sin((pos.y + pos.x) + frameCount*0.075), -1.0, 1.0, -yGridMax, yGridMax); 
      rect(pos.x, pos.y, 5, rectH);
    }
  }
}

```

and here’s my OPENRNDR

```auto
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.Random
import org.openrndr.math.Vector2
import org.openrndr.math.map

fun main() = application {
    configure {
        width = 800
        height = 460
    }
    program {

        var xGridMax = 100.0
        var yGridMax = 15.0

        extend {
            drawer.background(ColorRGBa.WHITE)
            drawer.stroke = null

            for (x in 0..xGridMax.toInt()) {
                for (y in 0..yGridMax.toInt()) {
                    val pos = Vector2(
                        map(0.0, xGridMax, 100.0, width - 100.0, x * 1.0),
                        map(0.0, yGridMax, 100.0, height - 100.0, y * 1.0)
                    )
                    val amount = Random.perlin(pos.x * 0.015, pos.y * 0.015)
                    val alpha = map(0.0, 1.0, 0.0, 255.0, amount)
                    drawer.fill = ColorRGBa(0.0, 0.0, 255.0, alpha)

                    val rectH = map(-1.0,1.0,-yGridMax, yGridMax,
                        Math.sin((pos.y + pos.x) + frameCount*0.075))
                    drawer.rectangle(pos,5.0, rectH)

                }
            }
        }
    }
}

```

PS: Sorry for the formatting or rather lack of it.

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [April 12, 2020, 5:00pm UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/7 "2020-04-12T17:00:46Z")

</div>

Hi Mark,

Nice to see your experiment! 🙂

- To format your block of code you can add “code fences”: that’s an empty line with three backticks ````` before and after your code (I did that for you). Another option is to use the `</>` button above the editor, but I like it less because it indents everything and apparently it doesn’t do syntax highlighting.
- Colors in OPENRNDR use normalized values. So use values between 0.0 and 1.0 for R, G, B and A.
- Perlin noise returns values between -1.0 and 1.0 in OPENRNDR, so adjust your `map` accordingly.

After changing these I get the same look in both. With one difference though: in Processing it runs at 60 FPS and in OPENRNDR at about 30 FPS in this laptop.

OPENRNDR provides `drawer.rectangles()` which is more efficient and does run at 60 FPS for this program. BUT you can’t set the color of each rectangle manually afaik. Maybe @edwin can provide some suggestions here. The way I would colorize those rectangles to achieve the same look is with a shade style, but that’s not trivial unless you know about GLSL shaders already. In a nutshell, what the shade style would do is tell all pixels to have a certain alpha based on their position in the screen.

---

<div class="post-metadata">

**Author:** ![MarkWebster](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/markwebster/32/79_2.png) [@MarkWebster](https://openrndr.discourse.group/u/MarkWebster)\
**Post date:** [April 13, 2020, 8:24am UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/8 "2020-04-13T08:24:14Z")

</div>

Hi Abe,

thank you for your kind reply and solutions. All makes sense now. From reading a little about your move from Processing to OPENRNDR in another post, you mention shaders and although I’ve only dabbled in a few with P5, I get the impression that its not the best environment for working with them. I imagine that OPENRNDR is far more capable and perhaps better designed for working with and incorporating GLSL? Having looked at OF and Cinder, I saw a substantial use of shaders and it is something I’d like to have more time to learn. Perhaps my learning of OPENRNDR could be orientated towards that? Any suggestions?

Best

Mark

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [April 13, 2020, 11:37am UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/9 "2020-04-13T11:37:41Z")

</div>

Hi, I found it ok to work with shaders in Processing. Only that you can’t use the Processing IDE to edit them. I made a [tool](https://discourse.processing.org/t/processing-shader-tool/5476) to make it a bit easier.

Then OPENRNDR is the only environment I know with shade styles, which let you add shader effects with one line of code.

What you can do with shaders is more or less the same in all environments. Ok, some may let you add your own attributes to vertices, some provide Compute shaders… but the basics are the same.

I think I should really record and put my shader workshop online 🙂 Would you be interested?

---

<div class="post-metadata">

**Author:** ![MarkWebster](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/markwebster/32/79_2.png) [@MarkWebster](https://openrndr.discourse.group/u/MarkWebster)\
**Post date:** [April 13, 2020, 1:20pm UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/10 "2020-04-13T13:20:18Z")

</div>

Would love to read up more on working with shaders in OPENRNDR. 😍

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [March 15, 2023, 4:38pm UTC](https://openrndr.discourse.group/t/openrndr-processing-loops-shades-and-randomness/80/11 "2023-03-15T16:38:18Z")

</div>

I’ve been reviewing the [tutorials linked in the OPENRNDR](https://openrndr.org/getting-started/#tutorials) website to make sure they stay up to date.

Here’s how I would write the program above 3 years later:

> **imports**
>
> ```auto
> import org.openrndr.application
> import org.openrndr.color.ColorRGBa
> import org.openrndr.extra.noise.Random
> import org.openrndr.extra.shapes.grid
> 
> ```

```auto
fun main() = application {
    configure {
        width = 900
        height = 450
    }
    program {
        val colors = listOf(ColorRGBa.PINK, ColorRGBa.WHITE,
                            ColorRGBa.WHITE, ColorRGBa.PINK.shade(0.5))
        val cells = drawer.bounds.grid(16, 6, 100.0, 100.0).flatten()
        extend {
            Random.resetState()
            drawer.clear(ColorRGBa.WHITE)
            cells.forEach { cell ->
                val brightness = Random.simplex(cell.center * 0.0035) + 0.5
                drawer.stroke = ColorRGBa.PINK.opacify(0.4)
                drawer.fill = ColorRGBa.PINK.shade(brightness)
                drawer.circle(cell.center, cell.width * 0.4)
                if (Random.bool()) {
                    drawer.fill = Random.pick(colors)
                    drawer.circle(cell.center, cell.width * 0.2)
                }
            }
        }
    }
}

```

The main differences are:

- I would use `Rectangle.grid()` to create a grid layout, instead of writing my own for loops. The intention becomes clearer and the grid is now defined by 4 values instead of 14 (depending on how you count).
- `Random.simplex()` now accepts `Vector2` and `Vector3` arguments. Both can be multiplied by a scalar, making the call to `simplex` a bit shorter (if you don’t care about scaling x and y differently).
- I made the circle sizes proportional to the cell width. That way I can easily adjust column and row counts on the grid and have non-overlapping circles. Here with 32 x 12:

 ![image](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/7754ac5b70aadbe53bd4de8b4e05905b50f018b2.jpeg)

- In some cases I would use `colors.random()` instead of `Random.pick(colors)` but the first one is not seeded and the second one is. In this case we want it seeded to avoid having the colors change on every animation frame. On the other hand, if we are displaying a static result, it would be better to render everything to a renderTarget/colorBuffer outside the `extend {}` block and then drawing that image instead of redrawing all the circles on every animation frame 🙂
