Blog

  • BooBoo 3.0.14

    • Standalone docs
    • draw_3d named draw_vertex_buffer
    • draw_3d/draw_model/draw_billboard no longer mess with the depth buffer
    • file_read_line now includes newline, add file_read/write_byte
    • Add string_set_char_at
    • vector_clear and map_clear can clear multiple containers
  • the new draw_vertex_buffer

    Can draw in 2d also. Actually the difference is draw_3d (removed) manages the depth buffer but draw_vertex_buffer doesn’t. So if you’re drawing 3d geometry you’ll want to enable/disable depth write and test as required.

  • BooBoo benchmarking

    EDIT: here’s a better benchmark. I’m getting 3 million tris at 60 FPS. EDIT it’s 2 million textured with alpha testing

    This is a 75px triangle (running at 1280×720 default window) benchmark to see how your system compares to PS2 running BooBoo. You should probably texture the triangle to get a more accurate result. I get about 900,000 textured and 1.2 million untextured per frame.

    EDIT: PlayStation 2 claims max 16 million per second, that’s 266,000 per frame.

    var tris
    = tris 3000000
    
    var font
    = font (font_load "font.ttf" 32 1)
    
    var vertex_buffer
    call load_vb
    
    set_projection (identity 4) (ortho 0 640 360 0)
    
    function load_vb
    {
    	var verts faces colours normals texcoords
    
    	var i
    	for i 0 (< i tris) 1 next
    		var x y
    		= x (rand 0 1280)
    		= y (rand 0 720)
    		vector_add verts x y 0
    		vector_add verts (+ x 6) y 0
    		vector_add verts x (+ y 6) 0
    		vector_add faces (+ (* i 3) 0) (+ (* i 3) 1) (+ (* i 3) 2)
    	:next
    
    	= vertex_buffer (create_vertex_buffer (@ verts) (@ faces) (@ colours) (@ normals) (@ texcoords) tris TRUE)
    
            vector_clear verts
    	vector_clear faces
    }
    
    function draw
    {
    	enable_depth_test TRUE
    	enable_depth_write TRUE
    	draw_vertex_buffer vertex_buffer
    	enable_depth_test FALSE
    	enable_depth_write FALSE
    
    	font_draw font 255 255 0 255 (string_format "%(.0f)" tris) 5 50
    }
    
    function event type a b c d
    {
    	if (== type EVENT_KEY_DOWN) key
    		if (== a KEY_UP) up (== a KEY_DOWN) down
    			= tris (+ tris 100000)
    			destroy_vertex_buffer vertex_buffer
    			call load_vb
    		:up
    			if (> tris 100000) go
    				= tris (- tris 100000)
    				destroy_vertex_buffer vertex_buffer
    				call load_vb
    			:go
    		:down
    	:key
    }
  • BooBoo 3.0.13

    • Add VBOs for create_vertex_buffer (optional last boolean parameter) for greater speed
    • Fix winding order of faces in lit3d, 3dcube and DOOMED examples now that we are culling backfaces
    • vector_clear now free memory not just vec.clear()
  • VBO backed vertex buffers

    The vertex buffers in BooBoo 3.0.12 are just a streamlined format, they’re quite a lot faster but the next version will have a boolean to create a VBO. I tested it and I get 900,000 tris per frame, up from 600,000.

    EDIT: the playstation 2 can do about 250-275,000. I’m sure with programmable shaders though you can do a lot more than a PS2.

  • BooBoo 3.0.12

    • Fix loading of multiple the same models
    • Turn multisampling off by default
    • Add set_front_face and constants
    • Document model_clone
    • draw_3d* now requires creation of a vertex buffer with (create_vertex_buffer)
    • Don’t set cull mode every frame
  • Faster 3D

    I’ve found draw_3d* to be quite slow so I added vertex buffers. You must use one to use draw_3d.

    I’ve found I can draw double the triangles of a PlayStation 2 (with more features) on this PC… PS2 can draw 16 million 75 px tris per second and I can double that with vertex buffers. That’s around 550,000 tris per frame.

  • 3D performance

    I can get 100 of these lit/individually animated models at 60 FPS.

    That’s with lighting.

    EDIT: the model has 494 triangles btw

    EDIT2: it’s double (200 models) without animation

    EDIT3: It also depends on pixel coverage, this scene with 375 models renders about 60 FPS:

  • BooBoo 3.0.11

    • Optimisations
    • Add speedtest example
  • This runs at 60 FPS

    If it weren’t for the recording it’d be 60 FPS at 5100 sprites. Using 256×256 images instead, I get 550 before 60 FPS drops. This is 1920×1080 with 1280×720 projection, so these 16×16 sprites are really drawn around 24×24 and the 256×256 sprites are drawn using 384×384 pixels.

    EDIT: this is a new example for the next version, press up/down to increase/decrease the number of sprites.

    EDIT2: I think the 16×16 sprites one is bound by the CPU running the language itself. I tried a faster GPU/slower CPU machine, and I get 1400 256×256 sprites but fewer than 5000 16×16. Here is the code:

    EDIT3: with current optimisations, I’ve got it at over 5500 sprites at 60 FPS

    const SCR_W 1280 SCR_H 720
    
    resize SCR_W SCR_H
    
    var img
    = img (image_load "bingo.png")
    
    var w h
    explode (image_size img) w h
    
    var font
    = font (font_load "font.ttf" 64 1)
    
    var imgs
    
    call spawn
    
    function spawn
    {
    	var v dx dy
    	= dx (rand 0 1)
    	= dy (rand 0 1)
    	if (== dx 0) neg_dx
    		= dx -1
    	:neg_dx
    	if (== dy 0) neg_dy
    		= dy -1
    	:neg_dy
    	vector_init v (rand (/ w 2) (- SCR_W (/ w 2))) (rand (/ h 2) (- SCR_H (/ h 2))) dx dy
    	vector_add imgs v
    }
    
    function draw
    {
    	var sz i
    	= sz (vector_size imgs)
    
    	image_start img
    
    	for i 0 (< i sz) 1 next
    		image_draw img 255 255 255 255 (- [imgs i 0] (/ w 2)) (- [imgs i 1] (/ h 2))
    	:next
    
    	image_end img
    
    	font_draw font 255 255 0 255 (string_format "%" sz) 5 5
    }
    
    function run
    {
    	var sz i
    	= sz (vector_size imgs)
    
    	for i 0 (< i sz) 1 next
    		= [imgs i 0] (+ [imgs i 0] [imgs i 2])
    		= [imgs i 1] (+ [imgs i 1] [imgs i 3])
    		if (< [imgs i 0] (/ w 2)) pos_x (< [imgs i 1] (/ h 2)) pos_y (> [imgs i 0] (- SCR_W (/ w 2))) neg_x (> [imgs i 1] (- SCR_H (/ h 2))) neg_y
    			= [imgs i 0] (/ w 2)
    			= [imgs i 2] (neg [imgs i 2])
    		:pos_x
    			= [imgs i 1] (/ h 2)
    			= [imgs i 3] (neg [imgs i 3])
    		:pos_y
    			= [imgs i 0] (- SCR_W (/ w 2))
    			= [imgs i 2] (neg [imgs i 2])
    		:neg_x
    			= [imgs i 1] (- SCR_H (/ h 2))
    			= [imgs i 3] (neg [imgs i 3])
    		:neg_y
    	:next
    }
    
    function event type a b c d
    {
    	if (== type EVENT_KEY_DOWN) key
    		if (== a KEY_UP) up (&& (== a KEY_DOWN) (> (vector_size imgs) 1)) down
    			call spawn
    		:up
    			vector_erase imgs (- (vector_size imgs) 1)
    		:down
    	:key
    }