Ver código fonte

Add WebAssemply example

rexim 3 anos atrás
pai
commit
0d83698173
9 arquivos alterados com 142 adições e 13 exclusões
  1. 36 9
      README.md
  2. 4 4
      build.sh
  3. 1 0
      examples/gallery.c
  4. 44 0
      examples/triangle.c
  5. 9 0
      index.html
  6. 47 0
      index.js
  7. 1 0
      olive.c
  8. 0 0
      thirdparty/stb_image.h
  9. 0 0
      thirdparty/stb_image_write.h

+ 36 - 9
README.md

@@ -2,19 +2,27 @@
 
 
 Simple 2D Graphics Library for C.
 Simple 2D Graphics Library for C.
 
 
+## Gallery
+
+![checker](./imgs/checker.png)
+
+![circle](./imgs/circle.png)
+
+![lines](./imgs/lines.png)
+
 ## Quick Start
 ## Quick Start
 
 
-### Test the Library
+> The truly reusable code is the one that you can simply copy-paste.
+
+The library itself does not require any special building. You can simple copy-paste [./olive.c](./olive.c) to your project and `#include` it. But you may want to build the binary tools for this project that are located in `./bin/`:
 
 
 ```console
 ```console
 $ ./build.sh
 $ ./build.sh
 ```
 ```
 
 
-### Use the Library
-
-> The truly reusable code is the one that you can simply copy-paste.
+## How to Use the Library
 
 
-Copy-paste [./olive.c](./olive.c) to your project.
+*This example uses [stb_image_write.h](https://raw.githubusercontent.com/nothings/stb/master/stb_image_write.h) to create the PNG image*
 
 
 ```c
 ```c
 // flag_jp.c
 // flag_jp.c
@@ -43,10 +51,29 @@ int main(void)
 }
 }
 ```
 ```
 
 
-## Gallery
+## Test the Library
 
 
-![checker](./imgs/checker.png)
+```console
+$ ./bin/test
+```
 
 
-![circle](./imgs/circle.png)
+### Update the test cases
 
 
-![lines](./imgs/lines.png)
+If the expected behaviour of the library has changed in the way that breaks current test cases, you probably want to update them:
+
+```console
+$ ./bin/test record
+```
+
+## Regenerate the Gallery Above
+
+```console
+$ ./bin/gallery
+```
+
+## WebAssembly Triangle Example
+
+```console
+$ python3 -m http.server 6969
+$ iexplore.exe http://localhost:6969/
+```

+ 4 - 4
build.sh

@@ -3,7 +3,7 @@
 set -xe
 set -xe
 
 
 mkdir -p ./bin/
 mkdir -p ./bin/
-cc -Wall -Wextra -ggdb -o ./bin/example example.c
-cc -Wall -Wextra -ggdb -o ./bin/test test.c -lm
-./bin/example
-./bin/test
+
+cc -Wall -Wextra -ggdb -o ./bin/test -Ithirdparty test.c -lm
+cc -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-all -Wl,--allow-undefined  -o ./bin/triangle.wasm -I. ./examples/triangle.c

+ 1 - 0
example.c → examples/gallery.c

@@ -1,3 +1,4 @@
+// This example generates the gallery that is displayed in the README of the project
 #include <stdio.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdbool.h>

+ 44 - 0
examples/triangle.c

@@ -0,0 +1,44 @@
+// This example renders a rotating triangle.
+// This idea is that you can take this code and compile it to different platforms with different rendering machanisms:
+// native with SDL, WebAssembly with HTML5 canvas, etc.
+#include "olive.c"
+
+#define WIDTH 800
+#define HEIGHT 600
+
+uint32_t pixels[WIDTH*HEIGHT];
+float angle = 0;
+
+float sqrtf(float x);
+float atan2f(float y, float x);
+float sinf(float x);
+float cosf(float x);
+
+#define PI 3.14159265359
+
+void rotate_point(int *x, int *y)
+{
+    int dx = *x - WIDTH/2;
+    int dy = *y - HEIGHT/2;
+    float mag = sqrtf(dx*dx + dy*dy);
+    float dir = atan2f(dy, dx) + angle;
+    *x = cosf(dir)*mag + WIDTH/2; 
+    *y = sinf(dir)*mag + HEIGHT/2;
+}
+
+uint32_t *render(float dt)
+{
+    angle += 0.5f*PI*dt;
+
+    olivec_fill(pixels, WIDTH, HEIGHT, 0xFF181818);
+    {
+        int x1 = WIDTH/2, y1 = HEIGHT/8;
+        int x2 = WIDTH/8, y2 = HEIGHT/2;
+        int x3 = WIDTH*7/8, y3 = HEIGHT*7/8;
+        rotate_point(&x1, &y1);
+        rotate_point(&x2, &y2);
+        rotate_point(&x3, &y3);
+        olivec_fill_triangle(pixels, WIDTH, HEIGHT, x1, y1, x2, y2, x3, y3, 0xFF2020AA);
+    }
+    return pixels;
+}

+ 9 - 0
index.html

@@ -0,0 +1,9 @@
+<html>
+  <head>
+    <title>Olive.c</title>
+  </head>
+  <body>
+    <canvas id="app"></canvas>
+    <script src="index.js"></script>
+  </body>
+</html>

+ 47 - 0
index.js

@@ -0,0 +1,47 @@
+let app = document.getElementById("app");
+app.width = 800;
+app.height = 600;
+let ctx = app.getContext("2d");
+let w = null;
+
+function make_environment(...envs) {
+    return new Proxy(envs, {
+        get(target, prop, receiver) {
+            for (let env of envs) {
+                if (env.hasOwnProperty(prop)) {
+                    return env[prop];
+                }
+            }
+            return (...args) => {console.error("NOT IMPLEMENTED: "+prop, args)}
+        }
+    });
+}
+
+WebAssembly.instantiateStreaming(fetch('./bin/triangle.wasm'), {
+    "env": make_environment({
+        "atan2f": Math.atan2,
+        "cosf": Math.cos,
+        "sinf": Math.sin,
+        "sqrtf": Math.sqrt,
+    })
+}).then(w0 => {
+    w = w0;
+
+    let prev = null;
+    function first(timestamp) {
+        prev = timestamp;
+        window.requestAnimationFrame(loop);
+    }
+    function loop(timestamp) {
+        const dt = timestamp - prev;
+        prev = timestamp;
+
+        const pixels = w.instance.exports.render(dt*0.001);
+        const buffer = w.instance.exports.memory.buffer;
+        const image = new ImageData(new Uint8ClampedArray(buffer, pixels, app.width*app.height*4), app.width);
+        ctx.putImageData(image, 0, 0);
+
+        window.requestAnimationFrame(loop);
+    }
+    window.requestAnimationFrame(first);
+})

+ 1 - 0
olive.c

@@ -1,6 +1,7 @@
 #ifndef OLIVE_C_
 #ifndef OLIVE_C_
 #define OLIVE_C_
 #define OLIVE_C_
 
 
+#include <stddef.h>
 #include <stdint.h>
 #include <stdint.h>
 
 
 #define OLIVEC_SWAP(T, a, b) do { T t = a; a = b; b = t; } while (0)
 #define OLIVEC_SWAP(T, a, b) do { T t = a; a = b; b = t; } while (0)

+ 0 - 0
stb_image.h → thirdparty/stb_image.h


+ 0 - 0
stb_image_write.h → thirdparty/stb_image_write.h