examples: cleanup code duplication in examples/sokol/04_multi_shader_glsl/rt_glsl.v, document gg.m4 (#20978)

This commit is contained in:
Delyan Angelov 2024-03-08 11:39:23 +02:00 committed by GitHub
parent 8ddceabb0e
commit 4cf05083ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 173 additions and 459 deletions

View file

@ -1,22 +1,15 @@
/********************************************************************** /**********************************************************************
*
* Sokol 3d cube multishader demo * Sokol 3d cube multishader demo
* * Copyright (c) 2024 Dario Deledda. All rights reserved.
* Copyright (c) 2021 Dario Deledda. All rights reserved.
* Use of this source code is governed by an MIT license * Use of this source code is governed by an MIT license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
* *
* HOW TO COMPILE SHADERS: * HOW TO COMPILE SHADERS:
* Run `v shader .` in this directory to compile the shaders. * Run `v shader .` in this directory to compile the shaders.
* For more info and help with shader compilation see `docs.md` and `v help shader`. * For more info and help with shader compilation see `docs.md` and `v help shader`.
*
* TODO:
* - frame counter
**********************************************************************/ **********************************************************************/
import gg import gg
import gg.m4 import gg.m4
import gx
// import math
import sokol.sapp import sokol.sapp
import sokol.gfx import sokol.gfx
import sokol.sgl import sokol.sgl
@ -29,27 +22,23 @@ import time
fn C.rt_march_shader_desc(gfx.Backend) &gfx.ShaderDesc fn C.rt_march_shader_desc(gfx.Backend) &gfx.ShaderDesc
fn C.rt_puppy_shader_desc(gfx.Backend) &gfx.ShaderDesc fn C.rt_puppy_shader_desc(gfx.Backend) &gfx.ShaderDesc
const win_width = 800 const start_ticks = time.ticks()
const win_height = 800
const bg_color = gx.white
@[heap]
struct App { struct App {
mut: mut:
gg &gg.Context = unsafe { nil } gg &gg.Context = unsafe { nil }
texture gfx.Image texture gfx.Image
sampler gfx.Sampler sampler gfx.Sampler
init_flag bool init_flag bool
frame_count int mouse_x int = 502
mouse_x int = -1 mouse_y int = 394
mouse_y int = -1
mouse_down bool mouse_down bool
// glsl // glsl
cube_pip_glsl gfx.Pipeline cube_pip_glsl gfx.Pipeline
cube_bind gfx.Bindings cube_bind gfx.Bindings
pipe map[string]gfx.Pipeline pipe map[string]gfx.Pipeline
bind map[string]gfx.Bindings bind map[string]gfx.Bindings
// time
ticks i64
} }
/****************************************************************************** /******************************************************************************
@ -60,45 +49,22 @@ fn create_texture(w int, h int, buf byteptr) (gfx.Image, gfx.Sampler) {
mut img_desc := gfx.ImageDesc{ mut img_desc := gfx.ImageDesc{
width: w width: w
height: h height: h
num_mipmaps: 0
// min_filter: .linear
// mag_filter: .linear
// usage: .dynamic
// wrap_u: .clamp_to_edge
// wrap_v: .clamp_to_edge
label: &u8(0)
d3d11_texture: 0
} }
// comment if .dynamic is enabled
img_desc.data.subimage[0][0] = gfx.Range{ img_desc.data.subimage[0][0] = gfx.Range{
ptr: buf ptr: buf
size: usize(sz) size: usize(sz)
} }
sg_img := gfx.make_image(&img_desc) sg_img := gfx.make_image(&img_desc)
mut smp_desc := gfx.SamplerDesc{ mut smp_desc := gfx.SamplerDesc{
min_filter: .linear min_filter: .linear
mag_filter: .linear mag_filter: .linear
wrap_u: .clamp_to_edge wrap_u: .clamp_to_edge
wrap_v: .clamp_to_edge wrap_v: .clamp_to_edge
} }
sg_smp := gfx.make_sampler(&smp_desc) sg_smp := gfx.make_sampler(&smp_desc)
return sg_img, sg_smp return sg_img, sg_smp
} }
// Use only if usage: .dynamic is enabled
fn update_text_texture(sg_img gfx.Image, w int, h int, buf byteptr) {
sz := w * h * 4
mut tmp_sbc := gfx.ImageData{}
tmp_sbc.subimage[0][0] = gfx.Range{
ptr: buf
size: usize(sz)
}
gfx.update_image(sg_img, &tmp_sbc)
}
/****************************************************************************** /******************************************************************************
* Draw functions * Draw functions
****************************************************************************** ******************************************************************************
@ -109,281 +75,108 @@ Cube vertex buffer with packed vertex formats for color and texture coords.
to floating point formats in the vertex shader inputs. to floating point formats in the vertex shader inputs.
The reason is that D3D11 cannot convert from non-normalized The reason is that D3D11 cannot convert from non-normalized
formats to floating point inputs (only to integer inputs), formats to floating point inputs (only to integer inputs),
and WebGL2 / GLES2 don't support integer vertex shader inputs. and WebGL2 / GLES2 does not support integer vertex shader inputs.
*/ */
struct Vertex_t { struct Vertex_t {
x f32 x f32
y f32 y f32
z f32 z f32
color u32 color u32
// u u16 // for compatibility with D3D11
// v u16 // for compatibility with D3D11
u f32 u f32
v f32 v f32
} }
// march shader init const vertices = cube_vertices()
fn init_cube_glsl_m(mut app App) {
// cube vertex buffer
// d := u16(32767) // for compatibility with D3D11, 32767 stand for 1
d := f32(1.0)
c := u32(0xFFFFFF_FF) // color RGBA8
// vfmt off
vertices := [
// Face 0
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{ 1.0, -1.0, -1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, -1.0, c, d, d},
Vertex_t{-1.0, 1.0, -1.0, c, 0, d},
// Face 1
Vertex_t{-1.0, -1.0, 1.0, c, 0, 0},
Vertex_t{ 1.0, -1.0, 1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
Vertex_t{-1.0, 1.0, 1.0, c, 0, d},
// Face 2
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{-1.0, 1.0, -1.0, c, d, 0},
Vertex_t{-1.0, 1.0, 1.0, c, d, d},
Vertex_t{-1.0, -1.0, 1.0, c, 0, d},
// Face 3
Vertex_t{ 1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{ 1.0, 1.0, -1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
Vertex_t{ 1.0, -1.0, 1.0, c, 0, d},
// Face 4
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{-1.0, -1.0, 1.0, c, d, 0},
Vertex_t{ 1.0, -1.0, 1.0, c, d, d},
Vertex_t{ 1.0, -1.0, -1.0, c, 0, d},
// Face 5
Vertex_t{-1.0, 1.0, -1.0, c, 0, 0},
Vertex_t{-1.0, 1.0, 1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
Vertex_t{ 1.0, 1.0, -1.0, c, 0, d},
]
// vfmt on
mut vert_buffer_desc := gfx.BufferDesc{ fn cube_vertices() []Vertex_t {
label: c'cube-vertices' // cube vertex buffer
} d := f32(1.0)
unsafe { vmemset(&vert_buffer_desc, 0, int(sizeof(vert_buffer_desc))) } c := u32(0xFF_FF_FF_FF) // white color RGBA8
vert_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t))) // vfmt off
// 6 faces, each defined by 4 vertices:
cube := [
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{ 1.0, -1.0, -1.0, c, d, 0}, Vertex_t{ 1.0, 1.0, -1.0, c, d, d}, Vertex_t{-1.0, 1.0, -1.0, c, 0, d},
Vertex_t{-1.0, -1.0, 1.0, c, 0, 0}, Vertex_t{ 1.0, -1.0, 1.0, c, d, 0}, Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, Vertex_t{-1.0, 1.0, 1.0, c, 0, d},
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{-1.0, 1.0, -1.0, c, d, 0}, Vertex_t{-1.0, 1.0, 1.0, c, d, d}, Vertex_t{-1.0, -1.0, 1.0, c, 0, d},
Vertex_t{ 1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{ 1.0, 1.0, -1.0, c, d, 0}, Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, Vertex_t{ 1.0, -1.0, 1.0, c, 0, d},
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{-1.0, -1.0, 1.0, c, d, 0}, Vertex_t{ 1.0, -1.0, 1.0, c, d, d}, Vertex_t{ 1.0, -1.0, -1.0, c, 0, d},
Vertex_t{-1.0, 1.0, -1.0, c, 0, 0}, Vertex_t{-1.0, 1.0, 1.0, c, d, 0}, Vertex_t{ 1.0, 1.0, 1.0, c, d, d}, Vertex_t{ 1.0, 1.0, -1.0, c, 0, d},
]
// vfmt off
return cube
}
fn (mut app App) init_glsl_shader(shader_name string, shader_desc &gfx.ShaderDesc, indices []u16) {
mut vert_buffer_desc := gfx.BufferDesc{}
unsafe { vmemset(&vert_buffer_desc, 0, sizeof(vert_buffer_desc)) }
vert_buffer_desc.label = c'cube-vertices'
vert_buffer_desc.size = usize(vertices.len) * sizeof(Vertex_t)
vert_buffer_desc.data = gfx.Range{ vert_buffer_desc.data = gfx.Range{
ptr: vertices.data ptr: vertices.data
size: usize(vertices.len * int(sizeof(Vertex_t))) size: vert_buffer_desc.size
} }
vert_buffer_desc.@type = .vertexbuffer vert_buffer_desc.@type = .vertexbuffer
vbuf := gfx.make_buffer(&vert_buffer_desc) vbuf := gfx.make_buffer(&vert_buffer_desc)
// create an index buffer for the cube mut index_buffer_desc := gfx.BufferDesc{}
// vfmt off unsafe { vmemset(&index_buffer_desc, 0, sizeof(index_buffer_desc)) }
indices := [ index_buffer_desc.label = c'cube-indices'
u16(0), 1, 2, 0, 2, 3, index_buffer_desc.size = usize(indices.len) * sizeof(u16)
6 , 5, 4, 7, 6, 4,
8 , 9, 10, 8, 10, 11,
/*
u16(14), 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20,
*/
]
// vfmt on
mut index_buffer_desc := gfx.BufferDesc{
label: c'cube-indices'
}
unsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }
index_buffer_desc.size = usize(indices.len * int(sizeof(u16)))
index_buffer_desc.data = gfx.Range{ index_buffer_desc.data = gfx.Range{
ptr: indices.data ptr: indices.data
size: usize(indices.len * int(sizeof(u16))) size: index_buffer_desc.size
} }
index_buffer_desc.@type = .indexbuffer index_buffer_desc.@type = .indexbuffer
ibuf := gfx.make_buffer(&index_buffer_desc) ibuf := gfx.make_buffer(&index_buffer_desc)
// create shader // create shader
shader := gfx.make_shader(C.rt_march_shader_desc(C.sg_query_backend())) shader := gfx.make_shader(shader_desc)
mut pipdesc := gfx.PipelineDesc{} mut pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) } unsafe { vmemset(&pipdesc, 0, sizeof(pipdesc)) }
pipdesc.label = c'glsl_shader pipeline'
pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t)) pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t))
// vfmt off
// the constants [C.ATTR_vs_m_pos, C.ATTR_vs_m_color0, C.ATTR_vs_m_texcoord0] are generated by sokol-shdc // the constants [C.ATTR_vs_m_pos, C.ATTR_vs_m_color0, C.ATTR_vs_m_texcoord0] are generated by sokol-shdc
pipdesc.layout.attrs[C.ATTR_vs_m_pos ].format = .float3 // x,y,z as f32 pipdesc.layout.attrs[C.ATTR_vs_m_pos].format = .float3 // x,y,z as f32
pipdesc.layout.attrs[C.ATTR_vs_m_color0 ].format = .ubyte4n // color as u32 pipdesc.layout.attrs[C.ATTR_vs_m_color0].format = .ubyte4n // color as u32
pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .float2 // u,v as f32 pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .float2 // u,v as f32
// pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .short2n // u,v as u16 // pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .short2n // u,v as u16
// vfmt on
pipdesc.shader = shader pipdesc.shader = shader
pipdesc.index_type = .uint16 pipdesc.index_type = .uint16
pipdesc.depth = gfx.DepthState{
write_enabled: true
compare: .less_equal
}
pipdesc.cull_mode = .back
pipdesc.label = 'glsl_shader pipeline'.str
mut bind := gfx.Bindings{}
unsafe { vmemset(&bind, 0, int(sizeof(bind))) }
bind.vertex_buffers[0] = vbuf
bind.index_buffer = ibuf
bind.fs.images[C.SLOT_tex] = app.texture
bind.fs.samplers[C.SLOT_smp] = app.sampler
app.bind['march'] = bind
app.pipe['march'] = gfx.make_pipeline(&pipdesc)
println('GLSL March init DONE!')
}
// putty shader init
fn init_cube_glsl_p(mut app App) {
// cube vertex buffer
// d := u16(32767) // for compatibility with D3D11, 32767 stand for 1
d := f32(1.0)
c := u32(0xFFFFFF_FF) // color RGBA8
// vfmt off
vertices := [
// Face 0
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{ 1.0, -1.0, -1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, -1.0, c, d, d},
Vertex_t{-1.0, 1.0, -1.0, c, 0, d},
// Face 1
Vertex_t{-1.0, -1.0, 1.0, c, 0, 0},
Vertex_t{ 1.0, -1.0, 1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
Vertex_t{-1.0, 1.0, 1.0, c, 0, d},
// Face 2
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{-1.0, 1.0, -1.0, c, d, 0},
Vertex_t{-1.0, 1.0, 1.0, c, d, d},
Vertex_t{-1.0, -1.0, 1.0, c, 0, d},
// Face 3
Vertex_t{ 1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{ 1.0, 1.0, -1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
Vertex_t{ 1.0, -1.0, 1.0, c, 0, d},
// Face 4
Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
Vertex_t{-1.0, -1.0, 1.0, c, d, 0},
Vertex_t{ 1.0, -1.0, 1.0, c, d, d},
Vertex_t{ 1.0, -1.0, -1.0, c, 0, d},
// Face 5
Vertex_t{-1.0, 1.0, -1.0, c, 0, 0},
Vertex_t{-1.0, 1.0, 1.0, c, d, 0},
Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
Vertex_t{ 1.0, 1.0, -1.0, c, 0, d},
]
// vfmt off
mut vert_buffer_desc := gfx.BufferDesc{label: c'cube-vertices'}
unsafe { vmemset(&vert_buffer_desc, 0, int(sizeof(vert_buffer_desc))) }
vert_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t)))
vert_buffer_desc.data = gfx.Range{
ptr: vertices.data
size: usize(vertices.len * int(sizeof(Vertex_t)))
}
vert_buffer_desc.@type = .vertexbuffer
vbuf := gfx.make_buffer(&vert_buffer_desc)
// create an index buffer for the cube
// vfmt off
indices := [
/*
u16(0), 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
*/
u16(14), 13, 12, 15, 14, 12,
16 , 17, 18, 16, 18, 19,
22 , 21, 20, 23, 22, 20,
]
// vfmt on
mut index_buffer_desc := gfx.BufferDesc{
label: c'cube-indices'
}
unsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }
index_buffer_desc.size = usize(indices.len * int(sizeof(u16)))
index_buffer_desc.data = gfx.Range{
ptr: indices.data
size: usize(indices.len * int(sizeof(u16)))
}
index_buffer_desc.@type = .indexbuffer
ibuf := gfx.make_buffer(&index_buffer_desc)
// create shader
shader := gfx.make_shader(C.rt_puppy_shader_desc(C.sg_query_backend()))
mut pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t))
// vfmt off
// the constants [C.ATTR_vs_p_pos, C.ATTR_vs_p_color0, C.ATTR_vs_p_texcoord0] are generated by sokol-shdc
pipdesc.layout.attrs[C.ATTR_vs_p_pos ].format = .float3 // x,y,z as f32
pipdesc.layout.attrs[C.ATTR_vs_p_color0 ].format = .ubyte4n // color as u32
pipdesc.layout.attrs[C.ATTR_vs_p_texcoord0].format = .float2 // u,v as f32
// pipdesc.layout.attrs[C.ATTR_vs_p_texcoord0].format = .short2n // u,v as u16
// vfmt on
pipdesc.shader = shader
pipdesc.index_type = .uint16
pipdesc.depth = gfx.DepthState{ pipdesc.depth = gfx.DepthState{
write_enabled: true write_enabled: true
compare: .less_equal compare: .less_equal
} }
pipdesc.cull_mode = .back pipdesc.cull_mode = .back
pipdesc.label = 'glsl_shader pipeline'.str
mut bind := gfx.Bindings{} mut bind := gfx.Bindings{}
unsafe { vmemset(&bind, 0, int(sizeof(bind))) } unsafe { vmemset(&bind, 0, sizeof(bind)) }
bind.vertex_buffers[0] = vbuf bind.vertex_buffers[0] = vbuf
bind.index_buffer = ibuf bind.index_buffer = ibuf
bind.fs.images[C.SLOT_tex] = app.texture bind.fs.images[C.SLOT_tex] = app.texture
bind.fs.samplers[C.SLOT_smp] = app.sampler bind.fs.samplers[C.SLOT_smp] = app.sampler
app.bind['puppy'] = bind app.bind[shader_name] = bind
app.pipe[shader_name] = gfx.make_pipeline(&pipdesc)
app.pipe['puppy'] = gfx.make_pipeline(&pipdesc) println('${@FN} for shader `${shader_name}` done.')
println('GLSL Puppy init DONE!')
}
@[inline]
fn vec4(x f32, y f32, z f32, w f32) m4.Vec4 {
return m4.Vec4{
e: [x, y, z, w]!
}
} }
fn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) m4.Mat4 { fn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) m4.Mat4 {
proj := m4.perspective(60, w / h, 0.01, 10.0) proj := m4.perspective(60, w / h, 0.01, 10.0)
view := m4.look_at(vec4(f32(0.0), 0, 6, 0), vec4(f32(0), 0, 0, 0), vec4(f32(0), 1, view := m4.look_at(m4.vec4(0.0, 0, 6, 0), m4.vec4(0, 0, 0, 0), m4.vec4(0, 1, 0, 0))
0, 0))
view_proj := view * proj view_proj := view * proj
rxm := m4.rotate(m4.rad(rx), vec4(f32(1), 0, 0, 0)) rxm := m4.rotate(m4.rad(rx), m4.vec4(1, 0, 0, 0))
rym := m4.rotate(m4.rad(ry), vec4(f32(0), 1, 0, 0)) rym := m4.rotate(m4.rad(ry), m4.vec4(0, 1, 0, 0))
model := rym * rxm model := rym * rxm
scale_m := m4.scale(vec4(in_scale, in_scale, in_scale, 1)) scale_m := m4.scale(m4.vec4(in_scale, in_scale, in_scale, 1))
res := (scale_m * model) * view_proj res := (scale_m * model) * view_proj
return res return res
} }
// march triangles draw fn (app &App) draw_glsl_shader(shader_name string) {
fn draw_cube_glsl_m(app App) {
if app.init_flag == false {
return
}
ws := gg.window_size_real_pixels() ws := gg.window_size_real_pixels()
ratio := f32(ws.width) / ws.height ratio := f32(ws.width) / ws.height
dw := f32(ws.width / 2) dw := f32(ws.width / 2)
@ -392,8 +185,9 @@ fn draw_cube_glsl_m(app App) {
rot := [f32(app.mouse_y), f32(app.mouse_x)] rot := [f32(app.mouse_y), f32(app.mouse_x)]
tr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3) tr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3)
gfx.apply_pipeline(app.pipe['march']) // apply the pipeline and bindings
gfx.apply_bindings(app.bind['march']) gfx.apply_pipeline(app.pipe[shader_name])
gfx.apply_bindings(app.bind[shader_name])
// Uniforms // Uniforms
// *** vertex shadeer uniforms *** // *** vertex shadeer uniforms ***
@ -406,8 +200,7 @@ fn draw_cube_glsl_m(app App) {
gfx.apply_uniforms(.vs, C.SLOT_vs_params_m, &vs_uniforms_range) gfx.apply_uniforms(.vs, C.SLOT_vs_params_m, &vs_uniforms_range)
// *** fragment shader uniforms *** // *** fragment shader uniforms ***
time_ticks := f32(time.ticks() - app.ticks) / 1000 time_ticks := f32(time.ticks() - start_ticks) / 1000
// vfmt off
mut tmp_fs_params := [ mut tmp_fs_params := [
f32(ws.width), f32(ws.width),
ws.height * ratio, // x,y resolution to pass to FS ws.height * ratio, // x,y resolution to pass to FS
@ -416,60 +209,7 @@ fn draw_cube_glsl_m(app App) {
// app.mouse_x, // mouse x // app.mouse_x, // mouse x
// ws.height - app.mouse_y*2, // mouse y scaled // ws.height - app.mouse_y*2, // mouse y scaled
time_ticks, // time as f32 time_ticks, // time as f32
app.frame_count, // frame count f32(app.gg.frame), // frame count
0,
0 // padding bytes , see "fs_params" struct paddings in rt_glsl.h
]!
// vfmt on
fs_uniforms_range := gfx.Range{
ptr: unsafe { &tmp_fs_params }
size: usize(sizeof(tmp_fs_params))
}
gfx.apply_uniforms(.fs, C.SLOT_fs_params_p, &fs_uniforms_range)
// 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw
gfx.draw(0, (3 * 2) * 3, 1)
}
// puppy triangles draw
fn draw_cube_glsl_p(app App) {
if app.init_flag == false {
return
}
ws := gg.window_size_real_pixels()
ratio := f32(ws.width) / ws.height
dw := f32(ws.width / 2)
dh := f32(ws.height / 2)
rot := [f32(app.mouse_y), f32(app.mouse_x)]
tr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3)
// apply the pipeline and bindings
gfx.apply_pipeline(app.pipe['puppy'])
gfx.apply_bindings(app.bind['puppy'])
// Uniforms
// *** vertex shadeer uniforms ***
// passing the view matrix as uniform
// res is a 4x4 matrix of f32 thus: 4*16 byte of size
vs_uniforms_range := gfx.Range{
ptr: &tr_matrix
size: usize(4 * 16)
}
gfx.apply_uniforms(.vs, C.SLOT_vs_params_p, &vs_uniforms_range)
// *** fragment shader uniforms ***
time_ticks := f32(time.ticks() - app.ticks) / 1000
mut tmp_fs_params := [
f32(ws.width),
ws.height * ratio, // x,y resolution to pass to FS
0,
0, // dont send mouse position
// app.mouse_x, // mouse x
// ws.height - app.mouse_y*2, // mouse y scaled
time_ticks, // time as f32
app.frame_count, // frame count
0, 0,
0, // padding bytes , see "fs_params" struct paddings in rt_glsl.h 0, // padding bytes , see "fs_params" struct paddings in rt_glsl.h
]! ]!
@ -483,73 +223,37 @@ fn draw_cube_glsl_p(app App) {
gfx.draw(0, (3 * 2) * 3, 1) gfx.draw(0, (3 * 2) * 3, 1)
} }
fn draw_start_glsl(app App) { fn (mut app App) frame() {
if app.init_flag == false { mut pass_action := gfx.PassAction{}
pass_action.colors[0] = gfx.ColorAttachmentAction{
load_action: .clear
clear_value: gfx.Color{b: 0.9}
}
gfx.begin_pass(sapp.create_default_pass(pass_action))
if !app.init_flag {
return return
} }
ws := gg.window_size_real_pixels() ws := gg.window_size_real_pixels()
// ratio := f32(ws.width) / ws.height
// dw := f32(ws.width / 2)
// dh := f32(ws.height / 2)
gfx.apply_viewport(0, 0, ws.width, ws.height, true) gfx.apply_viewport(0, 0, ws.width, ws.height, true)
} app.draw_glsl_shader('march')
app.draw_glsl_shader('puppy')
fn draw_end_glsl(app App) {
gfx.end_pass() gfx.end_pass()
gfx.commit() gfx.commit()
} }
fn frame(mut app App) { fn (mut app App) on_init() {
// clear // set max vertices, but note, that for a large number of the same type of object it is better use the instances!!
mut color_action := gfx.ColorAttachmentAction{ gfx.setup(sapp.create_desc())
load_action: .clear sgl.setup(sgl.Desc{max_vertices: 50 * 65536})
clear_value: gfx.Color{
r: 0.0
g: 0.0
b: 0.0
a: 1.0
}
}
mut pass_action := gfx.PassAction{}
pass_action.colors[0] = color_action
pass := sapp.create_default_pass(pass_action)
gfx.begin_pass(&pass)
/*
// glsl cube
if app.frame_count % 1 == 1{
draw_cube_glsl_m(app)
} else {
draw_cube_glsl_p(app)
}
*/
draw_start_glsl(app)
draw_cube_glsl_m(app)
draw_cube_glsl_p(app)
draw_end_glsl(app)
app.frame_count++
}
/******************************************************************************
* Init / Cleanup
******************************************************************************/
fn my_init(mut app App) {
// set max vertices,
// for a large number of the same type of object it is better use the instances!!
desc := sapp.create_desc()
gfx.setup(&desc)
sgl_desc := sgl.Desc{
max_vertices: 50 * 65536
}
sgl.setup(&sgl_desc)
// create chessboard texture 256*256 RGBA // create chessboard texture 256*256 RGBA
w := 256 w := 256
h := 256 h := 256
sz := w * h * 4 sz := w * h * 4
tmp_txt := unsafe { malloc(sz) } tmp_txt := unsafe { malloc(sz) }
defer {
unsafe { free(tmp_txt) }
}
mut i := 0 mut i := 0
for i < sz { for i < sz {
unsafe { unsafe {
@ -557,40 +261,48 @@ fn my_init(mut app App) {
x := (i & 0xFF) >> 5 // 8 cell x := (i & 0xFF) >> 5 // 8 cell
// upper left corner // upper left corner
if x == 0 && y == 0 { if x == 0 && y == 0 {
tmp_txt[i + 0] = u8(0xFF) tmp_txt[i + 0] = 0xFF
tmp_txt[i + 1] = u8(0) tmp_txt[i + 1] = 0
tmp_txt[i + 2] = u8(0) tmp_txt[i + 2] = 0
tmp_txt[i + 3] = u8(0xFF) tmp_txt[i + 3] = 0xFF
} }
// low right corner // low right corner
else if x == 7 && y == 7 { else if x == 7 && y == 7 {
tmp_txt[i + 0] = u8(0) tmp_txt[i + 0] = 0
tmp_txt[i + 1] = u8(0xFF) tmp_txt[i + 1] = 0xFF
tmp_txt[i + 2] = u8(0) tmp_txt[i + 2] = 0
tmp_txt[i + 3] = u8(0xFF) tmp_txt[i + 3] = 0xFF
} else { } else {
col := if ((x + y) & 1) == 1 { 0xFF } else { 128 } col := if ((x + y) & 1) == 1 { u8(0xFF) } else { 128 }
tmp_txt[i + 0] = u8(col) // red tmp_txt[i + 0] = col // red
tmp_txt[i + 1] = u8(col) // green tmp_txt[i + 1] = col // green
tmp_txt[i + 2] = u8(col) // blue tmp_txt[i + 2] = col // blue
tmp_txt[i + 3] = u8(0xFF) // alpha tmp_txt[i + 3] = 0xFF // alpha
} }
i += 4 i += 4
} }
} }
app.texture, app.sampler = create_texture(w, h, tmp_txt) app.texture, app.sampler = create_texture(w, h, tmp_txt)
unsafe { free(tmp_txt) }
// glsl // vfmt off
init_cube_glsl_m(mut app) app.init_glsl_shader('march', C.rt_march_shader_desc(C.sg_query_backend()), [
init_cube_glsl_p(mut app) u16(0), 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
])
app.init_glsl_shader('puppy', C.rt_puppy_shader_desc(C.sg_query_backend()), [
u16(14), 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20,
])
// vfmt on
app.init_flag = true app.init_flag = true
} }
/****************************************************************************** /******************************************************************************
* events handling * events handling
******************************************************************************/ ******************************************************************************/
fn my_event_manager(mut ev gg.Event, mut app App) { fn (mut app App) on_event(ev &gg.Event, x voidptr) {
if ev.typ == .mouse_down { if ev.typ == .mouse_down {
app.mouse_down = true app.mouse_down = true
} }
@ -608,21 +320,19 @@ fn my_event_manager(mut ev gg.Event, mut app App) {
app.mouse_y = int(touch_point.pos_y) app.mouse_y = int(touch_point.pos_y)
} }
} }
// eprintln('> app.mouse_x: ${app.mouse_x} | app.mouse_y: ${app.mouse_y}')
} }
fn main() { fn main() {
mut app := &App{} mut app := &App{}
app.gg = gg.new_context( app.gg = gg.new_context(
width: win_width width: 800
height: win_height height: 800
create_window: true
window_title: '3D Dual shader Cube - click and rotate with the mouse' window_title: '3D Dual shader Cube - click and rotate with the mouse'
user_data: app user_data: app
bg_color: bg_color frame_fn: app.frame
frame_fn: frame init_fn: app.on_init
init_fn: my_init event_fn: app.on_event
event_fn: my_event_manager
) )
app.ticks = time.ticks()
app.gg.run() app.gg.run()
} }

