Setup for 2D
This commit is contained in:
parent
79f8d6d4dc
commit
6692bcf7ad
|
|
@ -0,0 +1 @@
|
||||||
|
app.*
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Win32",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"_DEBUG",
|
||||||
|
"UNICODE",
|
||||||
|
"_UNICODE"
|
||||||
|
],
|
||||||
|
"windowsSdkVersion": "10.0.22621.0",
|
||||||
|
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "${default}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Emscripten",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/../sokol",
|
||||||
|
"${workspaceFolder}/../sokol_gp"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"_DEBUG",
|
||||||
|
"UNICODE",
|
||||||
|
"_UNICODE"
|
||||||
|
],
|
||||||
|
"windowsSdkVersion": "10.0.22621.0",
|
||||||
|
"compilerPath": "C:\\Users\\c.pons\\Documents\\Perso\\Git\\emsdk\\upstream\\emscripten\\emcc.bat",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "windows-clang-x64",
|
||||||
|
"compilerPathInCppPropertiesJson": "C:\\Users\\c.pons\\Documents\\Perso\\Git\\emsdk\\upstream\\bin\\clang.exe",
|
||||||
|
"mergeConfigurations": false,
|
||||||
|
"browse": {
|
||||||
|
"path": [
|
||||||
|
"c:/Users/c.pons/Documents/Perso/Git/flecs_tests/**",
|
||||||
|
"c:/Users/c.pons/Documents/Perso/Git/flecs_tests"
|
||||||
|
],
|
||||||
|
"limitSymbolsToIncludedHeaders": true
|
||||||
|
},
|
||||||
|
"compilerArgs": [
|
||||||
|
"-O2",
|
||||||
|
"-sUSE_WEBGL2",
|
||||||
|
"-sASSERTIONS",
|
||||||
|
"-sWASM_BIGINT",
|
||||||
|
"-pthread",
|
||||||
|
"-sFILESYSTEM=0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"sokol_app.h": "c",
|
||||||
|
"emsc.h": "c",
|
||||||
|
"gl3.h": "c",
|
||||||
|
"sokol_gp.h": "c",
|
||||||
|
"sokol_glue.h": "c",
|
||||||
|
"sokol_gfx.h": "c",
|
||||||
|
"webgpu.h": "c",
|
||||||
|
"html5.h": "c",
|
||||||
|
"emscripten.h": "c",
|
||||||
|
"stddef.h": "c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
emcc -O2 src/main.c -o app.html -sUSE_WEBGL2 -sASSERTIONS -sWASM_BIGINT -pthread -I../sokol --shell-file=shell.html --closure 1
|
emcc -O3 src/main.c -o app.html -sUSE_WEBGL2 -sWASM_BIGINT -pthread -I../sokol -I../sokol_gp --shell-file=shell.html -sFILESYSTEM=0
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
emcc src/main.c -o app.html -sUSE_WEBGL2 -sASSERTIONS -sWASM_BIGINT -pthread -I../sokol -I../sokol_gp --shell-file=shell.html -sFILESYSTEM=0 -g
|
||||||
2884
src/HandmadeMath.h
2884
src/HandmadeMath.h
File diff suppressed because it is too large
Load Diff
80
src/emsc.h
80
src/emsc.h
|
|
@ -1,80 +0,0 @@
|
||||||
#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,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
234
src/main.c
234
src/main.c
|
|
@ -1,172 +1,90 @@
|
||||||
//------------------------------------------------------------------------------
|
// This is an example on how to set up and use Sokol GP to draw a filled rectangle.
|
||||||
// cube-emsc.c
|
|
||||||
// Shader uniforms updates.
|
// Includes Sokol GFX, Sokol GP and Sokol APP, doing all implementations.
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
#define HANDMADE_MATH_IMPLEMENTATION
|
|
||||||
#define HANDMADE_MATH_NO_SSE
|
|
||||||
#include "HandmadeMath.h"
|
|
||||||
#define SOKOL_IMPL
|
#define SOKOL_IMPL
|
||||||
#define SOKOL_GLES3
|
#define SOKOL_GLES3
|
||||||
#include "sokol_gfx.h"
|
#include "sokol_gfx.h"
|
||||||
#include "sokol_log.h"
|
#include "sokol_gp.h"
|
||||||
#include "emsc.h"
|
#include "sokol_app.h"
|
||||||
|
#include "sokol_glue.h"
|
||||||
|
|
||||||
static struct {
|
#include <stdio.h> // for fprintf()
|
||||||
float rx, ry;
|
#include <stdlib.h> // for exit()
|
||||||
sg_pipeline pip;
|
#include <math.h> // for sinf() and cosf()
|
||||||
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 {
|
// Called on every frame of the application.
|
||||||
hmm_mat4 mvp;
|
static void frame(void) {
|
||||||
} params_t;
|
// Get current window size.
|
||||||
|
int width = sapp_width(), height = sapp_height();
|
||||||
|
float ratio = width/(float)height;
|
||||||
|
|
||||||
static EM_BOOL draw(double time, void* userdata);
|
// Begin recording draw commands for a frame buffer of size (width, height).
|
||||||
|
sgp_begin(width, height);
|
||||||
|
// Set frame buffer drawing region to (0,0,width,height).
|
||||||
|
sgp_viewport(0, 0, width, height);
|
||||||
|
// Set drawing coordinate space to (left=-ratio, right=ratio, top=1, bottom=-1).
|
||||||
|
sgp_project(-ratio, ratio, 1.0f, -1.0f);
|
||||||
|
|
||||||
int main() {
|
// Clear the frame buffer.
|
||||||
// setup WebGL context
|
sgp_set_color(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
emsc_init("#canvas", EMSC_ANTIALIAS);
|
sgp_clear();
|
||||||
|
|
||||||
// setup sokol_gfx
|
// Draw an animated rectangle that rotates and changes its colors.
|
||||||
sg_setup(&(sg_desc){
|
float time = sapp_frame_count() * sapp_frame_duration();
|
||||||
.environment = emsc_environment(),
|
float r = sinf(time)*0.5+0.5, g = cosf(time)*0.5+0.5;
|
||||||
.logger.func = slog_func
|
sgp_set_color(r, g, 0.3f, 1.0f);
|
||||||
});
|
sgp_rotate_at(time, 0.0f, 0.0f);
|
||||||
assert(sg_isvalid());
|
sgp_draw_filled_rect(-0.5f, -0.5f, 1.0f, 1.0f);
|
||||||
|
|
||||||
// cube vertex buffer
|
// Begin a render pass.
|
||||||
float vertices[] = {
|
sg_pass pass = {.swapchain = sglue_swapchain()};
|
||||||
-1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
sg_begin_pass(&pass);
|
||||||
1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
// Dispatch all draw commands to Sokol GFX.
|
||||||
1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
sgp_flush();
|
||||||
-1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0,
|
// Finish a draw command queue, clearing it.
|
||||||
|
sgp_end();
|
||||||
-1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
// End render pass.
|
||||||
1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
sg_end_pass();
|
||||||
1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
// Commit Sokol render.
|
||||||
-1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,
|
sg_commit();
|
||||||
|
|
||||||
-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
|
// Called when the application is initializing.
|
||||||
static EM_BOOL draw(double time, void* userdata) {
|
static void init(void) {
|
||||||
(void)time; (void)userdata;
|
// Initialize Sokol GFX.
|
||||||
// compute model-view-projection matrix for vertex shader
|
sg_desc sgdesc = {
|
||||||
hmm_mat4 proj = HMM_Perspective(60.0f, (float)emsc_width()/(float)emsc_height(), 0.01f, 10.0f);
|
.environment = sglue_environment(),
|
||||||
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)
|
|
||||||
};
|
};
|
||||||
|
sg_setup(&sgdesc);
|
||||||
|
if (!sg_isvalid()) {
|
||||||
|
fprintf(stderr, "Failed to create Sokol GFX context!\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
// ...and draw
|
// Initialize Sokol GP, adjust the size of command buffers for your own use.
|
||||||
sg_begin_pass(&(sg_pass){ .action = state.pass_action, .swapchain = emsc_swapchain() });
|
sgp_desc sgpdesc = {0};
|
||||||
sg_apply_pipeline(state.pip);
|
sgp_setup(&sgpdesc);
|
||||||
sg_apply_bindings(&state.bind);
|
if (!sgp_is_valid()) {
|
||||||
sg_apply_uniforms(0, &SG_RANGE(vs_params));
|
fprintf(stderr, "Failed to create Sokol GP context: %s\n", sgp_get_error_message(sgp_get_last_error()));
|
||||||
sg_draw(0, 36, 1);
|
exit(-1);
|
||||||
sg_end_pass();
|
}
|
||||||
sg_commit();
|
}
|
||||||
return EM_TRUE;
|
|
||||||
|
// Called when the application is shutting down.
|
||||||
|
static void cleanup(void) {
|
||||||
|
// Cleanup Sokol GP and Sokol GFX resources.
|
||||||
|
sgp_shutdown();
|
||||||
|
sg_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement application main through Sokol APP.
|
||||||
|
sapp_desc sokol_main(int argc, char* argv[]) {
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
return (sapp_desc){
|
||||||
|
.init_cb = init,
|
||||||
|
.frame_cb = frame,
|
||||||
|
.cleanup_cb = cleanup,
|
||||||
|
.window_title = "Rectangle (Sokol GP)",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue