Sprite, transform, render overhaul

This commit is contained in:
John Alanbrook 2024-05-02 13:52:28 -05:00
parent 41eadce13e
commit e86e126894
16 changed files with 237 additions and 499 deletions

View file

@ -13,6 +13,10 @@ this.view2world = function(pos) {
pos = pos.scale(this.zoom); pos = pos.scale(this.zoom);
pos = pos.add(this.pos); pos = pos.add(this.pos);
} }
if (window.mode === window.modetypes.expand) {
pos = pos.sub(window.size.scale(0.5));
pos = pos.scale([window.rendersize.x/window.size.x, window.rendersize.y/window.size.y]);
}
return pos; return pos;
}; };
this.world2view = function(pos) { this.world2view = function(pos) {
@ -25,6 +29,9 @@ this.world2view = function(pos) {
pos = pos.sub(this.pos); pos = pos.sub(this.pos);
pos = pos.scale(1/this.zoom); pos = pos.scale(1/this.zoom);
pos = pos.add(window.size.scale(0.5)); pos = pos.add(window.size.scale(0.5));
}
if (window.mode === window.modetypes.expand) {
} }
return pos; return pos;
}; };

View file

@ -124,9 +124,9 @@ render.text = function(str, pos, size = 1, color = Color.white, wrap = -1, ancho
}; };
render.image = function(tex, pos, rotation = 0, color = Color.white, dimensions = [tex.width, tex.height]) { render.image = function(tex, pos, rotation = 0, color = Color.white, dimensions = [tex.width, tex.height]) {
var scale = [dimensions.x/tex.width, dimensions.y/tex.height]; //var scale = [dimensions.x/tex.width, dimensions.y/tex.height];
gui.img(tex,pos, scale, 0.0, false, [0.0,0.0], color); //gui.img(tex,pos, scale, 0.0, false, [0.0,0.0], color);
return bbox.fromcwh([0,0], [tex.width,tex.height]); //return bbox.fromcwh([0,0], [tex.width,tex.height]);
} }
render.fontcache = {}; render.fontcache = {};

View file