View file

@ -61,7 +61,6 @@ mut:
texture gfx.Image texture gfx.Image
sampler gfx.Sampler sampler gfx.Sampler
init_flag bool init_flag bool
frame_count int
mouse_x int = -1 mouse_x int = -1
mouse_y int = -1 mouse_y int = -1
scroll_y int scroll_y int
@ -563,7 +562,6 @@ fn frame(mut app App) {
} }
app.gg.end() app.gg.end()
app.frame_count++
} }
// draw readable text // draw readable text

View file

@ -1,12 +1,8 @@
/********************************************************************** /**********************************************************************
* * Simple vector/matrix utility
* Simply vector/matrix utility * Copyright (c) 2024 Dario Deledda. All rights reserved.
*
* Copyright (c) 2021 Dario Deledda. All rights reserved.
* Use of this source code is governed by an MIT license * Use of this source code is governed by an MIT license
* that can be found in the LICENSE file. * that can be found in the LICENSE file.
*
* TODO:
**********************************************************************/ **********************************************************************/
module m4 module m4
@ -17,24 +13,28 @@ pub mut:
e [4]f32 e [4]f32
} }
/*********************************************************************
*
* Utility
*
*********************************************************************/
// str returns a `string` representation of `Vec4`. // str returns a `string` representation of `Vec4`.
pub fn (x Vec4) str() string { pub fn (x Vec4) str() string {
return '|${x.e[0]:-6.3},${x.e[1]:-6.3},${x.e[2]:-6.3},${x.e[3]:-6.3}|' return '|${x.e[0]:-6.3},${x.e[1]:-6.3},${x.e[2]:-6.3},${x.e[3]:-6.3}|'
} }
// create a Vec4 function passing x,y,z as parameters. w is set to 1 // vec3 creates a Vec4 value, passing x,y,z as parameters. The w element is set to 1
@[inline]
pub fn vec3(x f32, y f32, z f32) Vec4 { pub fn vec3(x f32, y f32, z f32) Vec4 {
return Vec4{ return Vec4{
e: [x, y, z, 1]! e: [x, y, z, 1]!
} }
} }
// Check if two vector are equal using module precision // vec4 creates a Vec4 value, based on the x,y,z,w parameters
@[inline]
pub fn vec4(x f32, y f32, z f32, w f32) Vec4 {
return Vec4{
e: [x, y, z, w]!
}
}
// is_equal checks if two vector are equal using the module precision (10e-7)
@[direct_array_access] @[direct_array_access]
pub fn (x Vec4) is_equal(y Vec4) bool { pub fn (x Vec4) is_equal(y Vec4) bool {
unsafe { unsafe {
@ -47,45 +47,44 @@ pub fn (x Vec4) is_equal(y Vec4) bool {
} }
} }
// Remove all the raw zeros // clean returns a new vector, based on `x`, but with all the values < precision, set to 0
@[direct_array_access] @[direct_array_access]
pub fn (a Vec4) clean() Vec4 { pub fn (x Vec4) clean() Vec4 {
mut x := Vec4{} mut n := x
for c, value in a.e { for c, value in x.e {
if f32_abs(value) < precision { if f32_abs(value) < precision {
x.e[c] = 0 n.e[c] = 0
} else {
x.e[c] = value
} }
} }
return x return n
} }
// Set all elements to value // copy sets all elements of `x` to `value`
pub fn (mut x Vec4) copy(value f32) { pub fn (mut x Vec4) copy(value f32) {
x.e = [value, value, value, value]! x.e = [value, value, value, value]!
} }
// Scale the vector using a scalar // mul_scalar returns the result of multiplying the vector `x`, by the scalar `value`
@[inline]
pub fn (x Vec4) mul_scalar(value f32) Vec4 { pub fn (x Vec4) mul_scalar(value f32) Vec4 {
return Vec4{ return Vec4{
e: [x.e[0] * value, x.e[1] * value, x.e[2] * value, x.e[3] * value]! e: [x.e[0] * value, x.e[1] * value, x.e[2] * value, x.e[3] * value]!
} }
} }
// Reciprocal of the vector // inv returns the reciprocal of the vector `x`
pub fn (x Vec4) inv() Vec4 { pub fn (x Vec4) inv() Vec4 {
return Vec4{ return Vec4{
e: [ e: [
if x.e[0] != 0 { 1.0 / x.e[0] } else { f32(0) }, if x.e[0] != 0 { 1.0 / x.e[0] } else { 0 },
if x.e[1] != 0 { 1.0 / x.e[1] } else { f32(0) }, if x.e[1] != 0 { 1.0 / x.e[1] } else { 0 },
if x.e[2] != 0 { 1.0 / x.e[2] } else { f32(0) }, if x.e[2] != 0 { 1.0 / x.e[2] } else { 0 },
if x.e[3] != 0 { 1.0 / x.e[3] } else { f32(0) }, if x.e[3] != 0 { 1.0 / x.e[3] } else { 0 },
]! ]!
} }
} }
// Normalize the vector // normalize returns a normalized form of the vector `x`
pub fn (x Vec4) normalize() Vec4 { pub fn (x Vec4) normalize() Vec4 {
m := x.mod() m := x.mod()
if m == 0 { if m == 0 {
@ -101,7 +100,7 @@ pub fn (x Vec4) normalize() Vec4 {
} }
} }
// Normalize only xyz, w set to 0 // normalize3 returns a normalized form of the vector `x`, where the w element is set to 0
pub fn (x Vec4) normalize3() Vec4 { pub fn (x Vec4) normalize3() Vec4 {
m := x.mod3() m := x.mod3()
if m == 0 { if m == 0 {
@ -117,22 +116,23 @@ pub fn (x Vec4) normalize3() Vec4 {
} }
} }
// Module of the vector xyzw // mod returns a module of the vector `x`
@[inline]
pub fn (x Vec4) mod() f32 { pub fn (x Vec4) mod() f32 {
return f32(math.sqrt(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2] + x.e[3] * x.e[3])) return math.sqrtf(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2] + x.e[3] * x.e[3])
} }
// Module for 3d vector xyz, w ignored // mod3 returns a module of the 3d vector `x`, ignoring the value of its w element
@[inline]
pub fn (x Vec4) mod3() f32 { pub fn (x Vec4) mod3() f32 {
return f32(math.sqrt(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2])) return math.sqrtf(x.e[0] * x.e[0] + x.e[1] * x.e[1] + x.e[2] * x.e[2])
} }
/********************************************************************* /*********************************************************************
*
* Math * Math
*
*********************************************************************/ *********************************************************************/
// Return a zero vector // zero_v4 returns a zero vector (all elements set to 0)
@[inline]
pub fn zero_v4() Vec4 { pub fn zero_v4() Vec4 {
return Vec4{ return Vec4{
e: [ e: [
@ -144,7 +144,8 @@ pub fn zero_v4() Vec4 {
} }
} }
// Return all one vector // one_v4 returns a vector, where all elements are set to 1
@[inline]
pub fn one_v4() Vec4 { pub fn one_v4() Vec4 {
return Vec4{ return Vec4{
e: [ e: [
@ -156,7 +157,7 @@ pub fn one_v4() Vec4 {
} }
} }
// Return a blank vector // blank_v4 returns a vector, where all elements are set to 0, except `w`, which is set to 1
pub fn blank_v4() Vec4 { pub fn blank_v4() Vec4 {
return Vec4{ return Vec4{
e: [ e: [
@ -168,7 +169,8 @@ pub fn blank_v4() Vec4 {
} }
} }
// Set all elements to value // set_v4 returns a vector, where all elements are set to `value`
@[inline]
pub fn set_v4(value f32) Vec4 { pub fn set_v4(value f32) Vec4 {
return Vec4{ return Vec4{
e: [ e: [
@ -180,17 +182,17 @@ pub fn set_v4(value f32) Vec4 {
} }
} }
// Sum of all the elements // sum returns a sum of all the elements
@[inline]
pub fn (x Vec4) sum() f32 { pub fn (x Vec4) sum() f32 {
return x.e[0] + x.e[1] + x.e[2] + x.e[3] return x.e[0] + x.e[1] + x.e[2] + x.e[3]
} }
/********************************************************************* /*********************************************************************
*
* Operators * Operators
*
*********************************************************************/ *********************************************************************/
// Addition // + returns `a` + `b` (corresponding elements are addded)
@[inline]
pub fn (a Vec4) + (b Vec4) Vec4 { pub fn (a Vec4) + (b Vec4) Vec4 {
return Vec4{ return Vec4{
e: [ e: [
@ -202,7 +204,8 @@ pub fn (a Vec4) + (b Vec4) Vec4 {
} }
} }
// Subtraction // - returns `a` + `b` (corresponding elements are subtracted)
@[inline]
pub fn (a Vec4) - (b Vec4) Vec4 { pub fn (a Vec4) - (b Vec4) Vec4 {
return Vec4{ return Vec4{
e: [ e: [
@ -214,12 +217,14 @@ pub fn (a Vec4) - (b Vec4) Vec4 {
} }
} }
// Dot product // * returns `a` * `b` (corresponding elements are multiplied, then summed), i.e. a dot product
@[inline]
pub fn (a Vec4) * (b Vec4) f32 { pub fn (a Vec4) * (b Vec4) f32 {
return a.e[0] * b.e[0] + a.e[1] * b.e[1] + a.e[2] * b.e[2] + a.e[3] * b.e[3] return a.e[0] * b.e[0] + a.e[1] * b.e[1] + a.e[2] * b.e[2] + a.e[3] * b.e[3]
} }
// Cross product // % returns a cross product of the vectors `a` and `b`
@[inline]
pub fn (a Vec4) % (b Vec4) Vec4 { pub fn (a Vec4) % (b Vec4) Vec4 {
return Vec4{ return Vec4{
e: [ e: [
@ -231,7 +236,8 @@ pub fn (a Vec4) % (b Vec4) Vec4 {
} }
} }
// Components multiplication // mul_vec4 returns a vectore, where the corresponding `x` and `y` elements are multiplied
@[inline]
pub fn (x Vec4) mul_vec4(y Vec4) Vec4 { pub fn (x Vec4) mul_vec4(y Vec4) Vec4 {
return Vec4{ return Vec4{
e: [ e: [