Skip to content

Commit de4045d

Browse files
committed
examples: add random_stars.v, to illustrate that the streaming image can be moved/scaled just like any other static image
1 parent f724c56 commit de4045d

3 files changed

Lines changed: 122 additions & 0 deletions

File tree

‎examples/gg/random_stars.v‎

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import gg
2+
import math
3+
import time
4+
import rand
5+
6+
const pwidth = 800
7+
8+
const pheight = 600
9+
10+
struct AppState {
11+
mut:
12+
gg &gg.Context = unsafe { nil }
13+
istream_idx int
14+
pixels [pheight][pwidth]gg.Color
15+
}
16+
17+
@[direct_array_access]
18+
fn (mut state AppState) update() {
19+
for {
20+
unsafe { vmemset(&state.pixels, 0, pwidth * pheight * sizeof[gg.Color]()) }
21+
state.draw_sky() or {}
22+
time.sleep(30_000 * time.millisecond)
23+
}
24+
}
25+
26+
fn (mut state AppState) draw_sky() ! {
27+
for _ in 0 .. 2000 {
28+
mut star_size := 1
29+
for rand.i32_in_range(0, 100)! < 5 {
30+
star_size += 10
31+
}
32+
for rand.i32_in_range(0, 100000)! < 5 {
33+
star_size += 85
34+
}
35+
sx := if star_size < 10 {
36+
rand.i32_in_range(-40, pwidth + 40)!
37+
} else {
38+
rand.i32_in_range(40, pwidth - 40)!
39+
}
40+
sy := if star_size < 10 {
41+
rand.i32_in_range(-40, pheight + 40)!
42+
} else {
43+
rand.i32_in_range(40, pheight - 40)!
44+
}
45+
state.draw_star(sx, sy, gg.Color{
46+
r: u8(rand.i32_in_range(50, 255)!)
47+
g: u8(rand.i32_in_range(50, 255)!)
48+
b: u8(rand.i32_in_range(50, 255)!)
49+
}, star_size)
50+
}
51+
}
52+
53+
@[direct_array_access]
54+
fn (mut state AppState) draw_star(x int, y int, c gg.Color, radius int) {
55+
if radius == 0 {
56+
return
57+
}
58+
minx := math.max(0, x - radius)
59+
miny := math.max(0, y - radius)
60+
maxx := math.min(pwidth, x + radius)
61+
maxy := math.min(pheight, y + radius)
62+
for cx in minx .. maxx {
63+
for cy in miny .. maxy {
64+
dx := math.abs[f32](cx - x) / f32(radius)
65+
dy := math.abs[f32](cy - y) / f32(radius)
66+
gradient := math.max[f32](0, math.min[f32](1, 1 - (math.sqrtf(dx) + math.sqrtf(dy))))
67+
if gradient < 0.01 {
68+
continue
69+
}
70+
mut pixel := unsafe { &state.pixels[cy][cx] }
71+
color := gg.Color{
72+
r: u8(math.min(255, int(pixel.r) + int(f32(c.r) * gradient)))
73+
g: u8(math.min(255, int(pixel.g) + int(f32(c.g) * gradient)))
74+
b: u8(math.min(255, int(pixel.b) + int(f32(c.b) * gradient)))
75+
a: 255
76+
}
77+
unsafe {
78+
*pixel = color
79+
}
80+
}
81+
}
82+
}
83+
84+
fn (mut state AppState) draw() {
85+
mut istream_image := state.gg.get_cached_image_by_idx(state.istream_idx)
86+
istream_image.update_pixel_data(unsafe { &u8(&state.pixels) })
87+
size := gg.window_size()
88+
sx := -50 + 50 * math.sinf(f32(state.gg.frame) / 100)
89+
sy := -50 + 50 * math.cosf(f32(state.gg.frame) / 100)
90+
scale := 200 + 50 * math.sinf(f32(state.gg.frame) / 300)
91+
wx := size.width + scale
92+
wy := size.height + scale
93+
state.gg.draw_image(sx, sy, wx, wy, istream_image)
94+
}
95+
96+
fn graphics_init(mut state AppState) {
97+
state.istream_idx = state.gg.new_streaming_image(pwidth, pheight, 4, pixel_format: .rgba8)
98+
}
99+
100+
fn graphics_frame(mut state AppState) {
101+
state.gg.begin()
102+
state.draw()
103+
state.gg.end()
104+
}
105+
106+
fn main() {
107+
mut state := &AppState{}
108+
state.gg = gg.new_context(
109+
width: pwidth
110+
height: pheight
111+
window_title: 'Random stars'
112+
init_fn: graphics_init
113+
frame_fn: graphics_frame
114+
user_data: state
115+
)
116+
spawn state.update()
117+
state.gg.run()
118+
}

‎vlib/gg/README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ Another approach to that problem, is to draw everything yourself in a streaming
5656
texture, then upload that streaming texture as a single draw command to the GPU.
5757
You can see an example of that done in:
5858
https://github.com/vlang/v/blob/master/examples/gg/random.v
59+
and in:
60+
https://github.com/vlang/v/blob/master/examples/gg/random_stars.v
5961

6062
A third approach, is to only upload your changing inputs to the GPU, and do all
6163
the calculations and drawing there in shaders.

‎vlib/sokol/README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ Another approach to that problem, is to draw everything yourself in a streaming
7676
texture, then upload that streaming texture as a single draw command to the GPU.
7777
You can see an example of that done in:
7878
https://github.com/vlang/v/blob/master/examples/gg/random.v
79+
and in:
80+
https://github.com/vlang/v/blob/master/examples/gg/random_stars.v
7981

8082
A third approach, is to only upload your changing inputs to the GPU, and do all
8183
the calculations and drawing there in shaders.

0 commit comments

Comments
 (0)