@ -30,84 +30,9 @@ static void processnode();
static void processmesh(); static void processmesh();
static void processtexture(); static void processtexture();
static sg_pipeline model_pipe;
static sg_pipeline model_st_pipe;
struct bone_weights {
char b1;
char b2;
char b3;
char b4;
};
struct joints {
char j1;
char j2;
char j3;
char j4;
};
#define MAT_POS 0
#define MAT_UV 1
#define MAT_NORM 2
#define MAT_BONE 3
#define MAT_WEIGHT 4
#define MAT_COLOR 5
static cgltf_data *cdata; static cgltf_data *cdata;
static char *cpath; static char *cpath;
struct joints joint_nul = { 0, 0, 0, 0 };
struct bone_weights weight_nul = {0, 0, 0, 0};
void model_init() {
model_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = sg_make_shader(unlit_shader_desc(sg_query_backend())),
.layout = {
.attrs = {
[MAT_POS].format = SG_VERTEXFORMAT_FLOAT3,
[MAT_UV].format = SG_VERTEXFORMAT_USHORT2N,
[MAT_UV].buffer_index = MAT_UV,
[MAT_NORM].format = SG_VERTEXFORMAT_UINT10_N2,
[MAT_NORM].buffer_index = MAT_NORM,
[MAT_WEIGHT] = {
.format = SG_VERTEXFORMAT_UBYTE4N,
.buffer_index = MAT_WEIGHT
},
[MAT_BONE] = {
.format = SG_VERTEXFORMAT_UBYTE4,
.buffer_index = MAT_BONE
}
},
},
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
model_st_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = sg_make_shader(unlit_st_shader_desc(sg_query_backend())),
.layout = {
.attrs = {
[ATTR_vs_st_a_pos].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_vs_st_a_uv] = {
.format = SG_VERTEXFORMAT_USHORT2N,
.buffer_index = MAT_UV
},
[ATTR_vs_st_a_norm] = {
.format = SG_VERTEXFORMAT_UINT10_N2,
.buffer_index = MAT_NORM
}
},
},
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
}
cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t) cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t)
{ {
for (int i = 0; i < p->attributes_count; i++) { for (int i = 0; i < p->attributes_count; i++) {
@ -184,6 +109,24 @@ sg_buffer normal_floats(float *f, int verts, int comp)
}); });
} }
sg_buffer ubyten_buffer(float *f, int v, int c)
{
unsigned char b[v*c];
for (int i = 0; i < (v*c); i++)
b[i] = f[i]*255;
return sg_make_buffer(&(sg_buffer_desc){.data=SG_RANGE(b)});
}
sg_buffer ubyte_buffer(float *f, int v, int c)
{
unsigned char b[v*c];
for (int i = 0; i < (v*c); i++)
b[i] = f[i];
return sg_make_buffer(&(sg_buffer_desc){.data=SG_RANGE(b)});
}
sg_buffer joint_buf(float *f, int v, int c) sg_buffer joint_buf(float *f, int v, int c)
{ {
char joints[v*c]; char joints[v*c];
@ -275,14 +218,15 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
break; break;
case cgltf_attribute_type_color: case cgltf_attribute_type_color:
retp.color = ubyten_buffer(vs,verts,comp);
break; break;
case cgltf_attribute_type_weights: case cgltf_attribute_type_weights:
retp.weight = weight_buf(vs, verts, comp); retp.weight = ubyten_buffer(vs, verts, comp);
break; break;
case cgltf_attribute_type_joints: case cgltf_attribute_type_joints:
retp.bone = joint_buf(vs, verts, comp); retp.bone = ubyte_buffer(vs, verts, comp);
break; break;
case cgltf_attribute_type_texcoord: case cgltf_attribute_type_texcoord:
@ -294,29 +238,31 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
case cgltf_attribute_type_custom: case cgltf_attribute_type_custom:
break; break;
case cgltf_attribute_type_max_enum: case cgltf_attribute_type_max_enum:
break; break;
} }
} }
/*
if (!retp.bind.vertex_buffers[JOINT].id) { if (!retp.bone.id) {
struct joints jnts[retp.idx_count]; char joints[retp.idx_count*4];
for (int i = 0; i < retp.idx_count; i++) memset(joints, 0, retp.idx_count*4);
jnts[i] = joint_nul; retp.bone = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(joints)});
retp.bind.vertex_buffers[JOINT] = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(jnts)});
} }
if (!retp.bind.vertex_buffers[WEIGHT].id) { if (!retp.weight.id) {
struct bone_weights v[retp.idx_count]; char weights[retp.idx_count*4];
for (int i = 0; i < retp.idx_count; i++) memset(weights,0,retp.idx_count*4);
v[i] = weight_nul; retp.weight = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(weights)});
}
retp.bind.vertex_buffers[WEIGHT] = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(v)});
if (!retp.color.id) {
char colors[retp.idx_count*4];
memset(colors,0,retp.idx_count*4);
retp.color = sg_make_buffer(&(sg_buffer_desc) { .data = SG_RANGE(colors) });
} }
*/
if (retp.norm.id) { if (!retp.norm.id) {
YughInfo("Making normals."); YughInfo("Making normals.");
cgltf_attribute *pa = get_attr_type(prim, cgltf_attribute_type_position); cgltf_attribute *pa = get_attr_type(prim, cgltf_attribute_type_position);
int n = cgltf_accessor_unpack_floats(pa->data, NULL,0); int n = cgltf_accessor_unpack_floats(pa->data, NULL,0);
@ -535,26 +481,19 @@ void model_draw_go(model *model, gameobject *go, gameobject *cam)
animation_run(&model->anim, apptime()); animation_run(&model->anim, apptime());
skin *sk = &model->skin; skin *sk = &model->skin;
if (arrlen(sk->joints) == 0) { for (int i = 0; i < arrlen(sk->joints); i++) {
sg_apply_pipeline(model_st_pipe); md5joint *md = sk->joints[i];
} else { HMM_Mat4 local = HMM_M4TRS(md->pos.xyz, md->rot, md->scale.xyz);
sg_apply_pipeline(model_pipe); if (md->parent)
local = HMM_MulM4(md->parent->t, local);
for (int i = 0; i < arrlen(sk->joints); i++) { md->t = local;
md5joint *md = sk->joints[i]; sk->binds[i] = HMM_MulM4(md->t, sk->invbind[i]);
HMM_Mat4 local = HMM_M4TRS(md->pos.xyz, md->rot, md->scale.xyz);
if (md->parent)
local = HMM_MulM4(md->parent->t, local);
md->t = local;
sk->binds[i] = HMM_MulM4(md->t, sk->invbind[i]);
}
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_skinv, &(sg_range){
.ptr = sk->binds,
.size = sizeof(*sk->binds)*50
});
} }
/*sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_skinv, &(sg_range){
sg_apply_pipeline(model_st_pipe); .ptr = sk->binds,
.size = sizeof(*sk->binds)*50
});
*/
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vp.e)); sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vp.e));
float ambient[4] = {1.0,1.0,1.0,1.0}; float ambient[4] = {1.0,1.0,1.0,1.0};

View file

