Skip to content

Commit

Permalink
add: pkg result of wasm export
Browse files Browse the repository at this point in the history
  • Loading branch information
Sufhal committed Sep 10, 2024
1 parent c3b4343 commit fa4660c
Show file tree
Hide file tree
Showing 11 changed files with 6,182 additions and 0 deletions.
107 changes: 107 additions & 0 deletions pkg/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# M2RS

M2RS is an experimental projet which targets to entierly rewrite the game [Metin2](https://fr.wikipedia.org/wiki/Metin2) (an old Korean MMORPG) using pure Rust and [wgpu](https://github.com/gfx-rs/wgpu).

## Why I'm doing this

- I love Metin2, Rust, Web, graphics programming and performance critical things
- I was looking for a challenging project
- Because I can and you've probably already heard « L'impossible n'est pas Français 🇫🇷 »

## Features
- `WASM` support
- [x] std::time replaced by [web_time](https://docs.rs/web-time/latest/web_time/)
- [x] assets loading using [reqwest](https://docs.rs/reqwest/latest/reqwest/)
- `GLTF` support
- [x] material
- [x] mesh
- [x] skeleton
- [x] animation clip
- `AnimationMixer`
- [x] frames interpolation
- [x] blend two clips when playing a new clip
- `Character`
- [x] allow characters to control it's own animation mixer (pc/npc basically have more than one "wait" animation, we must play them randomly)
- [ ] dynamic `Object3DInstance` loading using (main) character position
- [ ] create character controller
- [ ] basic collisions (using 2d algorithms for performance reasons)
- `ThirdPersonCamera`
- [ ] third person camera
- `BoneAttachement`
- [ ] allow `Object3D` to be attached to a skeleton bone (hairs, weapons)
- `Terrain`
- [x] parse and generate terrain chunks
- [x] shader
- [ ] shadows
- [-] raycast to make characters walk above the ground
- [-] objects
- [ ] trees
- [x] water geometry
- [x] water shader
- `Environment`
- [ ] sun light that follow a realistic path between day and night
- [ ] environment colors
- [ ] fog
- [ ] clouds
- [ ] skybox
- `Particle system`
- [ ] ???

- `CLI`
- [x] textureset.txt
- [ ] setting.txt
- [ ] areaambiencedata.txt
- [x] areadata.txt
- [ ] areaproperty.txt
- [ ] property

## Optimization track
- `GLTF` loader currently produces 4 skeletons if there is 4 skinned mesh linked to the same skeleton.
- Water generation is currently slow due to vertices height comparaison between two planes without being equal in vertices count (HashMap set/get overhead)

## Start

To start the game, run the following command and Vulkan or Metal will be used for rendering depending on the platform (Windows, Linux or macOS).

```bash
cargo run --bin m2rs --release
```

## Export in the browser (WASM)

In order to export both WASM and JS glue code, you will need to install [wasm-pack](https://github.com/rustwasm/wasm-pack).

```bash
cargo install wasm-pack
```

Then, you can use `wasm-pack` command to export the game.

```bash
wasm-pack build --target web
```

Finally, use a live server to serve the content and open index.html on the selected port. I personnally use [Live Server VSCode extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer).


## CLI

A CLI is available if assets need conversion. Currently supported conversions are:
- `textureset.txt` -> `textureset.json`

In the future, this CLI will be used to optimize + encrypt assets.

```bash
cargo run --bin cli --release
```

## DDS to PNG
All DDS files should be converted to PNG files. I usually do this with [imagemagick](https://imagemagick.org/):
```bash
find . -type f -name "*.dds" -exec mogrify -format png {} +
```

## FBX to GLTF
To convert FBX files to GLTF:
- [w/ skinning](https://github.com/BabylonJS/Exporters/releases)
- [w/o skinning](https://github.com/facebookincubator/FBX2glTF/releases)
29 changes: 29 additions & 0 deletions pkg/game.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* tslint:disable */
/* eslint-disable */

export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;

export interface InitOutput {
readonly memory: WebAssembly.Memory;
}

export type SyncInitInput = BufferSource | WebAssembly.Module;
/**
* Instantiates the given `module`, which can either be bytes or
* a precompiled `WebAssembly.Module`.
*
* @param {SyncInitInput} module
*
* @returns {InitOutput}
*/
export function initSync(module: SyncInitInput): InitOutput;

/**
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
* for everything else, calls `WebAssembly.instantiate` directly.
*
* @param {InitInput | Promise<InitInput>} module_or_path
*
* @returns {Promise<InitOutput>}
*/
export default function __wbg_init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
89 changes: 89 additions & 0 deletions pkg/game.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
let wasm;

async function __wbg_load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);

} catch (e) {
if (module.headers.get('Content-Type') != 'application/wasm') {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);

} else {
throw e;
}
}
}

const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);

} else {
const instance = await WebAssembly.instantiate(module, imports);

if (instance instanceof WebAssembly.Instance) {
return { instance, module };

} else {
return instance;
}
}
}

