more sg javascript options

This commit is contained in:
John Alanbrook 2024-10-03 09:31:06 -05:00
parent 5eac1d03e9
commit 26b42a6747
13 changed files with 266 additions and 144 deletions

View file

@ -95,7 +95,11 @@ game.engine_start = function (s) {
s(); s();
shape.quad = { shape.quad = {
pos: os.make_buffer([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0], 0), pos: os.make_buffer([
0, 0, 0,
0, 1, 0,
1, 0, 0,
1, 1, 0], 0),
verts: 4, verts: 4,
uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2), uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2),
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1), index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
@ -107,11 +111,15 @@ game.engine_start = function (s) {
uv: os.make_buffer([0, 0, 0.5, 1, 1, 0], 2), uv: os.make_buffer([0, 0, 0.5, 1, 1, 0], 2),
verts: 3, verts: 3,
count: 3, count: 3,
index: os.make_buffer([0, 2, 1], 1), index: os.make_buffer([0, 1, 2], 1),
}; };
shape.centered_quad = { shape.centered_quad = {
pos: os.make_buffer([-0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5], 0), pos: os.make_buffer([
-0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5], 0),
verts: 4, verts: 4,
uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2), uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2),
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1), index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),

View file

@ -8,6 +8,188 @@ var cur = {};
cur.images = []; cur.images = [];
cur.samplers = []; cur.samplers = [];
/* A pipeline defines the characteristics of the incoming draw.
{
shader <--- the shader determines the vertex layout,
depth
compare always (never/less/equal/less_equal/greater/not_equal/greater_equal/always)
write false
bias 0
bias_slope_scale 0
bias_clamp 0
stencil
enabled false
front/back
compare always
fail_op keep (zero/replace/incr_clamp/decr_clamp/invert/incr_wrap/decr_wrap)
depth_fail_op keep
pass_op keep
read true
write false
ref 0 (0-255)
color
write_mask rgba
blend
enabled false
src_factor_rgb one
dst_factor_rgb zero
op_rgb add
src_factor_alpha one
dst_factor_alpha zero
op_alpha add
cull none
face_winding cw
alpha_to_coverage false
label ""
*/
var blendop = {
add: 1,
subtract: 2,
reverse_subtract: 3
};
var blendfactor = {
zero: 1,
one: 2,
src_color: 3,
one_minus_src_color: 4,
src_alpha: 5,
one_minus_src_alpha: 6,
dst_color: 7,
one_minus_dst_color: 8,
dst_alpha: 9,
one_minus_dst_alpha: 10,
src_alpha_saturated: 11,
blend_color: 12,
one_minus_blend_color: 13,
blend_alpha: 14,
one_minus_blend_alpha: 15
};
var colormask = {
none: 0x10,
r: 0x1,
g: 0x2,
rg: 0x3,
b: 0x4,
rb: 0x5,
gb: 0x6,
rgb: 0x7,
a: 0x8,
ra: 0x9,
ga: 0xA,
rga: 0xB,
ba: 0xC,
rba: 0xD,
gba: 0xE,
rgba: 0xF
};
var primitive_map = {
point: 1,
line: 2,
linestrip: 3,
triangle: 4,
trianglestrip: 5,
};
var cull_map = {
none: 1,
front: 2,
back: 3,
};
var stencilop = {
keep: 1,
zero: 2,
replace: 3,
incr_clamp: 4,
decr_clamp: 5,
invert: 6,
incr_wrap: 7,
decr_wrap: 8
};
var depth_map = {
off: false,
on: true,
};
var face_map = {
ccw: 1,
cw: 2,
};
var compare = {
never: 1,
less: 2,
equal: 3,
less_equal: 4,
greater: 5,
not_equal: 6,
greater_equal: 7,
always: 8
};
var base_pipeline = {
primitive: primitive_map.triangle,
depth: {
compare: compare.always,
write: false,
bias: 0,
bias_slope_scale: 0,
bias_clamp: 0
},
stencil: {
enabled: false,
front: {
compare: compare.always,
fail_op: stencilop.keep,
depth_fail_op: stencilop.keep,
pass_op: stencilop.keep
},
back: {
compare: compare.always,
fail_op: stencilop.keep,
depth_fail_op: stencilop.keep,
pass_op: stencilop.keep
},
read: true,
write: false,
ref: 0
},
write_mask: colormask.rgba,
blend: {
enabled: false,
src_factor_rgb: blendfactor.one,
dst_factor_rgb: blendfactor.zero,
op_rgb: blendop.add,
src_factor_alpha: blendfactor.one,
dst_factor_alpha: blendfactor.zero,
op_alpha: blendop.add,
},
cull: cull_map.none,
face: face_map.cw,
alpha_to_coverage: false,
label: "scripted pipeline"
}
render.base_pipeline = base_pipeline;
render.colormask = colormask;
render.primitive_map = primitive_map;
render.cull_map = cull_map;
render.stencilop = stencilop;
render.depth_map = depth_map;
render.face_map = face_map;
render.compare = compare;
render.blendfactor = blendfactor;
render.use_pipeline = function use_pipeline(pipeline)
{
}
// When changing a shader, everything must wipe // When changing a shader, everything must wipe
render.use_shader = function use_shader(shader) { render.use_shader = function use_shader(shader) {
if (typeof shader === "string") shader = make_shader(shader); if (typeof shader === "string") shader = make_shader(shader);
@ -72,35 +254,6 @@ var attr_map = {
a_scale: 11, a_scale: 11,
}; };
var blend_map = {
mix: true,
none: false,
};
var primitive_map = {
point: 1,
line: 2,
linestrip: 3,
triangle: 4,
trianglestrip: 5,
};
var cull_map = {
none: 1,
front: 2,
back: 3,
};
var depth_map = {
off: false,
on: true,
};
var face_map = {
cw: 2,
ccw: 1,
};
render.poly_prim = function poly_prim(verts) { render.poly_prim = function poly_prim(verts) {
var index = []; var index = [];
if (verts.length < 1) return undefined; if (verts.length < 1) return undefined;
@ -121,18 +274,6 @@ render.poly_prim = function poly_prim(verts) {
}; };
}; };
function shader_directive(shader, name, map) {
var reg = new RegExp(`#${name}.*`, "g");
var mat = shader.match(reg);
if (!mat) return undefined;
reg = new RegExp(`#${name}\s*`, "g");
var ff = mat.map(d => d.replace(reg, ""))[0].trim();
if (map) return map[ff];
return ff;
}
var uni_globals = { var uni_globals = {
time(stage, slot) { time(stage, slot) {
render.setuniv(stage, slot, profile.secs(profile.now())); render.setuniv(stage, slot, profile.secs(profile.now()));
@ -176,7 +317,7 @@ 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); 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;
@ -202,17 +343,6 @@ function create_shader_obj(file) {
files.push(filez); files.push(filez);
} }
var blend = shader_directive(shader, "blend", blend_map);
var primitive = shader_directive(shader, "primitive", primitive_map);
var cull = shader_directive(shader, "cull", cull_map);
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;
shader = shader.replace(/uniform\s+(\w+)\s+(\w+);/g, "uniform _$2 { $1 $2; };"); shader = shader.replace(/uniform\s+(\w+)\s+(\w+);/g, "uniform _$2 { $1 $2; };");
shader = shader.replace(/(texture2D|sampler) /g, "uniform $1 "); shader = shader.replace(/(texture2D|sampler) /g, "uniform $1 ");
@ -251,13 +381,7 @@ function create_shader_obj(file) {
add_code(obj.fs); add_code(obj.fs);
obj.blend = blend; obj.indexed = true;
obj.cull = cull;
obj.primitive = primitive;
obj.depth = depth;
obj.face = face;
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) {
@ -320,7 +444,7 @@ function make_shader(shader) {
var shaderobj = json.decode(io.slurp(writejson)); var shaderobj = json.decode(io.slurp(writejson));
var obj = shaderobj[os.sys()]; var obj = shaderobj[os.sys()];
obj.pipe = render.pipeline(obj); 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);
return obj; return obj;
@ -331,7 +455,7 @@ function make_shader(shader) {
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); 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);
@ -758,7 +882,6 @@ render.floodmask = function(val)
{ {
render.use_shader(polyshader); render.use_shader(polyshader);
render.use_mat({}); render.use_mat({});
render.draw(
} }
render.mask = function mask(tex, pos, scale, rotation = 0) render.mask = function mask(tex, pos, scale, rotation = 0)

View file

@ -1,8 +1,3 @@
#blend mix
#depth off
#primitive triangle
#cull none
@vs vs @vs vs
in vec3 a_pos; in vec3 a_pos;
in vec2 a_uv; in vec2 a_uv;

View file

@ -1,6 +1,3 @@
#depth off
#blend mix
@vs vs @vs vs
in vec2 a_pos; in vec2 a_pos;
in vec2 a_uv; in vec2 a_uv;

View file

@ -1,6 +1,3 @@
#depth off
#blend mix
@vs vs @vs vs
in vec2 a_pos; in vec2 a_pos;
in vec2 a_uv; in vec2 a_uv;

View file

@ -1,8 +1,3 @@
#blend mix
#primitive triangle
#cull none
#depth off
@vs vert @vs vert
in vec3 a_pos; in vec3 a_pos;

View file

@ -1,5 +1,3 @@
#stencil write
@block vert @block vert
uniform vec4 rect; uniform vec4 rect;
@ -16,7 +14,7 @@ void frag()
{ {
color = texture(sampler2D(diffuse,smp), uv); color = texture(sampler2D(diffuse,smp), uv);
if (color.a == 0.0) discard; if (color.a == 0.0) discard;
color = vec4(1.0); color = vec4(0.0);
} }
@end @end

View file

@ -1,8 +1,3 @@
#depth off
#blend mix
#primitive triangle
#cull none
@vs vs @vs vs
in vec3 a_pos; in vec3 a_pos;
uniform mat4 vp; uniform mat4 vp;

View file

@ -1,8 +1,3 @@
#depth off
#blend mix
#primitive triangle
#cull none
@vs vs @vs vs
in vec3 a_pos; in vec3 a_pos;
uniform mat4 vp; uniform mat4 vp;

View file

@ -1,5 +1,3 @@
#cull back
@vs vs @vs vs
in vec3 a_pos; in vec3 a_pos;
in vec2 a_uv; in vec2 a_uv;

View file

@ -1,8 +1,3 @@
#blend mix
#depth off
#primitive triangle
#cull none
@vs vs @vs vs
in vec3 a_pos; in vec3 a_pos;
in vec2 a_uv; in vec2 a_uv;

View file

@ -86,6 +86,12 @@ void sg_buffer_free(sg_buffer *b)
free(b); free(b);
} }
void sg_pipeline_free(sg_pipeline *p)
{
sg_destroy_pipeline(*p);
free(p);
}
void cpShape_free(cpShape *s) void cpShape_free(cpShape *s)
{ {
if (cpSpaceContainsShape(space, s)) if (cpSpaceContainsShape(space, s))
@ -115,6 +121,7 @@ QJSCLASS(warp_gravity)
QJSCLASS(warp_damp) QJSCLASS(warp_damp)
QJSCLASS(window) QJSCLASS(window)
QJSCLASS(sg_buffer) QJSCLASS(sg_buffer)
QJSCLASS(sg_pipeline)
QJSCLASS(datastream) QJSCLASS(datastream)
QJSCLASS(cpShape) QJSCLASS(cpShape)
QJSCLASS(cpConstraint) QJSCLASS(cpConstraint)
@ -757,6 +764,8 @@ JSC_CCALL(render_glue_pass,
.colors[0] = { .colors[0] = {
.load_action = SG_LOADACTION_CLEAR, .load_action = SG_LOADACTION_CLEAR,
.clear_value = (sg_color){0,0,0,1} .clear_value = (sg_color){0,0,0,1}
},
.stencil = { .clear_value = 1
} }
} }
}); });
@ -953,41 +962,73 @@ sg_vertex_layout_state js2layout(JSValue v)
return st; return st;
} }
sg_depth_state js2depth(JSValue v)
{
sg_depth_state depth = {0};
depth.compare = js2number(js_getpropstr(v, "compare"));
depth.write_enabled = js2boolean(js_getpropstr(v, "write"));
depth.bias = js2number(js_getpropstr(v, "bias"));
depth.bias_slope_scale = js2number(js_getpropstr(v, "bias_slope_scale"));
depth.bias_clamp = js2number(js_getpropstr(v, "bias_clamp"));
return depth;
}
sg_stencil_face_state js2face_state(JSValue v)
{
sg_stencil_face_state face = {0};
face.compare = js2number(js_getpropstr(v, "compare"));
face.fail_op = js2number(js_getpropstr(v, "fail"));
face.depth_fail_op = js2number(js_getpropstr(v, "depth_fail"));
face.pass_op = js2number(js_getpropstr(v, "pass_op"));
return face;
}
sg_stencil_state js2stencil(JSValue v)
{
sg_stencil_state stencil = {0};
stencil.enabled = js2boolean(js_getpropstr(v, "enabled"));
stencil.read_mask = js2boolean(js_getpropstr(v, "read")) ? 0xFF : 0x00;
stencil.write_mask = js2boolean(js_getpropstr(v, "write")) ? 0xFF : 0x00;
stencil.front = js2face_state(js_getpropstr(v, "front"));
stencil.back = js2face_state(js_getpropstr(v, "back"));
return stencil;
}
#define GETNUMVALUE(STRUCT, NAME) STRUCT.NAME = js2number(js_getpropstr(v, #NAME));
sg_blend_state js2blend(JSValue v)
{
sg_blend_state blend = {0};
blend.enabled = js2boolean(js_getpropstr(v, "enabled"));
GETNUMVALUE(blend, src_factor_rgb);
GETNUMVALUE(blend, dst_factor_rgb);
GETNUMVALUE(blend, op_rgb);
GETNUMVALUE(blend, src_factor_alpha);
GETNUMVALUE(blend, dst_factor_alpha);
GETNUMVALUE(blend, op_alpha);
return blend;
}
JSC_CCALL(render_pipeline, JSC_CCALL(render_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]);
p.cull_mode = js2number(js_getpropstr(argv[0], "cull"));
p.primitive_type = js2number(js_getpropstr(argv[0], "primitive")); p.primitive_type = js2number(js_getpropstr(argv[0], "primitive"));
//p.face_winding = js2number(js_getpropstr(argv[0], "face"));
p.face_winding = 1;
if (js2boolean(js_getpropstr(argv[0], "indexed"))) if (js2boolean(js_getpropstr(argv[0], "indexed")))
p.index_type = SG_INDEXTYPE_UINT16; p.index_type = SG_INDEXTYPE_UINT16;
if (js2boolean(js_getpropstr(argv[0], "blend")))
p.colors[0].blend = blend_trans;
int depth = js2boolean(js_getpropstr(argv[0], "depth"));
if (depth) {
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); JSValue pipe = argv[1];
p.primitive_type = js2number(js_getpropstr(pipe, "primitive"));
p.cull_mode = js2number(js_getpropstr(pipe, "cull"));
p.face_winding = js2number(js_getpropstr(pipe, "face"));
p.colors[0].blend = js2blend(js_getpropstr(pipe, "blend"));
p.colors[0].write_mask = js2number(js_getpropstr(pipe, "write_mask"));
p.alpha_to_coverage_enabled = js2boolean(js_getpropstr(pipe, "alpha_to_coverage"));
p.depth = js2depth(js_getpropstr(pipe, "depth"));
p.stencil = js2stencil(js_getpropstr(pipe, "stencil"));
return number2js(pipe.id); sg_pipeline *g = malloc(sizeof(*g));
*g = sg_make_pipeline(&p);
return sg_pipeline2js(g);
) )
JSC_CCALL(render_setuniv, JSC_CCALL(render_setuniv,
@ -1185,11 +1226,7 @@ JSC_CCALL(render_spdraw,
sg_draw(js2number(argv[0]),js2number(argv[1]),js2number(argv[2])); sg_draw(js2number(argv[0]),js2number(argv[1]),js2number(argv[2]));
) )
JSC_CCALL(render_setpipeline, JSC_CCALL(render_setpipeline, sg_apply_pipeline(*js2sg_pipeline(argv[0]));)
sg_pipeline p = {0};
p.id = js2number(argv[0]);
sg_apply_pipeline(p);
)
JSC_CCALL(render_screencolor, JSC_CCALL(render_screencolor,
texture *t = calloc(sizeof(*t), 1); texture *t = calloc(sizeof(*t), 1);

View file

@ -179,9 +179,6 @@ void render_init() {
.depth = { .depth = {
.load_action = SG_LOADACTION_CLEAR, .load_action = SG_LOADACTION_CLEAR,
.clear_value = 1 .clear_value = 1
},
.stencil = {
.clear_value = 1
} }
}; };
@ -264,11 +261,3 @@ float *rgba2floats(float *r, struct rgba c)
r[3] = (float)c.a / RGBA_MAX; r[3] = (float)c.a / RGBA_MAX;
return r; return r;
} }
sg_blend_state blend_trans = {
.enabled = true,
.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.src_factor_alpha = SG_BLENDFACTOR_SRC_ALPHA,
.dst_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA
};