@ -8,7 +8,13 @@
#include "anim.h" #include "anim.h"
#include "texture.h" #include "texture.h"
extern HMM_Vec3 eye; #define MAT_POS 0
#define MAT_UV 1
#define MAT_NORM 2
#define MAT_BONE 3
#define MAT_WEIGHT 4
#define MAT_COLOR 5
#define MAT_TAN 6
typedef struct material { typedef struct material {
texture *diffuse; texture *diffuse;
@ -31,15 +37,12 @@ typedef struct primitive {
sg_buffer uv; sg_buffer uv;
sg_buffer bone; sg_buffer bone;
sg_buffer weight; sg_buffer weight;
sg_buffer color;
sg_buffer idx; sg_buffer idx;
material *mat; material *mat;
uint32_t idx_count; uint32_t idx_count;
} primitive; } primitive;
typedef struct shader {
sg_pipeline pipeline;
} shader;
/* A single mesh */ /* A single mesh */
typedef struct mesh { typedef struct mesh {
primitive *primitives; primitive *primitives;

View file

@ -221,6 +221,7 @@ typedef union HMM_Vec2 {
}; };
float Elements[2]; float Elements[2];
float e[2];
cpVect cp; cpVect cp;
@ -404,6 +405,7 @@ typedef union HMM_Mat3 {
typedef union HMM_Mat4 { typedef union HMM_Mat4 {
float Elements[4][4]; float Elements[4][4];
HMM_Vec4 Columns[4]; HMM_Vec4 Columns[4];
HMM_Vec4 col[4];
float e[4][4]; float e[4][4];
float em[16]; float em[16];
} HMM_Mat4; } HMM_Mat4;

View file

@ -63,6 +63,8 @@ const char *js2str(JSValue v) {
void jsfreestr(const char *s) { JS_FreeCString(js, s); } void jsfreestr(const char *s) { JS_FreeCString(js, s); }
QJSCLASS(gameobject) QJSCLASS(gameobject)
QJSCLASS(transform3d)
QJSCLASS(transform2d)
QJSCLASS(emitter) QJSCLASS(emitter)
QJSCLASS(dsp_node) QJSCLASS(dsp_node)
QJSCLASS(texture) QJSCLASS(texture)
@ -141,6 +143,7 @@ JSValue ptr2js(void *ptr) {
} }
int js_arrlen(JSValue v) { int js_arrlen(JSValue v) {
if (JS_IsUndefined(v)) return 0;
int len; int len;
JS_ToInt32(js, &len, js_getpropstr( v, "length")); JS_ToInt32(js, &len, js_getpropstr( v, "length"));
return len; return len;
@ -332,6 +335,22 @@ JSValue vec32js(HMM_Vec3 v)
return array; return array;
} }
HMM_Vec4 js2vec4(JSValue v)
{
HMM_Vec4 v4;
for (int i = 0; i < 4; i++)
v4.e[i] = js2number(js_getpropidx(v,i));
return v4;
}
JSValue vec42js(HMM_Vec4 v)
{
JSValue array = JS_NewArray(js);
for (int i = 0; i < 4; i++)
js_setprop_num(array,i,number2js(v.e[i]));
return array;
}
cpBitmask js2bitmask(JSValue v) { cpBitmask js2bitmask(JSValue v) {
cpBitmask a; cpBitmask a;
JS_ToUint32(js, &a, v); JS_ToUint32(js, &a, v);
@ -624,11 +643,10 @@ JSC_CCALL(render_clear_color,
pass_action.colors[0].clear_value = c; pass_action.colors[0].clear_value = c;
) )
JSC_CCALL(render_set_sprite_tex, sprite_tex(js2texture(argv[0]))) sg_shader js2shader(JSValue v)
{
JSC_CCALL(render_pipeline,
sg_shader_desc desc = {0}; sg_shader_desc desc = {0};
JSValue prog = argv[0]; JSValue prog = v;
JSValue vs = js_getpropstr(prog, "vs"); JSValue vs = js_getpropstr(prog, "vs");
JSValue fs = js_getpropstr(prog, "fs"); JSValue fs = js_getpropstr(prog, "fs");
char *vsf = js2str(js_getpropstr(vs, "code")); char *vsf = js2str(js_getpropstr(vs, "code"));
@ -683,53 +701,107 @@ JSC_CCALL(render_pipeline,
desc.fs.image_sampler_pairs[0].sampler_slot = 0; desc.fs.image_sampler_pairs[0].sampler_slot = 0;
} }
sg_shader sgshader = sg_make_shader(&desc); sg_shader sh = sg_make_shader(&desc);
sg_pipeline_desc pdesc = {0};
pdesc.shader = sgshader;
pdesc.cull_mode = SG_CULLMODE_FRONT;
pdesc.depth.write_enabled = true;
pdesc.depth.compare = SG_COMPAREFUNC_LESS_EQUAL;
pdesc.layout.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
pdesc.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
//pdesc.colors[0].blend = blend_trans;
sg_pipeline pipe = sg_make_pipeline(&pdesc);
jsfreestr(vsf); jsfreestr(vsf);
jsfreestr(fsf); jsfreestr(fsf);
jsfreestr(vsmain); jsfreestr(vsmain);
jsfreestr(fsmain); jsfreestr(fsmain);
return sh;
}
JSC_CCALL(render_pipeline3d,
sg_shader sgshader = js2shader(argv[0]);
sg_pipeline_desc p = {0};
p.shader = sgshader;
sg_vertex_layout_state st = {0};
st.attrs[MAT_POS].format = SG_VERTEXFORMAT_FLOAT3;
st.attrs[MAT_UV].format = SG_VERTEXFORMAT_USHORT2N;
st.attrs[MAT_UV].buffer_index = MAT_UV;
st.attrs[MAT_NORM].format = SG_VERTEXFORMAT_UINT10_N2;
st.attrs[MAT_NORM].buffer_index = MAT_NORM;
st.attrs[MAT_WEIGHT].format = SG_VERTEXFORMAT_UBYTE4N;
st.attrs[MAT_WEIGHT].buffer_index = MAT_WEIGHT;
st.attrs[MAT_BONE].format = SG_VERTEXFORMAT_UBYTE4;
st.attrs[MAT_BONE].buffer_index = MAT_BONE;
st.attrs[MAT_COLOR].format = SG_VERTEXFORMAT_UBYTE4N;
st.attrs[MAT_COLOR].buffer_index = MAT_COLOR;
p.layout = st;
p.index_type = SG_INDEXTYPE_UINT16;
p.depth.write_enabled = true;
p.depth.compare = SG_COMPAREFUNC_LESS_EQUAL;
p.cull_mode = SG_CULLMODE_FRONT;
sg_pipeline pipe = sg_make_pipeline(&p);
return number2js(pipe.id); return number2js(pipe.id);
) )
JSC_CCALL(render_spritepipe, pip_sprite.id = js2number(argv[0])) JSC_CCALL(render_pipeline,
sg_shader sgshader = js2shader(argv[0]);
sg_pipeline_desc pdesc = {0};
pdesc.shader = sgshader;
pdesc.cull_mode = SG_CULLMODE_FRONT;
pdesc.layout.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
pdesc.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
if (js2boolean(js_getpropstr(argv[0], "blend")))
pdesc.colors[0].blend = blend_trans;
sg_pipeline pipe = sg_make_pipeline(&pdesc);
JSC_CCALL(render_texture, return number2js(pipe.id);
tex_draw(js2texture(argv[0]), js2gameobject(argv[1]));
) )
JSC_CCALL(render_setuniv, JSC_CCALL(render_setuniv,
float f = js2number(argv[0]); float f = js2number(argv[2]);
sg_apply_uniforms(SG_SHADERSTAGE_FS, js2number(argv[1]), SG_RANGE_REF(f)); sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(f));
)
JSC_CCALL(render_setuniv2,
HMM_Vec2 v = js2vec2(argv[2]);
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(v.e));
) )
JSC_CCALL(render_setuniv3, JSC_CCALL(render_setuniv3,
HMM_Vec3 v = js2vec3(argv[0]); HMM_Vec3 v = js2vec3(argv[2]);
sg_apply_uniforms(SG_SHADERSTAGE_FS, js2number(argv[1]), SG_RANGE_REF(v.e)); sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(v.e));
) )
JSC_CCALL(render_setuniv4,
HMM_Vec4 v = js2vec4(argv[2]);
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(v.e));
)
JSC_CCALL(render_setuniproj,
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(useproj));
)
JSC_CCALL(render_setunim4,
HMM_Mat4 m = transform2d2mat4(js2transform2d(argv[2]));
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
);
JSC_CCALL(render_spdraw, JSC_CCALL(render_spdraw,
gameobject *go = js2gameobject(argv[0]);
HMM_Mat4 m = transform2d2mat4(go2t(go));
sg_apply_uniforms(SG_SHADERSTAGE_VS, 1, SG_RANGE_REF(m.e));
sg_bindings bind = {0}; sg_bindings bind = {0};
bind.vertex_buffers[0] = sprite_quad; bind.vertex_buffers[0] = sprite_quad;
for (int i = 0; i < js_arrlen(argv[1]); i++) {
bind.fs.images[i] = js2texture(js_getpropidx(argv[1], i))->id;
bind.fs.samplers[i] = std_sampler;
}
sg_apply_bindings(&bind); sg_apply_bindings(&bind);
sg_draw(0,4,1); sg_draw(0,4,1);
) )
JSC_CCALL(render_setpipeline,
sg_pipeline p = {0};
p.id = js2number(argv[0]);
sg_apply_pipeline(p);
)
static const JSCFunctionListEntry js_render_funcs[] = { static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, grid, 3), MIST_FUNC_DEF(render, grid, 3),
MIST_FUNC_DEF(render, point, 3), MIST_FUNC_DEF(render, point, 3),
@ -744,13 +816,16 @@ static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, set_camera, 0), MIST_FUNC_DEF(render, set_camera, 0),
MIST_FUNC_DEF(render, hud_res, 1), MIST_FUNC_DEF(render, hud_res, 1),
MIST_FUNC_DEF(render, clear_color, 1), MIST_FUNC_DEF(render, clear_color, 1),
MIST_FUNC_DEF(render, set_sprite_tex, 1),
MIST_FUNC_DEF(render, pipeline, 1), MIST_FUNC_DEF(render, pipeline, 1),
MIST_FUNC_DEF(render, spritepipe, 1), MIST_FUNC_DEF(render, pipeline3d, 1),
MIST_FUNC_DEF(render, texture, 2),
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, 1) MIST_FUNC_DEF(render, spdraw, 2),
MIST_FUNC_DEF(render, setuniproj, 2),
MIST_FUNC_DEF(render, setunim4, 3),
MIST_FUNC_DEF(render, setuniv2, 2),
MIST_FUNC_DEF(render, setuniv4, 2),
MIST_FUNC_DEF(render, setpipeline, 1)
}; };
JSC_CCALL(gui_flush, text_flush(&useproj)); JSC_CCALL(gui_flush, text_flush(&useproj));
@ -768,21 +843,12 @@ JSC_CCALL(gui_text,
return ret; return ret;
) )
JSC_CCALL(gui_img,
transform2d t;
t.pos = js2vec2(argv[1]);
t.scale = js2vec2(argv[2]);
t.angle = js2number(argv[3]);
gui_draw_img(js2texture(argv[0]), t, js2boolean(argv[4]), js2vec2(argv[5]), 1.0, js2color(argv[6]));
)
JSC_CCALL(gui_font_set, font_set(js2font(argv[0]))) JSC_CCALL(gui_font_set, font_set(js2font(argv[0])))
static const JSCFunctionListEntry js_gui_funcs[] = { static const JSCFunctionListEntry js_gui_funcs[] = {
MIST_FUNC_DEF(gui, flush, 0), MIST_FUNC_DEF(gui, flush, 0),
MIST_FUNC_DEF(gui, scissor, 4), MIST_FUNC_DEF(gui, scissor, 4),
MIST_FUNC_DEF(gui, text, 6), MIST_FUNC_DEF(gui, text, 6),
MIST_FUNC_DEF(gui, img, 7),
MIST_FUNC_DEF(gui, font_set,1) MIST_FUNC_DEF(gui, font_set,1)
}; };
@ -1178,6 +1244,16 @@ static const JSCFunctionListEntry js_emitter_funcs[] = {
CGETSET_ADD(emitter, texture), CGETSET_ADD(emitter, texture),
}; };
JSC_GETSET(transform2d, pos, vec2)
JSC_GETSET(transform2d, scale, vec2)
JSC_GETSET(transform2d, angle, number)
static const JSCFunctionListEntry js_transform2d_funcs[] = {
CGETSET_ADD(transform2d, pos),
CGETSET_ADD(transform2d, scale),
CGETSET_ADD(transform2d, angle)
};
JSC_GETSET(dsp_node, pass, boolean) JSC_GETSET(dsp_node, pass, boolean)
JSC_GETSET(dsp_node, off, boolean) JSC_GETSET(dsp_node, off, boolean)
JSC_GETSET(dsp_node, gain, number) JSC_GETSET(dsp_node, gain, number)
@ -1430,22 +1506,12 @@ static const JSCFunctionListEntry js_pshape_funcs[] = {
JSC_GETSET(sprite, color, color) JSC_GETSET(sprite, color, color)
JSC_GETSET(sprite, emissive, color) JSC_GETSET(sprite, emissive, color)
JSC_GETSET(sprite, pos, vec2)
JSC_GETSET(sprite, scale, vec2)
JSC_GETSET(sprite, angle, number)
JSC_GETSET(sprite, spriteoffset, vec2) JSC_GETSET(sprite, spriteoffset, vec2)
JSC_GETSET(sprite, spritesize, vec2)
JSC_CCALL(sprite_draw, sprite_draw(js2sprite(this), js2gameobject(argv[0])))
static const JSCFunctionListEntry js_sprite_funcs[] = { static const JSCFunctionListEntry js_sprite_funcs[] = {
CGETSET_ADD(sprite,pos),
CGETSET_ADD(sprite,scale),
CGETSET_ADD(sprite,angle),
CGETSET_ADD(sprite,color), CGETSET_ADD(sprite,color),
CGETSET_ADD(sprite,emissive), CGETSET_ADD(sprite,emissive),
CGETSET_ADD(sprite, spriteoffset), CGETSET_ADD(sprite, spriteoffset),
CGETSET_ADD(sprite, spritesize),
MIST_FUNC_DEF(sprite, draw, 1)
}; };
JSC_GET(texture, width, number) JSC_GET(texture, width, number)
@ -1649,12 +1715,14 @@ JSC_SCALL(os_make_texture,
JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1])))) JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1]))))
JSC_SCALL(os_system, system(str); ) JSC_CCALL(os_make_transform2d,
return transform2d2js(make_transform2d());
)
JSC_SCALL(os_system, return number2js(system(str)); )
JSC_SCALL(os_make_model, ret = model2js(model_make(str))) JSC_SCALL(os_make_model, ret = model2js(model_make(str)))
JSC_CCALL(os_sprite_pipe, sprite_pipe())
static const JSCFunctionListEntry js_os_funcs[] = { static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os,sprite,1), MIST_FUNC_DEF(os,sprite,1),
MIST_FUNC_DEF(os, cwd, 0), MIST_FUNC_DEF(os, cwd, 0),
@ -1674,7 +1742,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, make_texture, 1), MIST_FUNC_DEF(os, make_texture, 1),
MIST_FUNC_DEF(os, make_font, 2), MIST_FUNC_DEF(os, make_font, 2),
MIST_FUNC_DEF(os, make_model, 1), MIST_FUNC_DEF(os, make_model, 1),
MIST_FUNC_DEF(os, sprite_pipe, 0) MIST_FUNC_DEF(os, make_transform2d, 0),
}; };
#include "steam.h" #include "steam.h"
@ -1683,10 +1751,13 @@ void ffi_load() {
globalThis = JS_GetGlobalObject(js); globalThis = JS_GetGlobalObject(js);
QJSCLASSPREP(ptr); QJSCLASSPREP(ptr);
QJSCLASSPREP(transform3d);
QJSGLOBALCLASS(os); QJSGLOBALCLASS(os);
QJSCLASSPREP_FUNCS(gameobject); QJSCLASSPREP_FUNCS(gameobject);
QJSCLASSPREP_FUNCS(transform2d);
QJSCLASSPREP_FUNCS(dsp_node); QJSCLASSPREP_FUNCS(dsp_node);
QJSCLASSPREP_FUNCS(emitter); QJSCLASSPREP_FUNCS(emitter);
QJSCLASSPREP_FUNCS(warp_gravity); QJSCLASSPREP_FUNCS(warp_gravity);

View file

@ -257,7 +257,6 @@ void render_init() {
font_init(); font_init();
debugdraw_init(); debugdraw_init();
sprite_initialize();
model_init(); model_init();

View file

@ -7,141 +7,13 @@
#include "texture.h" #include "texture.h"
#include "HandmadeMath.h" #include "HandmadeMath.h"
#include "sprite.sglsl.h"
#include "9slice.sglsl.h"
sg_pipeline pip_sprite;
sg_bindings bind_sprite;
static sg_shader slice9_shader;
static sg_pipeline slice9_pipe;
static sg_bindings slice9_bind;
struct slice9_vert {
HMM_Vec2 pos;
struct uv_n uv;
unsigned short border[4];
HMM_Vec2 scale;
struct rgba color;
};
sprite *sprite_make() sprite *sprite_make()
{ {
sprite *sp = calloc(sizeof(*sp), 1); sprite *sp = calloc(sizeof(*sp), 1);
sp->pos = v2zero;
sp->scale = v2one;
sp->angle = 0;
sp->color = color_white; sp->color = color_white;
sp->emissive = color_clear; sp->emissive = color_clear;
sp->spritesize = v2one; sp->rect = (HMM_Vec4){0,0,1,1};
sp->spriteoffset = v2zero;
return sp; return sp;
} }
void sprite_free(sprite *sprite) { free(sprite); } void sprite_free(sprite *sprite) { free(sprite); }
static texture *loadedtex;
static int sprite_count = 0;
void sprite_initialize() {
pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){
.shader = sg_make_shader(sprite_shader_desc(sg_query_backend())),
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT2
},
},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
.label = "sprite pipeline",
.colors[0].blend = blend_trans,
});
bind_sprite.vertex_buffers[0] = sprite_quad;
bind_sprite.fs.samplers[0] = std_sampler;
slice9_shader = sg_make_shader(slice9_shader_desc(sg_query_backend()));
slice9_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = slice9_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT2,
[1].format = SG_VERTEXFORMAT_FLOAT2,
[2].format = SG_VERTEXFORMAT_USHORT4N,
[3].format = SG_VERTEXFORMAT_FLOAT2,
[4].format = SG_VERTEXFORMAT_UBYTE4N
}},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
});
slice9_bind.vertex_buffers[0] = sprite_quad;
}
void sprite_pipe()
{
sg_apply_pipeline(pip_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vp, SG_RANGE_REF(useproj));
}
transform2d sprite2t(sprite *s)
{
return (transform2d){
.pos = s->pos,
.scale = HMM_MulV2(s->scale, (HMM_Vec2){loadedtex->width, loadedtex->height}),
.angle = HMM_TurnToRad*s->angle
};
}
void sprite_tex(texture *t)
{
loadedtex = t;
bind_sprite.fs.images[0] = t->id;
}
void sprite_setpipe(sg_pipeline p)
{
pip_sprite = p;
}
void tex_draw(texture *tex, gameobject *go)
{
HMM_Mat4 m = transform2d2mat4(go2t(go));
sg_apply_uniforms(SG_SHADERSTAGE_VS, 1, SG_RANGE_REF(m.e));
sg_bindings bind = {0};
bind.vertex_buffers[0] = sprite_quad;
bind.fs.images[0] = tex->id;
bind.fs.samplers[0] = std_sampler;
sg_apply_bindings(&bind);
sg_draw(0,4,1);
}
void sprite_draw(struct sprite *sprite, gameobject *go) {
HMM_Mat4 m = transform2d2mat4(go2t(go));
HMM_Mat4 sm = transform2d2mat4(sprite2t(sprite));
struct spriteuni spv;
rgba2floats(&spv.color.e, sprite->color);
rgba2floats(spv.emissive.e, sprite->emissive);
spv.size = sprite->spritesize;
spv.offset = sprite->spriteoffset;
spv.model = HMM_MulM4(m,sm);
sg_bindings bind = {0};
bind.vertex_buffers[0] = sprite_quad;
bind.fs.images[0] = loadedtex->id;
bind.fs.samplers[0] = std_sampler;
sg_draw(0,4,1);
}
void gui_draw_img(texture *tex, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color) {
sg_apply_pipeline(pip_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vp, SG_RANGE_REF(useproj));
sprite_tex(tex);
//tex_draw(transform2d2mat(t), ST_UNIT, color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0});
}
void slice9_draw(texture *tex, transform2d *t, HMM_Vec4 border, struct rgba color)
{
}

