Move primitive support to javascript
This commit is contained in:
parent
97e258ae7c
commit
44b3bf3a7d
2
Makefile
2
Makefile
|
@ -101,7 +101,7 @@ else ifeq ($(OS), IOS)
|
|||
LDFLAGS += -isysroot $(SDK_PATH) -miphoneos-version-min=13.0
|
||||
LDFLAGS += -framework Foundation -framework UIKit -framework AudioToolbox -framework Metal -framework MetalKit -framework AVFoundation
|
||||
CXXFLAGS += -std=c++11
|
||||
CFLAGS += -x objective-c
|
||||
CFLAGS += -x objective-c -DIOS
|
||||
INFO :=$(INFO)_ios
|
||||
else ifeq ($(OS), wasm) # Then WEB
|
||||
OS := Web
|
||||
|
|
|
@ -1605,10 +1605,10 @@ yaml.tojson = function(yaml)
|
|||
yaml = yaml.replace(/\s/g, '');
|
||||
yaml = yaml.replace(/,}/g, '}');
|
||||
yaml = yaml.replace(/,]/g, ']');
|
||||
yaml = yaml.replace(/,"[^"]+"\:,/, ',');
|
||||
return yaml;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
convert,
|
||||
time,
|
||||
|
|
|
@ -309,7 +309,6 @@ function process()
|
|||
frame_t = profile.secs(profile.now());
|
||||
|
||||
prosperon.appupdate(dt);
|
||||
prosperon.emitters_step(dt);
|
||||
input.procdown();
|
||||
|
||||
if (sim.mode === "play" || sim.mode === "step") {
|
||||
|
@ -342,7 +341,6 @@ function process()
|
|||
render.sprite_flush();
|
||||
});
|
||||
render.sprite_flush();*/
|
||||
render.emitters(); // blits emitters
|
||||
prosperon.draw(); // draw calls
|
||||
debug.draw(); // calls needed debugs
|
||||
render.flush();
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <string.h>
|
||||
#include "yugine.h"
|
||||
|
||||
#include "jsffi.h"
|
||||
|
||||
#include "texture.h"
|
||||
|
||||
#include "sokol/sokol_gfx.h"
|
||||
|
@ -40,14 +42,6 @@ cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
unsigned short pack_short_texcoord(float x, float y)
|
||||
{
|
||||
unsigned short s;
|
||||
char xc = x*255;
|
||||
char yc = y*255;
|
||||
return (((unsigned short)yc) << 8) | xc;
|
||||
}
|
||||
|
||||
unsigned short pack_short_tex(float c) { return c * USHRT_MAX; }
|
||||
|
||||
uint32_t pack_int10_n2(float *norm)
|
||||
|
@ -81,12 +75,16 @@ void mesh_add_material(primitive *prim, cgltf_material *mat)
|
|||
pmat->diffuse = texture_from_file("icons/moon.gif");
|
||||
}
|
||||
|
||||
sg_buffer texcoord_floats(float *f, int verts, int comp)
|
||||
sg_buffer texcoord_floats(float *f, int n)
|
||||
{
|
||||
int n = verts*comp;
|
||||
unsigned short packed[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
packed[i] = pack_short_tex(f[i]);
|
||||
for (int i = 0; i < n; i++) {
|
||||
float v = f[i];
|
||||
if (v < 0) v = 0;
|
||||
if (v > 1) v = 1;
|
||||
packed[i] = pack_short_tex(v);
|
||||
printf("val: %g, packed: %u\n", v, packed[i]);
|
||||
}
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = SG_RANGE(packed),
|
||||
|
@ -94,10 +92,43 @@ sg_buffer texcoord_floats(float *f, int verts, int comp)
|
|||
});
|
||||
}
|
||||
|
||||
sg_buffer normal_floats(float *f, int verts, int comp)
|
||||
sg_buffer par_idx_buffer(uint32_t *p, int v)
|
||||
{
|
||||
uint32_t packed_norms[verts];
|
||||
for (int v = 0, i = 0; v < verts; v++, i+= comp)
|
||||
uint16_t idx[v];
|
||||
for (int i = 0; i < v; i++) idx[i] = p[i];
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = SG_RANGE(idx),
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER
|
||||
});
|
||||
}
|
||||
|
||||
sg_buffer float_buffer(float *f, int v)
|
||||
{
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = (sg_range){
|
||||
.ptr = f,
|
||||
.size = sizeof(*f)*v
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sg_buffer index_buffer(float *f, int verts)
|
||||
{
|
||||
uint16_t idxs[verts];
|
||||
for (int i = 0; i < verts; i++)
|
||||
idxs[i] = f[i];
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = SG_RANGE(idxs),
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||
});
|
||||
}
|
||||
|
||||
sg_buffer normal_floats(float *f, int n)
|
||||
{
|
||||
uint32_t packed_norms[n/3];
|
||||
for (int v = 0, i = 0; v < n/3; v++, i+= 3)
|
||||
packed_norms[v] = pack_int10_n2(f+i);
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
|
@ -106,37 +137,37 @@ sg_buffer normal_floats(float *f, int verts, int comp)
|
|||
});
|
||||
}
|
||||
|
||||
sg_buffer ubyten_buffer(float *f, int v, int c)
|
||||
sg_buffer ubyten_buffer(float *f, int v)
|
||||
{
|
||||
unsigned char b[v*c];
|
||||
for (int i = 0; i < (v*c); i++)
|
||||
unsigned char b[v];
|
||||
for (int i = 0; i < (v); 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)
|
||||
sg_buffer ubyte_buffer(float *f, int v)
|
||||
{
|
||||
unsigned char b[v*c];
|
||||
for (int i = 0; i < (v*c); i++)
|
||||
unsigned char b[v];
|
||||
for (int i = 0; i < (v); 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)
|
||||
{
|
||||
char joints[v*c];
|
||||
for (int i = 0; i < (v*c); i++)
|
||||
char joints[v];
|
||||
for (int i = 0; i < (v); i++)
|
||||
joints[i] = f[i];
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(joints)});
|
||||
}
|
||||
|
||||
sg_buffer weight_buf(float *f, int v, int c)
|
||||
sg_buffer weight_buf(float *f, int v)
|
||||
{
|
||||
unsigned char weights[v*c];
|
||||
for (int i = 0; i < (v*c); i++)
|
||||
unsigned char weights[v];
|
||||
for (int i = 0; i < (v); i++)
|
||||
weights[i] = f[i]*255;
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(weights)});
|
||||
|
@ -147,6 +178,22 @@ HMM_Vec3 index_to_vert(uint32_t idx, float *f)
|
|||
return (HMM_Vec3){f[idx*3], f[idx*3+1], f[idx*3+2]};
|
||||
}
|
||||
|
||||
void primitive_gen_indices(primitive *prim)
|
||||
{
|
||||
if (prim->idx_count == 0) return;
|
||||
uint16_t *idxs = malloc(sizeof(*idxs)*prim->idx_count);
|
||||
|
||||
for (int z = 0; z < prim->idx_count; z++)
|
||||
idxs[z] = z;
|
||||
|
||||
prim->idx = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = idxs,
|
||||
.data.size = sizeof(uint16_t) * prim->idx_count,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
||||
|
||||
free(idxs);
|
||||
}
|
||||
|
||||
struct primitive mesh_add_primitive(cgltf_primitive *prim)
|
||||
{
|
||||
primitive retp = (primitive){0};
|
||||
|
@ -168,24 +215,12 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
|
|||
});
|
||||
|
||||
retp.idx_count = n;
|
||||
free(idxs);
|
||||
} else {
|
||||
YughWarn("Model does not have indices. Generating them.");
|
||||
int c = cgltf_accessor_unpack_floats(prim->attributes[0].data, NULL, 0);
|
||||
|
||||
retp.idx_count = c;
|
||||
idxs = malloc(sizeof(*idxs)*c);
|
||||
|
||||
for (int z = 0; z < c; z++)
|
||||
idxs[z] = z;
|
||||
|
||||
retp.idx = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = idxs,
|
||||
.data.size = sizeof(uint16_t) * c,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
||||
retp.idx_count = cgltf_accessor_unpack_floats(prim->attributes[0].data, NULL, 0);
|
||||
primitive_gen_indices(&retp);
|
||||
}
|
||||
|
||||
free(idxs);
|
||||
|
||||
printf("adding material\n");
|
||||
mesh_add_material(&retp, prim->material);
|
||||
|
||||
|
@ -208,26 +243,26 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
|
|||
break;
|
||||
|
||||
case cgltf_attribute_type_normal:
|
||||
retp.norm = normal_floats(vs, verts, comp);
|
||||
retp.norm = normal_floats(vs, n);
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_tangent:
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_color:
|
||||
retp.color = ubyten_buffer(vs,verts,comp);
|
||||
retp.color = ubyten_buffer(vs,n);
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_weights:
|
||||
retp.weight = ubyten_buffer(vs, verts, comp);
|
||||
retp.weight = ubyten_buffer(vs, n);
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_joints:
|
||||
retp.bone = ubyte_buffer(vs, verts, comp);
|
||||
retp.bone = ubyte_buffer(vs, n);
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_texcoord:
|
||||
retp.uv = texcoord_floats(vs, verts, comp);
|
||||
retp.uv = texcoord_floats(vs, n);
|
||||
break;
|
||||
case cgltf_attribute_type_invalid:
|
||||
YughWarn("Invalid type.");
|
||||
|
@ -505,6 +540,68 @@ void model_draw_go(model *model, gameobject *go, gameobject *cam)
|
|||
}
|
||||
}
|
||||
|
||||
int mat2type(int mat)
|
||||
{
|
||||
switch(mat) {
|
||||
case MAT_POS:
|
||||
case MAT_WH:
|
||||
case MAT_ST:
|
||||
return SG_VERTEXFORMAT_FLOAT2;
|
||||
case MAT_UV:
|
||||
case MAT_TAN:
|
||||
return SG_VERTEXFORMAT_USHORT2N;
|
||||
case MAT_NORM:
|
||||
return SG_VERTEXFORMAT_UINT10_N2;
|
||||
case MAT_BONE:
|
||||
return SG_VERTEXFORMAT_UBYTE4;
|
||||
case MAT_WEIGHT:
|
||||
case MAT_COLOR:
|
||||
return SG_VERTEXFORMAT_UBYTE4N;
|
||||
case MAT_ANGLE:
|
||||
return SG_VERTEXFORMAT_FLOAT;
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
sg_buffer mat2buffer(int mat, primitive *p)
|
||||
{
|
||||
switch(mat) {
|
||||
case MAT_POS: return p->pos;
|
||||
case MAT_NORM: return p->norm;
|
||||
case MAT_UV: return p->uv;
|
||||
case MAT_BONE: return p->bone;
|
||||
case MAT_WEIGHT: return p->weight;
|
||||
case MAT_COLOR: return p->color;
|
||||
};
|
||||
|
||||
return p->pos;
|
||||
}
|
||||
|
||||
sg_bindings primitive_bindings(primitive *p, JSValue v)
|
||||
{
|
||||
sg_bindings b = {0};
|
||||
JSValue inputs = js_getpropstr(js_getpropstr(v, "vs"), "inputs");
|
||||
for (int i = 0; i < js_arrlen(inputs); i++) {
|
||||
JSValue attr = js_getpropidx(inputs, i);
|
||||
int mat = js2number(js_getpropstr(attr, "mat"));
|
||||
int slot = js2number(js_getpropstr(attr, "slot"));
|
||||
sg_buffer buf = mat2buffer(mat,p);
|
||||
if (!buf.id) {
|
||||
// ERROR
|
||||
}
|
||||
b.vertex_buffers[slot] = buf;
|
||||
}
|
||||
|
||||
b.index_buffer = p->idx;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void primitive_free(primitive *prim)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void material_free(material *mat)
|
||||
{
|
||||
|
||||
|
|
|
@ -15,17 +15,20 @@
|
|||
#define MAT_WEIGHT 4
|
||||
#define MAT_COLOR 5
|
||||
#define MAT_TAN 6
|
||||
#define MAT_ANGLE 7
|
||||
#define MAT_WH 8
|
||||
#define MAT_ST 9
|
||||
|
||||
typedef struct material {
|
||||
texture *diffuse;
|
||||
texture *metalrough;
|
||||
struct texture *diffuse;
|
||||
struct texture *metalrough;
|
||||
float metal;
|
||||
float rough;
|
||||
texture *normal;
|
||||
struct texture *normal;
|
||||
float nrm;
|
||||
texture *occlusion;
|
||||
struct texture *occlusion;
|
||||
float occl;
|
||||
texture *emissive;
|
||||
struct texture *emissive;
|
||||
HMM_Vec3 emis;
|
||||
} material;
|
||||
|
||||
|
@ -83,6 +86,20 @@ struct model *model_make(const char *path);
|
|||
void model_free(model *m);
|
||||
|
||||
void model_draw_go(model *m, gameobject *go, gameobject *cam);
|
||||
sg_bindings primitive_bindings(primitive *p, JSValue pipe);
|
||||
void primitive_gen_indices(primitive *prim);
|
||||
int mat2type(int mat);
|
||||
|
||||
sg_buffer float_buffer(float *f, int v);
|
||||
sg_buffer index_buffer(float *f, int verts);
|
||||
sg_buffer texcoord_floats(float *f, int n);
|
||||
sg_buffer par_idx_buffer(uint32_t *i, int v);
|
||||
sg_buffer normal_floats(float *f, int n);
|
||||
sg_buffer ubyten_buffer(float *f, int v);
|
||||
sg_buffer ubyte_buffer(float *f, int v);
|
||||
sg_buffer joint_buf(float *f, int v);
|
||||
sg_buffer weight_buf(float *f, int v);
|
||||
void primitive_free(primitive *prim);
|
||||
|
||||
material *material_make();
|
||||
void material_free(material *mat);
|
||||
|
|
|
@ -111,9 +111,6 @@ struct circle_vertex {
|
|||
float fill;
|
||||
};
|
||||
|
||||
static sg_pipeline g3_pipe;
|
||||
static sg_shader g3_shader;
|
||||
|
||||
void debug_nextpass()
|
||||
{
|
||||
point_sc = point_c;
|
||||
|
@ -196,14 +193,6 @@ static sg_shader_uniform_block_desc time_ubo = {
|
|||
|
||||
void debugdraw_init()
|
||||
{
|
||||
/*
|
||||
g3_shader = sg_make_shader(grid3d_shader_desc(sg_query_backend()));
|
||||
g3_pipe = sg_make_pipeline(&(sg_pipeline_desc){
|
||||
.shader = g3_shader,
|
||||
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
|
||||
.index_type = SG_INDEXTYPE_UINT32
|
||||
});
|
||||
*/
|
||||
point_shader = sg_make_shader(point_shader_desc(sg_query_backend()));
|
||||
|
||||
point_pipe = sg_make_pipeline(&(sg_pipeline_desc){
|
||||
|
|
|
@ -33,8 +33,6 @@ struct text_vert {
|
|||
static struct text_vert *text_buffer;
|
||||
|
||||
void font_init() {
|
||||
bind_text.vertex_buffers[1] = sprite_quad;
|
||||
|
||||
bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(struct text_vert),
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "render.h"
|
||||
#include "model.h"
|
||||
#include "HandmadeMath.h"
|
||||
#include "par/par_streamlines.h"
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__))
|
||||
#include <direct.h>
|
||||
|
@ -61,6 +62,11 @@ const char *js2str(JSValue v) {
|
|||
return JS_ToCString(js, v);
|
||||
}
|
||||
|
||||
void sg_buffer_free(sg_buffer *b)
|
||||
{
|
||||
sg_dealloc_buffer(*b);
|
||||
}
|
||||
|
||||
void jsfreestr(const char *s) { JS_FreeCString(js, s); }
|
||||
QJSCLASS(gameobject)
|
||||
QJSCLASS(transform3d)
|
||||
|
@ -76,6 +82,8 @@ QJSCLASS(material)
|
|||
QJSCLASS(model)
|
||||
QJSCLASS(window)
|
||||
QJSCLASS(constraint)
|
||||
QJSCLASS(primitive)
|
||||
QJSCLASS(sg_buffer)
|
||||
|
||||
static JSValue sound_proto;
|
||||
sound *js2sound(JSValue v) { return js2dsp_node(v)->data; }
|
||||
|
@ -111,6 +119,11 @@ JSValue js_getpropstr(JSValue v, const char *str)
|
|||
return p;
|
||||
}
|
||||
|
||||
void js_setpropstr(JSValue v, const char *str, JSValue p)
|
||||
{
|
||||
JS_SetPropertyStr(js, v, str, p);
|
||||
}
|
||||
|
||||
static inline cpBody *js2body(JSValue v) { return js2gameobject(v)->body; }
|
||||
|
||||
JSValue strarr2js(char **c)
|
||||
|
@ -578,6 +591,21 @@ static const JSCFunctionListEntry js_warp_damp_funcs [] = {
|
|||
CGETSET_ADD(warp_damp, damp)
|
||||
};
|
||||
|
||||
sg_bindings js2bind(JSValue mat, JSValue prim)
|
||||
{
|
||||
sg_bindings bind = {0};
|
||||
for (int i = 0; i < js_arrlen(mat); i++) {
|
||||
bind.fs.images[i] = js2texture(js_getpropidx(mat, i))->id;
|
||||
bind.fs.samplers[i] = std_sampler;
|
||||
}
|
||||
|
||||
bind.vertex_buffers[0] = *js2sg_buffer(js_getpropstr(prim, "pos"));
|
||||
bind.index_buffer = *js2sg_buffer(js_getpropstr(prim, "index"));
|
||||
bind.vertex_buffers[1] = *js2sg_buffer(js_getpropstr(prim, "uv"));
|
||||
|
||||
return bind;
|
||||
}
|
||||
|
||||
JSC_GETSET(emitter, life, number)
|
||||
JSC_GETSET(emitter, life_var, number)
|
||||
JSC_GETSET(emitter, speed, number)
|
||||
|
@ -595,11 +623,9 @@ JSC_GETSET(emitter, die_after_collision, boolean)
|
|||
JSC_GETSET(emitter, persist, number)
|
||||
JSC_GETSET(emitter, persist_var, number)
|
||||
JSC_GETSET(emitter, warp_mask, bitmask)
|
||||
JSC_GETSET(emitter, texture, texture)
|
||||
|
||||
JSC_CCALL(emitter_start, start_emitter(js2emitter(this)))
|
||||
JSC_CCALL(emitter_stop, stop_emitter(js2emitter(this)))
|
||||
JSC_CCALL(emitter_emit, emitter_emit(js2emitter(this), js2number(argv[0])))
|
||||
JSC_CCALL(emitter_emit, emitter_emit(js2emitter(this), js2number(argv[0]), js2transform2d(argv[1])))
|
||||
JSC_CCALL(emitter_step, emitter_step(js2emitter(this), js2number(argv[0]), js2transform2d(argv[1])))
|
||||
JSC_CCALL(emitter_draw, emitter_draw(js2emitter(this), js2bind(argv[0], argv[1])))
|
||||
|
||||
JSC_CCALL(render_grid, draw_grid(js2number(argv[0]), js2number(argv[1]), js2color(argv[2]));)
|
||||
JSC_CCALL(render_point, draw_cppoint(js2vec2(argv[0]), js2number(argv[1]), js2color(argv[2])))
|
||||
|
@ -624,7 +650,6 @@ JSC_CCALL(render_line3d,
|
|||
arrfree(v1);
|
||||
);
|
||||
|
||||
JSC_CCALL(render_emitters, emitters_draw(&useproj))
|
||||
JSC_CCALL(render_flush, debug_flush(&useproj); )
|
||||
|
||||
JSC_CCALL(render_flushtext, text_flush())
|
||||
|
@ -740,20 +765,40 @@ JSC_CCALL(render_pipeline3d,
|
|||
return number2js(pipe.id);
|
||||
)
|
||||
|
||||
JSC_CCALL(render_pipelinetext,
|
||||
sg_shader fontshader = js2shader(argv[0]);
|
||||
sg_pipeline_desc p = {0};
|
||||
p.shader = fontshader;
|
||||
sg_vertex_layout_state js2layout(JSValue v)
|
||||
{
|
||||
sg_vertex_layout_state st = {0};
|
||||
st.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
|
||||
st.attrs[0].buffer_index = 1;
|
||||
st.attrs[1].format = SG_VERTEXFORMAT_FLOAT2;
|
||||
st.attrs[2].format = SG_VERTEXFORMAT_FLOAT2;
|
||||
st.attrs[3].format = SG_VERTEXFORMAT_USHORT2N;
|
||||
st.attrs[4].format = SG_VERTEXFORMAT_USHORT2N;
|
||||
st.attrs[5].format = SG_VERTEXFORMAT_UBYTE4N;
|
||||
st.buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE;
|
||||
p.layout = st;
|
||||
JSValue inputs = js_getpropstr(js_getpropstr(v, "vs"), "inputs");
|
||||
for (int i = 0; i < js_arrlen(inputs); i++) {
|
||||
JSValue attr = js_getpropidx(inputs, i);
|
||||
int slot = js2number(js_getpropstr(attr, "slot"));
|
||||
int mat = js2number(js_getpropstr(attr, "mat"));
|
||||
st.attrs[slot].format = mat2type(mat);
|
||||
st.attrs[slot].buffer_index = slot;
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
JSC_CCALL(render_pipelineparticle,
|
||||
sg_pipeline_desc p = {0};
|
||||
p.shader = js2shader(argv[0]);
|
||||
p.layout = js2layout(argv[0]);
|
||||
p.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
|
||||
p.index_type = SG_INDEXTYPE_UINT16;
|
||||
//p.cull_mode = SG_CULLMODE_BACK;
|
||||
//p.colors[0].blend = blend_trans;
|
||||
//p.depth.write_enabled = true;
|
||||
//p.depth.compare = SG_COMPAREFUNC_LESS_EQUAL;
|
||||
|
||||
sg_pipeline pipe = sg_make_pipeline(&p);
|
||||
return number2js(pipe.id);
|
||||
)
|
||||
|
||||
JSC_CCALL(render_pipelinetext,
|
||||
sg_pipeline_desc p = {0};
|
||||
p.shader = js2shader(argv[0]);
|
||||
p.layout = js2layout(argv[0]);
|
||||
p.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
|
||||
p.colors[0].blend = blend_trans;
|
||||
|
||||
|
@ -762,18 +807,15 @@ JSC_CCALL(render_pipelinetext,
|
|||
)
|
||||
|
||||
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;
|
||||
sg_pipeline_desc p = {0};
|
||||
p.shader = js2shader(argv[0]);
|
||||
p.layout = js2layout(argv[0]);
|
||||
//p.cull_mode = SG_CULLMODE_FRONT;
|
||||
p.index_type = SG_INDEXTYPE_UINT16;
|
||||
if (js2boolean(js_getpropstr(argv[0], "blend")))
|
||||
pdesc.colors[0].blend = blend_trans;
|
||||
p.colors[0].blend = blend_trans;
|
||||
|
||||
sg_pipeline pipe = sg_make_pipeline(&pdesc);
|
||||
sg_pipeline pipe = sg_make_pipeline(&p);
|
||||
|
||||
return number2js(pipe.id);
|
||||
)
|
||||
|
@ -822,16 +864,10 @@ JSC_CCALL(render_setunim4,
|
|||
);
|
||||
|
||||
JSC_CCALL(render_spdraw,
|
||||
sg_bindings bind = {0};
|
||||
bind.vertex_buffers[0] = sprite_quad;
|
||||
|
||||
for (int i = 0; i < js_arrlen(argv[0]); i++) {
|
||||
bind.fs.images[i] = js2texture(js_getpropidx(argv[0], i))->id;
|
||||
bind.fs.samplers[i] = std_sampler;
|
||||
}
|
||||
|
||||
sg_bindings bind = js2bind(argv[0], argv[1]);
|
||||
sg_apply_bindings(&bind);
|
||||
sg_draw(0,4,1);
|
||||
int p = js2number(js_getpropstr(argv[1], "count"));
|
||||
sg_draw(0,p,1);
|
||||
)
|
||||
|
||||
JSC_CCALL(render_setpipeline,
|
||||
|
@ -847,7 +883,6 @@ static const JSCFunctionListEntry js_render_funcs[] = {
|
|||
MIST_FUNC_DEF(render, poly, 2),
|
||||
MIST_FUNC_DEF(render, line, 3),
|
||||
MIST_FUNC_DEF(render, line3d, 2),
|
||||
MIST_FUNC_DEF(render, emitters, 0),
|
||||
MIST_FUNC_DEF(render, flushtext, 0),
|
||||
MIST_FUNC_DEF(render, flush, 0),
|
||||
MIST_FUNC_DEF(render, end_pass, 0),
|
||||
|
@ -858,9 +893,10 @@ static const JSCFunctionListEntry js_render_funcs[] = {
|
|||
MIST_FUNC_DEF(render, pipeline, 1),
|
||||
MIST_FUNC_DEF(render, pipeline3d, 1),
|
||||
MIST_FUNC_DEF(render, pipelinetext, 1),
|
||||
MIST_FUNC_DEF(render, pipelineparticle, 1),
|
||||
MIST_FUNC_DEF(render, setuniv3, 2),
|
||||
MIST_FUNC_DEF(render, setuniv, 2),
|
||||
MIST_FUNC_DEF(render, spdraw, 2),
|
||||
MIST_FUNC_DEF(render, spdraw, 1),
|
||||
MIST_FUNC_DEF(render, setuniproj, 2),
|
||||
MIST_FUNC_DEF(render, setunim4, 3),
|
||||
MIST_FUNC_DEF(render, setuniv2, 2),
|
||||
|
@ -958,7 +994,6 @@ static const JSCFunctionListEntry js_input_funcs[] = {
|
|||
MIST_FUNC_DEF(input, cursor_img, 1)
|
||||
};
|
||||
|
||||
JSC_CCALL(prosperon_emitters_step, emitters_step(js2number(argv[0])))
|
||||
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
|
||||
JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2transform2d(argv[0]), js2number(argv[1])))
|
||||
JSC_CCALL(prosperon_guid,
|
||||
|
@ -972,7 +1007,6 @@ JSC_CCALL(prosperon_guid,
|
|||
)
|
||||
|
||||
static const JSCFunctionListEntry js_prosperon_funcs[] = {
|
||||
MIST_FUNC_DEF(prosperon, emitters_step, 1),
|
||||
MIST_FUNC_DEF(prosperon, phys2d_step, 1),
|
||||
MIST_FUNC_DEF(prosperon, window_render, 0),
|
||||
MIST_FUNC_DEF(prosperon, guid, 0),
|
||||
|
@ -1247,8 +1281,6 @@ static const JSCFunctionListEntry js_physics_funcs[] = {
|
|||
MIST_FUNC_DEF(physics, make_gravity, 0),
|
||||
};
|
||||
|
||||
|
||||
|
||||
JSC_CCALL(model_draw_go,
|
||||
model_draw_go(js2model(this), js2gameobject(argv[0]), js2gameobject(argv[1]))
|
||||
);
|
||||
|
@ -1275,10 +1307,9 @@ static const JSCFunctionListEntry js_emitter_funcs[] = {
|
|||
CGETSET_ADD(emitter, persist),
|
||||
CGETSET_ADD(emitter, persist_var),
|
||||
CGETSET_ADD(emitter, warp_mask),
|
||||
MIST_FUNC_DEF(emitter, start, 0),
|
||||
MIST_FUNC_DEF(emitter, stop, 0),
|
||||
MIST_FUNC_DEF(emitter, emit, 1),
|
||||
CGETSET_ADD(emitter, texture),
|
||||
MIST_FUNC_DEF(emitter, step, 1),
|
||||
MIST_FUNC_DEF(emitter, draw, 1)
|
||||
};
|
||||
|
||||
JSC_GETSET(transform2d, pos, vec2)
|
||||
|
@ -1685,8 +1716,12 @@ JSValue js_os_sys(JSContext *js, JSValue this, int argc, JSValue *argv)
|
|||
return str2js("linux");
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
return str2js("windows");
|
||||
#elif defined(IOS)
|
||||
return str2js("ios");
|
||||
#elif defined(__APPLE__)
|
||||
return str2js("macos");
|
||||
#elif define(__EMSCRIPTEN__)
|
||||
return str2js("web");
|
||||
#endif
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
@ -1699,7 +1734,6 @@ JSC_SSCALL(os_eval, ret = script_eval(str, str2))
|
|||
JSC_SCALL(os_capture, capture_screen(js2number(argv[1]), js2number(argv[2]), js2number(argv[4]), js2number(argv[5]), str))
|
||||
|
||||
JSC_CCALL(os_sprite,
|
||||
if (js2boolean(argv[0])) return JS_GetClassProto(js,js_sprite_id);
|
||||
return sprite2js(sprite_make());
|
||||
)
|
||||
|
||||
|
@ -1768,9 +1802,89 @@ JSC_CCALL(os_make_transform2d,
|
|||
JSC_SCALL(os_system, return number2js(system(str)); )
|
||||
|
||||
JSC_SCALL(os_make_model, ret = model2js(model_make(str)))
|
||||
JSC_CCALL(os_make_emitter, ret = emitter2js(make_emitter()))
|
||||
|
||||
JSC_CCALL(os_make_buffer,
|
||||
int type = js2number(argv[1]);
|
||||
float *b = malloc(sizeof(float)*js_arrlen(argv[0]));
|
||||
for (int i = 0; i < js_arrlen(argv[0]); i++)
|
||||
b[i] = js2number(js_getpropidx(argv[0],i));
|
||||
|
||||
sg_buffer *p = malloc(sizeof(sg_buffer));
|
||||
|
||||
switch(type) {
|
||||
case 0:
|
||||
*p = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(float)*js_arrlen(argv[0]),
|
||||
.data = b
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
*p = index_buffer(b, js_arrlen(argv[0]));
|
||||
break;
|
||||
case 2:
|
||||
*p = texcoord_floats(b, js_arrlen(argv[0]));
|
||||
break;
|
||||
}
|
||||
|
||||
free(b);
|
||||
return sg_buffer2js(p);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_make_line_prim,
|
||||
JSValue prim = JS_NewObject(js);
|
||||
HMM_Vec2 *v = js2cpvec2arr(argv[0]);
|
||||
parsl_position par_v[arrlen(v)];
|
||||
for (int i = 0; i < arrlen(v); i++) {
|
||||
par_v[i].x = v[i].x;
|
||||
par_v[i].y = v[i].y;
|
||||
}
|
||||
|
||||
parsl_context *par_ctx = parsl_create_context((parsl_config){
|
||||
.thickness = js2number(argv[1]),
|
||||
.flags= PARSL_FLAG_ANNOTATIONS,
|
||||
.u_mode = PAR_U_MODE_NORMALIZED_DISTANCE
|
||||
});
|
||||
|
||||
uint16_t spine_lens[] = {arrlen(v)};
|
||||
|
||||
parsl_mesh *m = parsl_mesh_from_lines(par_ctx, (parsl_spine_list){
|
||||
.num_vertices = arrlen(v),
|
||||
.num_spines = 1,
|
||||
.vertices = par_v,
|
||||
.spine_lengths = spine_lens
|
||||
});
|
||||
|
||||
sg_buffer *pos = malloc(sizeof(*pos));
|
||||
*pos = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = (sg_range){
|
||||
.ptr = m->positions,
|
||||
.size = sizeof(parsl_position)*m->num_vertices
|
||||
}
|
||||
});
|
||||
js_setpropstr(prim, "pos", sg_buffer2js(pos));
|
||||
js_setpropstr(prim, "count", number2js(m->num_triangles*3));
|
||||
sg_buffer *idx = malloc(sizeof(*idx));
|
||||
*idx = par_idx_buffer(m->triangle_indices, m->num_triangles*3);
|
||||
js_setpropstr(prim, "index", sg_buffer2js(idx));
|
||||
|
||||
printf("there are %d verts\n", m->num_vertices);
|
||||
float uv[m->num_vertices*2];
|
||||
for (int i = 0; i < m->num_vertices; i++) {
|
||||
uv[i*2] = m->annotations[i].u_along_curve;
|
||||
uv[i*2+1] = m->annotations[i].v_across_curve;
|
||||
printf("uv is %g,%g\n", uv[i*2], uv[i*2+1]);
|
||||
}
|
||||
sg_buffer *buv = malloc(sizeof(*buv));
|
||||
*buv = texcoord_floats(uv, m->num_vertices*2);
|
||||
//*buv = float_buffer(uv, m->num_vertices*2);
|
||||
js_setpropstr(prim, "uv", sg_buffer2js(buv));
|
||||
|
||||
return prim;
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os,sprite,1),
|
||||
MIST_FUNC_DEF(os,sprite,0),
|
||||
MIST_FUNC_DEF(os, cwd, 0),
|
||||
MIST_FUNC_DEF(os, env, 1),
|
||||
MIST_FUNC_DEF(os, sys, 0),
|
||||
|
@ -1789,6 +1903,9 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||
MIST_FUNC_DEF(os, make_font, 2),
|
||||
MIST_FUNC_DEF(os, make_model, 1),
|
||||
MIST_FUNC_DEF(os, make_transform2d, 1),
|
||||
MIST_FUNC_DEF(os, make_emitter, 0),
|
||||
MIST_FUNC_DEF(os, make_buffer, 1),
|
||||
MIST_FUNC_DEF(os, make_line_prim, 2),
|
||||
};
|
||||
|
||||
#include "steam.h"
|
||||
|
|
|
@ -139,5 +139,6 @@ JSValue js_getpropidx(JSValue v, uint32_t i);
|
|||
JSValue js_getpropstr(JSValue v, const char *str);
|
||||
const char *js2str(JSValue v);
|
||||
void jsfreestr(const char *str);
|
||||
int js_arrlen(JSValue v);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,119 +1,37 @@
|
|||
#include "particle.h"
|
||||
#include "stb_ds.h"
|
||||
#include "render.h"
|
||||
#include "particle.sglsl.h"
|
||||
#include "2dphysics.h"
|
||||
#include "log.h"
|
||||
#include "simplex.h"
|
||||
#include "pthread.h"
|
||||
#include "math.h"
|
||||
|
||||
#define SCHED_IMPLEMENTATION
|
||||
#include "sched.h"
|
||||
|
||||
static emitter **emitters;
|
||||
|
||||
static sg_shader par_shader;
|
||||
static sg_pipeline par_pipe;
|
||||
static sg_bindings par_bind;
|
||||
static int draw_count;
|
||||
|
||||
#define MAX_PARTICLES 1000000
|
||||
|
||||
struct scheduler sched;
|
||||
void *mem;
|
||||
|
||||
struct par_vert {
|
||||
HMM_Vec2 pos;
|
||||
float angle;
|
||||
HMM_Vec2 scale;
|
||||
struct rgba color;
|
||||
};
|
||||
|
||||
typedef struct par_vert par_vert;
|
||||
|
||||
void particle_init()
|
||||
{
|
||||
sched_size needed;
|
||||
scheduler_init(&sched, &needed, 1, NULL);
|
||||
mem = calloc(needed, 1);
|
||||
scheduler_start(&sched,mem);
|
||||
|
||||
par_shader = sg_make_shader(particle_shader_desc(sg_query_backend()));
|
||||
|
||||
par_pipe = sg_make_pipeline(&(sg_pipeline_desc){
|
||||
.shader = par_shader,
|
||||
.layout = {
|
||||
.attrs = {
|
||||
[1].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
[2].format = SG_VERTEXFORMAT_FLOAT,
|
||||
[3].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
[4].format = SG_VERTEXFORMAT_UBYTE4N,
|
||||
[0].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
[0].buffer_index = 1
|
||||
},
|
||||
.buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE,
|
||||
},
|
||||
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
|
||||
.label = "particle pipeline",
|
||||
.cull_mode = SG_CULLMODE_BACK,
|
||||
.colors[0].blend = blend_trans,
|
||||
.depth = {
|
||||
.write_enabled = true,
|
||||
.compare = SG_COMPAREFUNC_LESS_EQUAL
|
||||
}
|
||||
});
|
||||
|
||||
par_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(par_vert)*MAX_PARTICLES,
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.usage = SG_USAGE_STREAM,
|
||||
.label = "particle buffer"
|
||||
});
|
||||
|
||||
float circleverts[8] = {
|
||||
0,0,
|
||||
0,1,
|
||||
1,0,
|
||||
1,1,
|
||||
};
|
||||
|
||||
par_bind.vertex_buffers[1] = sprite_quad;
|
||||
par_bind.fs.samplers[0] = std_sampler;
|
||||
}
|
||||
#include "log.h"
|
||||
|
||||
emitter *make_emitter() {
|
||||
emitter *e = calloc(sizeof(*e),1);
|
||||
|
||||
e->max = 20;
|
||||
arrsetcap(e->particles, e->max);
|
||||
arrsetcap(e->particles, 10);
|
||||
for (int i = 0; i < arrlen(e->particles); i++)
|
||||
e->particles[i].life = 0;
|
||||
|
||||
e->life = 10;
|
||||
e->tte = lerp(e->explosiveness, e->life/e->max, 0);
|
||||
//sampler_add(&e->color, 0, (HMM_Vec4){1,1,1,1});
|
||||
e->scale = 1;
|
||||
e->speed = 20;
|
||||
e->texture = NULL;
|
||||
arrpush(emitters,e);
|
||||
e->buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(struct par_vert),
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.usage = SG_USAGE_STREAM
|
||||
});
|
||||
return e;
|
||||
}
|
||||
|
||||
void emitter_free(emitter *e)
|
||||
{
|
||||
YughWarn("kill emitter");
|
||||
arrfree(e->particles);
|
||||
for (int i = arrlen(emitters)-1; i >= 0; i--)
|
||||
if (emitters[i] == e) {
|
||||
arrdelswap(emitters,i);
|
||||
break;
|
||||
}
|
||||
arrfree(e->verts);
|
||||
free(e);
|
||||
}
|
||||
|
||||
void start_emitter(emitter *e) { e->on = 1; }
|
||||
void stop_emitter(emitter *e) { e->on = 0; }
|
||||
|
||||
/* Variate a value around variance. Variance between 0 and 1. */
|
||||
|
||||
float variate(float val, float variance)
|
||||
|
@ -121,124 +39,84 @@ float variate(float val, float variance)
|
|||
return val + val*(frand(variance)-(variance/2));
|
||||
}
|
||||
|
||||
int emitter_spawn(emitter *e)
|
||||
int emitter_spawn(emitter *e, transform2d *t)
|
||||
{
|
||||
particle p;
|
||||
p.life = e->life;
|
||||
p.pos = (HMM_Vec4){e->t.pos.x,e->t.pos.y,0,0};
|
||||
float newan = e->t.rotation.Elements[0]+(2*HMM_PI*(frand(e->divergence)-(e->divergence/2)));
|
||||
p.pos = (HMM_Vec4){t->pos.x,t->pos.y,0,0};
|
||||
float newan = t->angle * HMM_TurnToRad*(frand(e->divergence)-(e->divergence/2));
|
||||
HMM_Vec2 norm = HMM_V2Rotate((HMM_Vec2){0,1}, newan);
|
||||
p.v = HMM_MulV4F((HMM_Vec4){norm.x,norm.y,0,0}, variate(e->speed, e->variation));
|
||||
p.angle = 0;
|
||||
p.scale = variate(e->scale, e->scale_var);
|
||||
// p.av = 1;
|
||||
p.angle = newan;
|
||||
p.scale = variate(e->scale*t->scale.x, e->scale_var);
|
||||
arrput(e->particles,p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void emitter_emit(emitter *e, int count)
|
||||
void emitter_emit(emitter *e, int count, transform2d *t)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
emitter_spawn(e);
|
||||
emitter_spawn(e, t);
|
||||
}
|
||||
|
||||
void emitters_step(double dt)
|
||||
void emitter_draw(emitter *e, sg_bindings bind)
|
||||
{
|
||||
for (int i = 0; i < arrlen(emitters); i++)
|
||||
emitter_step(emitters[i], dt);
|
||||
}
|
||||
|
||||
static struct par_vert pv[MAX_PARTICLES];
|
||||
|
||||
void parallel_pv(emitter *e, struct scheduler *sched, struct sched_task_partition t, sched_uint thread_num)
|
||||
{
|
||||
for (int i=t.start; i < t.end; i++) {
|
||||
if (arrlen(e->particles) == 0) return;
|
||||
arrsetlen(e->verts, arrlen(e->particles));
|
||||
for (int i = 0; i < arrlen(e->particles); i++) {
|
||||
if (e->particles[i].time >= e->particles[i].life) continue;
|
||||
particle *p = &e->particles[i];
|
||||
pv[i].pos = p->pos.xy;
|
||||
pv[i].angle = p->angle;
|
||||
float s = p->scale;
|
||||
if (p->time < e->grow_for)
|
||||
s = lerp(p->time/e->grow_for, 0, p->scale);
|
||||
particle *p = e->particles+i;
|
||||
e->verts[i].pos = p->pos.xy;
|
||||
e->verts[i].angle = p->angle;
|
||||
e->verts[i].scale = p->scale;
|
||||
/* if (p->time < e->grow_for)
|
||||
e->verts[i].scale = lerp(p->time/e->grow_for, 0, p->scale);
|
||||
else if (p->time > (p->life - e->shrink_for))
|
||||
s = lerp((p->time-(p->life-e->shrink_for))/e->shrink_for, p->scale, 0);
|
||||
pv[i].scale = HMM_ScaleV2((HMM_Vec2){e->texture->width,e->texture->height}, s);
|
||||
pv[i].color = vec2rgba(p->color);
|
||||
e->verts[i].scale = lerp((p->time-(p->life-e->shrink_for))/e->shrink_for, p->scale, 0);*/
|
||||
e->verts[i].color = vec2rgba(p->color);
|
||||
}
|
||||
}
|
||||
|
||||
void emitter_draw(emitter *e, gameobject *go)
|
||||
{
|
||||
sg_apply_pipeline(par_pipe);
|
||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(useproj));
|
||||
sg_apply_bindings(&par_bind);
|
||||
par_bind.fs.images[0] = e->texture->id;
|
||||
struct sched_task task;
|
||||
scheduler_add(&sched, &task, parallel_pv, e, arrlen(e->particles), arrlen(e->particles)/sched.threads_num);
|
||||
scheduler_join(&sched, &task);
|
||||
sg_append_buffer(par_bind.vertex_buffers[0], &(sg_range){.ptr=&pv, .size=sizeof(struct par_vert)*arrlen(e->particles)});
|
||||
draw_count += arrlen(e->particles);
|
||||
sg_draw(0,4,draw_count);
|
||||
}
|
||||
|
||||
void emitters_draw(HMM_Mat4 *proj)
|
||||
{
|
||||
if (arrlen(emitters) == 0) return;
|
||||
int draw_count = 0;
|
||||
for (int i = 0; i < arrlen(emitters); i++) {
|
||||
emitter *e = emitters[i];
|
||||
par_bind.fs.images[0] = e->texture->id;
|
||||
|
||||
struct sched_task task;
|
||||
scheduler_add(&sched, &task, parallel_pv, e, arrlen(e->particles), arrlen(e->particles)/sched.threads_num);
|
||||
scheduler_join(&sched, &task);
|
||||
sg_range verts;
|
||||
verts.ptr = e->verts;
|
||||
verts.size = sizeof(*e->verts)*arrlen(e->verts);
|
||||
if (sg_query_buffer_will_overflow(e->buffer, verts.size))
|
||||
e->buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = verts.size,
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.usage = SG_USAGE_STREAM
|
||||
});
|
||||
|
||||
sg_append_buffer(par_bind.vertex_buffers[0], &(sg_range){.ptr=&pv, .size=sizeof(struct par_vert)*arrlen(e->particles)});
|
||||
draw_count += arrlen(e->particles);
|
||||
}
|
||||
|
||||
sg_apply_pipeline(par_pipe);
|
||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(*proj));
|
||||
sg_apply_bindings(&par_bind);
|
||||
sg_draw(0, 4, draw_count);
|
||||
sg_append_buffer(e->buffer, &verts);
|
||||
|
||||
bind.vertex_buffers[0] = e->buffer;
|
||||
sg_apply_bindings(&bind);
|
||||
sg_draw(0,4,arrlen(e->verts));
|
||||
}
|
||||
|
||||
static double dt;
|
||||
static HMM_Vec4 g_accel;
|
||||
|
||||
void parallel_step(emitter *e, struct scheduler *shed, struct sched_task_partition t, sched_uint thread_num)
|
||||
{
|
||||
for (int i = t.end-1; i >=0; i--) {
|
||||
void emitter_step(emitter *e, double dt, transform2d *t) {
|
||||
HMM_Vec4 g_accel = HMM_MulV4F((HMM_Vec4){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0, 0}, dt);
|
||||
|
||||
for (int i = 0; i < arrlen(e->particles); i++) {
|
||||
if (e->particles[i].time >= e->particles[i].life) continue;
|
||||
|
||||
if (e->warp_mask & gravmask)
|
||||
e->particles[i].v = HMM_AddV4(e->particles[i].v, g_accel);
|
||||
|
||||
//if (e->warp_mask & gravmask)
|
||||
// e->particles[i].v = HMM_AddV4(e->particles[i].v, g_accel);
|
||||
|
||||
e->particles[i].pos = HMM_AddV4(e->particles[i].pos, HMM_MulV4F(e->particles[i].v, dt));
|
||||
e->particles[i].angle += e->particles[i].av*dt;
|
||||
e->particles[i].time += dt;
|
||||
e->particles[i].color = sample_sampler(&e->color, e->particles[i].time/e->particles[i].life);
|
||||
e->particles[i].scale = e->scale;
|
||||
|
||||
|
||||
if (e->particles[i].time >= e->particles[i].life)
|
||||
arrdelswap(e->particles, i);
|
||||
else if (query_point(e->particles[i].pos.xy))
|
||||
arrdelswap(e->particles,i);
|
||||
}
|
||||
}
|
||||
|
||||
void emitter_step(emitter *e, double mdt) {
|
||||
dt = mdt;
|
||||
g_accel = HMM_MulV4F((HMM_Vec4){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0, 0}, dt);
|
||||
if (arrlen(e->particles) == 0) return;
|
||||
struct sched_task task;
|
||||
scheduler_add(&sched, &task, parallel_step, e, arrlen(e->particles), arrlen(e->particles)/sched.threads_num);
|
||||
scheduler_join(&sched, &task);
|
||||
|
||||
if (!e->on) return;
|
||||
e->tte-=dt;
|
||||
if (e->tte <= 0) {
|
||||
emitter_spawn(e);
|
||||
emitter_spawn(e, t);
|
||||
e->tte = lerp(e->explosiveness, e->life/e->max,0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "texture.h"
|
||||
#include "anim.h"
|
||||
#include "gameobject.h"
|
||||
#include "render.h"
|
||||
|
||||
typedef struct particle {
|
||||
HMM_Vec4 pos;
|
||||
|
@ -23,9 +24,16 @@ typedef struct particle {
|
|||
#define CLOUD 1
|
||||
#define MESH 2
|
||||
|
||||
typedef struct par_vert {
|
||||
HMM_Vec2 pos;
|
||||
float angle;
|
||||
float scale;
|
||||
struct rgba color;
|
||||
} par_vert;
|
||||
|
||||
typedef struct emitter {
|
||||
struct particle *particles;
|
||||
transform3d t;
|
||||
par_vert *verts;
|
||||
HMM_Vec3 *mesh; /* list of points to optionally spawn from */
|
||||
HMM_Vec3 *norm; /* norm at each point */
|
||||
int type; /* spray, cloud, or mesh */
|
||||
|
@ -44,8 +52,6 @@ typedef struct emitter {
|
|||
float scale_var;
|
||||
float grow_for; /* seconds to grow from small until scale */
|
||||
float shrink_for; /* seconds to shrink to small prior to its death */
|
||||
/* PARTICLE TYPE */
|
||||
texture *texture;
|
||||
/* ROTATION AND COLLISION */
|
||||
int collision_mask; /* mask for collision */
|
||||
float bounce; /* bounce back after collision */
|
||||
|
@ -55,22 +61,15 @@ typedef struct emitter {
|
|||
float persist_var;
|
||||
/* TRAILS */
|
||||
warpmask warp_mask;
|
||||
int on;
|
||||
double tte; /* time to emit */
|
||||
double tte; /* time to emit */
|
||||
sg_buffer buffer;
|
||||
} emitter;
|
||||
|
||||
void particle_init();
|
||||
|
||||
emitter *make_emitter();
|
||||
void emitter_free(emitter *e);
|
||||
|
||||
void start_emitter(emitter *e);
|
||||
void stop_emitter(emitter *e);
|
||||
|
||||
void emitter_emit(emitter *e, int count);
|
||||
void emitters_step(double dt);
|
||||
void emitter_draw(emitter *e, gameobject *go);
|
||||
void emitters_draw(HMM_Mat4 *proj);
|
||||
void emitter_step(emitter *e, double dt);
|
||||
void emitter_emit(emitter *e, int count, transform2d *t);
|
||||
void emitter_step(emitter *e, double dt, transform2d *t);
|
||||
void emitter_draw(emitter *e, sg_bindings bind);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
#include "sokol/sokol_glue.h"
|
||||
#include "stb_image_write.h"
|
||||
|
||||
#include "box.sglsl.h"
|
||||
#include "shadow.sglsl.h"
|
||||
|
||||
#include "sokol/sokol_gfx.h"
|
||||
#include "sokol_gfx_ext.h"
|
||||
|
||||
|
@ -31,7 +28,6 @@
|
|||
HMM_Vec2 campos = {0,0};
|
||||
float camzoom = 1;
|
||||
|
||||
sg_buffer sprite_quad;
|
||||
sg_sampler std_sampler;
|
||||
sg_sampler tex_sampler;
|
||||
|
||||
|
@ -127,14 +123,6 @@ void capture_screen(int x, int y, int w, int h, const char *path)
|
|||
|
||||
sg_pass_action pass_action = {0};
|
||||
|
||||
static struct {
|
||||
sg_pass_action pass_action;
|
||||
|
||||
sg_pass pass;
|
||||
sg_pipeline pipe;
|
||||
sg_shader shader;
|
||||
} sg_shadow;
|
||||
|
||||
void trace_apply_pipeline(sg_pipeline pip, void *data)
|
||||
{
|
||||
// YughSpam("Applying pipeline %u %s.", pip, sg_query_pipeline_desc(pip).label);
|
||||
|
@ -227,20 +215,6 @@ void render_init() {
|
|||
.logger = { .func = sg_logging },
|
||||
.buffer_pool_size = 1024
|
||||
});
|
||||
|
||||
float quad[] = {
|
||||
0,0,
|
||||
1,0,
|
||||
0,1,
|
||||
1,1
|
||||
};
|
||||
|
||||
sprite_quad = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data = quad,
|
||||
.size = sizeof(quad),
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.label = "sprite quad"
|
||||
});
|
||||
|
||||
std_sampler = sg_make_sampler(&(sg_sampler_desc){});
|
||||
tex_sampler = sg_make_sampler(&(sg_sampler_desc){
|
||||
|
@ -262,69 +236,6 @@ void render_init() {
|
|||
pass_action = (sg_pass_action){
|
||||
.colors[0] = {.load_action = SG_LOADACTION_CLEAR, .clear_value = c},
|
||||
};
|
||||
|
||||
sg_gif.shader = sg_make_shader(box_shader_desc(sg_query_backend()));
|
||||
|
||||
sg_gif.pipe = sg_make_pipeline(&(sg_pipeline_desc){
|
||||
.shader = sg_gif.shader,
|
||||
.layout = {
|
||||
.attrs = {
|
||||
[0].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
[1].format = SG_VERTEXFORMAT_FLOAT2
|
||||
}
|
||||
},
|
||||
.colors[0].pixel_format = SG_PIXELFORMAT_RGBA8,
|
||||
.label = "gif pipe",
|
||||
});
|
||||
|
||||
float crt_quad[] = {
|
||||
-1, 1, 0, 1,
|
||||
-1, -1, 0, 0,
|
||||
1, -1, 1, 0,
|
||||
-1, 1, 0, 1,
|
||||
1, -1, 1, 0,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
|
||||
float gif_quad[] = {
|
||||
-1, 1, 0, 1,
|
||||
-1, -1, 0, 0,
|
||||
1, -1, 1, 0,
|
||||
-1, 1, 0, 1,
|
||||
1, -1, 1, 0,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
|
||||
sg_limits ll = sg_query_limits();
|
||||
printf("attribute limits %d\n", ll.max_vertex_attrs);
|
||||
|
||||
sg_gif.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(gif_quad),
|
||||
.data = gif_quad,
|
||||
.label = "gif vert buffer",
|
||||
});
|
||||
sg_gif.bind.fs.samplers[0] = std_sampler;
|
||||
|
||||
sg_crt.shader = sg_make_shader(crt_shader_desc(sg_query_backend()));
|
||||
sg_crt.pipe = sg_make_pipeline(&(sg_pipeline_desc){
|
||||
.shader = sg_crt.shader,
|
||||
.layout = {
|
||||
.attrs = {
|
||||
[0].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
[1].format = SG_VERTEXFORMAT_FLOAT2
|
||||
}
|
||||
},
|
||||
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
|
||||
});
|
||||
|
||||
sg_crt.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(crt_quad),
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.usage = SG_USAGE_IMMUTABLE,
|
||||
.data = SG_RANGE(crt_quad),
|
||||
|
||||
.label = "crt vert buffer",
|
||||
});
|
||||
}
|
||||
|
||||
HMM_Mat4 projection = {0.f};
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "HandmadeMath.h"
|
||||
#include "gameobject.h"
|
||||
#include "transform.h"
|
||||
#include "model.h"
|
||||
|
||||
#define RGBA_MAX 255
|
||||
|
||||
|
@ -33,7 +34,6 @@ extern HMM_Mat4 hudproj;
|
|||
extern HMM_Mat4 useproj;
|
||||
extern sg_pass_action pass_action;
|
||||
|
||||
extern sg_buffer sprite_quad;
|
||||
extern sg_sampler std_sampler;
|
||||
extern sg_sampler tex_sampler;
|
||||
|
||||
|
|
|
@ -21,18 +21,18 @@ typedef union NoiseUnion {
|
|||
noiseNDptr pn;
|
||||
} genericNoise;
|
||||
|
||||
extern double Noise2D(double x, double y);
|
||||
extern double Noise3D(double x, double y, double z);
|
||||
extern double Noise4D(double x, double y, double z, double w);
|
||||
double Noise2D(double x, double y);
|
||||
double Noise3D(double x, double y, double z);
|
||||
double Noise4D(double x, double y, double z, double w);
|
||||
|
||||
extern double GBlur1D(double stdDev, double x);
|
||||
extern double GBlur2D(double stdDev, double x, double y);
|
||||
double GBlur1D(double stdDev, double x);
|
||||
double GBlur2D(double stdDev, double x, double y);
|
||||
|
||||
extern double Noise(genericNoise func, int len, double args[]);
|
||||
double Noise(genericNoise func, int len, double args[]);
|
||||
|
||||
extern double TurbulentNoise(genericNoise func, int direction, int iterations, int len, double args[]);
|
||||
extern double FractalSumNoise(genericNoise func, int iterations, int len, double args[]);
|
||||
extern double FractalSumAbsNoise(genericNoise func, int iterations, int len, double args[]);
|
||||
double TurbulentNoise(genericNoise func, int direction, int iterations, int len, double args[]);
|
||||
double FractalSumNoise(genericNoise func, int iterations, int len, double args[]);
|
||||
double FractalSumAbsNoise(genericNoise func, int iterations, int len, double args[]);
|
||||
|
||||
double octave_3d(double x, double y, double z, int octaves, double persistence);
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ void c_init() {
|
|||
window_resize(sapp_width(), sapp_height());
|
||||
phys2d_init();
|
||||
render_init();
|
||||
particle_init();
|
||||
if (!JS_IsUndefined(c_start)) {
|
||||
script_call_sym(c_start,0,NULL);
|
||||
JS_FreeValue(js, c_start);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
@vs vs
|
||||
in vec2 pos;
|
||||
|
||||
uniform vs_p { mat4 proj; };
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = proj * vec4(pos,0.0,1.0);
|
||||
}
|
||||
@end
|
||||
|
||||
@fs fs
|
||||
void main()
|
||||
{
|
||||
|
||||
}
|
||||
@end
|
||||
|
||||
@program particle vs fs
|
|
@ -1,3 +0,0 @@
|
|||
void main(){
|
||||
color = texture( myTextureSampler, UV );
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
void main(){
|
||||
|
||||
// Output position of the vertex, in clip space
|
||||
// map [0..800][0..600] to [-1..1][-1..1]
|
||||
vec2 vertexPosition_homoneneousspace = vertexPosition_screenspace - vec2(400,300); // [0..800][0..600] -> [-400..400][-300..300]
|
||||
vertexPosition_homoneneousspace /= vec2(400,300);
|
||||
gl_Position = vec4(vertexPosition_homoneneousspace,0,1);
|
||||
|
||||
// UV of the vertex. No special space for this one.
|
||||
UV = vertexUV;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#version 330 core
|
||||
layout (location = 0) out vec4 color;
|
||||
|
||||
in vec3 vcolor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
color = vec4(vcolor, 1.f);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 color;
|
||||
|
||||
layout (std140) uniform Matrices {
|
||||
mat4 projection;
|
||||
mat4 view;
|
||||
};
|
||||
|
||||
out vec3 vcolor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * vec4(position, 1.0f);
|
||||
|
||||
vcolor = color;
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
@vs vs
|
||||
in vec3 a_pos;
|
||||
in vec2 a_tex_coords;
|
||||
in vec3 a_norm;
|
||||
|
||||
out vec2 tex_coords;
|
||||
out vec3 normal;
|
||||
out vec3 frag_pos;
|
||||
out vec4 frag_pos_light;
|
||||
|
||||
uniform vs_p {
|
||||
uniform mat4 vp;
|
||||
uniform mat4 model;
|
||||
uniform mat4 proj;
|
||||
uniform mat4 lsm;
|
||||
};
|
||||
|
||||
void main() {
|
||||
frag_pos = vec3(model * vec4(a_pos, 1.0));
|
||||
gl_Position = proj * vp * vec4(frag_pos, 1.0);
|
||||
tex_coords = a_tex_coords;
|
||||
normal = mat3(transpose(inverse(model))) * a_norm;
|
||||
frag_pos_light = lsm * vec4(frag_pos, 1.0);
|
||||
}
|
||||
@end
|
||||
|
||||
@fs fs
|
||||
in vec2 tex_coords;
|
||||
in vec3 normal;
|
||||
in vec3 frag_pos;
|
||||
in vec4 frag_pos_light;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
uniform texture2D diffuse;
|
||||
uniform texture2D normmap;
|
||||
uniform texture2D shadow_map;
|
||||
uniform sampler smp;
|
||||
|
||||
uniform fs_p {
|
||||
uniform vec3 point_pos;
|
||||
uniform vec3 dir_dir;
|
||||
uniform vec3 view_pos;
|
||||
uniform vec3 spot_pos;
|
||||
uniform vec3 spot_dir;
|
||||
uniform vec2 shadow_dim;
|
||||
};
|
||||
/* Ambient light */
|
||||
float amb_str = 0.3;
|
||||
|
||||
vec3 amb_color = vec3(1,1,1);
|
||||
|
||||
float spec_str = 0.5;
|
||||
|
||||
/* point */
|
||||
float constant = 1;
|
||||
float linear = 0.09;
|
||||
float quad = 0.032;
|
||||
|
||||
/* spotlight */
|
||||
float cutoff = 12.5; /* cutoff in radians */
|
||||
float outer_cutoff = 17.5;
|
||||
|
||||
vec3 norm = vec3(0,0,0);
|
||||
vec3 view = vec3(0,0,0);
|
||||
|
||||
float light_str(vec3 dir)
|
||||
{
|
||||
float d = max(dot(norm, dir), 0.0);
|
||||
vec3 refl = reflect(-dir, norm);
|
||||
float s = pow(max(dot(view,refl), 0.0), 32);
|
||||
|
||||
return s+d;
|
||||
}
|
||||
|
||||
float shadow_calc(vec4 fg)
|
||||
{
|
||||
vec3 pc = fg.xyz / fg.w;
|
||||
pc = pc * 0.5 + 0.5;
|
||||
|
||||
if (pc.z > 1.0)
|
||||
return 0.0;
|
||||
|
||||
float closest_depth = texture(sampler2D(shadow_map,smp), pc.xy).r;
|
||||
float cur_depth = pc.z;
|
||||
|
||||
vec3 light_dir = normalize(vec3(4,100,20) - frag_pos); /* light pos */
|
||||
float bias = max(0.05 * (1 - dot(norm, light_dir)), 0.005);
|
||||
|
||||
return cur_depth - bias > closest_depth ? 1.0 : 0.0;
|
||||
|
||||
float s;
|
||||
vec2 texel_size = 1 / shadow_dim;
|
||||
|
||||
for (int x = -1; x <= 1; ++x) {
|
||||
for (int y = -1; y <= 1; ++y) {
|
||||
float pcf_depth = texture(sampler2D(shadow_map,smp), pc.xy + vec2(x,y) * texel_size).r;
|
||||
s += cur_depth - bias > pcf_depth ? 1.0 : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
s /= 9.0;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void main() {
|
||||
norm = normalize(normal);
|
||||
view = normalize(view_pos - frag_pos);
|
||||
|
||||
float point_amt = light_str(normalize(point_pos-frag_pos));
|
||||
float dist = length(point_pos - frag_pos);
|
||||
float atten = 1.0 / (constant + linear * dist + quad * (dist*dist));
|
||||
point_amt *= atten;
|
||||
|
||||
float dir_amt = light_str(normalize(-dir_dir));
|
||||
|
||||
vec3 spot_dir = normalize(spot_pos - frag_pos);
|
||||
float theta = dot(spot_dir, normalize(-spot_dir));
|
||||
float spot_amt = 0;
|
||||
|
||||
float epsilon = cutoff - outer_cutoff;
|
||||
|
||||
if (theta > cutoff) {
|
||||
float intensity = clamp((theta - outer_cutoff)/epsilon,0.0,1.0);
|
||||
spot_amt = light_str(spot_dir) * intensity;
|
||||
}
|
||||
|
||||
vec4 mm = texture(sampler2D(diffuse,smp),tex_coords);
|
||||
float shadow = shadow_calc(frag_pos_light);
|
||||
vec3 res = mm.rgb * (amb_str + (point_amt + dir_amt) * (1 - shadow));
|
||||
frag_color = vec4(res, mm.a);
|
||||
}
|
||||
@end
|
||||
|
||||
@program diffuse vs fs
|
|
@ -1,44 +0,0 @@
|
|||
@vs vs
|
||||
in vec2 vertex;
|
||||
in vec2 apos;
|
||||
in float angle;
|
||||
in vec2 scale;
|
||||
in vec4 vc;
|
||||
|
||||
out vec4 fcolor;
|
||||
out vec2 uv;
|
||||
|
||||
uniform vs_p { mat4 proj; };
|
||||
|
||||
void main()
|
||||
{
|
||||
fcolor = vc;
|
||||
uv = vertex;
|
||||
vec2 v = vertex - 0.5;
|
||||
vec2 p = vec2(
|
||||
cos(angle)*v.x-sin(angle)*v.y,
|
||||
sin(angle)*v.x+cos(angle)*v.y
|
||||
);
|
||||
p *= scale;
|
||||
p += apos;
|
||||
|
||||
gl_Position = proj * vec4(p, 0.0, 1.0);
|
||||
}
|
||||
@end
|
||||
|
||||
@fs fs
|
||||
in vec4 fcolor;
|
||||
out vec4 color;
|
||||
|
||||
in vec2 uv;
|
||||
uniform texture2D image;
|
||||
uniform sampler smp;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(sampler2D(image,smp),uv);
|
||||
color *= fcolor;
|
||||
}
|
||||
@end
|
||||
|
||||
@program particle vs fs
|
Loading…
Reference in a new issue