Admin | Edit

Moirisc - RISC OS 256 bytes

640x480 version

Second Acorn Archimedes / RISC OS intro with two versions :
This is a follow-up of Acetaminophen with buffers / precomputation and it works best on ARM3 again but also okaish on ARM2, require ARM2 12MHz and MEMC1a at 16MHz to be smooth.

Mainly wanted to see if a buffered version could be done at 256 bytes since it is much prettier / faster than some widened circles (it is also more technically akin to the classic effect as seen in many demos), the main disadvantage is RAM usage and long precalc time. (more than 60 seconds on 1987 ARM2 !)

This use Minsky circle for the animation again, a 512x512 (1024x1024 for mode 28) buffer containing centered circles is precomputed, circles are generated per pixels using a short integer SQRT approximation, the draw loop just fetch buffer pixels two times with different offset, the values are then mixed with logical operators and the result is drawn onto the frame-buffer.

There is actually 4 buffers generated, each buffers is shifted in X by a single pixel, this is needed because of the lookup / draw instruction alignment requirements (each fetch / write needs to be aligned to a word boundary) otherwise graphics glitch appears, the correct buffer is then selected prior the draw loop.

The draw loop use blocks copy instruction to lookup / copy 16 pixels per iteration so it is pretty fast, could be faster by using more registers but this also induce more instructions.

320x256 version

Due to the buffers the program require around 1056k free RAM, double for mode 28, this must be allocated with the RISC OS Task manager ("Next") prior launch.

Could use a low colors mode to be smooth and not having to allocate RAM on 1987 Acorn Archimedes (A30x) but this induce alignment issues which must be fixed with some more instructions, perhaps it is doable at 256 bytes without compromises.

I actually had bit of troubles to fit it all in 256 bytes, one of the last minute cheap trick i used was to comment out the "OS_RemoveCursors" API call so the blinking cursor is visible... it is almost imperceptible due to what is going on screen anyway.

CodePressor (ARM code compressor) actually doesn't help on this one and makes the executable binary larger.

"Moirisc" is a portmanteau, a combination of Moiré and RISC.

The same algorithm could be used for checkered pseudo 3D layers perhaps and other effects by generating different buffer content.

the ARM code for the RPI version (i use BBC BASIC assembler)

Roughly similar effect with JS code (prototype)

// classic interference effect done per pixels with short integer sqrt approx.
function sqr(n) {
  let b = 0
  while (n >= 0) {
    n -= b
    b += 1
    //n -= b
  return b// - 1

function setup() {
  createCanvas(256, 256)

let mx = 92
let my = 0

function draw() {

  mx += (my >> 5)
  my -= (mx >> 5)
  for (let y = 0; y < height; y += 1) {
    for (let x = 0; x < width; x += 1) {
      let c = 0
      for (let i = 0; i < 2; i += 1) {
        let cx = mx
        let cy = my
        if (i == 0) {
          let ct = cx
          cx = cy
          cy = ct

        let xx = abs((x + cx) / width - 0.5) * 2 * width / 12
        let yy = abs((y + cy) / height - 0.5) * 2 * height / 12

        let sc = sqr(xx * xx + yy * yy)
        c ^= (sc & 7) * 32
      c = 255 - c

      let px = x
      let py = y

      if (px < 0 || px >= width || py < 0 || py >= height) continue

      let index = (px + py * width) * 4
      pixels[index + 0] += c
      pixels[index + 1] += c
      pixels[index + 2] += c

JavaScript prototype

early and bit buggy (lack of alignment ?) 4 colors version

some other Moiré effects could be made without cost by using different patterns (perhaps even fake plasma by adjusting the palette in real-time), here using inverted 1/4 patches of the original image

Speed optimizations

For demos with no size limitations the pre-computation can be done quicker by exploiting symmetry, just generate 1/4 of the image and copy/paste the rest.

back to topLicence Creative Commons