View file

@ -7,39 +7,14 @@
#include "transform.h" #include "transform.h"
#include "gameobject.h" #include "gameobject.h"
struct sprite { typedef struct sprite {
HMM_Vec2 pos;
HMM_Vec2 scale;
float angle;
struct rgba color; struct rgba color;
struct rgba emissive; struct rgba emissive;
HMM_Vec2 spritesize; HMM_Vec4 rect;
HMM_Vec2 spriteoffset; HMM_Vec2 spriteoffset;
}; } sprite;
struct spriteuni {
HMM_Vec4 color;
HMM_Vec4 emissive;
HMM_Vec2 size;
HMM_Vec2 offset;
HMM_Mat4 model;
};
typedef struct sprite sprite;
extern sg_bindings bind_sprite;
extern sg_pipeline pip_sprite;
sprite *sprite_make(); sprite *sprite_make();
void sprite_free(sprite *sprite); void sprite_free(sprite *sprite);
void sprite_tex(texture *t);
void sprite_initialize();
void tex_draw(texture *tex, gameobject *go);
void sprite_draw(struct sprite *sprite, gameobject *go);
void sprite_pipe();
void sprite_draw_all();
void sprite_setpipe(sg_pipeline p);
void gui_draw_img(texture *tex, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color);
#endif #endif

