Skip to content

Commit 70786d3

Browse files
committed
Other: 'One Small Step' - Floyd-Steinberg version.
1 parent 0334d36 commit 70786d3

File tree

4 files changed

+56
-29
lines changed

4 files changed

+56
-29
lines changed

Experiments/OneSmallStep/OneSmallStep.c

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// zcc +zx -lndos -create-app -lmz -o OneSmallStep ../utils.c ../glsl.c OneSmallStep.c
2-
// zcc +zx -lndos -lmz -o OneSmallStep.bin ../utils.c ../glsl.c OneSmallStep.c
1+
// zcc +zx -lndos -create-app -lmz -DAMALLOC -o OneSmallStep ../utils.c ../glsl.c OneSmallStep.c
2+
// zcc +zx -lndos -lmz -DAMALLOC -o OneSmallStep.bin ../utils.c ../glsl.c OneSmallStep.c
33
#include "../utils.h"
44
#include "../glsl.h"
55

@@ -36,7 +36,7 @@ static float box(vec3_t p, vec3_t b) {
3636
}
3737

3838
static float map(vec3_t p) {
39-
// return v3_length(p) - 1.6f;
39+
//return v3_length(p) - 1.6f;
4040
float r, k, t, h,
4141
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)),
4242
a = p.y - .27 - bmp,
@@ -115,7 +115,7 @@ static float mainImage(vec2_t fc) {
115115
return c;
116116
}
117117

118-
void main()
118+
int main()
119119
{
120120
srand(0);
121121
zx_border(INK_BLUE);
@@ -126,37 +126,56 @@ void main()
126126
// Footer.
127127
draw_footer("One Small Step (@DeanTheCoder)");
128128

129+
// Init Floyd-Steinberg errors.
130+
float* err1 = (float*)malloc(sizeof(float) * 257);
131+
float* err2 = (float*)malloc(sizeof(float) * 257);
132+
for (uint16_t i = 0; i < 256; ++i)
133+
{
134+
err1[i] = 0.0f;
135+
err2[i] = 0.0f;
136+
}
137+
129138
// Loop.
130139
in_GetKeyReset();
131-
for (uint16_t y = 0; y < 192 - 8; y += 4)
140+
gotoxy(0, 0);
141+
for (uint16_t y = 0; y < 192 - 8; ++y)
132142
{
133-
for (uint16_t x = 0; x < 256; x += 4)
143+
// Calculate a line of pixels.
144+
for (uint16_t x = 0; x < 256; ++x)
145+
err1[x] += clamp(mainImage(*vec2(x, 191 - y)), 0.0f, 1.0f) + 0.01f;
146+
147+
// Apply dithering.
148+
for (uint16_t x = 1; x < 255; ++x)
149+
{
150+
float oldPixel = err1[x];
151+
float newPixel = floor(oldPixel + 0.5f);
152+
err1[x] = newPixel;
153+
float pixelError = oldPixel - newPixel;
154+
155+
err1[x + 1] += pixelError * 0.4375f;
156+
err2[x - 1] += pixelError * 0.1875f;
157+
err2[x] += pixelError * 0.3125f;
158+
err2[x + 1] += pixelError * 0.0625f;
159+
160+
if (newPixel >= 0.5)
161+
plot(x, y);
162+
}
163+
164+
// Cycle the errors up a row.
165+
float* p = err1;
166+
err1 = err2;
167+
err2 = p;
168+
memset(err2, 0, sizeof(float) * 256);
169+
170+
for (uint16_t i = 0; i < 256; ++i)
134171
{
135-
float c = clamp(mainImage(*vec2(x, 191 - y)), 0.0f, 2.0f);
136-
137-
// Set the color.
138-
uint8_t ink, bright = 1 << 6;
139-
switch ((uint8_t)(floor(c * 0.99f)))
140-
{
141-
case 0:
142-
ink = INK_WHITE;
143-
break;
144-
145-
case 1:
146-
ink = INK_WHITE + bright;
147-
c *= 0.4;
148-
break;
149-
150-
default:
151-
ink = INK_WHITE + PAPER_RED;
152-
break;
153-
}
154-
155-
// Plot the pixels.
156-
c_plot_shade((x >> 2), (y >> 2), min(c * 255.0f, 255.0f));
157-
attrMem[((y >> 3) << 5) + (x >> 3)] = ink;
172+
if (err1[i] < 0.01f)
173+
err1[i] = 0.0f;
158174
}
159175
}
160176

161177
in_waitForKey();
178+
free(err1);
179+
free(err2);
180+
return 0;
162181
}
850 KB
Loading
18.6 KB
Binary file not shown.

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ A little more of a 'demo-style' with this one - I've added a DTC logo (which I'l
138138
The code is written in C and compiled into Z80 machine code ([here](Experiments/BreakOut/breakout.tap)).
139139
![](Experiments/BreakOut/Breakout.png)
140140

141+
# Experiments - One Small Step
142+
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.
143+
144+
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.
145+
146+
The executable is [here](Experiments/OneSmallStep/OneSmallStep.tap).
147+
![](Experiments/OneSmallStep/OneSmallStep.png)
148+
141149
## Contribution and Improvements
142150
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).
143151

0 commit comments

Comments
 (0)