Pārlūkot izejas kodu

Implement Terminal rendering

rexim 3 gadi atpakaļ
vecāks
revīzija
d78015ccd0
3 mainītis faili ar 210 papildinājumiem un 6 dzēšanām
  1. 8 4
      build.sh
  2. 101 1
      examples/3d.c
  3. 101 1
      examples/triangle.c

+ 8 - 4
build.sh

@@ -6,7 +6,11 @@ mkdir -p ./bin/
 
 clang -Wall -Wextra -ggdb -o ./bin/test -Ithirdparty test.c -lm
 clang -Wall -Wextra -ggdb -o ./bin/gallery -Ithirdparty -I. examples/gallery.c
-clang -Os -fno-builtin -Wall -Wextra -Wswitch-enum --target=wasm32 --no-standard-libraries -Wl,--no-entry -Wl,--export=render -Wl,--allow-undefined  -o ./bin/triangle.wasm -I. ./examples/triangle.c
-clang -Os -fno-builtin -Wall -Wextra -Wswitch-enum --target=wasm32 --no-standard-libraries -Wl,--no-entry -Wl,--export=render -Wl,--allow-undefined  -o ./bin/3d.wasm -I. ./examples/3d.c
-clang -O2 -Wall -Wextra -ggdb -I. -DSDL_PLATFORM -o ./bin/triangle ./examples/triangle.c -lm -lSDL2
-clang -O2 -Wall -Wextra -ggdb -I. -DSDL_PLATFORM -o ./bin/3d ./examples/3d.c -lm -lSDL2
+
+clang -Os -fno-builtin -Wall -Wextra -Wswitch-enum --target=wasm32 --no-standard-libraries -Wl,--no-entry -Wl,--export=render -Wl,--allow-undefined  -o ./bin/triangle.wasm -I. -DPLATFORM=WASM_PLATFORM ./examples/triangle.c
+clang -O2 -Wall -Wextra -ggdb -I. -o ./bin/triangle.sdl -DPLATFORM=SDL_PLATFORM ./examples/triangle.c -lm -lSDL2
+clang -O2 -Wall -Wextra -ggdb -I. -o ./bin/triangle.term -DPLATFORM=TERM_PLATFORM ./examples/triangle.c -lm
+
+clang -Os -fno-builtin -Wall -Wextra -Wswitch-enum --target=wasm32 --no-standard-libraries -Wl,--no-entry -Wl,--export=render -Wl,--allow-undefined  -o ./bin/3d.wasm -I. -DPLATFORM=WASM_PLATFORM ./examples/3d.c
+clang -O2 -Wall -Wextra -ggdb -I. -o ./bin/3d.sdl -DPLATFORM=SDL_PLATFORM ./examples/3d.c -lm -lSDL2
+clang -O2 -Wall -Wextra -ggdb -I. -o ./bin/3d.term -DPLATFORM=TERM_PLATFORM ./examples/3d.c -lm

+ 101 - 1
examples/3d.c

@@ -84,7 +84,11 @@ uint32_t *render(float dt)
     return pixels;
 }
 
-#ifdef SDL_PLATFORM
+#define WASM_PLATFORM 0
+#define SDL_PLATFORM 1
+#define TERM_PLATFORM 2
+
+#if PLATFORM == SDL_PLATFORM
 #include <stdio.h>
 #include <SDL2/SDL.h>
 
@@ -154,4 +158,100 @@ defer:
     SDL_Quit();
     return result;
 }