View file

@ -1,5 +1,6 @@
#include "transform.h" #include "transform.h"
#include <string.h> #include <string.h>
#include <stdio.h>
const transform2d t2d_unit = { const transform2d t2d_unit = {
.pos = {0,0}, .pos = {0,0},
@ -7,6 +8,23 @@ const transform2d t2d_unit = {
.angle = 0 .angle = 0
}; };
transform3d *make_transform3d()
{
transform3d *t = calloc(sizeof(transform3d),1);
return t;
}
void transform3d_free(transform3d *t) { free(t); }
transform2d *make_transform2d()
{
transform2d *t = calloc(sizeof(transform2d),1);
t->scale = (HMM_Vec2){1,1};
return t;
}
void transform2d_free(transform2d *t) { free(t); }
HMM_Vec3 trans_forward(const transform3d *const trans) { return HMM_QVRot(vFWD, trans->rotation); } HMM_Vec3 trans_forward(const transform3d *const trans) { return HMM_QVRot(vFWD, trans->rotation); }
HMM_Vec3 trans_back(const transform3d *trans) { return HMM_QVRot(vBKWD, trans->rotation); } HMM_Vec3 trans_back(const transform3d *trans) { return HMM_QVRot(vBKWD, trans->rotation); }
HMM_Vec3 trans_up(const transform3d *trans) { return HMM_QVRot(vUP, trans->rotation); } HMM_Vec3 trans_up(const transform3d *trans) { return HMM_QVRot(vUP, trans->rotation); }
@ -40,13 +58,19 @@ HMM_Mat3 transform2d2mat(transform2d trn) {
return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale))); return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale)));
} }
HMM_Mat4 transform2d2mat4(transform2d trn) HMM_Mat4 transform2d2mat4(transform2d *t)
{ {
transform3d t3d; HMM_Mat4 T = {0};
t3d.pos.xy = trn.pos; float c = cosf(t->angle);
t3d.scale.xy = trn.scale; float s = sinf(t->angle);
t3d.rotation = HMM_QFromAxisAngle_RH((HMM_Vec3){0,0,-1}, trn.angle); T.col[0].x = c*t->scale.x;
return transform3d2mat(t3d); T.col[0].y = s*t->scale.y;
T.col[1].x = -s*t->scale.x;
T.col[1].y = c*t->scale.y;
T.col[3].xy = t->pos;
T.col[2].z = 1;
T.col[3].w = 1;
return T;
} }
transform2d mat2transform2d(HMM_Mat3 m) transform2d mat2transform2d(HMM_Mat3 m)

