diff --git a/docs/index.md b/docs/index.md index 6a2fb2ab..8bc80c0a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,6 +2,11 @@ Prosperon is an opinionated Javascript-based runtime for making games, quickly. With Javascript's C-like syntax, it makes it easy to make classic style games like Pacman or Fantasy Zone, without diving into Unity, Godot or Unreal Engine. +# API usage +A lot of the API usage is informed from 'duck typing'. If something "looks" like a camera - it can be used like one! If something "looks" like a sprite, it can be used like one! There are fast paths on nearly everything for well defined objects + +Uniformity is prioritized. + # Gradual performance Prosperon makes it easy to make something quickly, and if it runs well, you're golden! But if it's slow, there are a plethora of options to make it faster. Plus, with native C plugins, there is nothing that can't be figured out. diff --git a/scripts/doc.js b/scripts/doc.js index 75c52f6f..fa0b6b38 100644 --- a/scripts/doc.js +++ b/scripts/doc.js @@ -1,3 +1,17 @@ var ret = {} ret.sym = Symbol() + +ret.print_api = function(obj) { + for (var prop in obj) { + if (!obj.hasOwnProperty(prop)) continue + var val = obj[prop] + console.log(prop) + if (val[ret.sym]) console.log(' doc: ' + val[ret.sym]) + if (typeof val === 'function') { + var m = val.toString().match(/\(([^)]*)\)/) + if (m) console.log(' function: ' + prop + '(' + m[1].trim() + ')') + } + } +} + return ret diff --git a/scripts/draw2d.js b/scripts/draw2d.js index 650f2d3b..7be3c3b4 100644 --- a/scripts/draw2d.js +++ b/scripts/draw2d.js @@ -1,11 +1,95 @@ var render = use('render') +var graphics = use('graphics') var math = use('math') +var base_pipeline = { + vertex: "sprite.vert", + fragment: "sprite.frag", + primitive: "triangle", // point, line, linestrip, triangle, trianglestrip + fill: true, // false for lines + depth: { + compare: "greater_equal", // never/less/equal/less_equal/greater/not_equal/greater_equal/always + test: false, + write: false, + bias: 0, + bias_slope_scale: 0, + bias_clamp: 0 + }, + stencil: { + enabled: true, + front: { + compare: "equal", // never/less/equal/less_equal/greater/neq/greq/always + fail: "keep", // keep/zero/replace/incr_clamp/decr_clamp/invert/incr_wrap/decr_wrap + depth_fail: "keep", + pass: "keep" + }, + back: { + compare: "equal", // never/less/equal/less_equal/greater/neq/greq/always + fail: "keep", // keep/zero/replace/incr_clamp/decr_clamp/invert/incr_wrap/decr_wrap + depth_fail: "keep", + pass: "keep" + }, + test: true, + compare_mask: 0, + write_mask: 0 + }, + blend: { + enabled: false, + src_rgb: "one", // zero/one/src_color/one_minus_src_color/dst_color/one_minus_dst_color/src_alpha/one_minus_src_alpha/dst_alpha/one_minus_dst_alpha/constant_color/one_minus_constant_color/src_alpha_saturate + dst_rgb: "zero", + op_rgb: "add", // add/sub/rev_sub/min/max + src_alpha: "one", + dst_alpha: "zero", + op_alpha: "add" + }, + cull: "none", // none/front/back + face: "cw", // cw/ccw + alpha_to_coverage: false, + multisample: { + count: 1, // number of multisamples + mask: 0xFFFFFFFF, + domask: false + }, + label: "scripted pipeline", + target: {} +} + + +var sprite_pipeline = Object.create(base_pipeline); +sprite_pipeline.blend = { + enabled:true, + src_rgb: "src_alpha", // zero/one/src_color/one_minus_src_color/dst_color/one_minus_dst_color/src_alpha/one_minus_src_alpha/dst_alpha/one_minus_dst_alpha/constant_color/one_minus_constant_color/src_alpha_saturate + dst_rgb: "one_minus_src_alpha", + op_rgb: "add", // add/sub/rev_sub/min/max + src_alpha: "one", + dst_alpha: "zero", + op_alpha: "add" +}; + +sprite_pipeline.target = { + color_targets: [{ + format:"rgba8", + blend:sprite_pipeline.blend + }], + depth: "d32 float s8" +}; + +var rect_pipeline = Object.create(sprite_pipeline) +rect_pipeline.fragment = "rectangle.frag" + +var circle_pipeline = Object.create(sprite_pipeline) +circle_pipeline.fragment = "circle.frag" + var draw = {} +/* All draw in screen space */ +draw.point = function (pos, size, color = Color.blue) { + render._main.point(pos,color); +}; + draw.line = function render_line(points, color = Color.white, thickness = 1, pipeline = rect_pipeline) { var mesh = os.make_line_prim(points,thickness, 0,0,color); - render.current_queue.push({ + render.queue({ type: 'geometry', mesh, pipeline, @@ -33,7 +117,7 @@ draw.arrow = function render_arrow(start, end, color = Color.red, wingspan = 4, draw.rectangle = function render_rectangle(rect, color = Color.white, pipeline = rect_pipeline) { var T = os.make_transform(); T.rect(rect); - render.current_queue.push({ + render.queue({ type:'sprite', transform:T, color, @@ -49,7 +133,7 @@ draw.tile = function(image, rect, color = Color.white, tile = tile_def, pipeline image = graphics.texture(image); var mesh = render._main.tile(image.texture, {x:0,y:0,width:image.texture.width,height:image.texture.height}, rect, tile); - current_queue.push({ + render.queue({ type:'geometry', mesh, image, @@ -74,7 +158,7 @@ draw.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.whit image = graphics.texture(image); var mesh = render._main.slice9(image.texture, rect, gizmo.normalizeSpacing(slice), info); - current_queue.push({ + render.queue({ type: 'geometry', mesh, image, @@ -83,3 +167,87 @@ draw.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.whit num_indices:mesh.num_indices }); }; + +var std_sprite_cmd = { + type: 'sprite', + pipeline: sprite_pipeline, + color: [1,1,1,1] +} + +draw.image = function image(image, rect = [0,0], rotation = 0, color, pipeline) { + if (!image) throw Error ('Need an image to render.') + if (typeof image === "string") + image = graphics.texture(image); + + rect.width ??= image.texture.width; + rect.height ??= image.texture.height; + var cmd = Object.create(std_sprite_cmd); + cmd.image = image; + cmd.rect = rect; + if (pipeline) cmd.pipeline = pipeline; + if (color) cmd.color = color; + render.queue(cmd) + + var sprite = os.make_sprite(); + sprite.set_image(image); + sprite.set_rect(rect); + return sprite; +}; + +draw.images = function images(image, rects, config) +{ + if (!image) throw Error ('Need an image to render.'); + if (typeof image === "string") image = graphics.texture(image); + + var bb = []; + bb.width = image.texture.width; + bb.height = image.texture.height; + + var sprites = []; + for (var rect of rects) { + // get sprite from sprite_buf, or make a new one + rect.__proto__ = bb; + var sprite = os.make_sprite(); + sprite.set_rect(rect); + sprite.set_image(image); + sprites.push(sprite) + } + +// var sprites = os.rects_to_sprites(image,rects); + var cmds = render._main.make_sprite_queue(sprites, prosperon.camera, sprite_pipeline) + for (var i = 0; i < cmds.length; i++) + render.queue(cmds[i]) + + return sprites; +} + +draw.sprites = function(sprites, sort = 0, pipeline = sprite_pipeline) +{ + var cmds = render._main.make_sprite_queue(sprites, prosperon.camera, pipeline, sort); + for (var i = 0; i < cmds.length; i++) + render.queue(cmds[i]); +} + +draw.circle = function render_circle(pos, radius, color, inner_radius = 1, pipeline = circle_pipeline) { + render.rectangle({x:pos.x, y:pos.y, width:radius*2,height:radius*2}, color, circle_pipeline); +}; + +var sysfont = graphics.get_font('fonts/c64.ttf', 8); + +draw.text = function text(text, rect, font = sysfont, size = 0, color = Color.white, wrap = 0, pipeline = sprite_pipeline) { + if (typeof font === 'string') + font = graphics.get_font(font) + var mesh = os.make_text_buffer(text, rect, 0, color, wrap, font); + + render.queue({ + type: 'geometry', + mesh, + image: font, + texture:font.texture, + pipeline, + first_index:0, + num_indices:mesh.num_indices + }); +}; + +return draw diff --git a/scripts/engine.js b/scripts/engine.js index 3a715f27..af364890 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -23,6 +23,7 @@ Object.defineProperty(Function.prototype, "hashify", { var io = use_embed('io') io.mount("core/scripts") +io.mount("core/scripts/modules") io.mount("core") var canonical = io.realdir('resources.js') + 'resources.js' @@ -31,6 +32,19 @@ var resources = os.eval('resources.js', `(function setup_resources(){${content}} console.print(resources.canonical('resources.js')) use_cache[resources.canonical('resources.js')] = resources + +function print_api(obj) { + for (var prop in obj) { + if (!obj.hasOwnProperty(prop)) continue + var val = obj[prop] + console.log(prop) + if (typeof val === 'function') { + var m = val.toString().match(/\(([^)]*)\)/) + if (m) console.log(' function: ' + prop + '(' + m[1].trim() + ')') + } + } +} + // path is the path of a module or script to resolve var script_fn = function script_fn(path) { var parsed = {} @@ -56,6 +70,8 @@ var script_fn = function script_fn(path) { if (parsed.module_ret === undefined || parsed.module_ret === null) throw new Error(`Module ${module_name} must return a value`); parsed.module_fn = module_fn; +// console.log(`api for ${path}`) +// print_api(parsed.module_ret) } if (parsed.program) { diff --git a/scripts/emitter.js b/scripts/modules/emitter.js similarity index 100% rename from scripts/emitter.js rename to scripts/modules/emitter.js diff --git a/scripts/layout.js b/scripts/modules/layout.js similarity index 89% rename from scripts/layout.js rename to scripts/modules/layout.js index a3c85e4f..44abf75b 100644 --- a/scripts/layout.js +++ b/scripts/modules/layout.js @@ -2,7 +2,7 @@ // Contain is for how it will treat its children. If they should be laid out as a row, or column, or in a flex style, etc. var geometry = use('geometry') -var render = use('render') +var draw = use('draw2d') var graphics = use('graphics') var util = use('util') @@ -182,7 +182,8 @@ layout.text = function text(str, ...configs) { var config = rectify_configs(configs); config.size ??= [0,0]; - var tsize = render.text_size(str, config.font, 0, 0, config.size.x); + config.font = graphics.get_font(config.font) + var tsize = config.font.text_size(str, 0, 0, config.size.x); config.size = config.size.map((x,i) => Math.max(x, tsize[i])); config.text = str; add_item(config); @@ -203,7 +204,8 @@ var button_base = Object.assign(Object.create(clay_base), { layout.button = function button(str, action, config = {}) { config.__proto__ = button_base; - config.size = render.text_size(str,config.font); + config.font = graphics.get_font(config.font) + config.size = config.font.text_size(str) add_item(config); config.text = str; config.action = action; @@ -228,16 +230,16 @@ layout.draw_commands = function draw_commands(cmds, pos = [0,0], mousepos = pros if (config.background_image) if (config.slice) - render.slice9(config.background_image, boundingbox, config.slice, config.background_color); + draw.slice9(config.background_image, boundingbox, config.slice, config.background_color); else - render.image(config.background_image, boundingbox, 0, config.color); + draw.image(config.background_image, boundingbox, 0, config.color); else if (config.background_color) - render.rectangle(boundingbox, config.background_color); + draw.rectangle(boundingbox, config.background_color); if (config.text) - render.text(config.text, content, config.font, config.font_size, config.color, config.size.x); + draw.text(config.text, content, config.font, config.font_size, config.color, config.size.x); if (config.image) - render.image(config.image, content, 0, config.color); + draw.image(config.image, content, 0, config.color); } } @@ -252,9 +254,9 @@ layout.draw_debug = function draw_debug(cmds, pos = [0,0]) var cmd = cmds[i]; var boundingbox = geometry.rect_move(cmd.boundingbox,pos); var content = geometry.rect_move(cmd.content,pos); - render.rectangle(content, dbg_colors.content); - render.rectangle(boundingbox, dbg_colors.boundingbox); -// render.rectangle(geometry.rect_move(cmd.marginbox,pos), dbg_colors.margin); + draw.rectangle(content, dbg_colors.content); + draw.rectangle(boundingbox, dbg_colors.boundingbox); +// draw.rectangle(geometry.rect_move(cmd.marginbox,pos), dbg_colors.margin); } } @@ -265,6 +267,4 @@ layout.inputs.mouse.left = function() if (hovered && hovered.action) hovered.action(); } -layout.toString = _ => "layout" - return layout diff --git a/scripts/sprite.js b/scripts/modules/sprite.js similarity index 100% rename from scripts/sprite.js rename to scripts/modules/sprite.js diff --git a/scripts/transform.js b/scripts/modules/transform.js similarity index 100% rename from scripts/transform.js rename to scripts/modules/transform.js diff --git a/scripts/render.js b/scripts/render.js index f8e34ff1..a1979196 100644 --- a/scripts/render.js +++ b/scripts/render.js @@ -78,86 +78,8 @@ function bind_pipeline(pass, pipeline) var main_pass; -var base_pipeline = { - vertex: "sprite.vert", - fragment: "sprite.frag", - primitive: "triangle", // point, line, linestrip, triangle, trianglestrip - fill: true, // false for lines - depth: { - compare: "greater_equal", // never/less/equal/less_equal/greater/not_equal/greater_equal/always - test: false, - write: false, - bias: 0, - bias_slope_scale: 0, - bias_clamp: 0 - }, - stencil: { - enabled: true, - front: { - compare: "equal", // never/less/equal/less_equal/greater/neq/greq/always - fail: "keep", // keep/zero/replace/incr_clamp/decr_clamp/invert/incr_wrap/decr_wrap - depth_fail: "keep", - pass: "keep" - }, - back: { - compare: "equal", // never/less/equal/less_equal/greater/neq/greq/always - fail: "keep", // keep/zero/replace/incr_clamp/decr_clamp/invert/incr_wrap/decr_wrap - depth_fail: "keep", - pass: "keep" - }, - test: true, - compare_mask: 0, - write_mask: 0 - }, - blend: { - enabled: false, - src_rgb: "one", // zero/one/src_color/one_minus_src_color/dst_color/one_minus_dst_color/src_alpha/one_minus_src_alpha/dst_alpha/one_minus_dst_alpha/constant_color/one_minus_constant_color/src_alpha_saturate - dst_rgb: "zero", - op_rgb: "add", // add/sub/rev_sub/min/max - src_alpha: "one", - dst_alpha: "zero", - op_alpha: "add" - }, - cull: "none", // none/front/back - face: "cw", // cw/ccw - alpha_to_coverage: false, - multisample: { - count: 1, // number of multisamples - mask: 0xFFFFFFFF, - domask: false - }, - label: "scripted pipeline", - target: {} -} - var cornflower = [62/255,96/255,113/255,1]; -var sprite_pipeline = Object.create(base_pipeline); -sprite_pipeline.blend = { - enabled:true, - src_rgb: "src_alpha", // zero/one/src_color/one_minus_src_color/dst_color/one_minus_dst_color/src_alpha/one_minus_src_alpha/dst_alpha/one_minus_dst_alpha/constant_color/one_minus_constant_color/src_alpha_saturate - dst_rgb: "one_minus_src_alpha", - op_rgb: "add", // add/sub/rev_sub/min/max - src_alpha: "one", - dst_alpha: "zero", - op_alpha: "add" -}; - -sprite_pipeline.target = { - color_targets: [{ - format:"rgba8", - blend:sprite_pipeline.blend - }], - depth: "d32 float s8" -}; - - -var rect_pipeline = Object.create(sprite_pipeline) -rect_pipeline.fragment = "rectangle.frag" - -var circle_pipeline = Object.create(sprite_pipeline) -circle_pipeline.fragment = "circle.frag" - function get_pipeline_ubo_slot(pipeline, name) { if (!pipeline.vertex.reflection.ubos) return; @@ -230,33 +152,9 @@ var sprite_model_ubo = { color: [1,1,1,1] }; -render.poly_prim = function poly_prim(verts) { - var index = []; - if (verts.length < 1) return undefined; - - for (var i = 0; i < verts.length; i++) verts[i][2] = 0; - - for (var i = 2; i < verts.length; i++) { - index.push(0); - index.push(i - 1); - index.push(i); - } - - return { - pos: os.make_buffer(verts.flat()), - verts: verts.length, - index: os.make_buffer(index, 1), - count: index.length, - }; -}; - var shader_cache = {}; var shader_times = {}; -render.hotreload = function shader_hotreload(file) { - console.warn('reimplement shader hot reloading for ' + file) -}; - function make_pipeline(pipeline) { if (pipeline.hasOwnProperty("gpu")) return; // this pipeline has already been made @@ -755,31 +653,13 @@ function gpupresent() } } -var pipeline_model; - -pipeline_model = Object.create(base_pipeline); -pipeline_model.vertex = "model.vert" -pipeline_model.fragment = "model.frag" - -render.draw_sprites = true; -render.draw_particles = true; -render.draw_hud = true; -render.draw_gui = true; - -function insertion_sort(arr, cmp) -{ - for (let i = 1; i < arr.length; i++) { - let key = arr[i] - let j = i - 1 - while (j >= 0 && cmp(arr[j], key) > 0) - arr[j + 1] = arr[j--] - arr[j + 1] = key - } - return arr +render.toggles = { + draw_sprites:true, + draw_particles:true, + draw_hud:true, + draw_gui:true } - - function sprites_to_queue(ysort = false) { var pos = prosperon.camera.transform.pos; @@ -796,84 +676,6 @@ function sprites_to_queue(ysort = false) return cmd; } -render.circle = function render_circle(pos, radius, color, inner_radius = 1, pipeline = circle_pipeline) { - render.rectangle({x:pos.x, y:pos.y, width:radius*2,height:radius*2}, color, circle_pipeline); - return; - if (inner_radius >= 1) inner_radius = inner_radius / radius; - else if (inner_radius < 0) inner_radius = 1.0; - - var mat = { - radius: radius, - inner_r: inner_radius, - coord: pos, - shade: color, - }; - render.use_shader(circleshader); - render.use_mat(mat); - render.draw(shape.quad); -}; -render.circle.doc = "Draw a circle at pos, with a given radius and color. If inner_radius is between 0 and 1, it acts as a percentage of radius. If it is above 1, is acts as a unit (usually a pixel)."; - -render.poly = function render_poly(points, color, transform) { - var buffer = render.poly_prim(points); - var mat = { shade: color }; - render.use_shader(polyshader); - set_model(transform); - render.use_mat(mat); - render.draw(buffer); -}; - -// render.line has uv and can be texture mapped; dbg_line is hardware standard lines -render.line = function render_line(points, color = Color.white, thickness = 1, pipeline = rect_pipeline) { - var mesh = os.make_line_prim(points,thickness, 0,0,color); - current_queue.push({ - type: 'geometry', - mesh, - pipeline, - first_index:0, - num_indices:mesh.num_indices - }); -}; - -/* All draw in screen space */ -render.point = function (pos, size, color = Color.blue) { - render._main.point(pos,color); -}; - -render.cross = function render_cross(pos, size, color = Color.red, thickness = 1, pipe = sprite_pipeline) { - var a = [pos.add([0, size]), pos.add([0, -size])]; - var b = [pos.add([size, 0]), pos.add([-size, 0])]; - render.line(a, color, thickness); - render.line(b, color, thickness); -}; - -render.arrow = function render_arrow(start, end, color = Color.red, wingspan = 4, wingangle = 10, pipe = sprite_pipeline) { - var dir = math.norm(end.sub(start)) - var wing1 = [math.rotate(dir, wingangle).scale(wingspan).add(end), end]; - var wing2 = [math.rotate(dir, -wingangle).scale(wingspan).add(end), end]; - render.line([start, end], color); - render.line(wing1, color); - render.line(wing2, color); -}; - -render.coordinate = function render_coordinate(pos, size, color) { - render.text(JSON.stringify(pos.map(p => Math.round(p))), pos, size, color); - render.point(pos, 2, color); -}; - -var queued_shader; -var queued_pipe; -render.rectangle = function render_rectangle(rect, color = Color.white, pipeline = rect_pipeline) { - var T = os.make_transform(); - T.rect(rect); - current_queue.push({ - type:'sprite', - transform:T, - color, - pipeline - }); -}; - render.particles = function render_particles(emitter, pipeline = sprite_pipeline) { var diff = graphics.texture(emitter.diffuse) @@ -891,44 +693,6 @@ render.particles = function render_particles(emitter, pipeline = sprite_pipeline }); } -var sysfont = graphics.get_font('fonts/c64.ttf', 8); - -render.text = function text(text, rect, font = sysfont, size = 0, color = Color.white, wrap = 0, pipeline = sprite_pipeline) { - if (typeof font === 'string') - font = graphics.get_font(font) - var mesh = os.make_text_buffer(text, rect, 0, color, wrap, font); -// full_upload(mesh) - - current_queue.push({ - type: 'geometry', - mesh, - image: font, - texture:font.texture, - pipeline, - first_index:0, - num_indices:mesh.num_indices - }); - - return; - - if (typeof font === 'string') - font = graphics.get_font(font); - - if (!font) return; - var pos = [rect.x,rect.y]; - pos.y -= font.descent; - if (rect.anchor_y) - pos.y -= rect.anchor_y*(font.ascent-font.descent); - os.make_text_buffer(str, pos, size, color, wrap, font); // this puts text into buffer -}; - -render.text_size = function(str, font, ...args) -{ - if (typeof font === 'string') - font = graphics.get_font(font); - return font.text_size(str, ...args); -} - var stencil_write = { compare: "always", fail_op: "replace", @@ -993,118 +757,6 @@ render.mask = function mask(image, pos, scale, rotation = 0, ref = 1) render.draw(shape.quad); } -var std_sprite_cmd = { - type: 'sprite', - pipeline: sprite_pipeline, - color: [1,1,1,1] -} - -render.image = function image(image, rect = [0,0], rotation = 0, color, pipeline) { - if (!image) throw Error ('Need an image to render.') - if (typeof image === "string") - image = graphics.texture(image); - - rect.width ??= image.texture.width; - rect.height ??= image.texture.height; - var cmd = Object.create(std_sprite_cmd); - cmd.image = image; - cmd.rect = rect; - if (pipeline) cmd.pipeline = pipeline; - if (color) cmd.color = color; - current_queue.push(cmd) - - var sprite = os.make_sprite(); - sprite.set_image(image); - sprite.set_rect(rect); - return sprite; -}; - -render.images = function images(image, rects, config) -{ - if (!image) throw Error ('Need an image to render.'); - if (typeof image === "string") image = graphics.texture(image); - - var bb = []; - bb.width = image.texture.width; - bb.height = image.texture.height; - - var sprites = []; - for (var rect of rects) { - // get sprite from sprite_buf, or make a new one - rect.__proto__ = bb; - var sprite = os.make_sprite(); - sprite.set_rect(rect); - sprite.set_image(image); - sprites.push(sprite) - } - -// var sprites = os.rects_to_sprites(image,rects); - var cmds = render._main.make_sprite_queue(sprites, prosperon.camera, sprite_pipeline) - for (var i = 0; i < cmds.length; i++) - current_queue.push(cmds[i]) - - return sprites; -} - -render.sprites = function(sprites, sort = 0, pipeline = sprite_pipeline) -{ - var cmds = render._main.make_sprite_queue(sprites, prosperon.camera, pipeline, sort); - for (var i = 0; i < cmds.length; i++) - current_queue.push(cmds[i]); -} - -var tile_def = {repeat_x:true, repeat_y:true}; -render.tile = function(image, rect, color = Color.white, tile = tile_def, pipeline = sprite_pipeline) -{ - if (!image) throw Error ('Need an image to render.') - if (typeof image === "string") - image = graphics.texture(image); - - var mesh = render._main.tile(image.texture, {x:0,y:0,width:image.texture.width,height:image.texture.height}, rect, tile); - current_queue.push({ - type:'geometry', - mesh, - image, - pipeline, - first_index:0, - num_indices:mesh.num_indices - }); -} - -// slice is given in pixels -var slice9_info = { - tile_top:true, - tile_bottom:true, - tile_left:true, - tile_right:true, - tile_center_x:true, - tile_center_right:true -}; - -render.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.white, info = slice9_info, pipeline = sprite_pipeline) { - if (!image) throw Error ('Need an image to render.') - if (typeof image === "string") - image = graphics.texture(image); - - var mesh = render._main.slice9(image.texture, rect, util.normalizeSpacing(slice), info); - current_queue.push({ - type: 'geometry', - mesh, - image, - pipeline, - first_index:0, - num_indices:mesh.num_indices - }); -}; - -var textssbos = []; -var tdraw = 0; - -render.doc = "Draw shapes in screen space."; -render.cross.doc = "Draw a cross centered at pos, with arm length size."; -render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle."; -render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright."; - render.viewport = function(rect) { render._main.viewport(rect); @@ -1330,4 +982,9 @@ render._main.present = gpupresent; imgui.init(render._main, prosperon.window); tracy.gpu_init() +render.queue = function(cmd) +{ + current_queue.push(cmd) +} + return render