mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
examples: add examples/gg/many_thousands_of_circles.v, thanks to @xjunko, document how to use ctx.end(how:.passthru)
. (#18832)
This commit is contained in:
parent
f8e89ae91c
commit
e7af25ec14
56
examples/gg/many_thousands_of_circles.v
Normal file
56
examples/gg/many_thousands_of_circles.v
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import gg
|
||||||
|
import gx
|
||||||
|
import rand
|
||||||
|
|
||||||
|
const max_circles_per_pass = 1000
|
||||||
|
|
||||||
|
// prepare some random colors ahead of time
|
||||||
|
const colors = []gx.Color{len: max_circles_per_pass, init: gx.Color{
|
||||||
|
r: u8(index * 0 + rand.u8())
|
||||||
|
g: u8(index * 0 + rand.u8())
|
||||||
|
b: u8(index * 0 + rand.u8())
|
||||||
|
}}
|
||||||
|
|
||||||
|
fn frame(mut ctx gg.Context) {
|
||||||
|
// First pass, just clears the background:
|
||||||
|
ctx.begin()
|
||||||
|
ctx.end()
|
||||||
|
|
||||||
|
// We want to draw thousands of circles, but sokol has a limit for how
|
||||||
|
// many primitives can be in a single pass, and if you reach that limit
|
||||||
|
// you will not see *anything at all* for that pass.
|
||||||
|
// For the circles below, that limit is ~2520 circles per pass.
|
||||||
|
// To overcome this, we will use several passes instead, where each one
|
||||||
|
// will draw just 1000 circles.
|
||||||
|
// In other words, in total we will have 4 * 1000 = 4000 circles, drawn with
|
||||||
|
// 4 passes.
|
||||||
|
for i := 0; i < 4 * max_circles_per_pass; i += max_circles_per_pass {
|
||||||
|
ctx.begin()
|
||||||
|
for c in 0 .. max_circles_per_pass {
|
||||||
|
rx := rand.int_in_range(0, ctx.window.width) or { 0 }
|
||||||
|
ry := rand.int_in_range(0, ctx.window.height) or { 0 }
|
||||||
|
ctx.draw_circle_filled(rx, ry, 10, colors[c])
|
||||||
|
}
|
||||||
|
ctx.end(how: .passthru)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The last pass, is for the fps overlay, that should be *always on top of everything*.
|
||||||
|
// Drawing it in a separate pass, guarantees, that it *will* be drawn, even if the drawing
|
||||||
|
// of all the other passes fail. Try increasing max_circles_per_pass to 3000 for example.
|
||||||
|
ctx.begin()
|
||||||
|
ctx.show_fps()
|
||||||
|
ctx.end(how: .passthru)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut ctx := gg.new_context(
|
||||||
|
window_title: 'Many Thousands of Circles'
|
||||||
|
bg_color: gx.black
|
||||||
|
width: 600
|
||||||
|
height: 400
|
||||||
|
frame_fn: frame
|
||||||
|
)
|
||||||
|
ctx.run()
|
||||||
|
}
|
@ -530,8 +530,56 @@ pub fn (ctx &Context) begin() {
|
|||||||
sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)
|
sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// end finishes drawing for the context.
|
pub enum EndEnum {
|
||||||
pub fn (ctx &Context) end() {
|
clear
|
||||||
|
passthru
|
||||||
|
}
|
||||||
|
|
||||||
|
[params]
|
||||||
|
pub struct EndOptions {
|
||||||
|
how EndEnum
|
||||||
|
}
|
||||||
|
|
||||||
|
const dontcare_pass = gfx.PassAction{
|
||||||
|
colors: [
|
||||||
|
gfx.ColorAttachmentAction{
|
||||||
|
action: .dontcare
|
||||||
|
value: gfx.Color{1.0, 1.0, 1.0, 1.0}
|
||||||
|
},
|
||||||
|
gfx.ColorAttachmentAction{
|
||||||
|
action: .dontcare
|
||||||
|
value: gfx.Color{1.0, 1.0, 1.0, 1.0}
|
||||||
|
},
|
||||||
|
gfx.ColorAttachmentAction{
|
||||||
|
action: .dontcare
|
||||||
|
value: gfx.Color{1.0, 1.0, 1.0, 1.0}
|
||||||
|
},
|
||||||
|
gfx.ColorAttachmentAction{
|
||||||
|
action: .dontcare
|
||||||
|
value: gfx.Color{1.0, 1.0, 1.0, 1.0}
|
||||||
|
},
|
||||||
|
]!
|
||||||
|
}
|
||||||
|
|
||||||
|
// end finishes all the drawing for the context ctx.
|
||||||
|
// All accumulated draw calls before ctx.end(), will be done in a separate Sokol pass.
|
||||||
|
//
|
||||||
|
// Note: each Sokol pass, has a limit on the number of draw calls, that can be done in it.
|
||||||
|
// Once that limit is reached, the whole pass will not draw anything, which can be frustrating.
|
||||||
|
//
|
||||||
|
// To overcome this limitation, you may use *several passes*, when you want to make thousands
|
||||||
|
// of draw calls (for example, if you need to draw thousands of circles/rectangles/sprites etc),
|
||||||
|
// where each pass will render just a limited amount of primitives.
|
||||||
|
//
|
||||||
|
// In the context of the gg module (without dropping to using sgl and gfx directly), it means,
|
||||||
|
// that you will need a new pair of ctx.begin() and ctx.end() calls, surrounding all the draw
|
||||||
|
// calls, that should be done in each pass.
|
||||||
|
//
|
||||||
|
// The default ctx.end() is equivalent to ctx.end(how:.clear). It will erase the existing
|
||||||
|
// rendered content with the background color, before drawing anything else.
|
||||||
|
// You can call ctx.end(how:.passthru) for a pass, that *will not* erase the previously
|
||||||
|
// rendered content in the context.
|
||||||
|
pub fn (ctx &Context) end(options EndOptions) {
|
||||||
$if show_fps ? {
|
$if show_fps ? {
|
||||||
ctx.show_fps()
|
ctx.show_fps()
|
||||||
} $else {
|
} $else {
|
||||||
@ -539,7 +587,14 @@ pub fn (ctx &Context) end() {
|
|||||||
ctx.show_fps()
|
ctx.show_fps()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gfx.begin_default_pass(ctx.clear_pass, sapp.width(), sapp.height())
|
match options.how {
|
||||||
|
.clear {
|
||||||
|
gfx.begin_default_pass(ctx.clear_pass, sapp.width(), sapp.height())
|
||||||
|
}
|
||||||
|
.passthru {
|
||||||
|
gfx.begin_default_pass(gg.dontcare_pass, sapp.width(), sapp.height())
|
||||||
|
}
|
||||||
|
}
|
||||||
sgl.draw()
|
sgl.draw()
|
||||||
gfx.end_pass()
|
gfx.end_pass()
|
||||||
gfx.commit()
|
gfx.commit()
|
||||||
|
Loading…
Reference in New Issue
Block a user