View file

@ -9,12 +9,18 @@ typedef struct transform3d {
HMM_Quat rotation; HMM_Quat rotation;
} transform3d; } transform3d;
transform3d *make_transform3d();
void transform3d_free(transform3d *t);
typedef struct { typedef struct {
HMM_Vec2 pos; HMM_Vec2 pos;
HMM_Vec2 scale; HMM_Vec2 scale;
float angle; float angle;
} transform2d; } transform2d;
transform2d *make_transform2d();
void transform2d_free(transform2d *t);
extern const transform2d t2d_unit; extern const transform2d t2d_unit;
#define VEC2_FMT "[%g,%g]" #define VEC2_FMT "[%g,%g]"
@ -27,7 +33,7 @@ HMM_Vec3 trans_down(const transform3d *trans);
HMM_Vec3 trans_right(const transform3d *trans); HMM_Vec3 trans_right(const transform3d *trans);
HMM_Vec3 trans_left(const transform3d *trans); HMM_Vec3 trans_left(const transform3d *trans);
HMM_Mat4 transform2d2mat4(transform2d trn); HMM_Mat4 transform2d2mat4(transform2d *t);
/* Transform a position via the matrix */ /* Transform a position via the matrix */
HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos); HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos);

View file

@ -1,65 +0,0 @@
@vs vs9
in vec2 vert;
in vec2 vuv;
in vec4 vborder;
in vec2 vscale;
in vec4 vcolor;
out vec2 uv;
out vec4 border;
out vec2 scale;
out vec4 fcolor;
uniform vs9_params { mat4 projection; };
void main()
{
gl_Position = projection * vec4(vert, 0.0, 1.0);
uv = vuv;
border = vborder;
scale = vscale;
fcolor = vcolor;
}
@end
@fs fs9
in vec2 uv; /* image uv */
in vec4 border; /* uv length of border, normalized to image dimensions; left, bottom, right, top */
in vec2 scale; /* polygon dimensions ~ texture dimensions */
in vec4 fcolor;
out vec4 color;
uniform texture2D image;
uniform sampler smp;
float map(float value, float min1, float max1, float min2, float max2)
{
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}
float processAxis(float coord, float texBorder, float winBorder)
{
if (coord < winBorder)
return map(coord, 0, winBorder, 0, texBorder);
if (coord < 1 - winBorder)
return map(coord, winBorder, 1 - winBorder, texBorder, 1 - texBorder);
return map(coord, 1 - winBorder, 1, 1 - texBorder, 1);
}
vec2 uv9slice(vec2 uv, vec2 s, vec4 b)
{
vec2 t = clamp((s * uv - b.xy) / (s - b.xy - b.zw), 0.0, 1.0);
return mix(uv * s, 1.0 - s * (1.0 - uv), t);
}
void main()
{
vec2 nuv = uv9slice(uv, scale, border);
color = fcolor * texture(sampler2D(image,smp), nuv);
}
@end
@program slice9 vs9 fs9

