Skip to content

Commit

Permalink
Other: 'One Small Step' - Floyd-Steinberg version.
Browse files Browse the repository at this point in the history
  • Loading branch information
deanthecoder committed Mar 31, 2024
1 parent 0334d36 commit 70786d3
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 29 deletions.
77 changes: 48 additions & 29 deletions Experiments/OneSmallStep/OneSmallStep.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// zcc +zx -lndos -create-app -lmz -o OneSmallStep ../utils.c ../glsl.c OneSmallStep.c
// zcc +zx -lndos -lmz -o OneSmallStep.bin ../utils.c ../glsl.c OneSmallStep.c
// zcc +zx -lndos -create-app -lmz -DAMALLOC -o OneSmallStep ../utils.c ../glsl.c OneSmallStep.c
// zcc +zx -lndos -lmz -DAMALLOC -o OneSmallStep.bin ../utils.c ../glsl.c OneSmallStep.c
#include "../utils.h"
#include "../glsl.h"

Expand Down Expand Up @@ -36,7 +36,7 @@ static float box(vec3_t p, vec3_t b) {
}

static float map(vec3_t p) {
// return v3_length(p) - 1.6f;
//return v3_length(p) - 1.6f;
float r, k, t, h,
bmp = (n31(p) + n31(*v3_mulf(&p, 2.12f)) * .5 + n31(*v3_mulf(&p, 4.42f)) * .25 + n31(*v3_mulf(&p, 8.54f)) * .125 + n31(*v3_mulf(&p, 63.52f)) * .0156) * .5 * (.5 + 2. * exp(-spow(v2_length(v2_sub(vec2(p.x, p.z), vec2(.5, 2.2))), 2.) * .26)),
a = p.y - .27 - bmp,
Expand Down Expand Up @@ -115,7 +115,7 @@ static float mainImage(vec2_t fc) {
return c;
}

void main()
int main()
{
srand(0);
zx_border(INK_BLUE);
Expand All @@ -126,37 +126,56 @@ void main()
// Footer.
draw_footer("One Small Step (@DeanTheCoder)");

// Init Floyd-Steinberg errors.
float* err1 = (float*)malloc(sizeof(float) * 257);
float* err2 = (float*)malloc(sizeof(float) * 257);
for (uint16_t i = 0; i < 256; ++i)
{
err1[i] = 0.0f;
err2[i] = 0.0f;
}

// Loop.
in_GetKeyReset();
for (uint16_t y = 0; y < 192 - 8; y += 4)
gotoxy(0, 0);
for (uint16_t y = 0; y < 192 - 8; ++y)
{
for (uint16_t x = 0; x < 256; x += 4)
// Calculate a line of pixels.
for (uint16_t x = 0; x < 256; ++x)
err1[x] += clamp(mainImage(*vec2(x, 191 - y)), 0.0f, 1.0f) + 0.01f;

// Apply dithering.
for (uint16_t x = 1; x < 255; ++x)
{
float oldPixel = err1[x];
float newPixel = floor(oldPixel + 0.5f);
err1[x] = newPixel;
float pixelError = oldPixel - newPixel;

err1[x + 1] += pixelError * 0.4375f;
err2[x - 1] += pixelError * 0.1875f;
err2[x] += pixelError * 0.3125f;
err2[x + 1] += pixelError * 0.0625f;

if (newPixel >= 0.5)
plot(x, y);
}

// Cycle the errors up a row.
float* p = err1;
err1 = err2;
err2 = p;
memset(err2, 0, sizeof(float) * 256);

for (uint16_t i = 0; i < 256; ++i)
{
float c = clamp(mainImage(*vec2(x, 191 - y)), 0.0f, 2.0f);

// Set the color.
uint8_t ink, bright = 1 << 6;
switch ((uint8_t)(floor(c * 0.99f)))
{
case 0:
ink = INK_WHITE;
break;

case 1:
ink = INK_WHITE + bright;
c *= 0.4;
break;

default:
ink = INK_WHITE + PAPER_RED;
break;
}

// Plot the pixels.
c_plot_shade((x >> 2), (y >> 2), min(c * 255.0f, 255.0f));
attrMem[((y >> 3) << 5) + (x >> 3)] = ink;
if (err1[i] < 0.01f)
err1[i] = 0.0f;
}
}

in_waitForKey();
free(err1);
free(err2);
return 0;
}
Binary file added Experiments/OneSmallStep/OneSmallStep.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Experiments/OneSmallStep/OneSmallStep.tap
Binary file not shown.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ A little more of a 'demo-style' with this one - I've added a DTC logo (which I'l
The code is written in C and compiled into Z80 machine code ([here](Experiments/BreakOut/breakout.tap)).
![](Experiments/BreakOut/Breakout.png)

# Experiments - One Small Step
This is based on a GLSL [shader](https://www.shadertoy.com/view/tt3yRH) I wrote a while ago. I built a library of GLSL-like functions in C to recreate the original code, then ran it over many hours.

The final quality was achieved with a Floyd-Steinberg dithering algorithm. A random dither is much easier to implement, but the result was way too noisy.

The executable is [here](Experiments/OneSmallStep/OneSmallStep.tap).
![](Experiments/OneSmallStep/OneSmallStep.png)

## Contribution and Improvements
ZX Speculator is an ongoing project and contributions are welcome. Whether it's improving emulation accuracy, testing on different platforms, or enhancing existing features, your input is valuable (although I can't always promise a fast response, as this is a side project).

Expand Down

0 comments on commit 70786d3

Please sign in to comment.