diff --git a/examples/sokol/04_multi_shader_glsl/rt_glsl.v b/examples/sokol/04_multi_shader_glsl/rt_glsl.v index 0e478eecc0..9da41f2635 100644 --- a/examples/sokol/04_multi_shader_glsl/rt_glsl.v +++ b/examples/sokol/04_multi_shader_glsl/rt_glsl.v @@ -1,22 +1,15 @@ /********************************************************************** -* * Sokol 3d cube multishader demo -* -* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Copyright (c) 2024 Dario Deledda. All rights reserved. * Use of this source code is governed by an MIT license * that can be found in the LICENSE file. * * HOW TO COMPILE 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`. -* -* TODO: -* - frame counter **********************************************************************/ import gg import gg.m4 -import gx -// import math import sokol.sapp import sokol.gfx import sokol.sgl @@ -29,27 +22,23 @@ import time fn C.rt_march_shader_desc(gfx.Backend) &gfx.ShaderDesc fn C.rt_puppy_shader_desc(gfx.Backend) &gfx.ShaderDesc -const win_width = 800 -const win_height = 800 -const bg_color = gx.white +const start_ticks = time.ticks() +@[heap] struct App { mut: - gg &gg.Context = unsafe { nil } - texture gfx.Image - sampler gfx.Sampler - init_flag bool - frame_count int - mouse_x int = -1 - mouse_y int = -1 - mouse_down bool + gg &gg.Context = unsafe { nil } + texture gfx.Image + sampler gfx.Sampler + init_flag bool + mouse_x int = 502 + mouse_y int = 394 + mouse_down bool // glsl cube_pip_glsl gfx.Pipeline cube_bind gfx.Bindings pipe map[string]gfx.Pipeline 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{ width: w 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{ ptr: buf size: usize(sz) } - sg_img := gfx.make_image(&img_desc) - mut smp_desc := gfx.SamplerDesc{ min_filter: .linear mag_filter: .linear wrap_u: .clamp_to_edge wrap_v: .clamp_to_edge } - sg_smp := gfx.make_sampler(&smp_desc) 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 ****************************************************************************** @@ -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. The reason is that D3D11 cannot convert from non-normalized 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 { x f32 y f32 z f32 color u32 - // u u16 // for compatibility with D3D11 - // v u16 // for compatibility with D3D11 - u f32 - v f32 + u f32 + v f32 } -// march shader init -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 +const vertices = cube_vertices() - 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))) +fn cube_vertices() []Vertex_t { + // cube vertex buffer + d := f32(1.0) + c := u32(0xFF_FF_FF_FF) // white color RGBA8 + // 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{ ptr: vertices.data - size: usize(vertices.len * int(sizeof(Vertex_t))) + size: vert_buffer_desc.size } 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))) + mut index_buffer_desc := gfx.BufferDesc{} + unsafe { vmemset(&index_buffer_desc, 0, sizeof(index_buffer_desc)) } + index_buffer_desc.label = c'cube-indices' + index_buffer_desc.size = usize(indices.len) * sizeof(u16) index_buffer_desc.data = gfx.Range{ ptr: indices.data - size: usize(indices.len * int(sizeof(u16))) + size: index_buffer_desc.size } index_buffer_desc.@type = .indexbuffer ibuf := gfx.make_buffer(&index_buffer_desc) // 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{} - 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)) - // vfmt off // 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_color0 ].format = .ubyte4n // color as u32 + 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_texcoord0].format = .float2 // u,v as f32 // pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .short2n // u,v as u16 - // vfmt on - pipdesc.shader = shader 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{ 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))) } + unsafe { vmemset(&bind, 0, 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['puppy'] = bind - - app.pipe['puppy'] = gfx.make_pipeline(&pipdesc) - - 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]! - } + app.bind[shader_name] = bind + app.pipe[shader_name] = gfx.make_pipeline(&pipdesc) + println('${@FN} for shader `${shader_name}` done.') } 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) - view := m4.look_at(vec4(f32(0.0), 0, 6, 0), vec4(f32(0), 0, 0, 0), vec4(f32(0), 1, - 0, 0)) + view := m4.look_at(m4.vec4(0.0, 0, 6, 0), m4.vec4(0, 0, 0, 0), m4.vec4(0, 1, 0, 0)) view_proj := view * proj - rxm := m4.rotate(m4.rad(rx), vec4(f32(1), 0, 0, 0)) - rym := m4.rotate(m4.rad(ry), vec4(f32(0), 1, 0, 0)) + rxm := m4.rotate(m4.rad(rx), m4.vec4(1, 0, 0, 0)) + rym := m4.rotate(m4.rad(ry), m4.vec4(0, 1, 0, 0)) 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 return res } -// march triangles draw -fn draw_cube_glsl_m(app App) { - if app.init_flag == false { - return - } - +fn (app &App) draw_glsl_shader(shader_name string) { ws := gg.window_size_real_pixels() ratio := f32(ws.width) / ws.height 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)] tr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3) - gfx.apply_pipeline(app.pipe['march']) - gfx.apply_bindings(app.bind['march']) + // apply the pipeline and bindings + gfx.apply_pipeline(app.pipe[shader_name]) + gfx.apply_bindings(app.bind[shader_name]) // Uniforms // *** vertex shadeer uniforms *** @@ -406,61 +200,7 @@ fn draw_cube_glsl_m(app App) { gfx.apply_uniforms(.vs, C.SLOT_vs_params_m, &vs_uniforms_range) // *** fragment shader uniforms *** - time_ticks := f32(time.ticks() - app.ticks) / 1000 - // vfmt off - 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 // 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 + time_ticks := f32(time.ticks() - start_ticks) / 1000 mut tmp_fs_params := [ f32(ws.width), ws.height * ratio, // x,y resolution to pass to FS @@ -469,7 +209,7 @@ fn draw_cube_glsl_p(app App) { // app.mouse_x, // mouse x // ws.height - app.mouse_y*2, // mouse y scaled 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 ]! @@ -483,73 +223,37 @@ fn draw_cube_glsl_p(app App) { gfx.draw(0, (3 * 2) * 3, 1) } -fn draw_start_glsl(app App) { - if app.init_flag == false { +fn (mut app App) frame() { + 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 } - 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) -} - -fn draw_end_glsl(app App) { + app.draw_glsl_shader('march') + app.draw_glsl_shader('puppy') gfx.end_pass() gfx.commit() } -fn frame(mut app App) { - // clear - mut color_action := gfx.ColorAttachmentAction{ - load_action: .clear - 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) +fn (mut app App) on_init() { + // set max vertices, but note, that for a large number of the same type of object it is better use the instances!! + gfx.setup(sapp.create_desc()) + sgl.setup(sgl.Desc{max_vertices: 50 * 65536}) // create chessboard texture 256*256 RGBA w := 256 h := 256 sz := w * h * 4 tmp_txt := unsafe { malloc(sz) } + defer { + unsafe { free(tmp_txt) } + } mut i := 0 for i < sz { unsafe { @@ -557,40 +261,48 @@ fn my_init(mut app App) { x := (i & 0xFF) >> 5 // 8 cell // upper left corner if x == 0 && y == 0 { - tmp_txt[i + 0] = u8(0xFF) - tmp_txt[i + 1] = u8(0) - tmp_txt[i + 2] = u8(0) - tmp_txt[i + 3] = u8(0xFF) + tmp_txt[i + 0] = 0xFF + tmp_txt[i + 1] = 0 + tmp_txt[i + 2] = 0 + tmp_txt[i + 3] = 0xFF } // low right corner else if x == 7 && y == 7 { - tmp_txt[i + 0] = u8(0) - tmp_txt[i + 1] = u8(0xFF) - tmp_txt[i + 2] = u8(0) - tmp_txt[i + 3] = u8(0xFF) + tmp_txt[i + 0] = 0 + tmp_txt[i + 1] = 0xFF + tmp_txt[i + 2] = 0 + tmp_txt[i + 3] = 0xFF } else { - col := if ((x + y) & 1) == 1 { 0xFF } else { 128 } - tmp_txt[i + 0] = u8(col) // red - tmp_txt[i + 1] = u8(col) // green - tmp_txt[i + 2] = u8(col) // blue - tmp_txt[i + 3] = u8(0xFF) // alpha + col := if ((x + y) & 1) == 1 { u8(0xFF) } else { 128 } + tmp_txt[i + 0] = col // red + tmp_txt[i + 1] = col // green + tmp_txt[i + 2] = col // blue + tmp_txt[i + 3] = 0xFF // alpha } i += 4 } } app.texture, app.sampler = create_texture(w, h, tmp_txt) - unsafe { free(tmp_txt) } - // glsl - init_cube_glsl_m(mut app) - init_cube_glsl_p(mut app) + // vfmt off + app.init_glsl_shader('march', C.rt_march_shader_desc(C.sg_query_backend()), [ + 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 } /****************************************************************************** * 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 { 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) } } + // eprintln('> app.mouse_x: ${app.mouse_x} | app.mouse_y: ${app.mouse_y}') } fn main() { mut app := &App{} app.gg = gg.new_context( - width: win_width - height: win_height - create_window: true + width: 800 + height: 800 window_title: '3D Dual shader Cube - click and rotate with the mouse' user_data: app - bg_color: bg_color - frame_fn: frame - init_fn: my_init - event_fn: my_event_manager + frame_fn: app.frame + init_fn: app.on_init + event_fn: app.on_event ) - app.ticks = time.ticks() app.gg.run() } diff --git a/examples/viewer/view.v b/examples/viewer/view.v index 499ae6017b..459c1b37f9 100644 --- a/examples/viewer/view.v +++ b/examples/viewer/view.v @@ -56,15 +56,14 @@ enum Viewer_state { struct App { mut: - gg &gg.Context = unsafe { nil } - pip_viewer sgl.Pipeline - texture gfx.Image - sampler gfx.Sampler - init_flag bool - frame_count int - mouse_x int = -1 - mouse_y int = -1 - scroll_y int + gg &gg.Context = unsafe { nil } + pip_viewer sgl.Pipeline + texture gfx.Image + sampler gfx.Sampler + init_flag bool + mouse_x int = -1 + mouse_y int = -1 + scroll_y int state Viewer_state = .scanning // translation @@ -563,7 +562,6 @@ fn frame(mut app App) { } app.gg.end() - app.frame_count++ } // draw readable text diff --git a/vlib/gg/m4/vector.v b/vlib/gg/m4/vector.v index b760158cf7..abe49d08f0 100644 --- a/vlib/gg/m4/vector.v +++ b/vlib/gg/m4/vector.v @@ -1,12 +1,8 @@ /********************************************************************** -* -* Simply vector/matrix utility -* -* Copyright (c) 2021 Dario Deledda. All rights reserved. +* Simple vector/matrix utility +* Copyright (c) 2024 Dario Deledda. All rights reserved. * Use of this source code is governed by an MIT license * that can be found in the LICENSE file. -* -* TODO: **********************************************************************/ module m4 @@ -17,24 +13,28 @@ pub mut: e [4]f32 } -/********************************************************************* -* -* Utility -* -*********************************************************************/ // str returns a `string` representation of `Vec4`. 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}|' } -// 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 { return Vec4{ 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] pub fn (x Vec4) is_equal(y Vec4) bool { 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] -pub fn (a Vec4) clean() Vec4 { - mut x := Vec4{} - for c, value in a.e { +pub fn (x Vec4) clean() Vec4 { + mut n := x + for c, value in x.e { if f32_abs(value) < precision { - x.e[c] = 0 - } else { - x.e[c] = value + n.e[c] = 0 } } - 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) { 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 { return Vec4{ 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 { return Vec4{ e: [ - if x.e[0] != 0 { 1.0 / x.e[0] } else { f32(0) }, - if x.e[1] != 0 { 1.0 / x.e[1] } else { f32(0) }, - if x.e[2] != 0 { 1.0 / x.e[2] } else { f32(0) }, - if x.e[3] != 0 { 1.0 / x.e[3] } 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 { 0 }, + if x.e[2] != 0 { 1.0 / x.e[2] } else { 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 { m := x.mod() 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 { m := x.mod3() 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 { - 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 { - 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 -* *********************************************************************/ -// Return a zero vector +// zero_v4 returns a zero vector (all elements set to 0) +@[inline] pub fn zero_v4() Vec4 { return Vec4{ 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 { return Vec4{ 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 { return Vec4{ 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 { return Vec4{ 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 { return x.e[0] + x.e[1] + x.e[2] + x.e[3] } /********************************************************************* -* * Operators -* *********************************************************************/ -// Addition +// + returns `a` + `b` (corresponding elements are addded) +@[inline] pub fn (a Vec4) + (b Vec4) Vec4 { return Vec4{ 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 { return Vec4{ 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 { 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 { return Vec4{ 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 { return Vec4{ e: [