fix videos, gifs, aseprite

This commit is contained in:
2024-12-04 09:08:44 -06:00
parent 92e07b3018
commit ae39e60095
12 changed files with 66 additions and 390 deletions

View File

@@ -87,7 +87,7 @@ if get_option('enet')
endif
sources = []
src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c','texture.c', 'timer.c', 'transform.c','warp.c','yugine.c', 'wildmatch.c', 'cv.cpp']
src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','warp.c','yugine.c', 'wildmatch.c', 'cv.cpp']
imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp']

View File

@@ -1014,6 +1014,9 @@ render.tile = function tile(image, rect = [0,0], color = Color.white)
if (typeof image === "string")
image = game.texture(image);
render._main.tile(image, rect, undefined, 1);
return;
var tex = image.texture;
if (!tex) return;
@@ -1136,10 +1139,6 @@ render.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.wh
render.draw(shape.quad);
};
function endframe() {
tdraw = 0;
}
var textssbos = [];
var tdraw = 0;
var cur_font = undefined;
@@ -1191,6 +1190,16 @@ render.draw = function render_draw(mesh, ssbo, inst = 1, e_start = 0) {
render.spdraw(e_start, cur.bind.count, inst);
};
render.viewport = function(rect)
{
render._main.viewport(rect);
}
render.scissor = function(rect)
{
render.viewport(rect)
}
// Camera viewport is a rectangle with the bottom left corner defined as x,y. Units are pixels on the window.
function camviewport() {
var aspect = (((this.viewport[2] - this.viewport[0]) / (this.viewport[3] - this.viewport[1])) * prosperon.size.x) / prosperon.size.y;
@@ -1423,75 +1432,19 @@ var imgui_fn = function imgui_fn() {
var clearcolor = [100,149,237,255].scale(1/255);
prosperon.render = function prosperon_render() {
try{
// render.glue_pass();
render._main.draw_color(clearcolor);
render._main.clear();
/* render.set_view(prosperon.camera.transform);
render.set_projection_ortho({
l:-prosperon.camera.size.x/2,
r:prosperon.camera.size.x/2,
b:-prosperon.camera.size.y/2,
t:prosperon.camera.size.y/2
}, prosperon.camera.near,prosperon.camera.far);
render.viewport(prosperon.camera.view(), false);
if (render.draw_sprites) render.sprites();
if (render.draw_particles) draw_emitters();
*/
// render.fillmask(0);
// render.forceflush();
/* render.set_projection_ortho({
l:0,
r:prosperon.camera.size.x,
b:-prosperon.camera.size.y,
t:0
},-1,1);
*/
// render.set_view(unit_transform);
// set to world cam
prosperon.draw();
if (render.draw_hud) prosperon.hud();
// render.forceflush();
/* render.set_projection_ortho({
l:0,
r:prosperon.size.x,
b:-prosperon.size.y,
t:0
},-1,1);
render.viewport({
t:0,
height:prosperon.size.y,
width:prosperon.size.x,
l:0
}, false);
*/
// prosperon.app();
// render.forceflush();
// if (debug.show) imgui_fn();
} catch(e) {
throw e;
} finally {
// random tracy image
/* var vals = Object.values(game.texture.cache);
var tex = vals[Math.floor(Math.random()*vals.length)].texture;
var texdata = os.tex_data(tex)
tracy.image(texdata, tex.width, tex.height);
*/
// render.end_pass();
// render.commit();
render._main.present();
endframe();
tracy.gpu_collect();
tracy.end_frame();
tracy.gpu_sync();
/* var rtinfo = os.rt_info();
for (var i in rtinfo) {
console.log(`${i} is ${rtinfo[i]}`);
tracy.plot(i, rtinfo[i]);
}*/
}
};
@@ -1537,7 +1490,8 @@ prosperon.process = function process() {
*/
}
tracy.gpu_zone(prosperon.render);
prosperon.render();
// tracy.gpu_zone(prosperon.render);
};
return { render };

View File

@@ -301,7 +301,7 @@ Cmdline.register_order(
if (io.exists("config.js")) global.mixin("config.js");
else console.warn("No config.js file found. Starting with default parameters.");
var window = game.engine_start(prosperon);
var renderer = window.make_renderer("vulkan");
var renderer = window.make_renderer("gpu");
render._main = renderer;
prosperon.init();

View File

@@ -112,19 +112,19 @@ Ease.elastic = {
Ease.elastic.c4 = (2 * Math.PI) / 3;
Ease.elastic.c5 = (2 * Math.PI) / 4.5;
var tween = function (from, to, time, fn, endfn) {
var start = profile.secs(profile.now());
var tween = function (from, to, time, fn) {
var start = profile.now()
var update = function tween_update(dt) {
var elapsed = profile.secs(profile.now()) - start;
var elapsed = profile.now() - start;
fn(from.lerp(to, elapsed / time));
if (elapsed >= time) {
fn(to);
if (stop.then) stop.then();
stop();
endfn?.();
}
};
var stop = Register.update.register(update);
console.log(update)
return stop;
};

View File

@@ -1,7 +1,6 @@
#include "datastream.h"
#include "limits.h"
#include "texture.h"
#include <stdbool.h>
#include <stdlib.h>
#include "font.h"
@@ -12,27 +11,10 @@
void datastream_free(JSRuntime *rt,datastream *ds)
{
// sg_destroy_image(ds->img);
plm_destroy(ds->plm);
free(ds);
}
//void soundstream_fillbuf(struct datastream *ds, soundbyte *buf, int frames) {
// for (int i = 0; i < frames*CHANNELS; i++)
// buf[i] = ringshift(ds->ring);
//}
static void render_frame(plm_t *mpeg, plm_frame_t *frame, struct datastream *ds) {
if (ds->dirty) return;
uint8_t rgb[frame->height*frame->width*4];
memset(rgb,255,frame->height*frame->width*4);
plm_frame_to_rgba(frame, rgb, frame->width*4);
// sg_image_data imgd = {0};
// imgd.subimage[0][0] = SG_RANGE(rgb);
// sg_update_image(ds->img, &imgd);
ds->dirty = true;
}
static void render_audio(plm_t *mpeg, plm_samples_t *samples, struct datastream *ds) {
// for (int i = 0; i < samples->count * CHANNELS; i++)
// ringpush(ds->ring, samples->interleaved[i]);
@@ -41,41 +23,20 @@ static void render_audio(plm_t *mpeg, plm_samples_t *samples, struct datastream
struct datastream *ds_openvideo(void *raw, size_t rawlen)
{
struct datastream *ds = malloc(sizeof(*ds));
ds->plm = plm_create_with_memory(raw, rawlen, 0);
free(raw);
void *newraw = malloc(rawlen);
memcpy(newraw,raw,rawlen);
ds->plm = plm_create_with_memory(newraw, rawlen, 1);
if (!ds->plm)
if (!ds->plm) {
free(ds);
free(newraw);
return NULL;
/* ds->img = sg_make_image(&(sg_image_desc){
.width = plm_get_width(ds->plm),
.height = plm_get_height(ds->plm),
.usage = SG_USAGE_STREAM,
.type = SG_IMAGETYPE_2D,
.pixel_format = SG_PIXELFORMAT_RGBA8,
});
*/
plm_set_video_decode_callback(ds->plm, render_frame, ds);
return ds;
// ds->ring = ringnew(ds->ring, 8192);
// plugin_node(make_node(ds, soundstream_fillbuf, NULL), masterbus);
plm_set_audio_decode_callback(ds->plm, render_audio, ds);
plm_set_loop(ds->plm, false);
plm_set_audio_enabled(ds->plm, true);
plm_set_audio_stream(ds->plm, 0);
// Adjust the audio lead time according to the audio_spec buffer size
// plm_set_audio_lead_time(ds->plm, BUF_FRAMES / SAMPLERATE);
}
return ds;
}
void ds_advance(struct datastream *ds, double s) {
ds->dirty = false;
plm_decode(ds->plm, s);
}
@@ -83,13 +44,6 @@ void ds_seek(struct datastream *ds, double time) {
plm_seek(ds->plm, time, false);
}
void ds_advanceframes(struct datastream *ds, int frames) {
for (int i = 0; i < frames; i++) {
plm_frame_t *frame = plm_decode_video(ds->plm);
render_frame(ds->plm, frame, ds);
}
}
double ds_length(struct datastream *ds) {
return plm_get_duration(ds->plm);
}

View File

@@ -5,26 +5,23 @@
#include <stdint.h>
#include <quickjs.h>
struct soundstream;
#include <SDL3/SDL.h>
struct datastream {
plm_t *plm;
JSValue callback;
JSContext *js;
int width;
int height;
int dirty;
};
typedef struct datastream datastream;
struct texture;
void datastream_free(JSRuntime *rt,datastream *ds);
struct datastream *ds_openvideo(void *raw, size_t rawlen);
struct texture *ds_maketexture(struct datastream *);
void ds_advance(struct datastream *ds, double);
void ds_advance(struct datastream *ds, double); // advance time in seconds
void ds_seek(struct datastream *ds, double);
void ds_advanceframes(struct datastream *ds, int frames);
void ds_pause(struct datastream *ds);
void ds_stop(struct datastream *ds);
int ds_videodone(struct datastream *ds);

View File

@@ -4,7 +4,6 @@
#include "render.h"
#include "HandmadeMath.h"
#include <quickjs.h>
#include "texture.h"
#include <SDL3/SDL.h>
#include "render.h"

View File

@@ -1431,6 +1431,7 @@ JSC_CCALL(game_renderers,
JSC_CCALL(game_cameras,
int num;
SDL_CameraID *ids = SDL_GetCameras(&num);
if (num == 0) return JS_UNDEFINED;
JSValue jsids = JS_NewArray(js);
for (int i = 0; i < num; i++)
JS_SetPropertyUint32(js,jsids, i, number2js(js,ids[i]));
@@ -2306,24 +2307,20 @@ static const JSCFunctionListEntry js_transform_funcs[] = {
};
JSC_CCALL(datastream_time, return number2js(js,plm_get_time(js2datastream(js,self)->plm)); )
JSC_CCALL(datastream_advance_frames, ds_advanceframes(js2datastream(js,self), js2number(js,argv[0])))
JSC_CCALL(datastream_seek, ds_seek(js2datastream(js,self), js2number(js,argv[0])))
JSC_CCALL(datastream_advance, ds_advance(js2datastream(js,self), js2number(js,argv[0])))
JSC_CCALL(datastream_duration, return number2js(js,ds_length(js2datastream(js,self))))
JSC_CCALL(datastream_framerate, return number2js(js,plm_get_framerate(js2datastream(js,self)->plm)))
JSC_GETSET_CALLBACK(datastream, callback)
static const JSCFunctionListEntry js_datastream_funcs[] = {
MIST_FUNC_DEF(datastream, time, 0),
MIST_FUNC_DEF(datastream, advance_frames, 1),
MIST_FUNC_DEF(datastream, seek, 1),
MIST_FUNC_DEF(datastream, advance, 1),
MIST_FUNC_DEF(datastream, duration, 0),
MIST_FUNC_DEF(datastream, framerate, 0),
CGETSET_ADD(datastream, callback),
};
JSC_GETSET_CALLBACK(timer, fn)
@@ -2663,8 +2660,6 @@ JSC_CCALL(os_make_texture,
void *raw = JS_GetArrayBuffer(js, &len, argv[0]);
if (!raw) return JS_ThrowReferenceError(js, "could not load texture with array buffer");
struct texture *tex = calloc(1, sizeof(*tex));
int n, width, height;
void *data = stbi_load_from_memory(raw, len, &width, &height, &n, 0);
@@ -2696,33 +2691,24 @@ JSC_CCALL(os_make_gif,
if (!raw) return JS_ThrowReferenceError(js, "could not load gif from supplied array buffer");
int n;
texture *tex = calloc(1,sizeof(*tex));
int frames;
int *delays;
tex->data = stbi_load_gif_from_memory(raw, rawlen, &delays, &tex->width, &tex->height, &frames, &n, 4);
tex->height *= frames;
int width;
int height;
void *pixels = stbi_load_gif_from_memory(raw, rawlen, &delays, &width, &height, &frames, &n, 4);
JSValue gif = JS_NewObject(js);
JSValue delay_arr = JS_NewArray(js);
JSValue jstex = JS_UNDEFINED; //texture2js(js,tex);
float yslice = 1.0/frames;
for (int i = 0; i < frames; i++) {
JSValue frame = JS_NewObject(js);
JS_SetPropertyStr(js, frame, "time", number2js(js,(float)delays[i]/1000.0));
JS_SetPropertyStr(js, frame, "rect", rect2js(js,(rect){
.x = 0,
.y = yslice*i,
.w = 1,
.h = yslice
}));
JS_SetPropertyStr(js, frame, "texture", JS_DupValue(js,jstex));
SDL_Surface *framesurf = SDL_CreateSurfaceFrom(width,height,SDL_PIXELFORMAT_RGBA32,pixels+(width*height*4*i), width*4);
JS_SetPropertyStr(js, frame, "surface", SDL_Surface2js(js,framesurf));
JS_SetPropertyUint32(js, delay_arr, i, frame);
}
JS_SetPropertyStr(js, gif, "frames", delay_arr);
JS_FreeValue(js,jstex);
free(delays);
ret = gif;
@@ -2731,12 +2717,8 @@ JSC_CCALL(os_make_gif,
JSValue aseframe2js(JSContext *js, ase_frame_t aframe)
{
JSValue frame = JS_NewObject(js);
texture *tex = calloc(1,sizeof(*tex));
tex->width = aframe.ase->w;
tex->height = aframe.ase->h;
tex->data = malloc(tex->width*tex->height*4);
memcpy(tex->data, aframe.pixels, tex->width*tex->height*4);
// JS_SetPropertyStr(js, frame, "texture", texture2js(js,tex));
SDL_Surface *surf = SDL_CreateSurfaceFrom(aframe.ase->w, aframe.ase->h, SDL_PIXELFORMAT_RGBA32, aframe.pixels, aframe.ase->w*4);
JS_SetPropertyStr(js, frame, "surface", SDL_Surface2js(js,surf));
JS_SetPropertyStr(js, frame, "rect", rect2js(js,(rect){.x=0,.y=0,.w=1,.h=1}));
JS_SetPropertyStr(js, frame, "time", number2js(js,(float)aframe.duration_milliseconds/1000.0));
return frame;
@@ -2969,14 +2951,30 @@ JSC_CCALL(os_make_plane,
return parmesh2js(js,par_shapes_create_plane(js2number(js,argv[0]), js2number(js,argv[1])));
)
static void render_frame(plm_t *mpeg, plm_frame_t *frame, datastream *ds) {
if (JS_IsUndefined(ds->callback)) return;
uint8_t *rgb = malloc(frame->height*frame->width*4);
memset(rgb,255,frame->height*frame->width*4);
plm_frame_to_rgba(frame, rgb, frame->width*4);
SDL_Surface *surf = SDL_CreateSurfaceFrom(frame->width,frame->height, SDL_PIXELFORMAT_RGBA32, rgb, frame->width*4);
JSValue s[1];
s[0] = SDL_Surface2js(ds->js,surf);
JSValue cb = JS_DupValue(ds->js,ds->callback);
JSValue ret = JS_Call(ds->js, cb, JS_UNDEFINED, 1, s);
JS_FreeValue(ds->js,ret);
JS_FreeValue(ds->js,cb);
free(rgb);
}
JSC_CCALL(os_make_video,
size_t len;
void *data = JS_GetArrayBuffer(js,&len,argv[0]);
datastream *ds = ds_openvideo(data, len);
ret = datastream2js(js,ds);
texture *t = malloc(sizeof(texture));
// t->id = ds->img;
// JS_SetPropertyStr(js, ret, "texture", texture2js(js,t));
if (!ds) return JS_ThrowReferenceError(js, "Video file was not valid.");
ds->js = js;
ds->callback = JS_UNDEFINED;
plm_set_video_decode_callback(ds->plm, render_frame, ds);
return datastream2js(js,ds);
)
JSC_CCALL(os_skin_calculate,

View File

@@ -19,10 +19,6 @@
#include "jsffi.h"
#include "texture.h"
#include "jsffi.h"
unsigned short pack_short_tex(float c) { return c * USHRT_MAX; }
SDL_GPUBuffer *texcoord_floats(float *f, int n)

View File

@@ -5,7 +5,6 @@
#include "transform.h"
#include "gameobject.h"
#include "anim.h"
#include "texture.h"
#include "cgltf.h"
#define MAT_POS 0

View File

@@ -1,168 +0,0 @@
#include "texture.h"
#include "render.h"
#include <math.h>
#include <stb_image.h>
#include <stb_image_write.h>
#include <string.h>
#include "stb_image_resize2.h"
#include <stdio.h>
#include <tracy/TracyC.h>
#include "qoi.h"
struct rect ST_UNIT = {0.f, 0.f, 1.f, 1.f};
unsigned int next_pow2(unsigned int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
int mip_levels(int width, int height)
{
int levels = 0;
while (width > 1 || height > 1)
{
width >>= 1;
height >>= 1;
levels++;
}
return levels;
}
int mip_wh(int w, int h, int *mw, int *mh, int lvl)
{
w >>= lvl;
h >>= lvl;
if (w == 0 && h == 0)
return 1;
*mw = w ? w : 1;
*mh = h ? h : 1;
return 0;
}
void texture_offload(texture *tex)
{
if (tex->data) {
TracyCFreeN(tex->data, "texture");
free(tex->data);
tex->data = NULL;
}
}
void texture_free(JSRuntime *rt, texture *tex)
{
if (!tex) return;
texture_offload(tex);
free(tex);
}
struct texture *texture_empty(int w, int h)
{
int n = 4;
texture *tex = calloc(1,sizeof(*tex));
tex->data = calloc(w*h*n, sizeof(unsigned char));
tex->width = w;
tex->height = h;
TracyCAllocN(tex->data, tex->height*tex->width*4, "texture");
return tex;
}
struct texture *texture_fromdata(void *raw, long size)
{
struct texture *tex = calloc(1, sizeof(*tex));
int n;
void *data = stbi_load_from_memory(raw, size, &tex->width, &tex->height, &n, 4);
if (data == NULL) {
free(tex);
return NULL;
}
tex->data = data;
TracyCAllocN(tex->data, tex->height*tex->width*4, "texture");
return tex;
}
void texture_save(texture *tex, const char *file)
{
if (!tex->data) return;
char *ext = strrchr(file, '.');
if (!strcmp(ext, ".png"))
stbi_write_png(file, tex->width, tex->height, 4, tex->data, 4*tex->width);
else if (!strcmp(ext, ".bmp"))
stbi_write_bmp(file, tex->width, tex->height, 4, tex->data);
else if (!strcmp(ext, ".tga"))
stbi_write_tga(file, tex->width, tex->height, 4, tex->data);
else if (!strcmp(ext, ".jpg") || !strcmp(ext, ".jpeg"))
stbi_write_jpg(file, tex->width, tex->height, 4, tex->data, 5);
else if (!strcmp(ext, ".qoi"))
qoi_write(file, tex->data, &(qoi_desc) {
.width = tex->width,
.height = tex->height,
.channels = 4,
.colorspace = QOI_SRGB
});
}
texture *texture_scale(texture *tex, int width, int height)
{
texture *new = calloc(1, sizeof(*new));
new->width = width;
new->height = height;
new->data = malloc(4*width*height);
stbir_resize_uint8_linear(tex->data, tex->width, tex->height, 0, new->data, width, height, 0, 4);
return new;
}
/*sapp_icon_desc texture2icon(texture *tex)
{
sapp_icon_desc desc = {0};
if (!tex->data) return desc;
struct isize {
int size;
unsigned char *data;
};
struct isize sizes[4];
sizes[0].size = 16;
sizes[1].size = 32;
sizes[2].size = 64;
sizes[3].size = 128;
for (int i = 0; i < 4; i++) {
sizes[i].data = malloc(4*sizes[i].size*sizes[i].size);
stbir_resize_uint8_linear(tex->data, tex->width, tex->height, 0, sizes[i].data, sizes[i].size, sizes[i].size, 0, 4);
}
desc = (sapp_icon_desc){
.images = {
{ .width = sizes[0].size, .height = sizes[0].size, .pixels = { .ptr=sizes[0].data, .size=4*sizes[0].size*sizes[0].size } },
{ .width = sizes[1].size, .height = sizes[1].size, .pixels = { .ptr=sizes[1].data, .size=4*sizes[1].size*sizes[1].size } },
{ .width = sizes[2].size, .height = sizes[2].size, .pixels = { .ptr=sizes[2].data, .size=4*sizes[2].size*sizes[2].size } },
{ .width = sizes[3].size, .height = sizes[3].size, .pixels = { .ptr=sizes[3].data, .size=4*sizes[3].size*sizes[3].size } },
}
};
return desc;
}
*/

View File

@@ -1,53 +0,0 @@
#ifndef TEXTURE_H
#define TEXTURE_H
#include "HandmadeMath.h"
#include "render.h"
#include <quickjs.h>
#include "stb_rect_pack.h"
#include <SDL3/SDL_render.h>
#define TEX_SPEC 0
#define TEX_NORM 1
#define TEX_HEIGHT 2
#define TEX_DIFF 3
#define FILTER_NEAREST SG_FILTER_NEAREST
#define FILTER_NONE SG_FILTER_NONE
#define FILTER_LINEAR SG_FILTER_LINEAR
extern struct rect ST_UNIT;
/* Represents an actual texture on the GPU */
struct texture {
SDL_Texture *id;
SDL_Surface *surface;
int width;
int height;
HMM_Vec3 dimensions;
unsigned char *data;
int vram;
};
typedef struct texture texture;
typedef struct img_sampler{
int wrap_u;
int wrap_v;
int wrap_w;
int min_filter;
int mag_filter;
int mip_filter;
} img_sampler;
texture *texture_fromdata(void *raw, long size);
texture *texture_empty(int width, int height); // Make an empty texture
texture *texture_dup(texture *tex); // return an identical texture
texture *texture_scale(texture *tex, int width, int height); // dup and scale the texture
void texture_free(JSRuntime *rt,texture *tex);
void texture_offload(texture *tex); // Remove the data from this texture
void texture_save(texture *tex, const char *file); // save the texture data to the given file
#endif