Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added C language demo to the 'reading-and-writing-graphics' example #171

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/reading-and-writing-graphics/demo/C/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Reading And Writing Graphics (C)
```bash
clang -target wasm32 -O3 -flto -nostdlib -Wl,--no-entry -Wl,--export-all -o index.wasm main.c
```
15 changes: 15 additions & 0 deletions examples/reading-and-writing-graphics/demo/C/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Reading and Writing Graphics - C</title>
<script type="module" src="./index.js"></script>
</head>
<body>
<canvas
width="20"
height="20"
style="image-rendering: pixelated; image-rendering: crisp-edges; width: 100%;"
></canvas>
</body>
</html>
75 changes: 75 additions & 0 deletions examples/reading-and-writing-graphics/demo/C/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Imports are from the demo-util folder in the repo
// https://github.com/torch2424/wasm-by-example/blob/master/demo-util/

import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js";

const runWasm = async () => {
// Instantiate our wasm module
const wasmModule = await wasmBrowserInstantiate("./index.wasm");

// Get our exports object, with all of our exported Wasm Properties
const exports = wasmModule.instance.exports;

// Get our memory object from the exports
const memory = exports.memory;

// Create a Uint8Array to give us access to Wasm Memory
const wasmByteMemoryArray = new Uint8Array(memory.buffer);

// Get our canvas element from our index.html
const canvasElement = document.querySelector("canvas");

// Set up Context and ImageData on the canvas
const canvasContext = canvasElement.getContext("2d");
const canvasImageData = canvasContext.createImageData(
canvasElement.width,
canvasElement.height
);

// Clear the canvas
canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height);

const getDarkValue = () => {
return Math.floor(Math.random() * 100);
};

const getLightValue = () => {
return Math.floor(Math.random() * 127) + 127;
};

const drawCheckerBoard = () => {
const checkerBoardSize = 20;

// Generate a new checkboard in wasm
exports.generateCheckerBoard(
getDarkValue(),
getDarkValue(),
getDarkValue(),
getLightValue(),
getLightValue(),
getLightValue()
);

// Pull out the RGBA values from Wasm memory, the we wrote to in wasm,
// starting at the checkerboard pointer (memory array index)
const startIndex = exports.CHECKERBOARD_BUFFER.valueOf(); // pointer
const endIndex = startIndex + exports.getCheckboardSize();

const imageDataArray = wasmByteMemoryArray.slice(startIndex, endIndex);

// Set the values to the canvas image data
canvasImageData.data.set(imageDataArray);

// Clear the canvas
canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height);

// Place the new generated checkerboard onto the canvas
canvasContext.putImageData(canvasImageData, 0, 0);
};

drawCheckerBoard();
setInterval(() => {
drawCheckerBoard();
}, 1000);
};
runWasm();
Binary file not shown.
74 changes: 74 additions & 0 deletions examples/reading-and-writing-graphics/demo/C/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <stdbool.h>
#include <stdint.h>

// Define the size of our checkerboard
#define CHECKERBOARD_SIZE 20

// Create a buffer to where in memory
// we are storing the pixels.
uint8_t CHECKERBOARD_BUFFER[CHECKERBOARD_SIZE * CHECKERBOARD_SIZE * 4] = { 0 };

// Function to generate our checkerboard, pixel by pixel
void
generateCheckerBoard(
uint8_t darkValueRed,
uint8_t darkValueGreen,
uint8_t darkValueBlue,
uint8_t lightValueRed,
uint8_t lightValueGreen,
uint8_t lightValueBlue
) {
// Since Linear memory is a 1 dimensional array, but we want a grid
// we will be doing 2d to 1d mapping
// https://softwareengineering.stackexchange.com/questions/212808/treating-a-1d-data-structure-as-2d-grid
for (int x = 0; x < CHECKERBOARD_SIZE; x++)
{
for (int y = 0; y < CHECKERBOARD_SIZE; y++)
{

// Set our default case to be dark squares
bool isDarkSquare = true;

// We should change our default case if
// We are on an odd y
if (y % 2 == 0)
{
isDarkSquare = false;
}

// Lastly, alternate on our x value
if (x % 2 == 0)
{
isDarkSquare = !isDarkSquare;
}

// Now that we determined if we are dark or light,
// Let's set our square value
uint8_t squareValueRed = darkValueRed;
uint8_t squareValueGreen = darkValueGreen;
uint8_t squareValueBlue = darkValueBlue;
if (!isDarkSquare)
{
squareValueRed = lightValueRed;
squareValueGreen = lightValueGreen;
squareValueBlue = lightValueBlue;
}

// Let's calculate our index, using our 2d -> 1d mapping.
// And then multiple by 4, for each pixel property (r,g,b,a).
int squareNumber = (x * CHECKERBOARD_SIZE) + y;
int squareRgbaIndex = squareNumber * 4;

// Finally store the values.
CHECKERBOARD_BUFFER[squareRgbaIndex + 0] = squareValueRed;
CHECKERBOARD_BUFFER[squareRgbaIndex + 1] = squareValueGreen;
CHECKERBOARD_BUFFER[squareRgbaIndex + 2] = squareValueBlue;
CHECKERBOARD_BUFFER[squareRgbaIndex + 3] = 255; // Alpha (Always opaque)
}
}
}

uint32_t getCheckboardSize()
{
return CHECKERBOARD_SIZE * CHECKERBOARD_SIZE * 4;
}
2 changes: 2 additions & 0 deletions examples/reading-and-writing-graphics/demo/C/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
index.wasm: main.c
clang -target wasm32 -O3 -flto -nostdlib -Wl,--no-entry -Wl,--export-all -o index.wasm main.c