transparent-cube

Minimal cross-platform native/wasm graphics example.
git clone git://git.amin.space/transparent-cube.git
Log | Files | Refs | README | LICENSE

commit e3e6a1a07cfe80b68f2e35f41dc86ab7c08af43b
parent 604c8c44f8d040b28e08dd9256000e3d007eae02
Author: amin <dev@aminmesbah.com>
Date:   Mon, 17 Jun 2019 00:36:43 +0000

Narrow down missing deps to cosf and sinf

FossilOrigin-Name: eeba3f0329a5d12a2bf554281e5a699ae36997a97034768788d4c8a4e903e0e1
Diffstat:
Mbuild_wasm.sh | 12+++++++++++-
Msrc/game.c | 13++++++++-----
Msrc/game.h | 49++++++++++++++++++++++++++++++++++++++++++++-----
Asrc/platform.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Msrc/platform_linux.c | 16++++++++++++++++
Msrc/platform_linux.h | 2++
Msrc/shader.c | 91+++++++++++++++++++++++++++++++-------------------------------------------------
Msrc/shader.h | 2+-
8 files changed, 162 insertions(+), 68 deletions(-)

diff --git a/build_wasm.sh b/build_wasm.sh @@ -3,5 +3,15 @@ clang -cc1 -Ofast -emit-llvm-bc -triple=wasm32-unknown-unknown-unknown-wasm -std -DGAME_WEBGL \ src/game.c llvm-link -o wasm.bc src/*.bc -llc -O3 -filetype=obj wasm.bc -o wasm.o +opt -O3 -disable-simplify-libcalls wasm.bc -o wasm.bc +llc -O3 -disable-simplify-libcalls -filetype=obj wasm.bc -o wasm.o wasm-ld --no-entry wasm.o -o binary.wasm --strip-all -allow-undefined-file wasm_js_implemented_symbols.txt --import-memory + +#clang \ +# --target=wasm32 \ +# -emit-llvm \ +# -fno-builtin \ +# -c \ +# -S \ +# -DGAME_WEBGL \ +# src/game.c diff --git a/src/game.c b/src/game.c @@ -6,7 +6,7 @@ #include "shader.c" -void game_init(struct GameState *game_state, uint32_t screen_width, uint32_t screen_height) +void game_init(struct GameState *game_state, u32 screen_width, u32 screen_height) { // load cube vertex data { @@ -64,9 +64,12 @@ void game_init(struct GameState *game_state, uint32_t screen_width, uint32_t scr struct PlatformApi platform = game_state->platform; char *v_source = platform.platform_read_entire_file("shader/cube_v.glsl"); char *f_source = platform.platform_read_entire_file("shader/cube_f.glsl"); - struct Shader main_shader = shader_compile(v_source, f_source); - free(v_source); - free(f_source); + print = platform.platform_print; + struct Shader main_shader = {0}; + // TODO: Check this result + shader_compile(v_source, f_source, &main_shader); + platform.platform_memory_free(v_source); + platform.platform_memory_free(f_source); game_state->cube_shader = main_shader; } @@ -77,7 +80,7 @@ void game_init(struct GameState *game_state, uint32_t screen_width, uint32_t scr #endif } -void game_update_and_render(struct GameState *game_state, float dt, uint32_t screen_width, uint32_t screen_height) +void game_update_and_render(struct GameState *game_state, float dt, u32 screen_width, u32 screen_height) { glDepthMask(GL_TRUE); glClearColor(0.2f, 0.2f, 0.3f, 1.0f); diff --git a/src/game.h b/src/game.h @@ -1,11 +1,33 @@ #pragma once -#include <assert.h> -#include <math.h> -#include <stdbool.h> +// TODO: Clean up +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#include <stddef.h> #include <stdint.h> -#include <stdio.h> -#include <stdlib.h> +#define static_assert _Static_assert + +static_assert(__has_builtin(__builtin_cosf), "cosf"); +static_assert(__has_builtin(__builtin_sinf), "sinf"); +static_assert(__has_builtin(__builtin_tanf), "tanf"); +static_assert(__has_builtin(__builtin_sqrtf), "sqrtf"); +static_assert(__has_builtin(__builtin_powf), "powf"); +#define cosf __builtin_cosf +#define sinf __builtin_sinf +#define tanf __builtin_tanf +#define sqrtf __builtin_sqrtf +#define powf __builtin_powf + +#define NULL ((void*)0) + +// TODO: fix this +#define assert(x) (void)0 + +typedef _Bool bool; +#define true 1 +#define false 0 #ifdef GAME_WEBGL #include "webgl.h" @@ -17,5 +39,22 @@ #include "shader.h" #include "platform.h" +void *memcpy(void *dst, const void *src, size_t n) +{ + u8 *destination = (u8 *)dst; + u8 *source = (u8 *)src; + + while (n--) { + *destination = *source; + destination++; + source++; + } + + return dst; +} + +// TODO: Consider finding a better way to make this func available +static platform_print_func* print; + void game_init(struct GameState *game_state, u32 screen_width, u32 screen_height); void game_cleanup(struct GameState *game_state); diff --git a/src/platform.h b/src/platform.h @@ -0,0 +1,45 @@ +#pragma once + +#define PLATFORM_READ_ENTIRE_FILE(name) char *(name)(char *file_path) +typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file_func); + +#define PLATFORM_PRINT(name) int (name)(const char *format, ...) +typedef PLATFORM_PRINT(platform_print_func); + +#define PLATFORM_MEMORY_FREE(name) void (name)(void *ptr) +typedef PLATFORM_MEMORY_FREE(platform_memory_free_func); + +struct PlatformApi +{ + platform_read_entire_file_func* platform_read_entire_file; + platform_print_func* platform_print; + platform_memory_free_func* platform_memory_free; +}; + +struct GameState +{ + u32 cube_vao; + u32 cube_vbo; + u32 cube_ebo; + struct Shader cube_shader; + struct PlatformApi platform; +}; + +#ifdef PLATFORM_HOTLOAD_GAME_CODE +#include <time.h> +// We need to call this from the platform layer in order for the game, when +// built as a shared object library to have access to the OpenGL symbols. +// https://github.com/Dav1dde/glad/issues/151 +typedef void (game_load_opengl_symbols_func)(void); + +typedef void (game_update_and_render_func)(struct GameState *game_state, float dt, u32 screen_width, u32 screen_height); + +struct GameCode +{ + bool is_valid; + void *game_code_library; + time_t last_write_time; + game_load_opengl_symbols_func *game_load_opengl_symbols; + game_update_and_render_func *game_update_and_render; +}; +#endif // PLATFORM_HOTLOAD_GAME_CODE diff --git a/src/platform_linux.c b/src/platform_linux.c @@ -73,6 +73,8 @@ int main(void) struct GameState game_state = {0}; game_state.platform.platform_read_entire_file = &linux_read_entire_file; + game_state.platform.platform_print = &linux_print; + game_state.platform.platform_memory_free = &linux_memory_free; game_init(&game_state, PLATFORM_SCR_WIDTH, PLATFORM_SCR_HEIGHT); @@ -154,6 +156,20 @@ time_t file_get_modified_time(char *file_path) return mtime; } +PLATFORM_MEMORY_FREE(linux_memory_free) +{ + free(ptr); +} + +PLATFORM_PRINT(linux_print) +{ + va_list args; + va_start(args, format); + int num_chars_printed = vprintf(format, args); + va_end(args); + return num_chars_printed; +} + PLATFORM_READ_ENTIRE_FILE(linux_read_entire_file) { FILE *handle = fopen(file_path, "r"); diff --git a/src/platform_linux.h b/src/platform_linux.h @@ -14,6 +14,8 @@ #define PLATFORM_MS_PER_UPDATE (PLATFORM_SECOND / PLATFORM_UPDATES_PER_SECOND) PLATFORM_READ_ENTIRE_FILE(linux_read_entire_file); +PLATFORM_PRINT(linux_print); +PLATFORM_MEMORY_FREE(linux_memory_free); #ifdef PLATFORM_HOTLOAD_GAME_CODE #define PLATFORM_GAME_LIB_PATH "./out/release/game.so" diff --git a/src/shader.c b/src/shader.c @@ -1,12 +1,12 @@ -struct Shader shader_compile(const GLchar *vertex_shader_source, const GLchar *fragment_shader_source) +bool shader_compile(const GLchar *vertex_shader_source, const GLchar *fragment_shader_source, struct Shader *compiled_shader) { GLint success; GLchar info_log[512]; if (!(vertex_shader_source && fragment_shader_source)) { - printf("Error: One or more shader source files weren't loaded.\n"); - exit(1); + print("Error: One or more shader source files weren't loaded.\n"); + return false; } else { @@ -17,9 +17,9 @@ struct Shader shader_compile(const GLchar *vertex_shader_source, const GLchar *f if (!success) { glGetShaderInfoLog(vertex_shader, 512, NULL, info_log); - printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n %s\n", info_log); + print("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n %s\n", info_log); // TODO: handle errors here in a better way - exit(1); + return false; } GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); @@ -29,134 +29,113 @@ struct Shader shader_compile(const GLchar *vertex_shader_source, const GLchar *f if (!success) { glGetShaderInfoLog(fragment_shader, 512, NULL, info_log); - printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n %s\n", info_log); + print("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n %s\n", info_log); // TODO: handle errors here in a better way - exit(1); + return false; } - struct Shader s; - s.program = glCreateProgram(); - glAttachShader(s.program, vertex_shader); - glAttachShader(s.program, fragment_shader); - glLinkProgram(s.program); - glGetProgramiv(s.program, GL_LINK_STATUS, &success); + compiled_shader->program = glCreateProgram(); + glAttachShader(compiled_shader->program, vertex_shader); + glAttachShader(compiled_shader->program, fragment_shader); + glLinkProgram(compiled_shader->program); + glGetProgramiv(compiled_shader->program, GL_LINK_STATUS, &success); if (!success) { - glGetShaderInfoLog(s.program, 512, NULL, info_log); - printf("ERROR::SHADER::LINKING_FAILED\n %s\n", info_log); + glGetShaderInfoLog(compiled_shader->program, 512, NULL, info_log); + print("ERROR::SHADER::LINKING_FAILED\n %s\n", info_log); // TODO: handle errors here in a better way - exit(1); + return false; } glDeleteShader(fragment_shader); glDeleteShader(vertex_shader); - return s; + return true; } } - -void shader_use(struct Shader *s) +bool shader_check_pointer(struct Shader *s) { if (s) { - glUseProgram(s->program); + return true; } else { - printf("Error: invalid Shader pointer\n"); + print("Error: invalid Shader pointer\n"); + return false; + } +} + +void shader_use(struct Shader *s) +{ + if (shader_check_pointer(s)) + { + glUseProgram(s->program); } } void shader_setb(struct Shader *s, char *name, bool value) { - if (s) + if (shader_check_pointer(s)) { glUniform1i(glGetUniformLocation(s->program, name), (int)value); } - else - { - printf("Error: invalid Shader pointer\n"); - } } void shader_seti(struct Shader *s, char *name, int value) { - if (s) + if (shader_check_pointer(s)) { glUniform1i(glGetUniformLocation(s->program, name), value); } - else - { - printf("Error: invalid Shader pointer\n"); - } } void shader_setf(struct Shader *s, char *name, f32 value) { - if (s) + if (shader_check_pointer(s)) { glUniform1f(glGetUniformLocation(s->program, name), value); } - else - { - printf("Error: invalid Shader pointer\n"); - } } void shader_setm4(struct Shader *s, char *name, m4 *mat) { - if (s) + if (shader_check_pointer(s)) { f32 valueptr[sizeof(m4)]; glmth_m4_valueptr(*mat, valueptr); glUniformMatrix4fv(glGetUniformLocation(s->program, name), 1, GL_TRUE, valueptr); } - else - { - printf("Error: invalid Shader pointer\n"); - } } void shader_setf3(struct Shader *s, char *name, f32 x, f32 y, f32 z) { - if (s) + if (shader_check_pointer(s)) { glUniform3f(glGetUniformLocation(s->program, name), x, y, z); } - else - { - printf("Error: invalid Shader pointer\n"); - } } void shader_setf3_1(struct Shader *s, char *name, f32 f) { - if (s) + if (shader_check_pointer(s)) { shader_setf3(s, name, f, f, f); } - else - { - printf("Error: invalid Shader pointer\n"); - } } void shader_setv3(struct Shader *s, char *name, v3 *v) { - if (s) + if (shader_check_pointer(s)) { shader_setf3(s, name, v->x, v->y, v->z); } - else - { - printf("Error: invalid Shader pointer\n"); - } } diff --git a/src/shader.h b/src/shader.h @@ -3,7 +3,7 @@ struct Shader u32 program; }; -struct Shader shader_compile(const GLchar *vertex_shader_source, const GLchar *fragment_shader_source); +bool shader_compile(const GLchar *vertex_shader_source, const GLchar *fragment_shader_source, struct Shader *compiled_shader); void shader_use(struct Shader *s); void shader_setb(struct Shader *s, char *name, bool value); void shader_seti(struct Shader *s, char *name, int value);