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
|
return buf1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (x size_t) str() string {
|
||||||
|
return u64(x).str()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (cptr &char) str() string {
|
pub fn (cptr &char) str() string {
|
||||||
return u64(cptr).hex()
|
return u64(cptr).hex()
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,9 +241,11 @@ fn gg_init_sokol_window(user_data voidptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0 .. g.image_cache.len {
|
for i in 0 .. g.image_cache.len {
|
||||||
|
if g.image_cache[i].simg.id == 0 {
|
||||||
g.image_cache[i].init_sokol_image()
|
g.image_cache[i].init_sokol_image()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn gg_frame_fn(user_data voidptr) {
|
fn gg_frame_fn(user_data voidptr) {
|
||||||
mut ctx := unsafe { &Context(user_data) }
|
mut ctx := unsafe { &Context(user_data) }
|
||||||
|
|
|
@ -4,7 +4,7 @@ module gg
|
||||||
|
|
||||||
// import gx
|
// import gx
|
||||||
// import sokol.sapp
|
// import sokol.sapp
|
||||||
// import sokol.gfx
|
import sokol.gfx
|
||||||
import os
|
import os
|
||||||
import sokol
|
import sokol
|
||||||
import sokol.sgl
|
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)
|
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 {
|
pub fn (mut img Image) init_sokol_image() &Image {
|
||||||
// println('\n init sokol image $img.path ok=$img.simg_ok')
|
// println('\n init sokol image $img.path ok=$img.simg_ok')
|
||||||
mut img_desc := C.sg_image_desc{
|
mut img_desc := C.sg_image_desc{
|
||||||
|
@ -161,7 +172,7 @@ pub fn (mut img Image) init_sokol_image() &Image {
|
||||||
num_mipmaps: 0
|
num_mipmaps: 0
|
||||||
wrap_u: .clamp_to_edge
|
wrap_u: .clamp_to_edge
|
||||||
wrap_v: .clamp_to_edge
|
wrap_v: .clamp_to_edge
|
||||||
label: &char(0)
|
label: img.path.str
|
||||||
d3d11_texture: 0
|
d3d11_texture: 0
|
||||||
}
|
}
|
||||||
img_desc.data.subimage[0][0] = C.sg_range{
|
img_desc.data.subimage[0][0] = C.sg_range{
|
||||||
|
@ -174,6 +185,53 @@ pub fn (mut img Image) init_sokol_image() &Image {
|
||||||
return img
|
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
|
// draw_image_with_config takes in a config that details how the
|
||||||
// provided image should be drawn onto the screen
|
// provided image should be drawn onto the screen
|
||||||
pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) {
|
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)
|
C.sg_destroy_image(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const sg_cubeface_num = 6
|
||||||
|
|
||||||
|
pub const sg_max_mipmaps = 16
|
||||||
|
|
||||||
pub struct C.sg_image_data {
|
pub struct C.sg_image_data {
|
||||||
pub mut:
|
pub mut:
|
||||||
// subimage [C.SG_CUBEFACE_NUM][C.SG_MAX_MIPMAPS]C.sg_range
|
subimage [sg_cubeface_num][sg_max_mipmaps]C.sg_range
|
||||||
subimage [6][16]C.sg_range
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct C.sg_features {
|
pub struct C.sg_features {
|
||||||
|
|
Loading…
Reference in New Issue