A sandboxed rainbow function

fwsGonzo
3 min readMay 13, 2024

--

I very recently wrote a rainbow color function for my game

It looks a little bit like this. We can make it nicer with shaders, of course.

The reason behind not immediately just using a shader is because of the minimap. You want the block to have a base color, but one that is based on its global position, looking like a rainbow. Like above!

As usual, I was a little bit curious to how this would perform.

uint32_t stdRainbowBlockColor(Block, int x, int z)
{
static constexpr float period = 0.5f;
// Rainbow block color
const int r = api::sin(x * period) * 127 + 128;
const int g = api::sin(z * period) * 127 + 128;
const int b = api::sin((x + z) * period) * 127 + 128;
return 255 << 24 | r << 16 | g << 8 | b;
}

I measured it to take ~57ns. There’s some overhead in the benchmark as it is actually running from the script, and I’m benchmarking from inside my game engine.

I occasionally check how eg. wasmtime performs running these kinds of functions. And I measured it to around ~107ns. That seems about right as it needs ~50ns just to call a function.

Each measured 30 times in sequence. Lower is better.

Enabling binary translation gave predictable results, as it is highly tuned towards low latency. With it, we can call the function 5.25 times before wasmtime has called it once.

When it comes to wasmtime, I did try a few things. For example, in libriscv it makes a lot of sense to just implement a host function that performs std::sin for us, because there’s almost no latency attached to asking the game engine to do something. With wasmtime that is not the case, as I implemented api_sinf as a test, and it just made the latency even worse clocking in at 150ns. I think it makes sense to pick the method that performs best in each solution, as neither approaches add any sort of attack vector.

For my games script I overrode sinf with a system call that uses the host function:

APICALL(api_math_sinf)
{
auto [x] = machine.sysargs<float>();
machine.set_result(std::sin(x));
}

A fairly simple system call that does one thing and does it well.

My work has recently been on colors and gradients.

A gradiented procedurally generated mushroom seen from above.

I also have almost completed a system for painting blocks with particle sprays. I haven’t yet decided all the game mechanics around how to obtain the sprays and what the items look like. But, yeah. I also don’t want to show too much.

Anyway. Just a short blog post this time.
-gonzo

--

--