fill mask

This commit is contained in:
John Alanbrook 2024-10-03 23:35:40 -05:00
parent 45bc8a8bb4
commit 0ffef3b602
7 changed files with 94 additions and 17 deletions

View file

@ -1534,6 +1534,7 @@ yaml.tojson = function (yaml) {
yaml = yaml.replace(/,}/g, "}"); yaml = yaml.replace(/,}/g, "}");
yaml = yaml.replace(/,]/g, "]"); yaml = yaml.replace(/,]/g, "]");
yaml = yaml.replace(/,"[^"]+"\:,/g, ","); yaml = yaml.replace(/,"[^"]+"\:,/g, ",");
yaml = yaml.replace(/,"[^"]+"\:}/g, "}");
return yaml; return yaml;
}; };

View file

@ -290,7 +290,7 @@ SpriteAnim.gif = function (path) {
var anim = {}; var anim = {};
anim.frames = []; anim.frames = [];
anim.path = path; anim.path = path;
var tex = game.texture(path); var tex = game.texture(path).texture;
var frames = tex.frames; var frames = tex.frames;
if (frames === 1) return undefined; if (frames === 1) return undefined;
var yslice = 1 / frames; var yslice = 1 / frames;

View file

@ -137,15 +137,15 @@ var base_pipeline = {
bias_clamp: 0 bias_clamp: 0
}, },
stencil: { stencil: {
enabled: false, enabled: true,
front: { front: {
compare: compare.always, compare: compare.equal,
fail_op: stencilop.keep, fail_op: stencilop.keep,
depth_fail_op: stencilop.keep, depth_fail_op: stencilop.keep,
pass_op: stencilop.keep pass_op: stencilop.keep
}, },
back: { back: {
compare: compare.always, compare: compare.equal,
fail_op: stencilop.keep, fail_op: stencilop.keep,
depth_fail_op: stencilop.keep, depth_fail_op: stencilop.keep,
pass_op: stencilop.keep pass_op: stencilop.keep
@ -184,18 +184,40 @@ render.use_pipeline = function use_pipeline(pipeline)
} }
// When changing a shader, everything must wipe var pipe_shaders = new WeakMap();
render.use_shader = function use_shader(shader) {
// Uses the shader with the specified pipeline. If none specified, uses the base pipeline
render.use_shader = function use_shader(shader, pipeline) {
pipeline ??= base_pipeline;
if (typeof shader === "string") shader = make_shader(shader); if (typeof shader === "string") shader = make_shader(shader);
if (cur.shader === shader) return; if (cur.shader === shader) return;
if (!pipe_shaders.has(shader)) pipe_shaders.set(shader, new WeakMap());
var shader_pipelines = pipe_shaders.get(shader);
if (!shader_pipelines.has(pipeline)) {
var new_pipeline = render.make_pipeline(shader,pipeline);
shader_pipelines.set(pipeline, new_pipeline);
}
var use_pipeline = shader_pipelines.get(pipeline);
if (cur.shader === shader && cur.pipeline === use_pipeline) return;
cur.shader = shader; cur.shader = shader;
cur.bind = undefined; cur.bind = undefined;
cur.mesh = undefined; cur.mesh = undefined;
cur.ssbo = undefined; cur.ssbo = undefined;
render.setpipeline(shader.pipe); cur.images = [];
cur.pipeline = use_pipeline;
// Grab or create a pipeline obj that utilizes the specific shader and pipeline
render.setpipeline(use_pipeline);
shader_globals(cur.shader); shader_globals(cur.shader);
}; };
render.use_pipeline = function use_pipeline(pipeline) {
}
render.use_mat = function use_mat(mat) { render.use_mat = function use_mat(mat) {
if (!cur.shader) return; if (!cur.shader) return;
if (cur.mat === mat) return; if (cur.mat === mat) return;
@ -311,7 +333,6 @@ render.hotreload = function () {
shader_times[i] = io.mod(i); shader_times[i] = io.mod(i);
var obj = create_shader_obj(i); var obj = create_shader_obj(i);
obj = obj[os.sys()]; obj = obj[os.sys()];
obj.pipe = render.pipeline(obj, base_pipeline);
var old = shader_cache[i]; var old = shader_cache[i];
Object.assign(shader_cache[i], obj); Object.assign(shader_cache[i], obj);
cur.bind = undefined; cur.bind = undefined;
@ -439,8 +460,6 @@ function make_shader(shader, pipe) {
var shaderobj = json.decode(io.slurp(writejson)); var shaderobj = json.decode(io.slurp(writejson));
var obj = shaderobj[os.sys()]; var obj = shaderobj[os.sys()];
pipe ??= base_pipeline;
obj.pipe = render.pipeline(obj, pipe);
shader_cache[file] = obj; shader_cache[file] = obj;
shader_times[file] = io.mod(file); shader_times[file] = io.mod(file);
return obj; return obj;
@ -451,7 +470,6 @@ function make_shader(shader, pipe) {
var compiled = create_shader_obj(file); var compiled = create_shader_obj(file);
io.slurpwrite(writejson, json.encode(compiled)); io.slurpwrite(writejson, json.encode(compiled));
var obj = compiled[os.sys()]; var obj = compiled[os.sys()];
obj.pipe = render.pipeline(obj, base_pipeline);
shader_cache[file] = obj; shader_cache[file] = obj;
shader_times[file] = io.mod(file); shader_times[file] = io.mod(file);
@ -600,7 +618,6 @@ 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 () {
@ -609,13 +626,13 @@ render.init = function () {
spritessboshader = make_shader("shaders/sprite_ssbo.cg"); spritessboshader = make_shader("shaders/sprite_ssbo.cg");
var postpipe = Object.create(base_pipeline); var postpipe = Object.create(base_pipeline);
postpipe.cull = cull_map.none; postpipe.cull = cull_map.none;
postpipe.primitive = primitive_map.triangle;
render.postshader = make_shader("shaders/simplepost.cg", postpipe); render.postshader = make_shader("shaders/simplepost.cg", postpipe);
slice9shader = make_shader("shaders/9slice.cg"); slice9shader = make_shader("shaders/9slice.cg");
circleshader = make_shader("shaders/circle.cg"); circleshader = make_shader("shaders/circle.cg");
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();
@ -882,11 +899,46 @@ render.floodmask = function(val)
render.use_mat({}); render.use_mat({});
} }
var stencil_write = {
compare: compare.always,
fail_op: stencilop.replace,
depth_fail_op:stencilop.replace,
pass_op: stencilop.replace
};
function stencil_writer(ref)
{
var pipe = Object.create(base_pipeline);
Object.assign(pipe, {
stencil: {
enabled: true,
front: stencil_write,
back: stencil_write,
write:true,
read:true,
ref:ref
},
write_mask: colormask.none
});
}
// objects by default draw where the stencil buffer is 0
var pipe_stencil_on = stencil_writer(1);
var pipe_stencil_off = stencil_writer(0);
render.fillmask = function(on)
{
var pipe = on ? pipe_stencil_on : pipe_stencil_off;
render.use_shader('shaders/screenfill.cg', pipe);
render.draw(shape.quad);
}
render.mask = function mask(tex, pos, scale, rotation = 0) render.mask = function mask(tex, pos, scale, rotation = 0)
{ {
if (typeof tex === 'string') tex = game.texture(tex); if (typeof tex === 'string') tex = game.texture(tex);
render.use_shader(maskshader); render.use_shader(spritessboshader, pipe_stencil_on);
var t = os.make_transform(); var t = os.make_transform();
t.pos = pos; t.pos = pos;
t.scale = scale; t.scale = scale;
@ -1238,7 +1290,7 @@ prosperon.render = function () {
prosperon.postvals.diffuse = prosperon.screencolor; prosperon.postvals.diffuse = prosperon.screencolor;
render.use_mat(prosperon.postvals); render.use_mat(prosperon.postvals);
render.draw(os.backend() === "directx" ? shape.flipquad : shape.quad); render.draw((os.backend() === "directx" || os.backend() === 'metal') ? shape.flipquad : shape.quad);
profile.endreport("post process"); profile.endreport("post process");

22
shaders/screenfill.cg Normal file
View file

@ -0,0 +1,22 @@
@vs vs
in vec3 a_pos;
void main()
{
vec3 pos = a_pos;
pos -= 0.5;
pos *= 2;
gl_Position = vec4(pos.xy, 0, 1.0);
}
@end
@fs fs
out vec4 color;
void main()
{
color = vec4(1.0);
}
@end
@program p vs fs

View file

@ -47,6 +47,7 @@ void frag()
{ {
color = texture(sampler2D(diffuse,smp), uv); color = texture(sampler2D(diffuse,smp), uv);
color *= shade; color *= shade;
if (color.a == 0.0) discard;
} }
void main() void main()

View file

@ -1012,7 +1012,7 @@ sg_blend_state js2blend(JSValue v)
return blend; return blend;
} }
JSC_CCALL(render_pipeline, JSC_CCALL(render_make_pipeline,
sg_pipeline_desc p = {0}; sg_pipeline_desc p = {0};
p.shader = js2shader(argv[0]); p.shader = js2shader(argv[0]);
p.layout = js2layout(argv[0]); p.layout = js2layout(argv[0]);
@ -1253,7 +1253,7 @@ static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, glue_pass, 0), MIST_FUNC_DEF(render, glue_pass, 0),
MIST_FUNC_DEF(render, text_size, 3), MIST_FUNC_DEF(render, text_size, 3),
MIST_FUNC_DEF(render, set_camera, 1), MIST_FUNC_DEF(render, set_camera, 1),
MIST_FUNC_DEF(render, pipeline, 1), MIST_FUNC_DEF(render, make_pipeline, 1),
MIST_FUNC_DEF(render, setuniv3, 2), MIST_FUNC_DEF(render, setuniv3, 2),
MIST_FUNC_DEF(render, setuniv, 2), MIST_FUNC_DEF(render, setuniv, 2),
MIST_FUNC_DEF(render, spdraw, 3), MIST_FUNC_DEF(render, spdraw, 3),

View file

@ -25,6 +25,7 @@ struct texture {
simgui_image_t simgui; simgui_image_t simgui;
int width; int width;
int height; int height;
HMM_Vec3 dimensions;
unsigned char *data; unsigned char *data;
int frames; int frames;
int *delays; int *delays;