fast sprite render
Some checks failed
Build and Deploy / package-dist (push) Has been cancelled
Build and Deploy / build-linux (push) Has been cancelled
Build and Deploy / deploy-itch (push) Has been cancelled
Build and Deploy / deploy-gitea (push) Has been cancelled
Build and Deploy / build-windows (CLANG64) (push) Has been cancelled
Some checks failed
Build and Deploy / package-dist (push) Has been cancelled
Build and Deploy / build-linux (push) Has been cancelled
Build and Deploy / deploy-itch (push) Has been cancelled
Build and Deploy / deploy-gitea (push) Has been cancelled
Build and Deploy / build-windows (CLANG64) (push) Has been cancelled
This commit is contained in:
@@ -170,22 +170,22 @@ function pprint(msg, lvl = 0) {
|
||||
if (tracy) tracy.message(fmt)
|
||||
}
|
||||
|
||||
console.spam = function(msg) {
|
||||
console.spam = function spam(msg) {
|
||||
pprint(msg, 0)
|
||||
}
|
||||
console.debug = function(msg) {
|
||||
console.debug = function debug(msg) {
|
||||
pprint(msg, 1)
|
||||
}
|
||||
console.info = function(msg) {
|
||||
console.info = function info(msg) {
|
||||
pprint(msg, 2)
|
||||
}
|
||||
console.warn = function(msg) {
|
||||
console.warn = function warn(msg) {
|
||||
pprint(msg, 3)
|
||||
}
|
||||
console.log = function(msg) {
|
||||
console.log = function log(msg) {
|
||||
pprint(msg, 2)
|
||||
}
|
||||
console.error = function(e) {
|
||||
console.error = function error(e) {
|
||||
if (!e)
|
||||
e = new Error()
|
||||
|
||||
@@ -195,11 +195,11 @@ ${e.stack}`, 4)
|
||||
else
|
||||
pprint(e,4)
|
||||
}
|
||||
console.panic = function(e) {
|
||||
console.panic = function panic(e) {
|
||||
pprint(e, 5)
|
||||
os.quit()
|
||||
}
|
||||
console.assert = function(op, str = `assertion failed [value '${op}']`) {
|
||||
console.assert = function assert(op, str = `assertion failed [value '${op}']`) {
|
||||
if (!op) console.panic(str)
|
||||
}
|
||||
|
||||
|
||||
@@ -459,18 +459,6 @@ draw.images[prosperon.DOC] = `
|
||||
:raises Error: If no image is provided.
|
||||
`
|
||||
|
||||
draw.sprites = function(sprites, sort = 0, pipeline) {
|
||||
var cmds = graphics.make_sprite_queue(sprites, prosperon.camera, pipeline, sort)
|
||||
for (var i = 0; i < cmds.length; i++)
|
||||
render.queue(cmds[i])
|
||||
}
|
||||
draw.sprites[prosperon.DOC] = `
|
||||
:param sprites: An array of sprite objects to draw.
|
||||
:param sort: Sorting mode or order, default 0.
|
||||
:param pipeline: (Optional) A pipeline or rendering state object.
|
||||
:return: None
|
||||
`
|
||||
|
||||
function software_circle(pos, radius)
|
||||
{
|
||||
if (radius <= 0) return // nothing to draw
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var ret = {
|
||||
return {
|
||||
get pos() {
|
||||
if (!this.transform) return
|
||||
return this.transform.pos;
|
||||
@@ -29,5 +29,3 @@ var ret = {
|
||||
this.scale = this.scale.map((x, i) => x * vec[i]);
|
||||
},
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var json = {}
|
||||
|
||||
json.encode = function(val,replacer,space = 1,whitelist)
|
||||
json.encode = function encode(val,replacer,space = 1,whitelist)
|
||||
{
|
||||
return JSON.stringify(val, replacer, space)
|
||||
}
|
||||
@@ -11,7 +11,7 @@ If the record does not have a json() method, and if whitelist is a record, then
|
||||
|
||||
If the space input is true, then line breaks and extra whitespace will be included in the text.`
|
||||
|
||||
json.decode = function(text,reviver)
|
||||
json.decode = function decode(text,reviver)
|
||||
{
|
||||
return JSON.parse(text,reviver)
|
||||
}
|
||||
|
||||
60
scripts/modules/lcdsprite.js
Normal file
60
scripts/modules/lcdsprite.js
Normal file
@@ -0,0 +1,60 @@
|
||||
var sprite = {}
|
||||
|
||||
var graphics = use('graphics')
|
||||
var render = use('render')
|
||||
var draw2d = use('draw2d')
|
||||
|
||||
var ursprite = {}
|
||||
|
||||
ursprite.move = function move(mv)
|
||||
{
|
||||
this.rect.x += mv.x
|
||||
this.rect.y += mv.y
|
||||
}
|
||||
|
||||
ursprite.moveto = function moveto(pos)
|
||||
{
|
||||
this.rect.x = pos.x
|
||||
this.rect.y = pos.y
|
||||
}
|
||||
|
||||
ursprite.draw = function draw()
|
||||
{
|
||||
draw2d.image(this.image, this.rect, 0, this.anchor)
|
||||
}
|
||||
|
||||
var sprites = []
|
||||
|
||||
sprite.create = function(image, pos, anchor = [0,0], layer = 0, props = {})
|
||||
{
|
||||
var sp = Object.create(ursprite)
|
||||
|
||||
var image = graphics.texture(image)
|
||||
sp.image = image
|
||||
sp.rect = {x:pos.x, y:pos.y, width: image.texture.width, height: image.texture.height}
|
||||
sp.layer = layer
|
||||
sp.props = props
|
||||
sp.anchor = anchor
|
||||
|
||||
sprites.push(sp)
|
||||
|
||||
return sp
|
||||
}
|
||||
|
||||
sprite.forEach = function(fn)
|
||||
{
|
||||
for (var sp of sprites)
|
||||
fn(sp)
|
||||
}
|
||||
|
||||
sprite.values = function()
|
||||
{
|
||||
return sprites.slice()
|
||||
}
|
||||
|
||||
sprite.geometry = function()
|
||||
{
|
||||
return graphics.make_sprite_mesh(sprites)
|
||||
}
|
||||
|
||||
return sprite
|
||||
@@ -28,9 +28,6 @@ render.initialize = function(config)
|
||||
url: "https://prosperon.dev"
|
||||
}
|
||||
|
||||
// for (var i in default_conf)
|
||||
// config[i] ??= default_conf[i]
|
||||
|
||||
prosperon.window = prosperon.engine_start({width:500,height:500})
|
||||
console.log(prosperon.window)
|
||||
context = prosperon.window.make_renderer()
|
||||
|
||||
@@ -42,16 +42,16 @@ time.strparse = {
|
||||
s: "second",
|
||||
};
|
||||
|
||||
time.isleap = function(year) {
|
||||
time.isleap = function isleap(year) {
|
||||
return this.yearsize(year) === 366;
|
||||
};
|
||||
|
||||
time.yearsize = function(y) {
|
||||
time.yearsize = function yearsize(y) {
|
||||
if (y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)) return 366;
|
||||
return 365;
|
||||
};
|
||||
|
||||
time.timecode = function(t, fps = 24) {
|
||||
time.timecode = function timecode(t, fps = 24) {
|
||||
var s = Math.trunc(t);
|
||||
t -= s;
|
||||
return `${s}:${Math.trunc(fps * s)}`;
|
||||
@@ -60,7 +60,7 @@ time.timecode = function(t, fps = 24) {
|
||||
time.monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
time.zones = { "-12": "IDLW" };
|
||||
|
||||
time.record = function(num, zone = this.computer_zone()) {
|
||||
time.record = function record(num, zone = this.computer_zone()) {
|
||||
if (typeof num === "object") {
|
||||
return num;
|
||||
} else if (typeof num === "number") {
|
||||
@@ -113,7 +113,7 @@ time.record = function(num, zone = this.computer_zone()) {
|
||||
}
|
||||
};
|
||||
|
||||
time.number = function(rec) {
|
||||
time.number = function number(rec) {
|
||||
if (typeof rec === "number") {
|
||||
return rec;
|
||||
} else if (typeof rec === "object") {
|
||||
@@ -153,7 +153,7 @@ time.number = function(rec) {
|
||||
|
||||
time.fmt = "vB mB d h:nn:ss TZz a y c";
|
||||
|
||||
time.text = function(num, fmt = this.fmt, zone) {
|
||||
time.text = function text(num, fmt = this.fmt, zone) {
|
||||
var rec = (typeof num === "number") ? time.record(num, zone) : num;
|
||||
zone = rec.zone;
|
||||
if (fmt.match("a")) {
|
||||
|
||||
@@ -2883,7 +2883,8 @@ JSC_CCALL(renderer_rects,
|
||||
|
||||
// Should take a single struct with pos, color, uv, and indices arrays
|
||||
JSC_CCALL(renderer_geometry,
|
||||
SDL_Renderer *r = js2renderer_ctx(js,self)->sdl;
|
||||
renderer_ctx *ctx = js2renderer_ctx(js,self);
|
||||
SDL_Renderer *r = ctx->sdl;
|
||||
JSValue pos = JS_GetPropertyStr(js,argv[1], "pos");
|
||||
JSValue color = JS_GetPropertyStr(js,argv[1], "color");
|
||||
JSValue uv = JS_GetPropertyStr(js,argv[1], "uv");
|
||||
@@ -2902,8 +2903,11 @@ JSC_CCALL(renderer_geometry,
|
||||
HMM_Vec2 *trans_pos = malloc(vertices*sizeof(HMM_Vec2));
|
||||
memcpy(trans_pos,posdata, sizeof(HMM_Vec2)*vertices);
|
||||
|
||||
for (int i = 0; i < vertices; i++)
|
||||
trans_pos[i] = HMM_MulM3V3(cam_mat, (HMM_Vec3){trans_pos[i].x, trans_pos[i].y, 1}).xy;
|
||||
for (int i = 0; i < vertices; i++) {
|
||||
SDL_FPoint p = renderer_world_to_screen(ctx, trans_pos[i]);
|
||||
trans_pos[i].x = p.x;
|
||||
trans_pos[i].y = p.y;
|
||||
}
|
||||
|
||||
if (!SDL_RenderGeometryRaw(r, tex, trans_pos, pos_stride,colordata,color_stride,uvdata, uv_stride, vertices, idxdata, count, indices_stride))
|
||||
ret = JS_ThrowReferenceError(js, "Error rendering geometry: %s",SDL_GetError());
|
||||
@@ -2914,7 +2918,6 @@ JSC_CCALL(renderer_geometry,
|
||||
JS_FreeValue(js,color);
|
||||
JS_FreeValue(js,uv);
|
||||
JS_FreeValue(js,indices);
|
||||
printf("AMDET\n");
|
||||
)
|
||||
|
||||
JSC_CCALL(renderer_logical_size,
|
||||
@@ -2988,7 +2991,6 @@ JSC_CCALL(renderer_target,
|
||||
|
||||
// Given an array of sprites, make the necessary geometry
|
||||
// A sprite is expected to have:
|
||||
// transform: a transform encoding position and rotation. its scale is in pixels - so a scale of 1 means the image will draw only on a single pixel.
|
||||
// image: a standard prosperon image of a surface, rect, and texture
|
||||
// color: the color this sprite should be hued by
|
||||
JSC_CCALL(renderer_make_sprite_mesh,
|
||||
@@ -3003,7 +3005,6 @@ JSC_CCALL(renderer_make_sprite_mesh,
|
||||
|
||||
for (int i = 0; i < quads; i++) {
|
||||
JSValue sub = JS_GetPropertyUint32(js,sprites,i);
|
||||
JSValue jstransform = JS_GetProperty(js,sub,transform);
|
||||
|
||||
JSValue jssrc = JS_GetProperty(js,sub,src);
|
||||
JSValue jscolor = JS_GetProperty(js,sub,color);
|
||||
@@ -3034,7 +3035,6 @@ JSC_CCALL(renderer_make_sprite_mesh,
|
||||
colordata[base+2] = color;
|
||||
colordata[base+3] = color;
|
||||
|
||||
JS_FreeValue(js,jstransform);
|
||||
JS_FreeValue(js,sub);
|
||||
JS_FreeValue(js,jscolor);
|
||||
JS_FreeValue(js,jssrc);
|
||||
|
||||
@@ -326,7 +326,7 @@ void actor_turn(prosperon_rt *actor, int greedy)
|
||||
{
|
||||
SDL_LockMutex(actor->turn);
|
||||
#ifdef TRACY_ENABLE
|
||||
TracyCFiberEnter(actor->id);
|
||||
// TracyCFiberEnter(actor->id);
|
||||
#endif
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
@@ -415,7 +415,7 @@ void actor_turn(prosperon_rt *actor, int greedy)
|
||||
|
||||
END:
|
||||
#ifdef TRACY_ENABLE
|
||||
TracyCFiberLeave(actor->id);
|
||||
// TracyCFiberLeave(actor->id);
|
||||
#endif
|
||||
SDL_UnlockMutex(actor->turn);
|
||||
set_actor_state(actor);
|
||||
@@ -423,7 +423,7 @@ void actor_turn(prosperon_rt *actor, int greedy)
|
||||
|
||||
KILL:
|
||||
#ifdef TRACY_ENABLE
|
||||
TracyCFiberLeave(actor->id);
|
||||
// TracyCFiberLeave(actor->id);
|
||||
#endif
|
||||
SDL_UnlockMutex(actor->turn);
|
||||
actor_free(actor);
|
||||
@@ -529,7 +529,15 @@ JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
prosperon_rt *actor = JS_GetContextOpaque(js);
|
||||
double seconds;
|
||||
JS_ToFloat64(js, &seconds, argv[1]);
|
||||
if (seconds <= 0) {
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
JSValue cb = JS_DupValue(js, argv[0]);
|
||||
arrput(actor->events, cb);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
return JS_NewInt32(js, -1);
|
||||
}
|
||||
Uint64 ns = seconds * SDL_NS_PER_SECOND;
|
||||
|
||||
Uint32 id = SDL_AddTimerNS(ns, actor_timer_cb, actor);
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
@@ -549,6 +557,8 @@ JSValue js_actor_removetimer(JSContext *js, JSValue self, int argc, JSValue *arg
|
||||
prosperon_rt *actor = JS_GetContextOpaque(js);
|
||||
Uint32 timer_id;
|
||||
JS_ToUint32(js, &timer_id, argv[0]);
|
||||
if (timer_id == -1) return JS_UNDEFINED;
|
||||
|
||||
SDL_RemoveTimer(timer_id);
|
||||
|
||||
JSValue cb = JS_UNDEFINED;
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
#include "quickjs.h"
|
||||
|
||||
struct sprite{
|
||||
rect affine;
|
||||
JSValue image;
|
||||
HMM_Vec2 pos; // x,y coordinates of the sprite
|
||||
HMM_Mat2 affine; // defines all deformation
|
||||
rect affine; //
|
||||
JSValue image; // the actual texture resource - perhaps SDL_GPUTexture, or SDL_Texture, or something else ...
|
||||
SDL_GPUTexture *tex;
|
||||
rect uv;
|
||||
int layer;
|
||||
HMM_Vec4 color;
|
||||
rect uv; // pixel coordinates of the sprite on its image
|
||||
int layer; // layer this sprite draws onto
|
||||
HMM_Vec4 color; // color in 0-1f
|
||||
};
|
||||
|
||||
typedef struct sprite sprite;
|
||||
|
||||
BIN
tests/bunny.png
Normal file
BIN
tests/bunny.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 449 B |
64
tests/bunnymark.js
Normal file
64
tests/bunnymark.js
Normal file
@@ -0,0 +1,64 @@
|
||||
// bunnymark
|
||||
var render = use('render')
|
||||
var os = use('os')
|
||||
var dim = [500,500]
|
||||
render.initialize({
|
||||
width:dim.x,
|
||||
height:dim.y,
|
||||
resolution_x:dim.x,
|
||||
resolution_y:dim.y,
|
||||
mode:"letterboxed",
|
||||
refresh: 60,
|
||||
})
|
||||
|
||||
var camera = {
|
||||
size: [500,500],
|
||||
transform: os.make_transform(),
|
||||
fov:50,
|
||||
near_z: 0,
|
||||
far_z: 1000,
|
||||
surface: undefined,
|
||||
viewport: {x:0,y:0,width:1,height:1},
|
||||
ortho:true,
|
||||
anchor:[0,0],
|
||||
}
|
||||
|
||||
var draw = use('draw2d')
|
||||
var sprite = use('lcdsprite')
|
||||
var graphics = use('graphics')
|
||||
|
||||
var bunny = graphics.texture('tests/bunny')
|
||||
|
||||
var center = [0.5,0.5]
|
||||
|
||||
var vel = 50
|
||||
|
||||
for (var i = 0; i < 20000; i++) {
|
||||
var sp = sprite.create(bunny, [Math.random()*dim.x, Math.random()*dim.y], center)
|
||||
sp.dir = [Math.random()*vel, Math.random()*vel]
|
||||
}
|
||||
|
||||
function movendraw(sp)
|
||||
{
|
||||
// sp.move([sp.dir[0]*dt, sp.dir[1]*dt])
|
||||
sp.draw()
|
||||
}
|
||||
|
||||
var dt = 0
|
||||
function loop()
|
||||
{
|
||||
var now = os.now()
|
||||
render.clear([22/255,120/255,194/255,255/255])
|
||||
render.camera(camera)
|
||||
|
||||
// sprite.forEach(movendraw)
|
||||
var mesh = sprite.geometry()
|
||||
render.geometry(bunny.texture, mesh)
|
||||
|
||||
render.present()
|
||||
dt = os.now() - now
|
||||
var delay = (1/60) - dt
|
||||
$_.delay(loop, delay)
|
||||
}
|
||||
|
||||
loop()
|
||||
@@ -38,13 +38,23 @@ var hudcam = {
|
||||
var angle = 0
|
||||
var pos = [0,0,0]
|
||||
|
||||
var dt = 0
|
||||
|
||||
var sprite = use('lcdsprite')
|
||||
sprite.create("ok", [50,50], [0.5,0])
|
||||
sprite.create("nope", [100,100], [0.5,0])
|
||||
sprite.create("sad", [150,150], [0.5,0])
|
||||
|
||||
function loop()
|
||||
{
|
||||
pos.x += 1
|
||||
var now = os.now()
|
||||
pos.x += dt*100
|
||||
camera.transform.pos = pos
|
||||
render.clear(Color.red)
|
||||
render.clear([22/255,120/255,194/255,255/255])
|
||||
render.camera(camera)
|
||||
draw.image("button_grey", [0,0])
|
||||
|
||||
for (var sp of sprite.sprites)
|
||||
draw.image(sp.image, sp.rect)
|
||||
|
||||
/* draw.line([[0,0],[100,50]])
|
||||
draw.point([100,100])
|
||||
@@ -58,9 +68,14 @@ function loop()
|
||||
draw.rectangle({x:350, y:60, width:200, height:120}, {radius:10,thickness:3})
|
||||
*/
|
||||
render.camera(hudcam)
|
||||
draw.slice9("button_grey", {x:0,y:0,width:200,height:250}, 10)
|
||||
draw.slice9("button_grey", {x:0,y:0,width:100,height:50}, 10)
|
||||
render.present()
|
||||
$_.delay(loop, 1/60)
|
||||
dt = os.now()-now
|
||||
var delay = (1/240) - dt
|
||||
if (delay <= 0)
|
||||
loop()
|
||||
else
|
||||
$_.delay(loop, delay)
|
||||
}
|
||||
|
||||
var sound = use('sound')
|
||||
|
||||
Reference in New Issue
Block a user