+#elif PLATFORM == TERM_PLATFORM
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+
+#define SCALE_DOWN_FACTOR 10
+static_assert(WIDTH%SCALE_DOWN_FACTOR == 0, "WIDTH must be divisible by the SCALE_DOWN_FACTOR");
+#define SCALED_DOWN_WIDTH (WIDTH/SCALE_DOWN_FACTOR)
+static_assert(HEIGHT%SCALE_DOWN_FACTOR == 0, "HEIGHT must be divisible by the SCALE_DOWN_FACTOR");
+#define SCALED_DOWN_HEIGHT (HEIGHT/SCALE_DOWN_FACTOR)
+
+char char_canvas[SCALED_DOWN_WIDTH*SCALED_DOWN_HEIGHT];
+
+char color_to_char(uint32_t pixel)
+{
+    char table[] = " .:a@#";
+    size_t n = sizeof(table) - 1;
+    size_t r = (0x000000FF&pixel)>>(8*0);
+    size_t g = (0x0000FF00&pixel)>>(8*1);
+    size_t b = (0x00FF0000&pixel)>>(8*2);
+    size_t bright = r;
+    if (bright < g) bright = g;
+    if (bright < b) bright = b;
+    return table[bright*n/256];
+}
+
+#define OLIVEC_RED(color)   (((color)&0x000000FF)>>(8*0))
+#define OLIVEC_GREEN(color) (((color)&0x0000FF00)>>(8*1))
+#define OLIVEC_BLUE(color)  (((color)&0x00FF0000)>>(8*2))
+#define OLIVEC_ALPHA(color) (((color)&0xFF000000)>>(8*3))
+#define OLIVEC_RGBA(r, g, b, a) ((((r)&0xFF)<<(8*0)) | (((g)&0xFF)<<(8*1)) | (((b)&0xFF)<<(8*2)) | (((a)&0xFF)<<(8*3)))
+
+uint32_t compress_pixels_chunk(Olivec_Canvas oc)
+{
+    size_t r = 0;
+    size_t g = 0;
+    size_t b = 0;
+    size_t a = 0;
+
+    for (size_t y = 0; y < oc.height; ++y) {
+        for (size_t x = 0; x < oc.width; ++x) {
+            r += OLIVEC_RED(OLIVEC_PIXEL(oc, x, y));
+            g += OLIVEC_GREEN(OLIVEC_PIXEL(oc, x, y));
+            b += OLIVEC_BLUE(OLIVEC_PIXEL(oc, x, y));
+            a += OLIVEC_ALPHA(OLIVEC_PIXEL(oc, x, y));
+        }
+    }
+
+    r /= oc.width*oc.height;
+    g /= oc.width*oc.height;
+    b /= oc.width*oc.height;
+    a /= oc.width*oc.height;
+
+    return OLIVEC_RGBA(r, g, b, a);
+}
+
+void compress_pixels(uint32_t *pixels)
+{
+    Olivec_Canvas oc = olivec_canvas(pixels, WIDTH, HEIGHT);
+    for (size_t y = 0; y < SCALED_DOWN_HEIGHT; ++y) {
+        for (size_t x = 0; x < SCALED_DOWN_WIDTH; ++x) {
+            Olivec_Canvas soc = olivec_subcanvas(oc, x*SCALE_DOWN_FACTOR, y*SCALE_DOWN_FACTOR, SCALE_DOWN_FACTOR, 
+SCALE_DOWN_FACTOR);
+            char_canvas[y*SCALED_DOWN_WIDTH + x] = color_to_char(compress_pixels_chunk(soc));
+        }
+    }
+}
+
+int main(void)
+{
+    for (;;) {
+        compress_pixels(render(1.f/60.f));
+        for (size_t y = 0; y < SCALED_DOWN_HEIGHT; ++y) {
+            for (size_t x = 0; x < SCALED_DOWN_WIDTH; ++x) {
+                putc(char_canvas[y*SCALED_DOWN_WIDTH + x], stdout);
+                putc(char_canvas[y*SCALED_DOWN_WIDTH + x], stdout);
+            }
+            putc('\n', stdout);
+        }
+
+        usleep(1000*1000/60);
+        printf("\033[%dA", SCALED_DOWN_HEIGHT);
+        printf("\033[%dD", SCALED_DOWN_WIDTH);
+    }
+    return 0;
+}
+
+#elif PLATFORM == WASM_PLATFORM
+// Do nothing
+#else
+#error "Unknown platform"
 #endif // SDL_PLATFORM

+ 101 - 1
examples/triangle.c

@@ -75,7 +75,11 @@ uint32_t *render(float dt)
     return pixels;
 }
 
-#ifdef SDL_PLATFORM
+#define WASM_PLATFORM 0
+#define SDL_PLATFORM 1
+#define TERM_PLATFORM 2
+
+#if PLATFORM == SDL_PLATFORM
 #include <stdio.h>
 #include <SDL2/SDL.h>
 
@@ -145,4 +149,100 @@ defer:
     SDL_Quit();
     return result;
 }
