fix wasm build; add sharpen shader; add masking

This commit is contained in:
John Alanbrook 2024-10-02 20:14:45 -05:00
parent 5149b9986f
commit 5eac1d03e9
7 changed files with 115 additions and 92 deletions

View file

@ -21,7 +21,7 @@ LDFLAGS += -lstdc++
ifeq ($(CROSS)$(CC), emcc) ifeq ($(CROSS)$(CC), emcc)
LDFLAGS += --shell-file shell.html --closure 1 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 NDEBUG = 1
ARCH:= wasm ARCH:= wasm
endif endif
@ -105,8 +105,9 @@ else ifeq ($(OS), IOS)
INFO :=$(INFO)_ios INFO :=$(INFO)_ios
else ifeq ($(OS), wasm) # Then WEB else ifeq ($(OS), wasm) # Then WEB
OS := Web OS := Web
LDFLAGS += -sUSE_WEBGPU LDFLAGS += -sUSE_WEBGPU -pthread
CPPFLAGS += -DNSTEAM CPPFLAGS += -DNSTEAM -pthread
CFLAGS += -pthread
LDLIBS += GL openal c m dl LDLIBS += GL openal c m dl
STEAMAPI := STEAMAPI :=
EXT = .html EXT = .html
@ -138,7 +139,7 @@ endif
# All other sources # All other sources
OBJS != find source -type f -name '*.c' | grep -vE 'test|tool|example|fuzz|main' | grep -vE 'quickjs' 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 += $(CPPOBJS)
OBJS += source/engine/yugine.c OBJS += source/engine/yugine.c
OBJS += $(shell find source/engine -type f -name '*.m') OBJS += $(shell find source/engine -type f -name '*.m')

View file

@ -208,6 +208,7 @@ function create_shader_obj(file) {
var depth = shader_directive(shader, "depth", depth_map); var depth = shader_directive(shader, "depth", depth_map);
var face = shader_directive(shader, "face", face_map); var face = shader_directive(shader, "face", face_map);
var indexed = shader_directive(shader, "indexed"); var indexed = shader_directive(shader, "indexed");
var stencil = shader_directive(shader, "stencil");
if (typeof indexed == "undefined") indexed = true; if (typeof indexed == "undefined") indexed = true;
if (indexed === "false") indexed = false; if (indexed === "false") indexed = false;
@ -256,6 +257,7 @@ function create_shader_obj(file) {
obj.depth = depth; obj.depth = depth;
obj.face = face; obj.face = face;
obj.indexed = indexed; obj.indexed = indexed;
obj.stencil = stencil === 'write';
if (obj.vs.inputs) if (obj.vs.inputs)
for (var i of 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) return;
if (material.diffuse === old.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.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]); 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 parshader;
var spritessboshader; var spritessboshader;
var polyssboshader; var polyssboshader;
var maskshader;
var sprite_ssbo; var sprite_ssbo;
render.init = function () { render.init = function () {
@ -489,6 +493,7 @@ render.init = function () {
polyshader = make_shader("shaders/poly.cg"); polyshader = make_shader("shaders/poly.cg");
parshader = make_shader("shaders/baseparticle.cg"); parshader = make_shader("shaders/baseparticle.cg");
polyssboshader = make_shader("shaders/poly_ssbo.cg"); polyssboshader = make_shader("shaders/poly_ssbo.cg");
maskshader = make_shader('shaders/mask.cg');
poly_ssbo = render.make_textssbo(); poly_ssbo = render.make_textssbo();
sprite_ssbo = render.make_textssbo(); sprite_ssbo = render.make_textssbo();
@ -749,6 +754,29 @@ function img_e() {
return img_cache[img_idx - 1]; 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) { render.image = function image(tex, pos, scale, rotation = 0, color = Color.white) {
if (typeof tex === "string") if (typeof tex === "string")
tex = game.texture(tex); tex = game.texture(tex);
@ -1037,6 +1065,8 @@ var imgui_fn = function () {
render.imgui_end(); render.imgui_end();
}; };
prosperon.postvals = {};
prosperon.postvals.offset_amt = 300;
prosperon.render = function () { prosperon.render = function () {
profile.report("world"); profile.report("world");
render.set_camera(prosperon.camera); render.set_camera(prosperon.camera);
@ -1085,7 +1115,8 @@ prosperon.render = function () {
profile.report("post process"); profile.report("post process");
render.viewport(...prosperon.camera.view()); render.viewport(...prosperon.camera.view());
render.use_shader(render.postshader); 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); render.draw(shape.quad);
profile.endreport("post process"); profile.endreport("post process");

23
shaders/mask.cg Normal file
View file

@ -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 <base.cg>

38
shaders/postsharpen.cg Normal file
View file

@ -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 <postbase.cg>

View file

@ -5,8 +5,6 @@
#include "imgui.h" #include "imgui.h"
#include "implot.h" #include "implot.h"
#include "imnodes.h" #include "imnodes.h"
#include "imgui_neo_sequencer.h"
#include "ImSequencer.h"
#include "stb_ds.h" #include "stb_ds.h"
@ -573,82 +571,6 @@ JSC_CCALL(imgui_nodelink,
JSC_CCALL(imgui_nodemini, ImNodes::MiniMap(js2number(argv[0]))) 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, &current, &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, &current, &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) ImVec2 js2imvec2(JSValue v)
{ {
HMM_Vec2 va = js2vec2(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, nodeout, 2),
MIST_FUNC_DEF(imgui, nodelink, 3), MIST_FUNC_DEF(imgui, nodelink, 3),
MIST_FUNC_DEF(imgui, nodemini, 1), 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, mousehoveringrect, 2),
MIST_FUNC_DEF(imgui, mouseclicked, 1), MIST_FUNC_DEF(imgui, mouseclicked, 1),
MIST_FUNC_DEF(imgui, mousedown, 1), MIST_FUNC_DEF(imgui, mousedown, 1),

View file

@ -1,8 +1,5 @@
#include "jsffi.h" #include "jsffi.h"
//#define STB_LEAKCHECK_IMPLEMENTATION
//#include "stb/stb_leakcheck.h"
#include "script.h" #include "script.h"
#include "font.h" #include "font.h"
#include "gameobject.h" #include "gameobject.h"
@ -974,6 +971,19 @@ JSC_CCALL(render_pipeline,
p.depth.write_enabled = true; p.depth.write_enabled = true;
p.depth.compare = SG_COMPAREFUNC_LESS; 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); sg_pipeline pipe = sg_make_pipeline(&p);

View file

@ -179,7 +179,9 @@ void render_init() {
.depth = { .depth = {
.load_action = SG_LOADACTION_CLEAR, .load_action = SG_LOADACTION_CLEAR,
.clear_value = 1 .clear_value = 1
//.store_action = SG_STOREACTION_STORE },
.stencil = {
.clear_value = 1
} }
}; };