examples: add examples/gg/random.v demonstrating how to stream images/pixels
parent
4bfe76123a
commit
b2391424d9
|
@ -0,0 +1,63 @@
|
|||
import gg
|
||||
import time
|
||||
|
||||
const pwidth = 800
|
||||
|
||||
const pheight = 600
|
||||
|
||||
const pbytes = 4
|
||||
|
||||
struct AppState {
|
||||
mut:
|
||||
gg &gg.Context = 0
|
||||
istream_idx int
|
||||
pixels [pwidth][pheight]u32
|
||||
}
|
||||
|
||||
[direct_array_access]
|
||||
fn (mut state AppState) update() {
|
||||
mut rcolor := u64(state.gg.frame)
|
||||
for {
|
||||
for x in 0 .. pwidth {
|
||||
for y in 0 .. pheight {
|
||||
rcolor = rcolor * 1664525 + 1013904223
|
||||
state.pixels[x][y] = u32(rcolor & 0x0000_0000_FFFF_FFFF) | 0x1010AFFF
|
||||
}
|
||||
}
|
||||
time.sleep(33 * time.millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut state AppState) draw() {
|
||||
mut istream_image := state.gg.get_cached_image_by_idx(state.istream_idx)
|
||||
istream_image.update_pixel_data(&state.pixels)
|
||||
size := gg.window_size()
|
||||
state.gg.draw_image(0, 0, size.width, size.height, istream_image)
|
||||
}
|
||||
|
||||
// gg callbacks:
|
||||
|
||||
fn graphics_init(mut state AppState) {
|
||||
state.istream_idx = state.gg.new_streaming_image(pwidth, pheight, pbytes)
|
||||
}
|
||||
|
||||
fn graphics_frame(mut state AppState) {
|
||||
state.gg.begin()
|
||||
state.draw()
|
||||
state.gg.end()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut state := &AppState{}
|
||||
state.gg = gg.new_context(
|
||||
width: 800
|
||||
height: 600
|
||||
create_window: true
|
||||
window_title: 'Random Static'
|
||||
init_fn: graphics_init
|
||||
frame_fn: graphics_frame
|
||||
user_data: state
|
||||
)
|
||||
go state.update()
|
||||
state.gg.run()
|
||||
}
|
|
@ -16,6 +16,10 @@ pub fn ptr_str(ptr voidptr) string {
|
|||
return buf1
|
||||
}
|
||||
|
||||
pub fn (x size_t) str() string {
|
||||
return u64(x).str()
|
||||
}
|
||||
|
||||
pub fn (cptr &char) str() string {
|
||||
return u64(cptr).hex()
|
||||
}
|
||||
|
|
|
@ -241,7 +241,9 @@ fn gg_init_sokol_window(user_data voidptr) {
|
|||
}
|
||||
|
||||
for i in 0 .. g.image_cache.len {
|
||||
g.image_cache[i].init_sokol_image()
|
||||
if g.image_cache[i].simg.id == 0 {
|
||||
g.image_cache[i].init_sokol_image()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ module gg
|
|||
|
||||
// import gx
|
||||
// import sokol.sapp
|
||||
// import sokol.gfx
|
||||
import sokol.gfx
|
||||
import os
|
||||
import sokol
|
||||
import sokol.sgl
|
||||
|
@ -153,6 +153,17 @@ pub fn (mut ctx Context) create_image_from_byte_array(b []byte) Image {
|
|||
return ctx.create_image_from_memory(b.data, b.len)
|
||||
}
|
||||
|
||||
pub fn (mut ctx Context) cache_image(img Image) int {
|
||||
ctx.image_cache << img
|
||||
image_idx := ctx.image_cache.len - 1
|
||||
ctx.image_cache[image_idx].id = image_idx
|
||||
return image_idx
|
||||
}
|
||||
|
||||
pub fn (mut ctx Context) get_cached_image_by_idx(image_idx int) &Image {
|
||||
return &ctx.image_cache[image_idx]
|
||||
}
|
||||
|
||||
pub fn (mut img Image) init_sokol_image() &Image {
|
||||
// println('\n init sokol image $img.path ok=$img.simg_ok')
|
||||
mut img_desc := C.sg_image_desc{
|
||||
|
@ -161,7 +172,7 @@ pub fn (mut img Image) init_sokol_image() &Image {
|
|||
num_mipmaps: 0
|
||||
wrap_u: .clamp_to_edge
|
||||
wrap_v: .clamp_to_edge
|
||||
label: &char(0)
|
||||
label: img.path.str
|
||||
d3d11_texture: 0
|
||||
}
|
||||
img_desc.data.subimage[0][0] = C.sg_range{
|
||||
|
@ -174,6 +185,53 @@ pub fn (mut img Image) init_sokol_image() &Image {
|
|||
return img
|
||||
}
|
||||
|
||||
// new_streaming_image returns a cached `image_idx` of a special image, that
|
||||
// can be updated *each frame* by calling: gg.update_pixel_data(image_idx, buf)
|
||||
// ... where buf is a pointer to the actual pixel data for the image.
|
||||
// NB: you still need to call app.gg.draw_image after that, to actually draw it.
|
||||
pub fn (mut ctx Context) new_streaming_image(w int, h int, channels int) int {
|
||||
mut img := Image{}
|
||||
img.width = w
|
||||
img.height = h
|
||||
img.nr_channels = channels // 4 bytes per pixel for .rgba8, see pixel_format
|
||||
mut img_desc := C.sg_image_desc{
|
||||
width: img.width
|
||||
height: img.height
|
||||
pixel_format: .rgba8
|
||||
num_slices: 1
|
||||
num_mipmaps: 1
|
||||
usage: .stream
|
||||
wrap_u: .clamp_to_edge
|
||||
wrap_v: .clamp_to_edge
|
||||
min_filter: .linear
|
||||
mag_filter: .linear
|
||||
label: img.path.str
|
||||
}
|
||||
// Sokol requires that streamed images have NO .ptr/.size initially:
|
||||
img_desc.data.subimage[0][0] = C.sg_range{
|
||||
ptr: 0
|
||||
size: size_t(0)
|
||||
}
|
||||
img.simg = C.sg_make_image(&img_desc)
|
||||
img.simg_ok = true
|
||||
img.ok = true
|
||||
img_idx := ctx.cache_image(img)
|
||||
return img_idx
|
||||
}
|
||||
|
||||
// update_pixel_data is a helper for working with image streams (i.e. images,
|
||||
// that are updated dynamically by the CPU on each frame)
|
||||
pub fn (mut ctx Context) update_pixel_data(cached_image_idx int, buf &byte) {
|
||||
ctx.get_cached_image_by_idx(cached_image_idx).update_pixel_data(buf)
|
||||
}
|
||||
|
||||
pub fn (mut img Image) update_pixel_data(buf &byte) {
|
||||
mut data := C.sg_image_data{}
|
||||
data.subimage[0][0].ptr = buf
|
||||
data.subimage[0][0].size = size_t(img.width * img.height * img.nr_channels)
|
||||
gfx.update_image(img.simg, &data)
|
||||
}
|
||||
|
||||
// draw_image_with_config takes in a config that details how the
|
||||
// provided image should be drawn onto the screen
|
||||
pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) {
|
||||
|
|
|
@ -396,10 +396,13 @@ pub fn (i C.sg_image) free() {
|
|||
C.sg_destroy_image(i)
|
||||
}
|
||||
|
||||
pub const sg_cubeface_num = 6
|
||||
|
||||
pub const sg_max_mipmaps = 16
|
||||
|
||||
pub struct C.sg_image_data {
|
||||
pub mut:
|
||||
// subimage [C.SG_CUBEFACE_NUM][C.SG_MAX_MIPMAPS]C.sg_range
|
||||
subimage [6][16]C.sg_range
|
||||
subimage [sg_cubeface_num][sg_max_mipmaps]C.sg_range
|
||||
}
|
||||
|
||||
pub struct C.sg_features {
|
||||
|
|
Loading…
Reference in New Issue