From 5eac1d03e947000bd79e2c362460ea2532f36679 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Wed, 2 Oct 2024 20:14:45 -0500 Subject: [PATCH] fix wasm build; add sharpen shader; add masking --- Makefile | 9 ++--- scripts/render.js | 35 ++++++++++++++++-- shaders/mask.cg | 23 ++++++++++++ shaders/postsharpen.cg | 38 ++++++++++++++++++++ source/engine/gui.cpp | 82 ------------------------------------------ source/engine/jsffi.c | 16 +++++++-- source/engine/render.c | 4 ++- 7 files changed, 115 insertions(+), 92 deletions(-) create mode 100644 shaders/mask.cg create mode 100644 shaders/postsharpen.cg diff --git a/Makefile b/Makefile index b0535297..ddf96852 100755 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ LDFLAGS += -lstdc++ ifeq ($(CROSS)$(CC), emcc) LDFLAGS += --shell-file shell.html --closure 1 - CPPFLAGS += -Wbad-function-cast -Wcast-function-type -sSTACK_SIZE=1MB -sALLOW_MEMORY_GROWTH -sINITIAL_MEMORY=128MB + CPPFLAGS += -Wbad-function-cast -Wcast-function-type -sSTACK_SIZE=1MB -sALLOW_MEMORY_GROWTH -sINITIAL_MEMORY=128MB -pthread -s USE_PTHREADS=1 NDEBUG = 1 ARCH:= wasm endif @@ -105,8 +105,9 @@ else ifeq ($(OS), IOS) INFO :=$(INFO)_ios else ifeq ($(OS), wasm) # Then WEB OS := Web - LDFLAGS += -sUSE_WEBGPU - CPPFLAGS += -DNSTEAM + LDFLAGS += -sUSE_WEBGPU -pthread + CPPFLAGS += -DNSTEAM -pthread + CFLAGS += -pthread LDLIBS += GL openal c m dl STEAMAPI := EXT = .html @@ -138,7 +139,7 @@ endif # All other sources OBJS != find source -type f -name '*.c' | grep -vE 'test|tool|example|fuzz|main' | grep -vE 'quickjs' -CPPOBJS != find source -type f -name '*.cpp' | grep -vE 'test|tool|example|fuzz|main' +CPPOBJS != find source -type f -name '*.cpp' | grep -vE 'test|tool|example|fuzz|main|ImCurveEdit|GraphEditor|neo_sequencer|imgui_neo_sequencer' OBJS += $(CPPOBJS) OBJS += source/engine/yugine.c OBJS += $(shell find source/engine -type f -name '*.m') diff --git a/scripts/render.js b/scripts/render.js index 0f27d267..4a82b7ee 100644 --- a/scripts/render.js +++ b/scripts/render.js @@ -208,6 +208,7 @@ function create_shader_obj(file) { var depth = shader_directive(shader, "depth", depth_map); var face = shader_directive(shader, "face", face_map); var indexed = shader_directive(shader, "indexed"); + var stencil = shader_directive(shader, "stencil"); if (typeof indexed == "undefined") indexed = true; if (indexed === "false") indexed = false; @@ -256,6 +257,7 @@ function create_shader_obj(file) { obj.depth = depth; obj.face = face; obj.indexed = indexed; + obj.stencil = stencil === 'write'; if (obj.vs.inputs) for (var i of obj.vs.inputs) { @@ -378,6 +380,8 @@ function shader_apply_material(shader, material = {}, old = {}) { if (!material.diffuse) return; if (material.diffuse === old.diffuse) return; + if ("diffuse_texel" in shader.fs.unimap) render.setuniv2(1, shader.fs.unimap.diffuse_texel.slot, [1,1].div([material.diffuse.width, material.diffuse.height])); + if ("diffuse_size" in shader.fs.unimap) render.setuniv2(1, shader.fs.unimap.diffuse_size.slot, [material.diffuse.width, material.diffuse.height]); if ("diffuse_size" in shader.vs.unimap) render.setuniv2(0, shader.vs.unimap.diffuse_size.slot, [material.diffuse.width, material.diffuse.height]); @@ -476,7 +480,7 @@ var slice9shader; var parshader; var spritessboshader; var polyssboshader; - +var maskshader; var sprite_ssbo; render.init = function () { @@ -489,6 +493,7 @@ render.init = function () { polyshader = make_shader("shaders/poly.cg"); parshader = make_shader("shaders/baseparticle.cg"); polyssboshader = make_shader("shaders/poly_ssbo.cg"); + maskshader = make_shader('shaders/mask.cg'); poly_ssbo = render.make_textssbo(); sprite_ssbo = render.make_textssbo(); @@ -749,6 +754,29 @@ function img_e() { return img_cache[img_idx - 1]; } +render.floodmask = function(val) +{ + render.use_shader(polyshader); + render.use_mat({}); + render.draw( +} + +render.mask = function mask(tex, pos, scale, rotation = 0) +{ + if (typeof tex === 'string') tex = game.texture(tex); + + render.use_shader(maskshader); + var t = os.make_transform(); + t.pos = pos; + t.scale = scale; + set_model(t); + render.use_mat({ + diffuse:tex, + rect: [0,0,1,1] + }); + render.draw(shape.quad); +} + render.image = function image(tex, pos, scale, rotation = 0, color = Color.white) { if (typeof tex === "string") tex = game.texture(tex); @@ -1037,6 +1065,8 @@ var imgui_fn = function () { render.imgui_end(); }; +prosperon.postvals = {}; +prosperon.postvals.offset_amt = 300; prosperon.render = function () { profile.report("world"); render.set_camera(prosperon.camera); @@ -1085,7 +1115,8 @@ prosperon.render = function () { profile.report("post process"); render.viewport(...prosperon.camera.view()); render.use_shader(render.postshader); - render.use_mat({ diffuse: prosperon.screencolor }); + prosperon.postvals.diffuse = prosperon.screencolor; + render.use_mat(prosperon.postvals); render.draw(shape.quad); profile.endreport("post process"); diff --git a/shaders/mask.cg b/shaders/mask.cg new file mode 100644 index 00000000..2f8b2d8e --- /dev/null +++ b/shaders/mask.cg @@ -0,0 +1,23 @@ +#stencil write + +@block vert +uniform vec4 rect; + +void vert() +{ + pos *= vec3(rect.zw,1); + uv = (uv*rect.zw)+rect.xy; +} +@end + +@block frag +uniform vec4 shade; +void frag() +{ + color = texture(sampler2D(diffuse,smp), uv); + if (color.a == 0.0) discard; + color = vec4(1.0); +} +@end + +#include \ No newline at end of file diff --git a/shaders/postsharpen.cg b/shaders/postsharpen.cg new file mode 100644 index 00000000..f8f39a68 --- /dev/null +++ b/shaders/postsharpen.cg @@ -0,0 +1,38 @@ +@block frag + +uniform float offset_amt; + +// Sharpen kernel +float kernel[9] = float[]( + -1, -1, -1, + -1, 9, -1, + -1, -1, -1 +); + +void frag() +{ + vec2 offset = vec2(1/offset_amt, 1/offset_amt); + vec2 offsets[9] = vec2[]( + vec2(-offset.x, offset.y), // top-left + vec2(0.0, offset.y), // top-center + vec2(offset.x, offset.y), // top-right + vec2(-offset.x, 0.0), // center-left + vec2(0.0, 0.0), // center-center (current pixel) + vec2(offset.x, 0.0), // center-right + vec2(-offset.x, -offset.y), // bottom-left + vec2(0.0, -offset.y), // bottom-center + vec2(offset.x, -offset.y) // bottom-right + ); + + color = vec4(0.0); + + // Apply the kernel to the current pixel and its neighbors + for (int i = 0; i < 9; i++) { + vec3 samp = texture(sampler2D(diffuse,smp),uv+offsets[i]).rgb; + color.rgb += samp * kernel[i]; + } + color.a = 1.0; +} +@end + +#include \ No newline at end of file diff --git a/source/engine/gui.cpp b/source/engine/gui.cpp index d4cad4ca..fac4f25c 100644 --- a/source/engine/gui.cpp +++ b/source/engine/gui.cpp @@ -5,8 +5,6 @@ #include "imgui.h" #include "implot.h" #include "imnodes.h" -#include "imgui_neo_sequencer.h" -#include "ImSequencer.h" #include "stb_ds.h" @@ -573,82 +571,6 @@ JSC_CCALL(imgui_nodelink, JSC_CCALL(imgui_nodemini, ImNodes::MiniMap(js2number(argv[0]))) -struct MySequence : public ImSequencer::SequenceInterface { - int GetFrameMin() const { return 0; } - int GetFrameMax() const { return 100; } - int GetItemCount() const { return 0; } - virtual void Get(int index, int **start, int **end, int *type, unsigned int *color) { - } -}; - -JSC_SCALL(imgui_seq, - struct MySequence mseq = {}; - - int selected = -1; - int first = 0; - int current = 100; - bool expanded = true; - Sequencer(&mseq, ¤t, &expanded, &selected, &first, ImSequencer::SEQUENCER_EDIT_STARTEND | ImSequencer::SEQUENCER_ADD | ImSequencer::SEQUENCER_DEL | ImSequencer::SEQUENCER_COPYPASTE | ImSequencer::SEQUENCER_CHANGE_FRAME); - -) - -JSC_SCALL(imgui_sequencer, - /*float start_time = js2number(js_getpropstr(argv[1], "start")); - float end_time = js2number(js_getpropstr(argv[1], "end")); - float current = js2number(js_getpropstr(argv[1], "current")); - - ImVec2 timeline_size = ImGui::GetContentRegionAvail(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - ImVec2 timeline_start = ImGui::GetCursorScreenPos(); - float total_time = end_time - start_time; - float pixels_per_second = zoom * (timeline_size.x / total_time); - - if(ImGui::BeginNeoSequencer(str, ¤t, &start, &end, {700,200}, - ImGuiNeoSequencerFlags_AllowLengthChanging | - ImGuiNeoSequencerFlags_EnableSelection | - ImGuiNeoSequencerFlags_Selection_EnableDragging | - ImGuiNeoSequencerFlags_Selection_EnableDeletion)) { - script_call_sym(argv[2], 0, NULL); - ImGui::EndNeoSequencer(); - } - - js_setpropstr(argv[1], "current", number2js(current)); - js_setpropstr(argv[1], "start", number2js(start)); - js_setpropstr(argv[1], "end", number2js(end)); */ -) - -JSC_SCALL(imgui_timeline, - float *k = js2newfloatarr(argv[1]); - int n = arrlen(k); - int32_t *keys = (int32_t*)malloc(n*sizeof(*keys)); - - for (int i = 0; i < n; i++) { - keys[i] = k[i]; - } - - arrfree(k); - - if (ImGui::BeginNeoTimelineEx(str)) { - for (int i = 0; i < n; i++) - ImGui::NeoKeyframe(keys+i); - ImGui::EndNeoTimeLine(); - } - - JSValue arr = JS_NewArray(js); - for (int i = 0; i < n; i++) - js_setprop_num(arr, i, number2js(keys[i])); - - free(keys); - ret = arr; -) - -JSC_SCALL(imgui_tlgroup, - if (ImGui::BeginNeoGroup(str)) { - script_call_sym(argv[1], 0, NULL); - ImGui::EndNeoGroup(); - } -) - ImVec2 js2imvec2(JSValue v) { HMM_Vec2 va = js2vec2(v); @@ -926,10 +848,6 @@ static const JSCFunctionListEntry js_imgui_funcs[] = { MIST_FUNC_DEF(imgui, nodeout, 2), MIST_FUNC_DEF(imgui, nodelink, 3), MIST_FUNC_DEF(imgui, nodemini, 1), - MIST_FUNC_DEF(imgui, sequencer, 3), - MIST_FUNC_DEF(imgui, timeline, 3), - MIST_FUNC_DEF(imgui, tlgroup, 2), - MIST_FUNC_DEF(imgui, seq, 3), MIST_FUNC_DEF(imgui, mousehoveringrect, 2), MIST_FUNC_DEF(imgui, mouseclicked, 1), MIST_FUNC_DEF(imgui, mousedown, 1), diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index fbf6103c..ff9790e7 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -1,8 +1,5 @@ #include "jsffi.h" -//#define STB_LEAKCHECK_IMPLEMENTATION -//#include "stb/stb_leakcheck.h" - #include "script.h" #include "font.h" #include "gameobject.h" @@ -974,6 +971,19 @@ JSC_CCALL(render_pipeline, p.depth.write_enabled = true; p.depth.compare = SG_COMPAREFUNC_LESS; } + + int stencil = js2boolean(js_getpropstr(argv[0], "stencil")); + + p.stencil.enabled = true; + p.stencil.front.compare = p.stencil.back.compare = SG_COMPAREFUNC_EQUAL; + p.stencil.read_mask = 0xFF; + p.stencil.ref = 1; + + if (stencil) { + p.stencil.write_mask = 0xFF; + p.stencil.front.compare = p.stencil.back.compare = SG_COMPAREFUNC_NEVER; + p.stencil.front.pass_op = p.stencil.back.pass_op = p.stencil.front.fail_op = p.stencil.front.depth_fail_op = p.stencil.back.depth_fail_op = p.stencil.back.fail_op = SG_STENCILOP_REPLACE; + } sg_pipeline pipe = sg_make_pipeline(&p); diff --git a/source/engine/render.c b/source/engine/render.c index f393e293..7d15b63d 100644 --- a/source/engine/render.c +++ b/source/engine/render.c @@ -179,7 +179,9 @@ void render_init() { .depth = { .load_action = SG_LOADACTION_CLEAR, .clear_value = 1 - //.store_action = SG_STOREACTION_STORE + }, + .stencil = { + .clear_value = 1 } };