+#elif PLATFORM == TERM_PLATFORM
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+
+#define SCALE_DOWN_FACTOR 40
+static_assert(WIDTH%SCALE_DOWN_FACTOR == 0, "WIDTH must be divisible by the SCALE_DOWN_FACTOR");
+#define SCALED_DOWN_WIDTH (WIDTH/SCALE_DOWN_FACTOR)
+static_assert(HEIGHT%SCALE_DOWN_FACTOR == 0, "HEIGHT must be divisible by the SCALE_DOWN_FACTOR");
+#define SCALED_DOWN_HEIGHT (HEIGHT/SCALE_DOWN_FACTOR)
+
+char char_canvas[SCALED_DOWN_WIDTH*SCALED_DOWN_HEIGHT];
+
+char color_to_char(uint32_t pixel)
+{
+    char table[] = " .:a@#";
+    size_t n = sizeof(table) - 1;
+    size_t r = (0x000000FF&pixel)>>(8*0);
+    size_t g = (0x0000FF00&pixel)>>(8*1);
+    size_t b = (0x00FF0000&pixel)>>(8*2);
+    size_t bright = r;
+    if (bright < g) bright = g;
+    if (bright < b) bright = b;
+    return table[bright*n/256];
+}
+
+#define OLIVEC_RED(color)   (((color)&0x000000FF)>>(8*0))
+#define OLIVEC_GREEN(color) (((color)&0x0000FF00)>>(8*1))
+#define OLIVEC_BLUE(color)  (((color)&0x00FF0000)>>(8*2))
+#define OLIVEC_ALPHA(color) (((color)&0xFF000000)>>(8*3))
+#define OLIVEC_RGBA(r, g, b, a) ((((r)&0xFF)<<(8*0)) | (((g)&0xFF)<<(8*1)) | (((b)&0xFF)<<(8*2)) | (((a)&0xFF)<<(8*3)))
+
+uint32_t compress_pixels_chunk(Olivec_Canvas oc)
+{
+    size_t r = 0;
+    size_t g = 0;
+    size_t b = 0;
+    size_t a = 0;
+
+    for (size_t y = 0; y < oc.height; ++y) {
+        for (size_t x = 0; x < oc.width; ++x) {
+            r += OLIVEC_RED(OLIVEC_PIXEL(oc, x, y));
+            g += OLIVEC_GREEN(OLIVEC_PIXEL(oc, x, y));
+            b += OLIVEC_BLUE(OLIVEC_PIXEL(oc, x, y));
+            a += OLIVEC_ALPHA(OLIVEC_PIXEL(oc, x, y));
+        }
+    }
+
+    r /= oc.width*oc.height;
+    g /= oc.width*oc.height;
+    b /= oc.width*oc.height;
+    a /= oc.width*oc.height;
+
+    return OLIVEC_RGBA(r, g, b, a);
+}
+
+void compress_pixels(uint32_t *pixels)
+{
+    Olivec_Canvas oc = olivec_canvas(pixels, WIDTH, HEIGHT);
+    for (size_t y = 0; y < SCALED_DOWN_HEIGHT; ++y) {
+        for (size_t x = 0; x < SCALED_DOWN_WIDTH; ++x) {
+            Olivec_Canvas soc = olivec_subcanvas(oc, x*SCALE_DOWN_FACTOR, y*SCALE_DOWN_FACTOR, SCALE_DOWN_FACTOR, 
+SCALE_DOWN_FACTOR);
+            char_canvas[y*SCALED_DOWN_WIDTH + x] = color_to_char(compress_pixels_chunk(soc));
+        }
+    }
+}
+
+int main(void)
+{
+    for (;;) {
+        compress_pixels(render(1.f/60.f));
+        for (size_t y = 0; y < SCALED_DOWN_HEIGHT; ++y) {
+            for (size_t x = 0; x < SCALED_DOWN_WIDTH; ++x) {
+                putc(char_canvas[y*SCALED_DOWN_WIDTH + x], stdout);
+                putc(char_canvas[y*SCALED_DOWN_WIDTH + x], stdout);
+            }
+            putc('\n', stdout);
+        }
+
+        usleep(1000*1000/60);
+        printf("\033[%dA", SCALED_DOWN_HEIGHT);
+        printf("\033[%dD", SCALED_DOWN_WIDTH);
+    }
+    return 0;
+}
+
+#elif PLATFORM == WASM_PLATFORM
+// Do nothing
+#else
+#error "Unknown platform"
 #endif // SDL_PLATFORM