View file

@ -1,14 +0,0 @@
#version 330
in vec2 TexCoords;
out vec4 color;
uniform sampler2DArray image;
uniform float frame;
uniform vec3 spriteColor;
void main()
{
color = vec4(spriteColor, 1.f) * texture(image, vec3(TexCoords,frame));
if (color.a < 0.1)
discard;
}

View file

@ -1,17 +0,0 @@
#version 330 core
layout (location = 0) in vec2 vertex; // <vec2 position, vec2 texCoords>
out vec2 TexCoords;
layout (std140) uniform Projection
{
mat4 projection;
};
uniform mat4 model;
void main()
{
TexCoords = vertex.xy;
gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);
}

View file

@ -1,52 +0,0 @@
@vs vs
in vec2 vertex;
out vec2 texcoords;
out vec4 fcolor;
out vec4 femissive;
uniform app {
float time;
vec2 window;
};
uniform vp {
mat4 proj;
};
uniform sprite {
vec4 vcolor;
vec4 vemissive;
vec2 spritesize;
vec2 spriteoff;
mat4 model;
};
void main()
{
texcoords = vertex;
gl_Position = proj * model * vec4(vertex, 0, 1.0);
fcolor = vcolor;
femissive = vemissive;
}
@end
@fs fs
in vec2 texcoords;
in vec4 fcolor;
in vec4 femissive;
out vec4 color;
uniform texture2D image;
uniform sampler smp;
void main()
{
color = texture(sampler2D(image,smp), texcoords);
color *= fcolor;
color.xyz = mix(color.xyz, femissive.xyz, femissive.a);
}
@end
@program sprite vs fs

View file

@ -1,12 +0,0 @@
#version 330 core
in vec2 texcoords;
out vec4 color;
uniform sampler2D image;
uniform vec3 spriteColor;
void main()
{
color = vec4(spriteColor, 1.f) * texture(image, texcoords);
color.a = 1.f;
}