ppu rendering
This commit is contained in:
@@ -102,13 +102,13 @@ draw.arrow = function render_arrow(start, end, wingspan = 4, wingangle = 10, def
|
||||
draw.line(wing2, defl, material)
|
||||
}
|
||||
|
||||
draw.rectangle = function render_rectangle(rect, defl, material) {
|
||||
draw.rectangle = function render_rectangle(rect, defl, material = {color:{r:1,g:1,b:1,a:1}}) {
|
||||
var opt = defl ? {...rect_def, ...defl} : rect_def
|
||||
|
||||
add_command("draw_rect", {
|
||||
rect: rect,
|
||||
opt: opt,
|
||||
material: material
|
||||
rect,
|
||||
opt,
|
||||
material
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -23,22 +23,19 @@ function makeOrthoMetal(l,r,b,t,n,f){
|
||||
}
|
||||
|
||||
function make_camera_pblob(camera) {
|
||||
def zoom = camera.zoom;
|
||||
// Use surface dimensions if rendering to a surface, otherwise window dimensions
|
||||
def cw = camera.surface ? camera.surface.width : win_size.width;
|
||||
def ch = camera.surface ? camera.surface.height : win_size.height;
|
||||
// how big is the world window?
|
||||
def world_w = cw / zoom;
|
||||
def world_h = ch / zoom;
|
||||
def cw = camera.surface ? camera.surface.width : win_size.width;
|
||||
def ch = camera.surface ? camera.surface.height : win_size.height;
|
||||
|
||||
def zoom = camera.zoom || ch
|
||||
|
||||
def world_h = zoom;
|
||||
def world_w = zoom * cw / ch;
|
||||
|
||||
// compute world‐space bounds so that camera.pos lands at the anchor
|
||||
// anchor.x = 0 → origin at left; 1 → origin at right
|
||||
def l = camera.pos[0] - camera.anchor[0] * world_w;
|
||||
def b = camera.pos[1] - camera.anchor[1] * world_h;
|
||||
def r = l + world_w;
|
||||
def t = b + world_h;
|
||||
|
||||
// now build the Metal/Vulkan‐style ortho (z ∈ [0,1])
|
||||
def mat = makeOrthoMetal(l, r, b, t, 0, 1);
|
||||
return geometry.array_blob(mat);
|
||||
}
|
||||
@@ -150,6 +147,29 @@ win_config.__proto__ = default_window
|
||||
win_config.metal = true
|
||||
|
||||
var window = new video.window(win_config)
|
||||
var win_proto = window.__proto__
|
||||
win_proto.toJSON = function()
|
||||
{
|
||||
var flags = this.flags
|
||||
var ret = {
|
||||
title: this.title,
|
||||
size: this.size,
|
||||
pixel_size: this.sizeInPixels,
|
||||
display_scale: this.displayScale,
|
||||
pixel_density: this.pixelDensity,
|
||||
pos: this.position,
|
||||
opacity: this.opacity,
|
||||
fullscreen: this.fullscreen,
|
||||
safe_area: this.safe_area(),
|
||||
}
|
||||
|
||||
for (var i in flags)
|
||||
ret[i] = flags[i]
|
||||
return ret
|
||||
}
|
||||
|
||||
window.resizable = true
|
||||
|
||||
var device = new sdl_gpu.gpu({
|
||||
shaders_msl:true,
|
||||
shaders_metallib:true,
|
||||
@@ -158,6 +178,15 @@ var device = new sdl_gpu.gpu({
|
||||
device.claim_window(window)
|
||||
device.set_swapchain(window, 'sdr', 'vsync')
|
||||
|
||||
var white_pixel = {
|
||||
width:1,
|
||||
height:1,
|
||||
pixels: new blob(32, true), // 32 bits, all set to 1 for a white blob
|
||||
pitch:32
|
||||
}
|
||||
|
||||
stone(white_pixel.pixels)
|
||||
|
||||
var shader_type = device.shader_format()[0]
|
||||
shader_type = 'msl'
|
||||
|
||||
@@ -398,24 +427,6 @@ function poll_input() {
|
||||
}
|
||||
|
||||
if (shouldInclude) {
|
||||
// Transform mouse coordinates from window to renderer coordinates
|
||||
if (event.pos && (event.type == 'mouse_motion' ||
|
||||
event.type == 'mouse_button_down' ||
|
||||
event.type == 'mouse_button_up' ||
|
||||
event.type == 'mouse_wheel')) {
|
||||
// Convert window coordinates to renderer logical coordinates
|
||||
// var logicalPos = renderer.coordsFromWindow(event.pos)
|
||||
// event.pos = logicalPos
|
||||
}
|
||||
// Handle drop events which also have position
|
||||
if (event.pos && (event.type == 'drop_file' ||
|
||||
event.type == 'drop_text' ||
|
||||
event.type == 'drop_position')) {
|
||||
// var logicalPos = renderer.coordsFromWindow(event.pos)
|
||||
// event.pos = logicalPos
|
||||
}
|
||||
|
||||
// Handle window events
|
||||
if (event.type == 'window_pixel_size_changed') {
|
||||
win_size.width = event.width
|
||||
win_size.height = event.height
|
||||
@@ -431,7 +442,6 @@ function poll_input() {
|
||||
|
||||
if (event.type.startsWith('mouse_') && event.pos && event.pos.y)
|
||||
event.pos.y = -event.pos.y + win_size.height
|
||||
// event.pos.y = -event.pos.y + logical.height
|
||||
|
||||
filteredEvents.push(event)
|
||||
}
|
||||
@@ -537,7 +547,8 @@ function get_img_gpu(surface)
|
||||
d: 1
|
||||
}, false);
|
||||
|
||||
new_tex.push(gpu)
|
||||
if (full_mip > 1)
|
||||
new_tex.push(gpu)
|
||||
|
||||
return gpu
|
||||
}
|
||||
@@ -670,6 +681,21 @@ cmd_fns.draw_slice9 = function(cmd)
|
||||
render_geom(mesh, img)
|
||||
}
|
||||
|
||||
cmd_fns.draw_rect = function(cmd)
|
||||
{
|
||||
// Create geometry for a rectangle quad
|
||||
var geom = geometry.make_rect_quad(cmd.rect, null, cmd.material.color || [1,1,1,1])
|
||||
geom.indices = geometry.make_quad_indices(1)
|
||||
geom.num_indices = 6
|
||||
|
||||
// Use white_pixel as the texture so the color modulation works
|
||||
if (!white_pixel[GPU]) {
|
||||
white_pixel[GPU] = get_img_gpu(white_pixel)
|
||||
}
|
||||
|
||||
render_geom(geom, {[GPU]: white_pixel[GPU]})
|
||||
}
|
||||
|
||||
var copy_pass
|
||||
|
||||
prosperon.create_batch = function create_batch(draw_cmds, done) {
|
||||
@@ -806,7 +832,6 @@ function poll_file_changes() {
|
||||
}
|
||||
})
|
||||
|
||||
// Schedule next poll in 0.5 seconds
|
||||
$_.delay(poll_file_changes, 0.5)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ function tilemap()
|
||||
this.tiles = [];
|
||||
this.offset_x = 0;
|
||||
this.offset_y = 0;
|
||||
this.size_x = 32;
|
||||
this.size_y = 32;
|
||||
this.ppu = 32
|
||||
this.layer = 0; // Default layer for scene tree sorting
|
||||
this._geometry_cache = {}; // Cache actual geometry data by texture
|
||||
this._dirty = true;
|
||||
@@ -113,13 +112,17 @@ tilemap.prototype =
|
||||
var textureKey = imageToKey.get(tile);
|
||||
|
||||
if (!textureGroups[textureKey]) {
|
||||
// compute world-unit size of one tile of this texture
|
||||
var tile_wu = tile.width / this.ppu;
|
||||
var tile_hu = tile.height / this.ppu;
|
||||
|
||||
textureGroups[textureKey] = {
|
||||
tiles: [],
|
||||
image: tile, // Store the image object
|
||||
offset_x: this.offset_x,
|
||||
offset_y: this.offset_y,
|
||||
size_x: this.size_x,
|
||||
size_y: this.size_y
|
||||
size_x: tile_wu,
|
||||
size_y: tile_hu
|
||||
};
|
||||
}
|
||||
textureGroups[textureKey].tiles.push({
|
||||
@@ -142,7 +145,7 @@ tilemap.prototype =
|
||||
tiles: [],
|
||||
offset_x: group.offset_x,
|
||||
offset_y: group.offset_y,
|
||||
size_x: group.size_x,
|
||||
size_x: group.size_x, // now in world-units
|
||||
size_y: group.size_y,
|
||||
pos_x: pos.x,
|
||||
pos_y: pos.y
|
||||
|
||||
@@ -1428,9 +1428,8 @@ JSC_CCALL(geometry_make_rect_quad,
|
||||
uv_data[6] = uv.x + uv.w; uv_data[7] = uv.y; // top-right
|
||||
|
||||
// Set colors
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
color_data[i] = color;
|
||||
}
|
||||
|
||||
// Create result object
|
||||
ret = JS_NewObject(js);
|
||||
|
||||
@@ -319,10 +319,18 @@ static int event2wota_count_props(const SDL_Event *event)
|
||||
count += 1;
|
||||
break;
|
||||
|
||||
/* Window events (just group them all together) */
|
||||
/* Window events that only need 'which' */
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||
// which => 1 extra
|
||||
count += 1;
|
||||
break;
|
||||
|
||||
/* Window events that need data1 and data2 */
|
||||
case SDL_EVENT_WINDOW_SHOWN:
|
||||
case SDL_EVENT_WINDOW_HIDDEN:
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
case SDL_EVENT_WINDOW_RESIZED:
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
@@ -332,14 +340,10 @@ static int event2wota_count_props(const SDL_Event *event)
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER:
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||
case SDL_EVENT_WINDOW_HIT_TEST:
|
||||
case SDL_EVENT_WINDOW_ICCPROF_CHANGED:
|
||||
case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
|
||||
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
|
||||
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
|
||||
case SDL_EVENT_WINDOW_OCCLUDED:
|
||||
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
|
||||
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
|
||||
@@ -349,6 +353,11 @@ static int event2wota_count_props(const SDL_Event *event)
|
||||
count += 3;
|
||||
break;
|
||||
|
||||
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
|
||||
// which, x, y, width, height => 5 extra
|
||||
count += 5;
|
||||
break;
|
||||
|
||||
case SDL_EVENT_JOYSTICK_ADDED:
|
||||
case SDL_EVENT_JOYSTICK_REMOVED:
|
||||
case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
|
||||
@@ -557,17 +566,20 @@ static void event2wota_write(WotaBuffer *wb, const SDL_Event *e, int c) {
|
||||
wota_write_text(wb, "owner");
|
||||
wota_write_sym(wb, e->clipboard.owner ? WOTA_TRUE : WOTA_FALSE);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||
wota_write_text(wb, "which");
|
||||
wota_write_number(wb, (double)e->window.windowID);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_SHOWN:
|
||||
case SDL_EVENT_WINDOW_HIDDEN:
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
case SDL_EVENT_WINDOW_MINIMIZED:
|
||||
case SDL_EVENT_WINDOW_MAXIMIZED:
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER:
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||
case SDL_EVENT_WINDOW_HIT_TEST:
|
||||
case SDL_EVENT_WINDOW_ICCPROF_CHANGED:
|
||||
case SDL_EVENT_WINDOW_OCCLUDED:
|
||||
@@ -575,7 +587,6 @@ static void event2wota_write(WotaBuffer *wb, const SDL_Event *e, int c) {
|
||||
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
|
||||
case SDL_EVENT_WINDOW_DESTROYED:
|
||||
case SDL_EVENT_WINDOW_HDR_STATE_CHANGED:
|
||||
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
|
||||
wota_write_text(wb, "which");
|
||||
wota_write_number(wb, (double)e->window.windowID);
|
||||
wota_write_text(wb, "data1");
|
||||
@@ -583,6 +594,32 @@ static void event2wota_write(WotaBuffer *wb, const SDL_Event *e, int c) {
|
||||
wota_write_text(wb, "data2");
|
||||
wota_write_number(wb, (double)e->window.data2);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
|
||||
{
|
||||
SDL_Window *window = SDL_GetWindowFromID(e->window.windowID);
|
||||
SDL_Rect safe_area = {0, 0, 0, 0};
|
||||
if (window && SDL_GetWindowSafeArea(window, &safe_area)) {
|
||||
wota_write_text(wb, "which");
|
||||
wota_write_number(wb, (double)e->window.windowID);
|
||||
wota_write_text(wb, "x");
|
||||
wota_write_number(wb, (double)safe_area.x);
|
||||
wota_write_text(wb, "y");
|
||||
wota_write_number(wb, (double)safe_area.y);
|
||||
wota_write_text(wb, "width");
|
||||
wota_write_number(wb, (double)safe_area.w);
|
||||
wota_write_text(wb, "height");
|
||||
wota_write_number(wb, (double)safe_area.h);
|
||||
} else {
|
||||
// Fallback to original behavior if SDL_GetWindowSafeArea fails
|
||||
wota_write_text(wb, "which");
|
||||
wota_write_number(wb, (double)e->window.windowID);
|
||||
wota_write_text(wb, "data1");
|
||||
wota_write_number(wb, (double)e->window.data1);
|
||||
wota_write_text(wb, "data2");
|
||||
wota_write_number(wb, (double)e->window.data2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
wota_write_text(wb, "which");
|
||||
wota_write_number(wb, (double)e->window.windowID);
|
||||
|
||||
@@ -286,9 +286,11 @@ JSValue js_window_theme(JSContext *js, JSValue self)
|
||||
JSValue js_window_safe_area(JSContext *js, JSValue self)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
rect r;
|
||||
SDL_Rect r;
|
||||
SDL_GetWindowSafeArea(w, &r);
|
||||
return rect2js(js,r);
|
||||
rect newr;
|
||||
SDL_RectToFRect(&r, &newr);
|
||||
return rect2js(js,newr);
|
||||
}
|
||||
|
||||
JSValue js_window_bordered(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
@@ -700,7 +702,36 @@ JSValue js_window_updateSurfaceRects(JSContext *js, JSValue self, int argc, JSVa
|
||||
JSValue js_window_get_flags(JSContext *js, JSValue self)
|
||||
{
|
||||
SDL_Window *w = js2SDL_Window(js,self);
|
||||
return number2js(js, SDL_GetWindowFlags(w));
|
||||
SDL_WindowFlags flags = SDL_GetWindowFlags(w);
|
||||
|
||||
JSValue ret = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, ret, "fullscreen", JS_NewBool(js, flags & SDL_WINDOW_FULLSCREEN));
|
||||
JS_SetPropertyStr(js, ret, "opengl", JS_NewBool(js, flags & SDL_WINDOW_OPENGL));
|
||||
JS_SetPropertyStr(js, ret, "occluded", JS_NewBool(js, flags & SDL_WINDOW_OCCLUDED));
|
||||
JS_SetPropertyStr(js, ret, "hidden", JS_NewBool(js, flags & SDL_WINDOW_HIDDEN));
|
||||
JS_SetPropertyStr(js, ret, "borderless", JS_NewBool(js, flags & SDL_WINDOW_BORDERLESS));
|
||||
JS_SetPropertyStr(js, ret, "resizable", JS_NewBool(js, flags & SDL_WINDOW_RESIZABLE));
|
||||
JS_SetPropertyStr(js, ret, "minimized", JS_NewBool(js, flags & SDL_WINDOW_MINIMIZED));
|
||||
JS_SetPropertyStr(js, ret, "maximized", JS_NewBool(js, flags & SDL_WINDOW_MAXIMIZED));
|
||||
JS_SetPropertyStr(js, ret, "mouseGrabbed", JS_NewBool(js, flags & SDL_WINDOW_MOUSE_GRABBED));
|
||||
JS_SetPropertyStr(js, ret, "inputFocus", JS_NewBool(js, flags & SDL_WINDOW_INPUT_FOCUS));
|
||||
JS_SetPropertyStr(js, ret, "mouseFocus", JS_NewBool(js, flags & SDL_WINDOW_MOUSE_FOCUS));
|
||||
JS_SetPropertyStr(js, ret, "external", JS_NewBool(js, flags & SDL_WINDOW_EXTERNAL));
|
||||
JS_SetPropertyStr(js, ret, "modal", JS_NewBool(js, flags & SDL_WINDOW_MODAL));
|
||||
JS_SetPropertyStr(js, ret, "highPixelDensity", JS_NewBool(js, flags & SDL_WINDOW_HIGH_PIXEL_DENSITY));
|
||||
JS_SetPropertyStr(js, ret, "mouseCapture", JS_NewBool(js, flags & SDL_WINDOW_MOUSE_CAPTURE));
|
||||
JS_SetPropertyStr(js, ret, "mouseRelativeMode", JS_NewBool(js, flags & SDL_WINDOW_MOUSE_RELATIVE_MODE));
|
||||
JS_SetPropertyStr(js, ret, "alwaysOnTop", JS_NewBool(js, flags & SDL_WINDOW_ALWAYS_ON_TOP));
|
||||
JS_SetPropertyStr(js, ret, "utility", JS_NewBool(js, flags & SDL_WINDOW_UTILITY));
|
||||
JS_SetPropertyStr(js, ret, "tooltip", JS_NewBool(js, flags & SDL_WINDOW_TOOLTIP));
|
||||
JS_SetPropertyStr(js, ret, "popupMenu", JS_NewBool(js, flags & SDL_WINDOW_POPUP_MENU));
|
||||
JS_SetPropertyStr(js, ret, "keyboardGrabbed", JS_NewBool(js, flags & SDL_WINDOW_KEYBOARD_GRABBED));
|
||||
JS_SetPropertyStr(js, ret, "vulkan", JS_NewBool(js, flags & SDL_WINDOW_VULKAN));
|
||||
JS_SetPropertyStr(js, ret, "metal", JS_NewBool(js, flags & SDL_WINDOW_METAL));
|
||||
JS_SetPropertyStr(js, ret, "transparent", JS_NewBool(js, flags & SDL_WINDOW_TRANSPARENT));
|
||||
JS_SetPropertyStr(js, ret, "notFocusable", JS_NewBool(js, flags & SDL_WINDOW_NOT_FOCUSABLE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue js_window_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
|
||||
Reference in New Issue
Block a user