function __wbg_get_imports() {
const imports = {};
imports.wbg = {};

return imports;
}

function __wbg_init_memory(imports, maybe_memory) {

}

function __wbg_finalize_init(instance, module) {
wasm = instance.exports;
__wbg_init.__wbindgen_wasm_module = module;


return wasm;
}

function initSync(module) {
if (wasm !== undefined) return wasm;

const imports = __wbg_get_imports();

__wbg_init_memory(imports);

if (!(module instanceof WebAssembly.Module)) {
module = new WebAssembly.Module(module);
}

const instance = new WebAssembly.Instance(module, imports);

return __wbg_finalize_init(instance, module);
}

async function __wbg_init(input) {
if (wasm !== undefined) return wasm;

if (typeof input === 'undefined') {
input = new URL('game_bg.wasm', import.meta.url);
}
const imports = __wbg_get_imports();

if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}

__wbg_init_memory(imports);

const { instance, module } = await __wbg_load(await input, imports);

return __wbg_finalize_init(instance, module);
}

export { initSync }
export default __wbg_init;
Binary file added pkg/game_bg.wasm
Binary file not shown.
3 changes: 3 additions & 0 deletions pkg/game_bg.wasm.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
96 changes: 96 additions & 0 deletions pkg/m2rs.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* tslint:disable */
/* eslint-disable */
/**
* @returns {Promise<void>}
*/
export function run(): Promise<void>;

export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;

