Initial boilerplate
This commit is contained in:
commit
79f8d6d4dc
|
|
@ -0,0 +1 @@
|
||||||
|
emcc -O2 src/main.c -o app.html -sUSE_WEBGL2 -sASSERTIONS -sWASM_BIGINT -pthread -I../sokol --shell-file=shell.html --closure 1
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
|
||||||
|
<title>Code</title>
|
||||||
|
<style>
|
||||||
|
body { margin: 0; background-color: black }
|
||||||
|
.game {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
|
image-rendering: optimizeSpeed;
|
||||||
|
image-rendering: -moz-crisp-edges;
|
||||||
|
image-rendering: -o-crisp-edges;
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
image-rendering: optimize-contrast;
|
||||||
|
image-rendering: crisp-edges;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
-ms-interpolation-mode: nearest-neighbor;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas class="game" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
var Module = {
|
||||||
|
preRun: [],
|
||||||
|
print: (...args) => console.log('[stdout]: ' + args.join(' ')),
|
||||||
|
printErr: (...args) => console.log('[stderr]: ' + args.join(' ')),
|
||||||
|
};
|
||||||
|
window.onerror = (event) => console.log('[onerror]: ' + event.message);
|
||||||
|
</script>
|
||||||
|
{{{ SCRIPT }}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,80 @@
|
||||||
|
#pragma once
|
||||||
|
/* common emscripten platform helper functions */
|
||||||
|
#include <emscripten/emscripten.h>
|
||||||
|
#include <emscripten/html5.h>
|
||||||
|
#include <GLES3/gl3.h>
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-braces"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char* _emsc_canvas_name = 0;
|
||||||
|
static int _emsc_sample_count = 0;
|
||||||
|
static double _emsc_width = 0;
|
||||||
|
static double _emsc_height = 0;
|
||||||
|
static GLint _emsc_framebuffer = 0;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
EMSC_NONE = 0,
|
||||||
|
EMSC_ANTIALIAS = (1<<1)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* track CSS element size changes and update the WebGL canvas size */
|
||||||
|
static EM_BOOL _emsc_size_changed(int event_type, const EmscriptenUiEvent* ui_event, void* user_data) {
|
||||||
|
(void)event_type;
|
||||||
|
(void)ui_event;
|
||||||
|
(void)user_data;
|
||||||
|
emscripten_get_element_css_size(_emsc_canvas_name, &_emsc_width, &_emsc_height);
|
||||||
|
emscripten_set_canvas_element_size(_emsc_canvas_name, _emsc_width, _emsc_height);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize WebGL context and canvas */
|
||||||
|
void emsc_init(const char* canvas_name, int flags) {
|
||||||
|
_emsc_canvas_name = canvas_name;
|
||||||
|
emscripten_get_element_css_size(canvas_name, &_emsc_width, &_emsc_height);
|
||||||
|
emscripten_set_canvas_element_size(canvas_name, _emsc_width, _emsc_height);
|
||||||
|
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, false, _emsc_size_changed);
|
||||||
|
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
|
||||||
|
EmscriptenWebGLContextAttributes attrs;
|
||||||
|
emscripten_webgl_init_context_attributes(&attrs);
|
||||||
|
attrs.antialias = flags & EMSC_ANTIALIAS;
|
||||||
|
attrs.majorVersion = 2;
|
||||||
|
_emsc_sample_count = (flags & EMSC_ANTIALIAS) ? 4 : 1;
|
||||||
|
ctx = emscripten_webgl_create_context(canvas_name, &attrs);
|
||||||
|
emscripten_webgl_make_context_current(ctx);
|
||||||
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&_emsc_framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int emsc_width(void) {
|
||||||
|
return (int) _emsc_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emsc_height(void) {
|
||||||
|
return (int) _emsc_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
sg_environment emsc_environment(void) {
|
||||||
|
return (sg_environment){
|
||||||
|
.defaults = {
|
||||||
|
.color_format = SG_PIXELFORMAT_RGBA8,
|
||||||
|
.depth_format = SG_PIXELFORMAT_DEPTH_STENCIL,
|
||||||
|
.sample_count = _emsc_sample_count,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sg_swapchain emsc_swapchain(void) {
|
||||||
|
return (sg_swapchain) {
|
||||||
|
.width = (int)_emsc_width,
|
||||||
|
.height = (int)_emsc_height,
|
||||||
|
.sample_count = _emsc_sample_count,
|
||||||
|
.color_format = SG_PIXELFORMAT_RGBA8,
|
||||||
|
.depth_format = SG_PIXELFORMAT_DEPTH_STENCIL,
|
||||||
|
.gl = {
|
||||||
|
.framebuffer = (uint32_t)_emsc_framebuffer,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// cube-emsc.c
|
||||||
|
// Shader uniforms updates.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
#define HANDMADE_MATH_IMPLEMENTATION
|
||||||
|
#define HANDMADE_MATH_NO_SSE
|
||||||
|
#include "HandmadeMath.h"
|
||||||
|
#define SOKOL_IMPL
|
||||||
|
#define SOKOL_GLES3
|
||||||
|
#include "sokol_gfx.h"
|
||||||
|
#include "sokol_log.h"
|
||||||
|
#include "emsc.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
float rx, ry;
|
||||||
|
sg_pipeline pip;
|
||||||
|
sg_bindings bind;
|
||||||
|
sg_pass_action pass_action;
|
||||||
|
} state = {
|
||||||
|
.pass_action.colors[0] = { .load_action = SG_LOADACTION_CLEAR, .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f } }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hmm_mat4 mvp;
|
||||||
|
} params_t;
|
||||||
|
|
||||||
|
static EM_BOOL draw(double time, void* userdata);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// setup WebGL context
|
||||||
|
emsc_init("#canvas", EMSC_ANTIALIAS);
|
||||||
|
|
||||||
|
// setup sokol_gfx
|
||||||
|
sg_setup(&(sg_desc){
|
||||||
|
.environment = emsc_environment(),
|
||||||
|
.logger.func = slog_func
|
||||||
|
});
|
||||||
|
assert(sg_isvalid());
|
||||||
|
|
||||||
|
// cube vertex buffer
|
||||||
|
float vertices[] = {
|
||||||
|
-1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
||||||
|
1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
||||||
|
1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
||||||
|
-1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
||||||
|
|
||||||
|
-1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
||||||
|
1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
||||||
|
1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
||||||
|
-1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
||||||
|
|
||||||
|
-1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 1.0,
|
||||||
|
-1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 1.0,
|
||||||
|
-1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0,
|
||||||
|
-1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0,
|
||||||
|
|
||||||
|
1.0, -1.0, -1.0, 1.0, 0.5, 0.0, 1.0,
|
||||||
|
1.0, 1.0, -1.0, 1.0, 0.5, 0.0, 1.0,
|
||||||
|
1.0, 1.0, 1.0, 1.0, 0.5, 0.0, 1.0,
|
||||||
|
1.0, -1.0, 1.0, 1.0, 0.5, 0.0, 1.0,
|
||||||
|
|
||||||
|
-1.0, -1.0, -1.0, 0.0, 0.5, 1.0, 1.0,
|
||||||
|
-1.0, -1.0, 1.0, 0.0, 0.5, 1.0, 1.0,
|
||||||
|
1.0, -1.0, 1.0, 0.0, 0.5, 1.0, 1.0,
|
||||||
|
1.0, -1.0, -1.0, 0.0, 0.5, 1.0, 1.0,
|
||||||
|
|
||||||
|
-1.0, 1.0, -1.0, 1.0, 0.0, 0.5, 1.0,
|
||||||
|
-1.0, 1.0, 1.0, 1.0, 0.0, 0.5, 1.0,
|
||||||
|
1.0, 1.0, 1.0, 1.0, 0.0, 0.5, 1.0,
|
||||||
|
1.0, 1.0, -1.0, 1.0, 0.0, 0.5, 1.0
|
||||||
|
};
|
||||||
|
state.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.data = SG_RANGE(vertices)
|
||||||
|
});
|
||||||
|
|
||||||
|
// create an index buffer for the cube
|
||||||
|
uint16_t indices[] = {
|
||||||
|
0, 1, 2, 0, 2, 3,
|
||||||
|
6, 5, 4, 7, 6, 4,
|
||||||
|
8, 9, 10, 8, 10, 11,
|
||||||
|
14, 13, 12, 15, 14, 12,
|
||||||
|
16, 17, 18, 16, 18, 19,
|
||||||
|
22, 21, 20, 23, 22, 20
|
||||||
|
};
|
||||||
|
state.bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||||
|
.data = SG_RANGE(indices)
|
||||||
|
});
|
||||||
|
|
||||||
|
// create shader
|
||||||
|
sg_shader shd = sg_make_shader(&(sg_shader_desc){
|
||||||
|
.vertex_func.source =
|
||||||
|
"#version 300 es\n"
|
||||||
|
"uniform mat4 mvp;\n"
|
||||||
|
"in vec4 position;\n"
|
||||||
|
"in vec4 color0;\n"
|
||||||
|
"out vec4 color;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = mvp * position;\n"
|
||||||
|
" color = color0;\n"
|
||||||
|
"}\n",
|
||||||
|
.fragment_func.source =
|
||||||
|
"#version 300 es\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"in vec4 color;\n"
|
||||||
|
"out vec4 frag_color;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" frag_color = color;\n"
|
||||||
|
"}\n",
|
||||||
|
.attrs = {
|
||||||
|
[0].glsl_name = "position",
|
||||||
|
[1].glsl_name = "color0"
|
||||||
|
},
|
||||||
|
.uniform_blocks[0] = {
|
||||||
|
.stage = SG_SHADERSTAGE_VERTEX,
|
||||||
|
.size = sizeof(params_t),
|
||||||
|
.glsl_uniforms = {
|
||||||
|
[0] = { .glsl_name = "mvp", .type = SG_UNIFORMTYPE_MAT4 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// create pipeline object
|
||||||
|
state.pip = sg_make_pipeline(&(sg_pipeline_desc){
|
||||||
|
.layout = {
|
||||||
|
// test to provide buffer stride, but no attr offsets
|
||||||
|
.buffers[0].stride = 28,
|
||||||
|
.attrs = {
|
||||||
|
[0].format=SG_VERTEXFORMAT_FLOAT3,
|
||||||
|
[1].format=SG_VERTEXFORMAT_FLOAT4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.shader = shd,
|
||||||
|
.index_type = SG_INDEXTYPE_UINT16,
|
||||||
|
.depth = {
|
||||||
|
.compare = SG_COMPAREFUNC_LESS_EQUAL,
|
||||||
|
.write_enabled = true
|
||||||
|
},
|
||||||
|
.cull_mode = SG_CULLMODE_BACK
|
||||||
|
});
|
||||||
|
|
||||||
|
// hand off control to browser loop
|
||||||
|
emscripten_request_animation_frame_loop(draw, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw one frame
|
||||||
|
static EM_BOOL draw(double time, void* userdata) {
|
||||||
|
(void)time; (void)userdata;
|
||||||
|
// compute model-view-projection matrix for vertex shader
|
||||||
|
hmm_mat4 proj = HMM_Perspective(60.0f, (float)emsc_width()/(float)emsc_height(), 0.01f, 10.0f);
|
||||||
|
hmm_mat4 view = HMM_LookAt(HMM_Vec3(0.0f, 1.5f, 6.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
hmm_mat4 view_proj = HMM_MultiplyMat4(proj, view);
|
||||||
|
|
||||||
|
state.rx += 1.0f; state.ry += 2.0f;
|
||||||
|
hmm_mat4 rxm = HMM_Rotate(state.rx, HMM_Vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
hmm_mat4 rym = HMM_Rotate(state.ry, HMM_Vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
hmm_mat4 model = HMM_MultiplyMat4(rxm, rym);
|
||||||
|
const params_t vs_params = {
|
||||||
|
.mvp = HMM_MultiplyMat4(view_proj, model)
|
||||||
|
};
|
||||||
|
|
||||||
|
// ...and draw
|
||||||
|
sg_begin_pass(&(sg_pass){ .action = state.pass_action, .swapchain = emsc_swapchain() });
|
||||||
|
sg_apply_pipeline(state.pip);
|
||||||
|
sg_apply_bindings(&state.bind);
|
||||||
|
sg_apply_uniforms(0, &SG_RANGE(vs_params));
|
||||||
|
sg_draw(0, 36, 1);
|
||||||
|
sg_end_pass();
|
||||||
|
sg_commit();
|
||||||
|
return EM_TRUE;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue