2024-02-29 13:54:33 -06:00
render . doc = {
doc : "Functions for rendering modes." ,
normal : "Final render with all lighting." ,
2024-09-26 11:36:09 -05:00
wireframe : "Show only wireframes of models." ,
2024-02-29 13:54:33 -06:00
} ;
2024-07-11 14:25:45 -05:00
var cur = { } ;
2024-09-27 10:19:05 -05:00
cur . images = [ ] ;
2024-07-11 14:25:45 -05:00
2024-09-27 10:19:05 -05:00
// When changing a shader, everything must wipe
2024-09-26 11:36:09 -05:00
render . use _shader = function use _shader ( shader ) {
if ( typeof shader === "string" ) shader = make _shader ( shader ) ;
2024-07-11 14:25:45 -05:00
if ( cur . shader === shader ) return ;
cur . shader = shader ;
cur . bind = undefined ;
cur . mesh = undefined ;
2024-09-27 10:19:05 -05:00
cur . ssbo = undefined ;
2024-07-11 14:25:45 -05:00
render . setpipeline ( shader . pipe ) ;
2024-08-02 20:52:50 -05:00
shader _globals ( cur . shader ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-11 14:25:45 -05:00
2024-09-26 11:36:09 -05:00
render . use _mat = function use _mat ( mat ) {
2024-07-11 14:25:45 -05:00
if ( ! cur . shader ) return ;
if ( cur . mat === mat ) return ;
2024-08-02 20:52:50 -05:00
shader _apply _material ( cur . shader , mat , cur . mat ) ;
2024-09-26 11:36:09 -05:00
2024-07-11 14:25:45 -05:00
cur . mat = mat ;
2024-09-27 10:19:05 -05:00
cur . images . length = 0 ;
2024-07-11 14:25:45 -05:00
if ( ! cur . shader . fs . images ) return ;
for ( var img of cur . shader . fs . images )
2024-09-26 11:36:09 -05:00
if ( mat [ img . name ] ) cur . images . push ( mat [ img . name ] ) ;
else cur . images . push ( game . texture ( "icons/no_tex.gif" ) ) ;
} ;
2024-07-11 14:25:45 -05:00
var models _array = [ ] ;
2024-09-26 11:36:09 -05:00
function set _model ( t ) {
if ( cur . shader . vs . unimap . model ) render . setunim4 ( 0 , cur . shader . vs . unimap . model . slot , t ) ;
2024-07-11 14:25:45 -05:00
}
2024-08-08 17:32:58 -05:00
render . set _model = set _model ;
2024-05-15 14:16:05 -05:00
var shaderlang = {
2024-09-26 11:36:09 -05:00
macos : "metal_macos" ,
windows : "hlsl5" ,
linux : "glsl430" ,
web : "wgsl" ,
ios : "metal_ios" ,
} ;
2024-05-15 14:16:05 -05:00
var attr _map = {
a _pos : 0 ,
2024-09-26 11:36:09 -05:00
a _uv : 1 ,
2024-05-15 14:16:05 -05:00
a _norm : 2 ,
2024-08-09 14:39:31 -05:00
a _joint : 3 ,
2024-05-15 14:16:05 -05:00
a _weight : 4 ,
a _color : 5 ,
a _tan : 6 ,
a _angle : 7 ,
a _wh : 8 ,
a _st : 9 ,
a _ppos : 10 ,
2024-09-26 11:36:09 -05:00
a _scale : 11 ,
} ;
2024-05-15 14:16:05 -05:00
var blend _map = {
mix : true ,
2024-09-26 11:36:09 -05:00
none : false ,
} ;
2024-05-15 14:16:05 -05:00
var primitive _map = {
point : 1 ,
line : 2 ,
linestrip : 3 ,
triangle : 4 ,
2024-09-26 11:36:09 -05:00
trianglestrip : 5 ,
} ;
2024-05-15 14:16:05 -05:00
var cull _map = {
2024-09-26 11:36:09 -05:00
none : 1 ,
front : 2 ,
back : 3 ,
} ;
2024-05-15 14:16:05 -05:00
var depth _map = {
off : false ,
2024-09-26 11:36:09 -05:00
on : true ,
} ;
2024-05-15 14:16:05 -05:00
var face _map = {
cw : 2 ,
2024-09-26 11:36:09 -05:00
ccw : 1 ,
} ;
2024-05-15 14:16:05 -05:00
2024-09-26 11:36:09 -05:00
render . poly _prim = function poly _prim ( verts ) {
2024-05-15 14:16:05 -05:00
var index = [ ] ;
if ( verts . length < 1 ) return undefined ;
2024-09-26 11:36:09 -05:00
for ( var i = 0 ; i < verts . length ; i ++ ) verts [ i ] [ 2 ] = 0 ;
2024-05-15 14:16:05 -05:00
for ( var i = 2 ; i < verts . length ; i ++ ) {
index . push ( 0 ) ;
2024-09-26 11:36:09 -05:00
index . push ( i - 1 ) ;
2024-05-15 14:16:05 -05:00
index . push ( i ) ;
}
2024-09-26 11:36:09 -05:00
2024-05-15 14:16:05 -05:00
return {
pos : os . make _buffer ( verts . flat ( ) ) ,
verts : verts . length ,
index : os . make _buffer ( index , 1 ) ,
2024-09-26 11:36:09 -05:00
count : index . length ,
2024-05-15 14:16:05 -05:00
} ;
2024-09-26 11:36:09 -05:00
} ;
2024-05-15 14:16:05 -05:00
2024-09-26 11:36:09 -05:00
function shader _directive ( shader , name , map ) {
var reg = new RegExp ( ` # ${ name } .* ` , "g" ) ;
2024-05-15 14:16:05 -05:00
var mat = shader . match ( reg ) ;
2024-05-16 08:21:13 -05:00
if ( ! mat ) return undefined ;
2024-09-26 11:36:09 -05:00
reg = new RegExp ( ` # ${ name } \s * ` , "g" ) ;
var ff = mat . map ( d => d . replace ( reg , "" ) ) [ 0 ] . trim ( ) ;
2024-05-16 08:21:13 -05:00
if ( map ) return map [ ff ] ;
return ff ;
2024-05-15 14:16:05 -05:00
}
2024-08-02 20:52:50 -05:00
var uni _globals = {
2024-09-26 11:36:09 -05:00
time ( stage , slot ) {
render . setuniv ( stage , slot , profile . secs ( profile . now ( ) ) ) ;
} ,
projection ( stage , slot ) {
render . setuniproj ( stage , slot ) ;
} ,
view ( stage , slot ) {
render . setuniview ( stage , slot ) ;
} ,
vp ( stage , slot ) {
render . setunivp ( stage , slot ) ;
} ,
} ;
2024-08-02 20:52:50 -05:00
function set _global _uni ( uni , stage ) {
2024-09-26 11:36:09 -05:00
uni _globals [ uni . name ] ? . ( stage , uni . slot ) ;
2024-05-15 14:16:05 -05:00
}
2024-07-14 16:09:50 -05:00
var setcam = render . set _camera ;
2024-09-26 11:36:09 -05:00
render . set _camera = function ( cam ) {
2024-07-23 12:02:46 -05:00
if ( nextflush ) {
nextflush ( ) ;
nextflush = undefined ;
}
2024-07-14 16:09:50 -05:00
delete cur . shader ;
setcam ( cam ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-22 15:40:58 -05:00
var shader _cache = { } ;
2024-08-07 16:55:08 -05:00
var shader _times = { } ;
2024-08-02 20:52:50 -05:00
2024-09-26 11:36:09 -05:00
function strip _shader _inputs ( shader ) {
for ( var a of shader . vs . inputs ) a . name = a . name . slice ( 2 ) ;
2024-08-02 20:52:50 -05:00
}
2024-07-25 17:53:53 -05:00
2024-09-26 11:36:09 -05:00
render . hotreload = function ( ) {
2024-08-07 16:55:08 -05:00
for ( var i in shader _times ) {
if ( io . mod ( i ) <= shader _times [ i ] ) continue ;
say ( ` HOT RELOADING SHADER ${ i } ` ) ;
shader _times [ i ] = io . mod ( i ) ;
var obj = create _shader _obj ( i ) ;
obj = obj [ os . sys ( ) ] ;
2024-05-16 14:50:18 -05:00
obj . pipe = render . pipeline ( obj ) ;
2024-08-07 16:55:08 -05:00
var old = shader _cache [ i ] ;
Object . assign ( shader _cache [ i ] , obj ) ;
cur . bind = undefined ;
cur . mesh = undefined ;
2024-05-15 14:16:05 -05:00
}
2024-09-26 11:36:09 -05:00
} ;
2024-08-07 16:55:08 -05:00
2024-09-26 11:36:09 -05:00
function create _shader _obj ( file ) {
2024-05-15 14:16:05 -05:00
var files = [ file ] ;
2024-08-07 16:55:08 -05:00
var out = ".prosperon/tmp.shader" ;
var shader = io . slurp ( file ) ;
2024-05-30 17:12:32 -05:00
2024-05-15 14:16:05 -05:00
var incs = shader . match ( /#include <.*>/g ) ;
if ( incs )
2024-09-26 11:36:09 -05:00
for ( var inc of incs ) {
var filez = inc . match ( /#include <(.*)>/ ) [ 1 ] ;
var macro = io . slurp ( filez ) ;
if ( ! macro ) {
filez = ` shaders/ ${ filez } ` ;
macro = io . slurp ( filez ) ;
}
shader = shader . replace ( inc , macro ) ;
files . push ( filez ) ;
2024-06-07 00:43:15 -05:00
}
2024-09-26 11:36:09 -05:00
var blend = shader _directive ( shader , "blend" , blend _map ) ;
var primitive = shader _directive ( shader , "primitive" , primitive _map ) ;
var cull = shader _directive ( shader , "cull" , cull _map ) ;
var depth = shader _directive ( shader , "depth" , depth _map ) ;
var face = shader _directive ( shader , "face" , face _map ) ;
var indexed = shader _directive ( shader , "indexed" ) ;
if ( typeof indexed == "undefined" ) indexed = true ;
if ( indexed === "false" ) indexed = false ;
2024-05-15 14:16:05 -05:00
shader = shader . replace ( /uniform\s+(\w+)\s+(\w+);/g , "uniform _$2 { $1 $2; };" ) ;
shader = shader . replace ( /(texture2D|sampler) /g , "uniform $1 " ) ;
io . slurpwrite ( out , shader ) ;
2024-05-16 14:50:18 -05:00
var compiled = { } ;
// shader file is created, now cross compile to all targets
for ( var platform in shaderlang ) {
var backend = shaderlang [ platform ] ;
var ret = os . system ( ` sokol-shdc -f bare_yaml --slang= ${ backend } -i ${ out } -o ${ out } ` ) ;
if ( ret ) {
console . error ( ` error compiling shader ${ file } . No compilation found for ${ platform } : ${ backend } , and no cross compiler available. ` ) ;
return ;
}
2024-05-15 14:16:05 -05:00
2024-09-26 11:36:09 -05:00
/* Take YAML and create the shader object */
var yamlfile = ` ${ out } _reflection.yaml ` ;
var jjson = yaml . tojson ( io . slurp ( yamlfile ) ) ;
var obj = json . decode ( jjson ) ;
io . rm ( yamlfile ) ;
2024-05-16 14:50:18 -05:00
2024-09-26 11:36:09 -05:00
obj = obj . shaders [ 0 ] . programs [ 0 ] ;
function add _code ( stage ) {
stage . code = io . slurp ( stage . path ) ;
2024-06-03 16:45:08 -05:00
2024-09-26 11:36:09 -05:00
io . rm ( stage . path ) ;
delete stage . path ;
2024-05-15 14:16:05 -05:00
}
2024-09-26 11:36:09 -05:00
add _code ( obj . vs ) ;
if ( ! obj . fs && obj . vs . fs ) {
obj . fs = obj . vs . fs ;
delete obj . vs . fs ;
2024-05-15 14:16:05 -05:00
}
2024-05-16 14:50:18 -05:00
2024-09-26 11:36:09 -05:00
add _code ( obj . fs ) ;
obj . blend = blend ;
obj . cull = cull ;
obj . primitive = primitive ;
obj . depth = depth ;
obj . face = face ;
obj . indexed = indexed ;
if ( obj . vs . inputs )
for ( var i of obj . vs . inputs ) {
if ( ! ( i . name in attr _map ) ) i . mat = - 1 ;
else i . mat = attr _map [ i . name ] ;
}
function make _unimap ( stage ) {
if ( ! stage . uniform _blocks ) return { } ;
var unimap = { } ;
for ( var uni of stage . uniform _blocks ) {
var uniname = uni . struct _name [ 0 ] == "_" ? uni . struct _name . slice ( 1 ) : uni . struct _name ;
unimap [ uniname ] = {
name : uniname ,
slot : Number ( uni . slot ) ,
size : Number ( uni . size ) ,
} ;
}
return unimap ;
}
obj . vs . unimap = make _unimap ( obj . vs ) ;
obj . fs . unimap = make _unimap ( obj . fs ) ;
obj . name = file ;
2024-08-07 16:55:08 -05:00
2024-09-26 11:36:09 -05:00
strip _shader _inputs ( obj ) ;
compiled [ platform ] = obj ;
2024-05-16 14:50:18 -05:00
}
compiled . files = files ;
2024-08-07 16:55:08 -05:00
compiled . source = shader ;
2024-09-26 11:36:09 -05:00
2024-08-07 16:55:08 -05:00
return compiled ;
}
2024-09-26 11:36:09 -05:00
function make _shader ( shader ) {
2024-08-07 16:55:08 -05:00
if ( shader _cache [ shader ] ) return shader _cache [ shader ] ;
2024-09-26 11:36:09 -05:00
2024-08-07 16:55:08 -05:00
var file = shader ;
shader = io . slurp ( file ) ;
if ( ! shader ) {
console . info ( ` not found! slurping shaders/ ${ file } ` ) ;
shader = io . slurp ( ` shaders/ ${ file } ` ) ;
}
var writejson = ` .prosperon/ ${ file . name ( ) } .shader.json ` ;
profile . cache ( "shader" , file ) ;
2024-09-26 11:36:09 -05:00
2024-08-07 16:55:08 -05:00
breakme : if ( io . exists ( writejson ) ) {
var data = json . decode ( io . slurp ( writejson ) ) ;
var filemod = io . mod ( writejson ) ;
if ( ! data . files ) break breakme ;
for ( var i of data . files ) {
if ( io . mod ( i ) > filemod ) {
break breakme ;
}
}
profile . endcache ( " [cached]" ) ;
var shaderobj = json . decode ( io . slurp ( writejson ) ) ;
var obj = shaderobj [ os . sys ( ) ] ;
obj . pipe = render . pipeline ( obj ) ;
shader _cache [ file ] = obj ;
shader _times [ file ] = io . mod ( file ) ;
return obj ;
}
2024-09-26 11:36:09 -05:00
2024-08-07 16:55:08 -05:00
var compiled = create _shader _obj ( file ) ;
io . slurpwrite ( writejson , json . encode ( compiled ) ) ;
2024-05-16 14:50:18 -05:00
var obj = compiled [ os . sys ( ) ] ;
2024-05-15 14:16:05 -05:00
obj . pipe = render . pipeline ( obj ) ;
2024-08-07 16:55:08 -05:00
shader _cache [ file ] = obj ;
shader _times [ file ] = io . mod ( file ) ;
2024-09-26 11:36:09 -05:00
2024-05-15 14:16:05 -05:00
return obj ;
}
var shader _unisize = {
4 : render . setuniv ,
8 : render . setuniv2 ,
12 : render . setuniv3 ,
2024-09-26 11:36:09 -05:00
16 : render . setuniv4 ,
2024-05-15 14:16:05 -05:00
} ;
2024-08-02 20:52:50 -05:00
2024-09-26 11:36:09 -05:00
function shader _globals ( shader ) {
for ( var p in shader . vs . unimap ) set _global _uni ( shader . vs . unimap [ p ] , 0 ) ;
for ( var p in shader . fs . unimap ) set _global _uni ( shader . fs . unimap [ p ] , 1 ) ;
2024-08-02 20:52:50 -05:00
}
2024-09-26 11:36:09 -05:00
function shader _apply _material ( shader , material = { } , old = { } ) {
2024-05-15 14:16:05 -05:00
for ( var p in shader . vs . unimap ) {
2024-08-02 20:52:50 -05:00
if ( ! ( p in material ) ) continue ;
2024-07-11 14:25:45 -05:00
if ( material [ p ] === old [ p ] ) continue ;
assert ( p in material , ` shader ${ shader . name } has no uniform for ${ p } ` ) ;
2024-05-15 14:16:05 -05:00
var s = shader . vs . unimap [ p ] ;
2024-09-26 11:36:09 -05:00
if ( p === "bones" ) {
2024-08-09 14:39:31 -05:00
render . setunibones ( 0 , s . slot , material [ p ] ) ;
continue ;
}
2024-05-15 14:16:05 -05:00
shader _unisize [ s . size ] ( 0 , s . slot , material [ p ] ) ;
}
2024-09-26 11:36:09 -05:00
2024-05-15 14:16:05 -05:00
for ( var p in shader . fs . unimap ) {
2024-08-02 20:52:50 -05:00
if ( ! ( p in material ) ) continue ;
2024-07-11 14:25:45 -05:00
if ( material [ p ] === old [ p ] ) continue ;
2024-09-26 11:36:09 -05:00
assert ( p in material , ` shader ${ shader . name } has no uniform for ${ p } ` ) ;
2024-05-15 14:16:05 -05:00
var s = shader . fs . unimap [ p ] ;
shader _unisize [ s . size ] ( 1 , s . slot , material [ p ] ) ;
}
2024-09-26 11:36:09 -05:00
2024-06-19 18:52:41 -05:00
if ( ! material . diffuse ) return ;
2024-07-11 14:25:45 -05:00
if ( material . diffuse === old . diffuse ) return ;
2024-06-19 18:52:41 -05:00
2024-09-26 11:36:09 -05:00
if ( "diffuse_size" in shader . fs . unimap ) render . setuniv2 ( 1 , shader . fs . unimap . diffuse _size . slot , [ material . diffuse . width , material . diffuse . height ] ) ;
if ( "diffuse_size" in shader . vs . unimap ) render . setuniv2 ( 0 , shader . vs . unimap . diffuse _size . slot , [ material . diffuse . width , material . diffuse . height ] ) ;
2024-05-15 14:16:05 -05:00
}
2024-09-27 10:19:05 -05:00
// Creates a binding object for a given mesh and shader
var bindcache = { } ;
var bcache = new WeakMap ( ) ;
2024-09-26 11:36:09 -05:00
function sg _bind ( mesh , ssbo ) {
2024-09-27 10:19:05 -05:00
if ( cur . mesh === mesh && cur . ssbo === ssbo ) {
cur . bind . ssbo = [ ssbo ] ;
cur . bind . images = cur . images ;
render . setbind ( cur . bind ) ;
return ;
}
// var sid = os.value_id(cur.shader);
// var mid = os.value_id(mesh);
if ( bcache . has ( cur . shader ) && bcache . get ( cur . shader ) . has ( mesh ) ) {
cur . bind = bcache . get ( cur . shader ) . get ( mesh ) ;
cur . bind . images = cur . images ;
if ( ssbo )
cur . bind . ssbo = [ ssbo ] ;
render . setbind ( cur . bind ) ;
return ;
}
2024-05-15 14:16:05 -05:00
var bind = { } ;
2024-09-27 10:19:05 -05:00
if ( ! bcache . has ( cur . shader ) ) bcache . set ( cur . shader , new WeakMap ( ) ) ;
if ( ! bcache . get ( cur . shader ) . has ( mesh ) ) bcache . get ( cur . shader ) . set ( mesh , bind ) ;
cur . mesh = mesh ;
cur . ssbo = ssbo ;
cur . bind = bind ;
2024-05-15 14:16:05 -05:00
bind . attrib = [ ] ;
2024-07-11 14:25:45 -05:00
if ( cur . shader . vs . inputs )
2024-09-26 11:36:09 -05:00
for ( var a of cur . shader . vs . inputs ) {
if ( ! ( a . name in mesh ) ) {
console . error ( ` cannot draw shader ${ cur . shader . name } ; there is no attrib ${ a . name } in the given mesh. ${ json . encode ( mesh ) } ` ) ;
return undefined ;
} else bind . attrib . push ( mesh [ a . name ] ) ;
}
2024-07-11 14:25:45 -05:00
if ( cur . shader . indexed ) {
2024-05-15 14:16:05 -05:00
bind . index = mesh . index ;
bind . count = mesh . count ;
2024-09-26 11:36:09 -05:00
} else bind . count = mesh . verts ;
2024-05-15 14:16:05 -05:00
bind . ssbo = [ ] ;
2024-09-26 11:36:09 -05:00
if ( cur . shader . vs . storage _buffers ) for ( var b of cur . shader . vs . storage _buffers ) bind . ssbo . push ( ssbo ) ;
2024-07-11 14:25:45 -05:00
bind . images = cur . images ;
render . setbind ( cur . bind ) ;
2024-09-26 11:36:09 -05:00
2024-05-15 14:16:05 -05:00
return bind ;
}
2024-05-16 08:21:13 -05:00
render . device = {
2024-09-26 11:36:09 -05:00
pc : [ 1920 , 1080 ] ,
macbook _m2 : [ 2560 , 1664 , 13.6 ] ,
ds _top : [ 400 , 240 , 3.53 ] ,
ds _bottom : [ 320 , 240 , 3.02 ] ,
playdate : [ 400 , 240 , 2.7 ] ,
switch : [ 1280 , 720 , 6.2 ] ,
switch _lite : [ 1280 , 720 , 5.5 ] ,
switch _oled : [ 1280 , 720 , 7 ] ,
dsi : [ 256 , 192 , 3.268 ] ,
ds : [ 256 , 192 , 3 ] ,
dsixl : [ 256 , 192 , 4.2 ] ,
ipad _air _m2 : [ 2360 , 1640 , 11.97 ] ,
2024-05-16 08:21:13 -05:00
iphone _se : [ 1334 , 750 , 4.7 ] ,
2024-09-26 11:36:09 -05:00
iphone _12 _pro : [ 2532 , 1170 , 6.06 ] ,
iphone _15 : [ 2556 , 1179 , 6.1 ] ,
gba : [ 240 , 160 , 2.9 ] ,
gameboy : [ 160 , 144 , 2.48 ] ,
gbc : [ 160 , 144 , 2.28 ] ,
steamdeck : [ 1280 , 800 , 7 ] ,
vita : [ 960 , 544 , 5 ] ,
psp : [ 480 , 272 , 4.3 ] ,
imac _m3 : [ 4480 , 2520 , 23.5 ] ,
macbook _pro _m3 : [ 3024 , 1964 , 14.2 ] ,
ps1 : [ 320 , 240 , 5 ] ,
ps2 : [ 640 , 480 ] ,
snes : [ 256 , 224 ] ,
gamecube : [ 640 , 480 ] ,
n64 : [ 320 , 240 ] ,
c64 : [ 320 , 200 ] ,
macintosh : [ 512 , 342 , 9 ] ,
gamegear : [ 160 , 144 , 3.2 ] ,
2024-05-16 08:21:13 -05:00
} ;
render . device . doc = ` Device resolutions given as [x,y,inches diagonal]. ` ;
2024-06-07 00:43:15 -05:00
var textshader ;
var circleshader ;
var polyshader ;
2024-07-09 01:03:39 -05:00
var slice9shader ;
2024-07-18 12:39:58 -05:00
var parshader ;
2024-07-22 19:07:02 -05:00
var spritessboshader ;
2024-07-23 12:02:46 -05:00
var polyssboshader ;
2024-06-07 00:43:15 -05:00
2024-07-23 17:21:27 -05:00
var sprite _ssbo ;
2024-09-26 11:36:09 -05:00
render . init = function ( ) {
2024-08-02 20:52:50 -05:00
textshader = make _shader ( "shaders/text_base.cg" ) ;
render . spriteshader = make _shader ( "shaders/sprite.cg" ) ;
spritessboshader = make _shader ( "shaders/sprite_ssbo.cg" ) ;
render . postshader = make _shader ( "shaders/simplepost.cg" ) ;
slice9shader = make _shader ( "shaders/9slice.cg" ) ;
circleshader = make _shader ( "shaders/circle.cg" ) ;
polyshader = make _shader ( "shaders/poly.cg" ) ;
parshader = make _shader ( "shaders/baseparticle.cg" ) ;
polyssboshader = make _shader ( "shaders/poly_ssbo.cg" ) ;
2024-07-23 12:02:46 -05:00
poly _ssbo = render . make _textssbo ( ) ;
2024-07-23 17:21:27 -05:00
sprite _ssbo = render . make _textssbo ( ) ;
2024-09-26 11:36:09 -05:00
2024-06-07 00:43:15 -05:00
render . textshader = textshader ;
2024-09-26 11:36:09 -05:00
os . make _circle2d ( ) . draw = function ( ) {
render . circle ( this . body ( ) . transform ( ) . pos , this . radius , [ 1 , 1 , 0 , 1 ] ) ;
} ;
var disabled = [ 148 / 255 , 148 / 255 , 148 / 255 , 1 ] ;
var sleep = [ 1 , 140 / 255 , 228 / 255 , 1 ] ;
var dynamic = [ 1 , 70 / 255 , 46 / 255 , 1 ] ;
var kinematic = [ 1 , 194 / 255 , 64 / 255 , 1 ] ;
var static _color = [ 73 / 255 , 209 / 255 , 80 / 255 , 1 ] ;
os . make _poly2d ( ) . draw = function ( ) {
2024-06-07 09:49:13 -05:00
var body = this . body ( ) ;
2024-09-26 11:36:09 -05:00
var color = body . sleeping ( ) ? [ 0 , 0.3 , 0 , 0.4 ] : [ 0 , 1 , 0 , 0.4 ] ;
2024-06-07 09:49:13 -05:00
var t = body . transform ( ) ;
render . poly ( this . points , color , body . transform ( ) ) ;
color . a = 1 ;
render . line ( this . points . wrapped ( 1 ) , color , 1 , body . transform ( ) ) ;
2024-09-26 11:36:09 -05:00
} ;
os . make _seg2d ( ) . draw = function ( ) {
render . line ( [ this . a ( ) , this . b ( ) ] , [ 1 , 0 , 1 , 1 ] , Math . max ( this . radius / 2 , 1 ) , this . body ( ) . transform ( ) ) ;
} ;
joint . pin ( ) . draw = function ( ) {
2024-06-07 09:49:13 -05:00
var a = this . bodyA ( ) ;
var b = this . bodyB ( ) ;
2024-09-26 11:36:09 -05:00
render . line ( [ a . transform ( ) . pos . xy , b . transform ( ) . pos . xy ] , [ 0 , 1 , 1 , 1 ] , 1 ) ;
} ;
} ;
2024-06-07 00:43:15 -05:00
2024-08-25 14:23:22 -05:00
render . draw _sprites = true ;
render . draw _particles = true ;
render . draw _hud = true ;
render . draw _gui = true ;
2024-08-26 11:13:26 -05:00
render . draw _gizmos = true ;
2024-08-25 14:23:22 -05:00
2024-09-26 23:12:30 -05:00
render . buckets = [ ] ;
2024-09-27 10:19:05 -05:00
render . sprites = function render _sprites ( ) {
2024-07-25 10:33:51 -05:00
profile . frame ( "drawing" ) ;
2024-07-23 17:21:27 -05:00
render . use _shader ( spritessboshader ) ;
2024-09-26 23:12:30 -05:00
var buckets = component . sprite _buckets ( ) ;
for ( var l in buckets ) {
var layer = buckets [ l ] ;
for ( var img in layer ) {
var sparray = layer [ img ] ;
2024-09-26 11:36:09 -05:00
if ( sparray . length === 0 ) continue ;
var ss = sparray [ 0 ] ;
2024-09-29 06:10:42 -05:00
ss . baseinstance = render . make _sprite _ssbo ( sparray , sprite _ssbo ) ;
render . use _mat ( ss ) ;
2024-09-26 11:36:09 -05:00
render . draw ( shape . quad , sprite _ssbo , sparray . length ) ;
2024-07-23 17:21:27 -05:00
}
}
2024-07-25 10:33:51 -05:00
profile . endframe ( ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-23 17:21:27 -05:00
2024-08-07 16:55:08 -05:00
render . circle = function render _circle ( pos , radius , color , inner _radius = 1 ) {
2024-09-14 09:36:40 -05:00
check _flush ( undefined ) ;
2024-08-07 16:55:08 -05:00
2024-09-26 11:36:09 -05:00
if ( inner _radius >= 1 ) inner _radius = inner _radius / radius ;
else if ( inner _radius < 0 ) inner _radius = 1.0 ;
2024-06-07 00:43:15 -05:00
var mat = {
radius : radius ,
2024-08-07 16:55:08 -05:00
inner _r : inner _radius ,
2024-06-07 00:43:15 -05:00
coord : pos ,
2024-08-07 16:55:08 -05:00
shade : color ,
2024-06-07 00:43:15 -05:00
} ;
2024-07-11 14:25:45 -05:00
render . use _shader ( circleshader ) ;
render . use _mat ( mat ) ;
render . draw ( shape . quad ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-08-07 16:55:08 -05:00
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)." ;
2024-06-07 00:43:15 -05:00
2024-08-02 20:52:50 -05:00
render . poly = function render _poly ( points , color , transform ) {
2024-06-07 00:43:15 -05:00
var buffer = render . poly _prim ( points ) ;
2024-09-26 11:36:09 -05:00
var mat = { shade : color } ;
2024-07-11 14:25:45 -05:00
render . use _shader ( polyshader ) ;
2024-08-02 20:52:50 -05:00
set _model ( transform ) ;
2024-07-11 14:25:45 -05:00
render . use _mat ( mat ) ;
render . draw ( buffer ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-06-07 00:43:15 -05:00
2024-07-23 12:02:46 -05:00
var nextflush = undefined ;
2024-09-26 11:36:09 -05:00
function flush ( ) {
2024-08-02 20:52:50 -05:00
nextflush ? . ( ) ;
nextflush = undefined ;
}
2024-09-23 18:17:46 -05:00
// If flush_fn was already on deck, it does not flush. Otherwise, flushes and then sets the flush fn
2024-09-26 11:36:09 -05:00
function check _flush ( flush _fn ) {
if ( ! nextflush ) nextflush = flush _fn ;
2024-07-23 12:02:46 -05:00
else if ( nextflush !== flush _fn ) {
2024-08-02 20:52:50 -05:00
nextflush ( ) ;
nextflush = flush _fn ;
}
2024-07-23 12:02:46 -05:00
}
2024-09-13 10:27:01 -05:00
render . flush = check _flush ;
2024-09-29 06:10:42 -05:00
render . forceflush = function ( )
{
if ( nextflush ) nextflush ( ) ;
}
2024-09-13 10:27:01 -05:00
2024-07-23 12:02:46 -05:00
var poly _cache = [ ] ;
2024-08-02 20:52:50 -05:00
var poly _idx = 0 ;
2024-07-23 12:02:46 -05:00
var poly _ssbo ;
2024-09-26 11:36:09 -05:00
function poly _e ( ) {
2024-08-02 20:52:50 -05:00
var e ;
poly _idx ++ ;
if ( poly _idx > poly _cache . length ) {
e = {
2024-09-26 11:36:09 -05:00
transform : os . make _transform ( ) ,
color : Color . white ,
2024-08-02 20:52:50 -05:00
} ;
poly _cache . push ( e ) ;
return e ;
}
2024-09-26 11:36:09 -05:00
var e = poly _cache [ poly _idx - 1 ] ;
2024-08-02 20:52:50 -05:00
e . transform . unit ( ) ;
return e ;
}
2024-09-26 11:36:09 -05:00
function flush _poly ( ) {
2024-08-02 20:52:50 -05:00
if ( poly _idx === 0 ) return ;
2024-07-23 12:02:46 -05:00
render . use _shader ( polyssboshader ) ;
2024-09-29 06:10:42 -05:00
var base = render . make _particle _ssbo ( poly _cache . slice ( 0 , poly _idx ) , poly _ssbo ) ;
render . use _mat ( { baseinstance : base } ) ;
2024-08-24 18:40:29 -05:00
render . draw ( shape . centered _quad , poly _ssbo , poly _idx ) ;
2024-08-02 20:52:50 -05:00
poly _idx = 0 ;
2024-07-23 12:02:46 -05:00
}
2024-08-02 20:52:50 -05:00
render . line = function render _line ( points , color = Color . white , thickness = 1 ) {
2024-09-26 11:36:09 -05:00
for ( var i = 0 ; i < points . length - 1 ; i ++ ) {
2024-08-28 16:38:31 -05:00
var a = points [ i ] ;
2024-09-26 11:36:09 -05:00
var b = points [ i + 1 ] ;
2024-08-28 16:38:31 -05:00
var poly = poly _e ( ) ;
2024-09-26 11:36:09 -05:00
var dist = vector . distance ( a , b ) ;
poly . transform . move ( vector . midpoint ( a , b ) ) ;
poly . transform . rotate ( [ 0 , 0 , - 1 ] , vector . angle ( [ b . x - a . x , b . y - a . y ] ) ) ;
2024-08-28 16:38:31 -05:00
poly . transform . scale = [ dist , thickness , 1 ] ;
poly . color = color ;
}
2024-08-02 20:52:50 -05:00
check _flush ( flush _poly ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-06-07 00:43:15 -05:00
2024-05-16 08:21:13 -05:00
/* All draw in screen space */
2024-09-26 11:36:09 -05:00
render . point = function ( pos , size , color = Color . blue ) {
render . circle ( pos , size , size , color ) ;
2024-05-16 08:21:13 -05:00
} ;
2024-09-26 11:36:09 -05:00
2024-08-02 20:52:50 -05:00
render . cross = function render _cross ( pos , size , color = Color . red , thickness = 1 ) {
2024-09-26 11:36:09 -05:00
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 ) ;
2024-05-21 09:33:17 -05:00
} ;
2024-09-26 11:36:09 -05:00
2024-08-02 20:52:50 -05:00
render . arrow = function render _arrow ( start , end , color = Color . red , wingspan = 4 , wingangle = 10 ) {
2024-05-16 08:21:13 -05:00
var dir = end . sub ( start ) . normalized ( ) ;
2024-09-26 11:36:09 -05:00
var wing1 = [ Vector . rotate ( dir , wingangle ) . scale ( wingspan ) . add ( end ) , end ] ;
var wing2 = [ Vector . rotate ( dir , - wingangle ) . scale ( wingspan ) . add ( end ) , end ] ;
render . line ( [ start , end ] , color ) ;
render . line ( wing1 , color ) ;
render . line ( wing2 , color ) ;
2024-05-16 08:21:13 -05:00
} ;
2024-08-02 20:52:50 -05:00
render . coordinate = function render _coordinate ( pos , size , color ) {
2024-09-26 11:36:09 -05:00
render . text ( JSON . stringify ( pos . map ( p => Math . round ( p ) ) ) , pos , size , color ) ;
2024-05-16 08:21:13 -05:00
render . point ( pos , 2 , color ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-05-16 08:21:13 -05:00
2024-08-02 20:52:50 -05:00
render . boundingbox = function render _boundingbox ( bb , color = Color . white ) {
2024-07-10 09:39:28 -05:00
render . line ( bbox . topoints ( bb ) . wrapped ( 1 ) , color ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-05-16 08:21:13 -05:00
2024-08-02 20:52:50 -05:00
render . rectangle = function render _rectangle ( lowerleft , upperright , color ) {
2024-07-23 14:30:41 -05:00
var transform = os . make _transform ( ) ;
2024-09-26 11:36:09 -05:00
var wh = [ upperright . x - lowerleft . x , upperright . y - lowerleft . y ] ;
2024-08-02 20:52:50 -05:00
var poly = poly _e ( ) ;
2024-09-26 11:36:09 -05:00
poly . transform . move ( vector . midpoint ( lowerleft , upperright ) ) ;
poly . transform . scale = [ wh . x , wh . y , 1 ] ;
2024-08-02 20:52:50 -05:00
poly . color = color ;
check _flush ( flush _poly ) ;
2024-05-16 08:21:13 -05:00
} ;
2024-09-26 11:36:09 -05:00
2024-08-02 20:52:50 -05:00
render . box = function render _box ( pos , wh , color = Color . white ) {
var poly = poly _e ( ) ;
poly . transform . move ( pos ) ;
2024-09-26 11:36:09 -05:00
poly . transform . scale = [ wh . x , wh . y , 1 ] ;
2024-08-02 20:52:50 -05:00
poly . color = color ;
2024-09-26 11:36:09 -05:00
check _flush ( flush _poly ) ;
2024-05-16 08:21:13 -05:00
} ;
2024-09-26 11:36:09 -05:00
render . window = function render _window ( pos , wh , color ) {
render . box ( pos . add ( wh . scale ( 0.5 ) ) , wh , color ) ;
} ;
2024-05-16 08:21:13 -05:00
2024-09-26 11:36:09 -05:00
render . text _bb = function ( str , size = 1 , wrap = - 1 , pos = [ 0 , 0 ] ) {
var bb = render . text _size ( str , size , wrap ) ;
var w = bb . r - bb . l ;
var h = bb . t - bb . b ;
2024-07-09 13:48:15 -05:00
2024-07-09 01:03:39 -05:00
bb . r += pos . x ;
bb . l += pos . x ;
bb . t += pos . y ;
bb . b += pos . y ;
2024-07-09 13:48:15 -05:00
return bb ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-09 13:48:15 -05:00
2024-09-26 11:36:09 -05:00
render . text = function ( str , pos , size = 1 , color = Color . white , wrap = - 1 , anchor = [ 0 , 1 ] , cursor = - 1 ) {
2024-07-10 09:39:28 -05:00
var bb = render . text _bb ( str , size , wrap , pos ) ;
2024-09-06 22:47:04 -05:00
gui . text ( str , pos , size , color , wrap , cursor ) ; // this puts text into buffer
2024-07-23 12:02:46 -05:00
check _flush ( render . flush _text ) ;
2024-07-09 01:03:39 -05:00
return bb ;
2024-09-26 11:36:09 -05:00
2024-05-16 08:21:13 -05:00
p . x -= w * anchor . x ;
2024-09-26 11:36:09 -05:00
bb . r += w * anchor . x ;
bb . l += w * anchor . x ;
2024-05-16 08:21:13 -05:00
p . y += h * ( 1 - anchor . y ) ;
2024-09-26 11:36:09 -05:00
bb . t += h * ( 1 - anchor . y ) ;
bb . b += h * ( 1 - anchor . y ) ;
2024-07-09 01:03:39 -05:00
2024-05-16 08:21:13 -05:00
return bb ;
} ;
2024-09-23 18:17:46 -05:00
var lasttex = undefined ;
var img _cache = [ ] ;
var img _idx = 0 ;
2024-09-26 11:36:09 -05:00
function flush _img ( ) {
2024-09-23 18:17:46 -05:00
if ( img _idx === 0 ) return ;
render . use _shader ( spritessboshader ) ;
2024-09-29 06:10:42 -05:00
var startidx = render . make _sprite _ssbo ( img _cache . slice ( 0 , img _idx ) , sprite _ssbo ) ;
render . use _mat ( { baseinstance : startidx } ) ;
2024-09-27 14:30:15 -05:00
cur . images = [ lasttex ] ;
2024-09-29 06:10:42 -05:00
render . draw ( shape . quad , sprite _ssbo , img _idx ) ;
2024-09-23 18:17:46 -05:00
lasttex = undefined ;
img _idx = 0 ;
}
2024-09-26 11:36:09 -05:00
function img _e ( ) {
2024-09-23 18:17:46 -05:00
img _idx ++ ;
if ( img _idx > img _cache . length ) {
2024-09-26 19:28:54 -05:00
var e = {
2024-09-23 18:17:46 -05:00
transform : os . make _transform ( ) ,
shade : Color . white ,
2024-09-26 11:36:09 -05:00
rect : [ 0 , 0 , 1 , 1 ] ,
2024-09-23 18:17:46 -05:00
} ;
img _cache . push ( e ) ;
return e ;
}
2024-09-26 19:28:54 -05:00
return img _cache [ img _idx - 1 ] ;
2024-09-23 18:17:46 -05:00
}
2024-09-26 19:28:54 -05:00
render . image = function image ( tex , pos , scale , rotation = 0 , color = Color . white ) {
2024-09-27 10:19:05 -05:00
if ( typeof tex === "string" )
2024-09-11 12:25:42 -05:00
tex = game . texture ( tex ) ;
2024-09-27 10:19:05 -05:00
2024-09-29 06:10:42 -05:00
if ( scale )
scale = scale . div ( [ tex . width , tex . height ] ) ;
else
scale = vector . v3one ;
2024-09-11 12:25:42 -05:00
if ( ! tex ) return ;
2024-09-23 18:17:46 -05:00
if ( ! lasttex ) {
2024-09-26 11:36:09 -05:00
check _flush ( flush _img ) ;
2024-09-23 18:17:46 -05:00
lasttex = tex ;
}
2024-09-26 11:36:09 -05:00
2024-09-23 18:17:46 -05:00
if ( lasttex !== tex ) {
flush _img ( ) ;
lasttex = tex ;
}
2024-09-26 11:36:09 -05:00
2024-09-23 18:17:46 -05:00
var e = img _e ( ) ;
2024-09-27 10:19:05 -05:00
e . transform . trs ( pos , undefined , scale ) ;
2024-09-23 18:17:46 -05:00
e . shade = color ;
2024-09-27 14:30:15 -05:00
e . texture = tex ;
2024-09-29 06:10:42 -05:00
2024-09-23 18:17:46 -05:00
return ;
2024-07-09 01:03:39 -05:00
var bb = { } ;
bb . b = pos . y ;
bb . l = pos . x ;
2024-09-26 11:36:09 -05:00
bb . t = pos . y + tex . height * scale ;
bb . r = pos . x + tex . width * scale ;
2024-07-09 01:03:39 -05:00
return bb ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-15 15:54:18 -05:00
// pos is the lower left corner, scale is the width and height
2024-09-26 11:36:09 -05:00
render . slice9 = function ( tex , pos , bb , scale = [ tex . width , tex . height ] , color = Color . white ) {
2024-07-09 01:03:39 -05:00
var t = os . make _transform ( ) ;
t . pos = pos ;
2024-09-26 11:36:09 -05:00
t . scale = [ scale . x / tex . width , scale . y / tex . height , 1 ] ;
2024-07-09 16:43:09 -05:00
var border ;
2024-09-26 11:36:09 -05:00
if ( typeof bb === "number" ) border = [ bb / tex . width , bb / tex . height , bb / tex . width , bb / tex . height ] ;
else border = [ bb . l / tex . width , bb . b / tex . height , bb . r / tex . width , bb . t / tex . height ] ;
2024-07-11 14:25:45 -05:00
render . use _shader ( slice9shader ) ;
2024-08-02 20:52:50 -05:00
set _model ( t ) ;
2024-07-11 14:25:45 -05:00
render . use _mat ( {
2024-07-09 13:48:15 -05:00
shade : color ,
2024-09-26 11:36:09 -05:00
diffuse : tex ,
rect : [ 0 , 0 , 1 , 1 ] ,
2024-07-09 16:43:09 -05:00
border : border ,
2024-09-26 11:36:09 -05:00
scale : [ scale . x / tex . width , scale . y / tex . height ] ,
2024-07-09 01:03:39 -05:00
} ) ;
2024-07-11 14:25:45 -05:00
render . draw ( shape . quad ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-09 01:03:39 -05:00
2024-09-26 11:36:09 -05:00
function endframe ( ) {
2024-09-06 22:47:04 -05:00
tdraw = 0 ;
}
var textssbos = [ ] ;
var tdraw = 0 ;
2024-07-18 17:09:35 -05:00
2024-09-26 11:36:09 -05:00
render . flush _text = function ( ) {
2024-07-09 01:03:39 -05:00
if ( ! render . textshader ) return ;
2024-09-06 22:47:04 -05:00
tdraw ++ ;
2024-09-26 11:36:09 -05:00
if ( textssbos . length < tdraw ) textssbos . push ( render . make _textssbo ( ) ) ;
var textssbo = textssbos [ tdraw - 1 ] ;
2024-09-06 22:47:04 -05:00
var amt = render . flushtext ( textssbo ) ; // load from buffer into ssbo
2024-09-26 11:36:09 -05:00
2024-09-06 22:47:04 -05:00
if ( amt === 0 ) {
tdraw -- ;
2024-09-26 11:36:09 -05:00
return ;
}
2024-07-11 14:25:45 -05:00
render . use _shader ( render . textshader ) ;
2024-09-26 11:36:09 -05:00
render . use _mat ( { text : render . font . texture } ) ;
2024-07-18 17:09:35 -05:00
render . draw ( shape . quad , textssbo , amt ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-05-16 08:21:13 -05:00
2024-08-02 20:52:50 -05:00
var fontcache = { } ;
2024-09-26 11:36:09 -05:00
render . set _font = function ( path , size ) {
2024-05-16 08:21:13 -05:00
var fontstr = ` ${ path } - ${ size } ` ;
2024-08-02 20:52:50 -05:00
if ( render . font && fontcache [ fontstr ] === render . font ) return ;
if ( ! fontcache [ fontstr ] ) fontcache [ fontstr ] = os . make _font ( path , size ) ;
2024-09-26 11:36:09 -05:00
2024-07-09 01:03:39 -05:00
render . flush _text ( ) ;
2024-05-16 08:21:13 -05:00
2024-08-02 20:52:50 -05:00
gui . font _set ( fontcache [ fontstr ] ) ;
render . font = fontcache [ fontstr ] ;
2024-09-26 11:36:09 -05:00
} ;
2024-05-16 08:21:13 -05:00
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." ;
2024-09-26 11:36:09 -05:00
render . draw = function render _draw ( mesh , ssbo , inst = 1 , e _start = 0 ) {
2024-08-02 20:52:50 -05:00
sg _bind ( mesh , ssbo ) ;
profile . frame ( "gpu" ) ;
2024-09-07 00:11:34 -05:00
render . spdraw ( e _start , cur . bind . count , inst ) ;
2024-08-02 20:52:50 -05:00
profile . endframe ( ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-05-16 08:21:13 -05:00
2024-07-25 17:53:53 -05:00
// Returns an array in the form of [left, bottom, right, top] in pixels of the camera to render to
2024-08-22 13:31:00 -05:00
// Camera viewport is [left,bottom,width,height] in relative values
2024-09-26 11:36:09 -05:00
function camviewport ( ) {
var aspect = ( ( ( this . viewport [ 2 ] - this . viewport [ 0 ] ) / ( this . viewport [ 3 ] - this . viewport [ 1 ] ) ) * window . size . x ) / window . size . y ;
var raspect = this . size . x / this . size . y ;
2024-07-25 17:53:53 -05:00
2024-09-26 11:36:09 -05:00
var left = this . viewport [ 0 ] * window . size . x ;
var bottom = this . viewport [ 1 ] * window . size . y ;
2024-07-25 17:53:53 -05:00
var usemode = this . mode ;
2024-09-26 11:36:09 -05:00
if ( this . break && this . size . x > window . size . x && this . size . y > window . size . y ) usemode = this . break ;
2024-07-25 17:53:53 -05:00
if ( usemode === "fit" )
if ( raspect < aspect ) usemode = "height" ;
else usemode = "width" ;
2024-09-26 11:36:09 -05:00
switch ( usemode ) {
2024-07-25 17:53:53 -05:00
case "stretch" :
case "expand" :
return [ 0 , 0 , window . size . x , window . size . y ] ;
case "keep" :
2024-09-26 11:36:09 -05:00
return [ left , bottom , left + this . size . x , bottom + this . size . y ] ;
2024-07-25 17:53:53 -05:00
case "height" :
2024-09-26 11:36:09 -05:00
var ret = [ left , 0 , this . size . x * ( window . size . y / this . size . y ) , window . size . y ] ;
ret [ 0 ] = ( window . size . x - ( ret [ 2 ] - ret [ 0 ] ) ) / 2 ;
2024-07-25 17:53:53 -05:00
return ret ;
case "width" :
2024-09-26 11:36:09 -05:00
var ret = [ 0 , bottom , window . size . x , this . size . y * ( window . size . x / this . size . x ) ] ;
ret [ 1 ] = ( window . size . y - ( ret [ 3 ] - ret [ 1 ] ) ) / 2 ;
2024-07-25 17:53:53 -05:00
return ret ;
}
return [ 0 , 0 , window . size . x , window . size . y ] ;
}
// pos is pixels on the screen, lower left[0,0]
2024-09-26 11:36:09 -05:00
function camscreen2world ( pos ) {
2024-07-25 17:53:53 -05:00
var view = this . screen2cam ( pos ) ;
view . x *= this . size . x ;
view . y *= this . size . y ;
2024-09-26 11:36:09 -05:00
view = view . sub ( [ this . size . x / 2 , this . size . y / 2 ] ) ;
2024-07-25 17:53:53 -05:00
view = view . add ( this . pos . xy ) ;
return view ;
}
2024-08-22 13:31:00 -05:00
// three coordinatse
// world coordinates, the "actual" view relative to the game's universe
// camera coordinates, normalized from 0 to 1 inside of a camera's viewport, bottom left is 0,0, top right is 1,1
// screen coordinates, pixels, 0,0 at the bottom left of the window and [w,h] at the top right of the screen
2024-09-26 11:36:09 -05:00
camscreen2world . doc = "Convert a view position for a camera to world." ;
2024-07-25 17:53:53 -05:00
2024-08-22 13:31:00 -05:00
// return camera coordinates given a screen position
2024-09-26 11:36:09 -05:00
function screen2cam ( pos ) {
2024-07-25 17:53:53 -05:00
var viewport = this . view ( ) ;
2024-08-22 13:31:00 -05:00
var width = viewport [ 2 ] ;
var height = viewport [ 3 ] ;
2024-09-26 11:36:09 -05:00
var viewpos = pos . sub ( [ viewport [ 0 ] , viewport [ 1 ] ] ) ;
return viewpos . div ( [ width , height ] ) ;
2024-08-22 13:31:00 -05:00
}
2024-09-26 11:36:09 -05:00
function camextents ( ) {
var half = this . size ; //.scale(0.5);
2024-08-22 13:31:00 -05:00
return {
2024-09-26 11:36:09 -05:00
l : this . pos . x - half . x ,
r : this . pos . x + half . x ,
t : this . pos . y + half . y ,
b : this . pos . y - half . y ,
2024-08-22 13:31:00 -05:00
} ;
2024-07-25 17:53:53 -05:00
}
2024-09-26 11:36:09 -05:00
screen2cam . doc = "Convert a screen space position in pixels to a normalized viewport position in a camera." ;
2024-07-25 17:53:53 -05:00
2024-09-26 11:36:09 -05:00
prosperon . gizmos = function ( ) {
2024-08-27 14:58:08 -05:00
game . all _objects ( o => {
if ( o . gizmo ) render . image ( game . texture ( o . gizmo ) , o . pos ) ;
} ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-08-27 14:58:08 -05:00
2024-09-26 11:36:09 -05:00
prosperon . make _camera = function ( ) {
2024-07-25 17:53:53 -05:00
var cam = world . spawn ( ) ;
cam . near = 0.1 ;
cam . far = 1000 ;
cam . ortho = true ;
2024-09-26 11:36:09 -05:00
cam . viewport = [ 0 , 0 , 1 , 1 ] ;
2024-07-25 17:53:53 -05:00
cam . size = window . size . slice ( ) ; // The render size of this camera in pixels
// In ortho mode, this determines how many pixels it will see
cam . mode = "stretch" ;
cam . screen2world = camscreen2world ;
cam . screen2cam = screen2cam ;
2024-08-22 13:31:00 -05:00
cam . extents = camextents ;
2024-09-26 11:36:09 -05:00
cam . mousepos = function ( ) {
return this . screen2world ( input . mouse . screenpos ( ) ) ;
} ;
2024-07-25 17:53:53 -05:00
cam . view = camviewport ;
cam . offscreen = false ;
return cam ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-25 17:53:53 -05:00
var screencolor ;
2024-09-26 11:36:09 -05:00
globalThis . imtoggle = function ( name , obj , field ) {
2024-09-26 19:28:54 -05:00
var changed = false ;
var old = obj [ field ] ;
2024-09-26 11:36:09 -05:00
obj [ field ] = imgui . checkbox ( name , obj [ field ] ) ;
2024-09-26 19:28:54 -05:00
if ( old !== obj [ field ] ) return true ;
return false ;
2024-09-26 11:36:09 -05:00
} ;
2024-09-03 14:08:46 -05:00
var replstr = "" ;
2024-09-26 11:36:09 -05:00
var imdebug = function ( ) {
imtoggle ( "Physics" , debug , "draw_phys" ) ;
imtoggle ( "Bouning boxes" , debug , "draw_bb" ) ;
imtoggle ( "Gizmos" , debug , "draw_gizmos" ) ;
imtoggle ( "Names" , debug , "draw_names" ) ;
imtoggle ( "Sprite nums" , debug , "sprite_nums" ) ;
imtoggle ( "Debug overlay" , debug , "show" ) ;
imtoggle ( "Show ur names" , debug , "urnames" ) ;
} ;
2024-09-03 14:08:46 -05:00
2024-09-26 11:36:09 -05:00
var imgui _fn = function ( ) {
2024-09-03 14:08:46 -05:00
render . imgui _new ( window . size . x , window . size . y , 0.01 ) ;
2024-09-26 11:36:09 -05:00
if ( debug . console )
debug . console = imgui . window ( "console" , _ => {
imgui . text ( console . transcript ) ;
replstr = imgui . textinput ( undefined , replstr ) ;
imgui . button ( "submit" , _ => {
eval ( replstr ) ;
replstr = "" ;
} ) ;
} ) ;
2024-09-03 14:08:46 -05:00
2024-09-26 11:36:09 -05:00
imgui . mainmenubar ( _ => {
2024-09-03 14:08:46 -05:00
imgui . menu ( "File" , _ => {
imgui . menu ( "Game settings" , _ => {
window . title = imgui . textinput ( "Title" , window . title ) ;
window . icon = imgui . textinput ( "Icon" , window . icon ) ;
imgui . button ( "Refresh window" , _ => {
window . set _icon ( game . texture ( window . icon ) ) ;
} ) ;
} ) ;
imgui . button ( "quit" , os . quit ) ;
} ) ;
imgui . menu ( "Debug" , imdebug ) ;
imgui . menu ( "View" , _ => {
2024-09-26 11:36:09 -05:00
imtoggle ( "Profiler" , debug , "showprofiler" ) ;
imtoggle ( "Terminal out" , debug , "termout" ) ;
imtoggle ( "Meta [f7]" , debug , "meta" ) ;
imtoggle ( "Cheats [f8]" , debug , "cheat" ) ;
imtoggle ( "Console [f9]" , debug , "console" ) ;
2024-09-03 14:08:46 -05:00
} ) ;
imgui . sokol _gfx ( ) ;
imgui . menu ( "Graphics" , _ => {
2024-09-26 11:36:09 -05:00
imtoggle ( "Draw sprites" , render , "draw_sprites" ) ;
imtoggle ( "Draw particles" , render , "draw_particles" ) ;
imtoggle ( "Draw HUD" , render , "draw_hud" ) ;
imtoggle ( "Draw GUI" , render , "draw_gui" ) ;
imtoggle ( "Draw gizmos" , render , "draw_gizmos" ) ;
2024-09-03 14:08:46 -05:00
imgui . menu ( "Window" , _ => {
window . fullscreen = imgui . checkbox ( "fullscreen" , window . fullscreen ) ;
2024-09-26 11:36:09 -05:00
// window.vsync = imgui.checkbox("vsync", window.vsync);
2024-09-03 14:08:46 -05:00
imgui . menu ( "MSAA" , _ => {
2024-09-26 11:36:09 -05:00
for ( var msaa of gamestate . msaa ) imgui . button ( msaa + "x" , _ => ( window . sample _count = msaa ) ) ;
2024-09-03 14:08:46 -05:00
} ) ;
imgui . menu ( "Resolution" , _ => {
2024-09-26 11:36:09 -05:00
for ( var res of gamestate . resolutions ) imgui . button ( res , _ => ( window . resolution = res ) ) ;
2024-09-03 14:08:46 -05:00
} ) ;
} ) ;
} ) ;
prosperon . menu _hook ? . ( ) ;
} ) ;
2024-09-26 11:36:09 -05:00
2024-09-03 14:08:46 -05:00
prosperon . imgui ( ) ;
render . imgui _end ( ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-09-03 14:08:46 -05:00
2024-09-26 11:36:09 -05:00
prosperon . render = function ( ) {
2024-07-25 17:53:53 -05:00
profile . frame ( "world" ) ;
render . set _camera ( prosperon . camera ) ;
profile . frame ( "sprites" ) ;
2024-08-25 14:23:22 -05:00
if ( render . draw _sprites ) render . sprites ( ) ;
if ( render . draw _particles ) draw _emitters ( ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
profile . frame ( "draws" ) ;
prosperon . draw ( ) ;
2024-09-29 06:10:42 -05:00
// sgl.draw();
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
prosperon . hudcam . size = prosperon . camera . size ;
2024-09-26 11:36:09 -05:00
prosperon . hudcam . transform . pos = [ prosperon . hudcam . size . x / 2 , prosperon . hudcam . size . y / 2 , - 100 ] ;
2024-07-25 17:53:53 -05:00
render . set _camera ( prosperon . hudcam ) ;
profile . endframe ( ) ;
profile . frame ( "hud" ) ;
2024-08-25 14:23:22 -05:00
if ( render . draw _hud ) prosperon . hud ( ) ;
2024-08-27 14:58:08 -05:00
render . flush _text ( ) ;
render . set _camera ( prosperon . camera ) ;
2024-09-26 23:12:30 -05:00
//if (render.draw_gizmos && prosperon.gizmos) prosperon.gizmos();
2024-07-25 17:53:53 -05:00
render . flush _text ( ) ;
render . end _pass ( ) ;
profile . endframe ( ) ;
2024-08-05 15:26:18 -05:00
profile . endframe ( ) ;
profile . endframe ( ) ;
2024-07-25 17:53:53 -05:00
/* draw the image of the game world first */
render . glue _pass ( ) ;
2024-08-05 15:26:18 -05:00
profile . frame ( "frame" ) ;
profile . frame ( "render" ) ;
2024-09-26 11:36:09 -05:00
profile . frame ( "post process" ) ;
2024-07-25 17:53:53 -05:00
render . viewport ( ... prosperon . camera . view ( ) ) ;
render . use _shader ( render . postshader ) ;
2024-09-26 11:36:09 -05:00
render . use _mat ( { diffuse : prosperon . screencolor } ) ;
2024-07-25 17:53:53 -05:00
render . draw ( shape . quad ) ;
profile . endframe ( ) ;
profile . frame ( "app" ) ;
// Flush & render
2024-09-26 11:36:09 -05:00
prosperon . appcam . transform . pos = [ window . size . x / 2 , window . size . y / 2 , - 100 ] ;
2024-07-25 17:53:53 -05:00
prosperon . appcam . size = window . size . slice ( ) ;
2024-09-26 11:36:09 -05:00
if ( os . sys ( ) !== "macos" ) prosperon . appcam . size . y *= - 1 ;
2024-07-25 17:53:53 -05:00
render . set _camera ( prosperon . appcam ) ;
render . viewport ( ... prosperon . appcam . view ( ) ) ;
// Call gui functions
mum . style = mum . dbg _style ;
2024-08-25 14:23:22 -05:00
if ( render . draw _gui ) prosperon . gui ( ) ;
2024-07-25 17:53:53 -05:00
if ( mum . drawinput ) mum . drawinput ( ) ;
render . flush _text ( ) ;
mum . style = mum . base ;
2024-09-09 18:55:07 -05:00
check _flush ( ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
profile . frame ( "imgui" ) ;
2024-09-26 11:36:09 -05:00
if ( debug . show ) imgui _fn ( ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
render . end _pass ( ) ;
2024-09-26 19:28:54 -05:00
2024-07-25 17:53:53 -05:00
render . commit ( ) ;
2024-09-29 06:10:42 -05:00
profile . report _frame ( profile . secs ( profile . now ( ) ) - frame _t ) ;
2024-09-26 11:36:09 -05:00
2024-09-06 22:47:04 -05:00
endframe ( ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-25 17:53:53 -05:00
2024-08-02 20:52:50 -05:00
prosperon . process = function process ( ) {
2024-07-25 17:53:53 -05:00
profile . frame ( "frame" ) ;
var dt = profile . secs ( profile . now ( ) ) - frame _t ;
frame _t = profile . secs ( profile . now ( ) ) ;
2024-09-24 17:07:32 -05:00
var sst = profile . now ( ) ;
2024-09-26 11:36:09 -05:00
2024-08-06 14:23:21 -05:00
/* debugging: check for gc */
profile . print _gc ( ) ;
var cycles = os . check _cycles ( ) ;
if ( cycles ) say ( cycles ) ;
2024-07-25 17:53:53 -05:00
profile . frame ( "app update" ) ;
prosperon . appupdate ( dt ) ;
profile . endframe ( ) ;
profile . frame ( "input" ) ;
input . procdown ( ) ;
profile . endframe ( ) ;
if ( sim . mode === "play" || sim . mode === "step" ) {
2024-09-26 11:36:09 -05:00
profile . frame ( "update" ) ;
2024-07-25 17:53:53 -05:00
prosperon . update ( dt * game . timescale ) ;
2024-08-25 14:23:22 -05:00
update _emitters ( dt * game . timescale ) ;
2024-09-30 04:36:53 -05:00
os . update _timers ( dt * game . timescale ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
if ( sim . mode === "step" ) sim . pause ( ) ;
2024-09-24 17:07:32 -05:00
}
2024-09-26 11:36:09 -05:00
profile . pushdata ( profile . data . cpu . scripts , profile . now ( ) - sst ) ;
2024-09-24 17:07:32 -05:00
sst = profile . now ( ) ;
2024-07-25 17:53:53 -05:00
2024-09-24 17:07:32 -05:00
if ( sim . mode === "play" || sim . mode === "step" ) {
2024-07-25 17:53:53 -05:00
profile . frame ( "physics" ) ;
physlag += dt ;
while ( physlag > physics . delta ) {
physlag -= physics . delta ;
prosperon . phys2d _step ( physics . delta * game . timescale ) ;
prosperon . physupdate ( physics . delta * game . timescale ) ;
}
profile . endframe ( ) ;
2024-09-26 11:36:09 -05:00
profile . pushdata ( profile . data . cpu . physics , profile . now ( ) - sst ) ;
2024-09-24 17:07:32 -05:00
sst = profile . now ( ) ;
2024-07-25 17:53:53 -05:00
}
profile . frame ( "render" ) ;
prosperon . window _render ( window . size ) ;
prosperon . render ( ) ;
2024-09-26 11:36:09 -05:00
profile . pushdata ( profile . data . cpu . render , profile . now ( ) - sst ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
profile . endframe ( ) ;
2024-09-24 14:12:59 -05:00
profile . capture _data ( ) ;
2024-09-26 11:36:09 -05:00
} ;
2024-07-25 17:53:53 -05:00
2024-09-26 11:36:09 -05:00
return { render } ;