export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly run: () => void;
readonly wgpu_compute_pass_set_pipeline: (a: number, b: number) => void;
readonly wgpu_compute_pass_set_bind_group: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_compute_pass_set_push_constant: (a: number, b: number, c: number, d: number) => void;
readonly wgpu_compute_pass_insert_debug_marker: (a: number, b: number, c: number) => void;
readonly wgpu_compute_pass_push_debug_group: (a: number, b: number, c: number) => void;
readonly wgpu_compute_pass_pop_debug_group: (a: number) => void;
readonly wgpu_compute_pass_write_timestamp: (a: number, b: number, c: number) => void;
readonly wgpu_compute_pass_begin_pipeline_statistics_query: (a: number, b: number, c: number) => void;
readonly wgpu_compute_pass_end_pipeline_statistics_query: (a: number) => void;
readonly wgpu_compute_pass_dispatch_workgroups: (a: number, b: number, c: number, d: number) => void;
readonly wgpu_compute_pass_dispatch_workgroups_indirect: (a: number, b: number, c: number) => void;
readonly wgpu_render_bundle_set_pipeline: (a: number, b: number) => void;
readonly wgpu_render_bundle_set_bind_group: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_bundle_set_vertex_buffer: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_bundle_set_push_constants: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_bundle_draw: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_bundle_draw_indexed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
readonly wgpu_render_bundle_draw_indirect: (a: number, b: number, c: number) => void;
readonly wgpu_render_bundle_draw_indexed_indirect: (a: number, b: number, c: number) => void;
readonly wgpu_render_pass_set_pipeline: (a: number, b: number) => void;
readonly wgpu_render_pass_set_bind_group: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_pass_set_vertex_buffer: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_pass_set_push_constants: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_pass_draw: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_pass_draw_indexed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
readonly wgpu_render_pass_draw_indirect: (a: number, b: number, c: number) => void;
readonly wgpu_render_pass_draw_indexed_indirect: (a: number, b: number, c: number) => void;
readonly wgpu_render_pass_multi_draw_indirect: (a: number, b: number, c: number, d: number) => void;
readonly wgpu_render_pass_multi_draw_indexed_indirect: (a: number, b: number, c: number, d: number) => void;
readonly wgpu_render_pass_multi_draw_indirect_count: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
readonly wgpu_render_pass_multi_draw_indexed_indirect_count: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
readonly wgpu_render_pass_set_blend_constant: (a: number, b: number) => void;
readonly wgpu_render_pass_set_scissor_rect: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_pass_set_viewport: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
readonly wgpu_render_pass_set_stencil_reference: (a: number, b: number) => void;
readonly wgpu_render_pass_insert_debug_marker: (a: number, b: number, c: number) => void;
readonly wgpu_render_pass_push_debug_group: (a: number, b: number, c: number) => void;
readonly wgpu_render_pass_pop_debug_group: (a: number) => void;
readonly wgpu_render_pass_write_timestamp: (a: number, b: number, c: number) => void;
readonly wgpu_render_pass_begin_occlusion_query: (a: number, b: number) => void;
readonly wgpu_render_pass_end_occlusion_query: (a: number) => void;
readonly wgpu_render_pass_begin_pipeline_statistics_query: (a: number, b: number, c: number) => void;
readonly wgpu_render_pass_end_pipeline_statistics_query: (a: number) => void;
readonly wgpu_render_pass_execute_bundles: (a: number, b: number, c: number) => void;
readonly wgpu_render_bundle_set_index_buffer: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_bundle_pop_debug_group: (a: number) => void;
readonly wgpu_render_bundle_insert_debug_marker: (a: number, b: number) => void;
readonly wgpu_render_pass_set_index_buffer: (a: number, b: number, c: number, d: number, e: number) => void;
readonly wgpu_render_bundle_push_debug_group: (a: number, b: number) => void;
readonly __wbindgen_malloc: (a: number, b: number) => number;
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
readonly __wbindgen_export_2: WebAssembly.Table;
readonly wasm_bindgen__convert__closures__invoke1_mut__h965d7cf806862447: (a: number, b: number, c: number) => void;
readonly wasm_bindgen__convert__closures__invoke0_mut__hc43470411bc3d8ac: (a: number, b: number) => void;
readonly wasm_bindgen__convert__closures__invoke2_mut__h3fd7c17d84333042: (a: number, b: number, c: number, d: number) => void;
readonly wasm_bindgen__convert__closures__invoke1_mut__h1b18c64b843c17a3: (a: number, b: number, c: number) => void;
readonly wasm_bindgen__convert__closures__invoke0_mut__h789244e6b087238b: (a: number, b: number) => void;
readonly wasm_bindgen__convert__closures__invoke1_mut__haea07ce96dffa68d: (a: number, b: number, c: number) => void;
readonly wasm_bindgen__convert__closures__invoke1_mut__h60027181182f5300: (a: number, b: number, c: number) => void;
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
readonly __wbindgen_exn_store: (a: number) => void;
readonly __wbindgen_start: () => void;
}

export type SyncInitInput = BufferSource | WebAssembly.Module;
/**
* Instantiates the given `module`, which can either be bytes or
* a precompiled `WebAssembly.Module`.
*
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
*
* @returns {InitOutput}
*/
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;

/**
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
* for everything else, calls `WebAssembly.instantiate` directly.
*
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
*
* @returns {Promise<InitOutput>}
*/
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
Loading

0 comments on commit fa4660c

Please sign in to comment.