| 1 | module main |
| 2 | |
| 3 | import gg |
| 4 | import sokol.sgl |
| 5 | |
| 6 | struct App { |
| 7 | mut: |
| 8 | gg &gg.Context = unsafe { nil } |
| 9 | } |
| 10 | |
| 11 | const cmax_x = 115 |
| 12 | const cmax_y = 81 |
| 13 | const cs = 10 |
| 14 | |
| 15 | const c_fg = gg.rgb(20, 30, 255) |
| 16 | |
| 17 | fn main() { |
| 18 | mut app := &App{} |
| 19 | app.gg = gg.new_context( |
| 20 | bg_color: gg.white |
| 21 | width: cmax_x * cs |
| 22 | height: cmax_y * cs |
| 23 | create_window: true |
| 24 | window_title: 'Grid with many rectangles (drawn with no context)' |
| 25 | frame_fn: frame |
| 26 | user_data: app |
| 27 | ) |
| 28 | app.gg.run() |
| 29 | } |
| 30 | |
| 31 | fn frame(app &App) { |
| 32 | app.gg.begin() |
| 33 | // Note: this uses 2 separate loops, with each doing its own drawing for performance reasons. |
| 34 | // The underlying Sokol library can eliminate sgl begin/end calls, when multiple primitives of the |
| 35 | // same kind are drawn one after the other, without context changes. |
| 36 | // However, filled rectangles are drawn with quads, while empty rectangles are drawn with lines. |
| 37 | // In this case, if the draw calls are put in the same loop, using app.gg.draw_rect_filled/5 and app.gg.draw_rect_empty/5, |
| 38 | // sokol can not batch the begin/end calls, and their overhead becomes much bigger. |
| 39 | // |
| 40 | // That is why: |
| 41 | // a) we use several loops here. |
| 42 | // b) we use a single sgl.begin_quads() before the first loop, and a single sgl.end() after it. |
| 43 | // c) we use draw_rect_filled_no_context/5 inside the loop, instead of draw_rect_filled/5 . |
| 44 | // e) we use a single sgl.begin_lines() before the second loop, and a single sgl.end() after it. |
| 45 | // f) we use draw_rect_empty_no_context/5 inside the second loop, instead of draw_rect_empty/5 . |
| 46 | // Note: the separation of the loops/kinds of draws, is several times more important for eliminating |
| 47 | // the performance overhead (12-15% CPU usage), compared to the use of draw_rect_filled_no_context |
| 48 | // vs draw_rect_filled (1-2% CPU usage), because of Sokol's optimisation. |
| 49 | |
| 50 | $if !do_not_draw_rect_filled ? { |
| 51 | sgl.begin_quads() |
| 52 | for y in 0 .. cmax_y { |
| 53 | for x in 0 .. cmax_x { |
| 54 | cy, cx := y * cs, x * cs |
| 55 | app.gg.draw_rect_filled_no_context(cx, cy, cs - 2, cs - 2, c_fg) |
| 56 | } |
| 57 | } |
| 58 | sgl.end() |
| 59 | } |
| 60 | |
| 61 | $if draw_rect_empty ? { |
| 62 | sgl.begin_lines() |
| 63 | for y in 0 .. cmax_y { |
| 64 | for x in 0 .. cmax_x { |
| 65 | cy, cx := y * cs, x * cs |
| 66 | app.gg.draw_rect_empty_no_context(cx + 2, cy + 2, cs - 3, cs - 3, |
| 67 | gg.rgb(255, 50, 0)) |
| 68 | } |
| 69 | } |
| 70 | sgl.end() |
| 71 | } |
| 72 | |
| 73 | app.gg.end() |
| 74 | } |
| 75 | |