v2 / examples / sokol / 02_cubes_glsl / cube_glsl.v
626 lines · 560 sloc · 16.17 KB · bbb61ab3687afe512a1fa12492c876d011626107
Raw
1// vtest build: misc-tooling // needs .h files that are produced by `v shader`
2/**********************************************************************
3*
4* Sokol 3d cube demo
5*
6* Copyright (c) 2021 Dario Deledda. All rights reserved.
7* Use of this source code is governed by an MIT license
8* that can be found in the LICENSE file.
9*
10* HOW TO COMPILE SHADERS:
11* Run `v shader .` in this directory to compile the shaders.
12* For more info and help with shader compilation see `docs.md` and `v help shader`.
13*
14* TODO:
15* - add instancing
16**********************************************************************/
17import gg
18// import math
19import sokol.sapp
20import sokol.gfx
21import sokol.sgl
22import time
23import gg.m4
24
25// GLSL Include and functions
26#include "@VMODROOT/cube_glsl.h" # It should be generated with `v shader .` (see the instructions at the top of this file)
27
28fn C.cube_shader_desc(gfx.Backend) &gfx.ShaderDesc
29
30const win_width = 800
31const win_height = 800
32const bg_color = gg.white
33
34struct App {
35mut:
36 gg &gg.Context = unsafe { nil }
37 pip_3d sgl.Pipeline
38 texture gfx.Image
39 sampler gfx.Sampler
40 init_flag bool
41 frame_count int
42 mouse_x int = -1
43 mouse_y int = -1
44 // glsl
45 cube_pip_glsl gfx.Pipeline
46 cube_bind gfx.Bindings
47 // time
48 ticks i64
49}
50
51/******************************************************************************
52*
53* Texture functions
54*
55******************************************************************************/
56fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {
57 sz := w * h * 4
58 mut img_desc := gfx.ImageDesc{
59 width: w
60 height: h
61 num_mipmaps: 0
62 // usage: .dynamic
63 label: &char(unsafe { nil })
64 d3d11_texture: 0
65 }
66 // comment if .dynamic is enabled
67 img_desc.data.subimage[0][0] = gfx.Range{
68 ptr: buf
69 size: usize(sz)
70 }
71
72 sg_img := gfx.make_image(&img_desc)
73
74 mut smp_desc := gfx.SamplerDesc{
75 min_filter: .linear
76 mag_filter: .linear
77 wrap_u: .clamp_to_edge
78 wrap_v: .clamp_to_edge
79 }
80
81 sg_smp := gfx.make_sampler(&smp_desc)
82 return sg_img, sg_smp
83}
84
85fn destroy_texture(sg_img gfx.Image) {
86 gfx.destroy_image(sg_img)
87}
88
89// Use only if usage: .dynamic is enabled
90fn update_text_texture(sg_img gfx.Image, w int, h int, buf &u8) {
91 sz := w * h * 4
92 mut tmp_sbc := gfx.ImageData{}
93 tmp_sbc.subimage[0][0] = gfx.Range{
94 ptr: buf
95 size: usize(sz)
96 }
97 gfx.update_image(sg_img, &tmp_sbc)
98}
99
100/******************************************************************************
101*
102* Draw functions
103*
104******************************************************************************/
105fn draw_triangle() {
106 sgl.defaults()
107 sgl.begin_triangles()
108 {
109 // vfmt off
110 sgl.v2f_c3b( 0.0, 0.5, 255, 0 , 0 )
111 sgl.v2f_c3b(-0.5, -0.5, 0, 0 , 255)
112 sgl.v2f_c3b( 0.5, -0.5, 0, 255, 0 )
113 // vfmt on
114 }
115 sgl.end()
116}
117
118// vertex specification for a cube with colored sides and texture coords
119fn cube() {
120 sgl.begin_quads()
121 {
122 // vfmt off
123 sgl.c3f(1.0, 0.0, 0.0) // edge color
124 // edge coordinates
125 // x,y,z, texture cord: u,v
126 sgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0)
127 sgl.v3f_t2f( 1.0, 1.0, -1.0, 1.0, 1.0)
128 sgl.v3f_t2f( 1.0, -1.0, -1.0, 1.0, -1.0)
129 sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)
130 sgl.c3f(0.0, 1.0, 0.0)
131 sgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0)
132 sgl.v3f_t2f( 1.0, -1.0, 1.0, 1.0, 1.0)
133 sgl.v3f_t2f( 1.0, 1.0, 1.0, 1.0, -1.0)
134 sgl.v3f_t2f(-1.0, 1.0, 1.0, -1.0, -1.0)
135 sgl.c3f(0.0, 0.0, 1.0)
136 sgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0)
137 sgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0)
138 sgl.v3f_t2f(-1.0, 1.0, -1.0, 1.0, -1.0)
139 sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)
140 sgl.c3f(1.0, 0.5, 0.0)
141 sgl.v3f_t2f(1.0, -1.0, 1.0, -1.0, 1.0)
142 sgl.v3f_t2f(1.0, -1.0, -1.0, 1.0, 1.0)
143 sgl.v3f_t2f(1.0, 1.0, -1.0, 1.0, -1.0)
144 sgl.v3f_t2f(1.0, 1.0, 1.0, -1.0, -1.0)
145 sgl.c3f(0.0, 0.5, 1.0)
146 sgl.v3f_t2f( 1.0, -1.0, -1.0, -1.0, 1.0)
147 sgl.v3f_t2f( 1.0, -1.0, 1.0, 1.0, 1.0)
148 sgl.v3f_t2f(-1.0, -1.0, 1.0, 1.0, -1.0)
149 sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)
150 sgl.c3f(1.0, 0.0, 0.5)
151 sgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0)
152 sgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0)
153 sgl.v3f_t2f( 1.0, 1.0, 1.0, 1.0, -1.0)
154 sgl.v3f_t2f( 1.0, 1.0, -1.0, -1.0, -1.0)
155 // vfmt on
156 }
157 sgl.end()
158}
159
160fn draw_cubes(app App) {
161 rot := [f32(1.0) * (app.frame_count % 360), 0.5 * f32(app.frame_count % 360)]
162 // rot := [f32(app.mouse_x), f32(app.mouse_y)]
163
164 sgl.defaults()
165 sgl.load_pipeline(app.pip_3d)
166
167 sgl.matrix_mode_projection()
168 sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)
169
170 sgl.matrix_mode_modelview()
171 sgl.translate(0.0, 0.0, -12.0)
172 sgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)
173 sgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)
174 cube()
175 sgl.push_matrix()
176 {
177 sgl.translate(0.0, 0.0, 3.0)
178 sgl.scale(0.5, 0.5, 0.5)
179 sgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)
180 sgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)
181 cube()
182 sgl.push_matrix()
183 {
184 sgl.translate(0.0, 0.0, 3.0)
185 sgl.scale(0.5, 0.5, 0.5)
186 // vfmt off
187 sgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)
188 sgl.rotate( 3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)
189 // vfmt on
190 cube()
191 }
192 sgl.pop_matrix()
193 }
194 sgl.pop_matrix()
195}
196
197fn cube_texture(r f32, g f32, b f32) {
198 sgl.begin_quads()
199 {
200 sgl.c3f(r, g, b) // edge color
201 // edge coord
202 // x,y,z, texture cord: u,v
203 // vfmt off
204 sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0 , 0.25)
205 sgl.v3f_t2f( 1.0, 1.0, -1.0, 0.25, 0.25)
206 sgl.v3f_t2f( 1.0, -1.0, -1.0, 0.25, 0.0 )
207 sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0 , 0.0 )
208 sgl.c3f(r, g, b)
209 sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0 , 0.25)
210 sgl.v3f_t2f( 1.0, -1.0, 1.0, 0.25, 0.25)
211 sgl.v3f_t2f( 1.0, 1.0, 1.0, 0.25, 0.0 )
212 sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.0 , 0.0 )
213 sgl.c3f(r, g, b)
214 sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0 , 0.25)
215 sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25)
216 sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.25, 0.0 )
217 sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0 , 0.0 )
218 sgl.c3f(r, g, b)
219 sgl.v3f_t2f(1.0, -1.0, 1.0, 0.0 , 0.25)
220 sgl.v3f_t2f(1.0, -1.0, -1.0, 0.25, 0.25)
221 sgl.v3f_t2f(1.0, 1.0, -1.0, 0.25, 0.0 )
222 sgl.v3f_t2f(1.0, 1.0, 1.0, 0.0 , 0.0 )
223 sgl.c3f(r, g, b)
224 sgl.v3f_t2f( 1.0, -1.0, -1.0, 0.0 , 0.25)
225 sgl.v3f_t2f( 1.0, -1.0, 1.0, 0.25, 0.25)
226 sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.25, 0.0 )
227 sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0 , 0.0 )
228 sgl.c3f(r, g, b)
229 sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0 , 0.25)
230 sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25)
231 sgl.v3f_t2f( 1.0, 1.0, 1.0, 0.25, 0.0 )
232 sgl.v3f_t2f( 1.0, 1.0, -1.0, 0.0 , 0.0 )
233 // vfmt on
234 }
235 sgl.end()
236}
237
238/*
239Cube vertex buffer with packed vertex formats for color and texture coords.
240 Note that a vertex format which must be portable across all
241 backends must only use the normalized integer formats
242 (BYTE4N, UBYTE4N, SHORT2N, SHORT4N), which can be converted
243 to floating point formats in the vertex shader inputs.
244 The reason is that D3D11 cannot convert from non-normalized
245 formats to floating point inputs (only to integer inputs),
246 and WebGL2 / GLES2 don't support integer vertex shader inputs.
247*/
248
249struct Vertex_t {
250 x f32
251 y f32
252 z f32
253 color u32
254 // u u16
255 // v u16
256 u f32
257 v f32
258}
259
260fn init_cube_glsl(mut app App) {
261 // cube vertex buffer
262 // d := u16(32767/8) // for compatibility with D3D11, 32767 stand for 1
263 d := f32(1.0) // 0.05)
264 c := u32(0xFFFFFF_FF) // color RGBA8
265 // vfmt off
266 vertices := [
267 // Face 0
268 Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
269 Vertex_t{ 1.0, -1.0, -1.0, c, d, 0},
270 Vertex_t{ 1.0, 1.0, -1.0, c, d, d},
271 Vertex_t{-1.0, 1.0, -1.0, c, 0, d},
272 // Face 1
273 Vertex_t{-1.0, -1.0, 1.0, c, 0, 0},
274 Vertex_t{ 1.0, -1.0, 1.0, c, d, 0},
275 Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
276 Vertex_t{-1.0, 1.0, 1.0, c, 0, d},
277 // Face 2
278 Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
279 Vertex_t{-1.0, 1.0, -1.0, c, d, 0},
280 Vertex_t{-1.0, 1.0, 1.0, c, d, d},
281 Vertex_t{-1.0, -1.0, 1.0, c, 0, d},
282 // Face 3
283 Vertex_t{ 1.0, -1.0, -1.0, c, 0, 0},
284 Vertex_t{ 1.0, 1.0, -1.0, c, d, 0},
285 Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
286 Vertex_t{ 1.0, -1.0, 1.0, c, 0, d},
287 // Face 4
288 Vertex_t{-1.0, -1.0, -1.0, c, 0, 0},
289 Vertex_t{-1.0, -1.0, 1.0, c, d, 0},
290 Vertex_t{ 1.0, -1.0, 1.0, c, d, d},
291 Vertex_t{ 1.0, -1.0, -1.0, c, 0, d},
292 // Face 5
293 Vertex_t{-1.0, 1.0, -1.0, c, 0, 0},
294 Vertex_t{-1.0, 1.0, 1.0, c, d, 0},
295 Vertex_t{ 1.0, 1.0, 1.0, c, d, d},
296 Vertex_t{ 1.0, 1.0, -1.0, c, 0, d},
297 ]
298 // vfmt on
299
300 mut vert_buffer_desc := gfx.BufferDesc{
301 label: c'cube-vertices'
302 }
303 unsafe { vmemset(&vert_buffer_desc, 0, int(sizeof(vert_buffer_desc))) }
304
305 vert_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t)))
306 vert_buffer_desc.data = gfx.Range{
307 ptr: vertices.data
308 size: usize(vertices.len * int(sizeof(Vertex_t)))
309 }
310
311 vert_buffer_desc.type = .vertexbuffer
312 // vert_buffer_desc.usage = .immutable
313 vbuf := gfx.make_buffer(&vert_buffer_desc)
314
315 // create an index buffer for the cube
316 // vfmt off
317 indices := [
318 u16(0), 1, 2, 0, 2, 3,
319 6, 5, 4, 7, 6, 4,
320 8, 9, 10, 8, 10, 11,
321 14, 13, 12, 15, 14, 12,
322 16, 17, 18, 16, 18, 19,
323 22, 21, 20, 23, 22, 20,
324 ]
325 // vfmt on
326
327 mut index_buffer_desc := gfx.BufferDesc{
328 label: c'cube-indices'
329 }
330 unsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }
331
332 index_buffer_desc.size = usize(indices.len * int(sizeof(u16)))
333 index_buffer_desc.data = gfx.Range{
334 ptr: indices.data
335 size: usize(indices.len * int(sizeof(u16)))
336 }
337
338 index_buffer_desc.type = .indexbuffer
339 ibuf := gfx.make_buffer(&index_buffer_desc)
340
341 // create shader
342 shader := gfx.make_shader(voidptr(C.cube_shader_desc(C.sg_query_backend())))
343
344 mut pipdesc := gfx.PipelineDesc{}
345 unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
346
347 pipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t))
348 // the constants [C.ATTR_vs_pos, C.ATTR_vs_color0, C.ATTR_vs_texcoord0] are generated bysokol-shdc
349 pipdesc.layout.attrs[C.ATTR_vs_pos].format = .float3 // x,y,z as f32
350 pipdesc.layout.attrs[C.ATTR_vs_color0].format = .ubyte4n // color as u32
351 pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .float2 // u,v as f32
352 // pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .short2n // u,v as u16
353
354 pipdesc.shader = shader
355 pipdesc.index_type = .uint16
356
357 pipdesc.depth = gfx.DepthState{
358 write_enabled: true
359 compare: .less_equal
360 }
361 pipdesc.cull_mode = .back
362
363 pipdesc.label = c'glsl_shader pipeline'
364
365 app.cube_bind.vertex_buffers[0] = vbuf
366 app.cube_bind.index_buffer = ibuf
367 app.cube_bind.fs.images[C.SLOT_tex] = app.texture
368 app.cube_bind.fs.samplers[C.SLOT_smp] = app.sampler
369 app.cube_pip_glsl = gfx.make_pipeline(&pipdesc)
370 println('GLSL init DONE!')
371}
372
373fn draw_cube_glsl(app App) {
374 if app.init_flag == false {
375 return
376 }
377
378 // clear
379 ws := gg.window_size_real_pixels()
380 mut color_action := gfx.ColorAttachmentAction{
381 load_action: unsafe { gfx.LoadAction(C.SG_LOADACTION_DONTCARE) } // C.SG_ACTION_CLEAR)
382 clear_value: gfx.Color{
383 r: 1.0
384 g: 1.0
385 b: 1.0
386 a: 1.0
387 }
388 }
389 mut pass_action := gfx.PassAction{}
390 pass_action.colors[0] = color_action
391 pass := sapp.create_default_pass(pass_action)
392 gfx.begin_pass(&pass)
393 {
394 rot := [f32(app.mouse_y), f32(app.mouse_x)]
395 // ratio := f32(ws.width)/ws.height
396 dw := f32(ws.width / 2)
397 dh := f32(ws.height / 2)
398
399 tr_matrix := m4.calc_tr_matrices(dw, dh, rot[0], rot[1], 2.0)
400 gfx.apply_viewport(ws.width / 2, 0, ws.width / 2, ws.height / 2, true)
401
402 // apply the pipeline and bindings
403 gfx.apply_pipeline(app.cube_pip_glsl)
404 gfx.apply_bindings(app.cube_bind)
405
406 // Uniforms:
407 // passing the view matrix as uniform
408 // res is a 4x4 matrix of f32 thus: 4*16 byte of size
409 vs_uniforms_range := gfx.Range{
410 ptr: &tr_matrix
411 size: usize(4 * 16)
412 }
413 gfx.apply_uniforms(.vs, C.SLOT_vs_params, &vs_uniforms_range)
414
415 // fs uniforms
416 time_ticks := f32(time.ticks() - app.ticks) / 1000
417 mut text_res := [
418 f32(512),
419 512, // x,y resolution to pass to FS
420 time_ticks, // time as f32
421 0, // padding 4 Bytes == 1 f32
422 ]!
423 fs_uniforms_range := gfx.Range{
424 ptr: unsafe { &text_res }
425 size: usize(4 * 4)
426 }
427 gfx.apply_uniforms(.fs, C.SLOT_fs_params, &fs_uniforms_range)
428
429 gfx.draw(0, (3 * 2) * 6, 1)
430 }
431 gfx.end_pass()
432 gfx.commit()
433}
434
435fn draw_texture_cubes(app App) {
436 rot := [f32(app.mouse_x), f32(app.mouse_y)]
437 sgl.defaults()
438 sgl.load_pipeline(app.pip_3d)
439
440 sgl.enable_texture()
441 sgl.texture(app.texture, app.sampler)
442
443 sgl.matrix_mode_projection()
444 sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)
445
446 sgl.matrix_mode_modelview()
447 sgl.translate(0.0, 0.0, -12.0)
448 sgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)
449 sgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)
450 cube_texture(1, 1, 1)
451
452 sgl.push_matrix()
453 {
454 sgl.translate(0.0, 0.0, 3.0)
455 sgl.scale(0.5, 0.5, 0.5)
456 sgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)
457 sgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)
458 cube_texture(1, 1, 1)
459 sgl.push_matrix()
460 {
461 sgl.translate(0.0, 0.0, 3.0)
462 sgl.scale(0.5, 0.5, 0.5)
463 // vfmt off
464 sgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)
465 sgl.rotate( 3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)
466 // vfmt on
467 cube_texture(1, 1, 1)
468 }
469 sgl.pop_matrix()
470 }
471 sgl.pop_matrix()
472
473 sgl.disable_texture()
474}
475
476fn frame(mut app App) {
477 ws := gg.window_size_real_pixels()
478 ratio := f32(ws.width) / ws.height
479 dw := ws.width
480 dh := ws.height
481 ww := int(dh / 3) // not a bug
482 hh := int(dh / 3)
483 x0 := int(f32(dw) * 0.05)
484 // x1 := dw/2
485 y0 := 0
486 y1 := int(f32(dh) * 0.5)
487
488 app.gg.begin()
489 {
490 sgl.defaults()
491
492 // 2d triangle
493 sgl.viewport(x0, y0, ww, hh, true)
494 draw_triangle()
495
496 // colored cubes with viewport
497 sgl.viewport(x0, y1, ww, hh, true)
498 draw_cubes(app)
499
500 // textured cubed with viewport
501 sgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true)
502 draw_texture_cubes(app)
503 }
504 app.gg.end()
505
506 // glsl cube
507 draw_cube_glsl(app)
508
509 app.frame_count++
510}
511
512/******************************************************************************
513* Init / Cleanup
514******************************************************************************/
515fn my_init(mut app App) {
516 // set max vertices,
517 // for a large number of the same type of object it is better use the instances!!
518 desc := sapp.create_desc()
519 gfx.setup(&desc)
520 sgl_desc := sgl.Desc{
521 max_vertices: 50 * 65536
522 }
523 sgl.setup(&sgl_desc)
524
525 // 3d pipeline
526 mut pipdesc := gfx.PipelineDesc{}
527 unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
528
529 color_state := gfx.ColorTargetState{
530 blend: gfx.BlendState{
531 enabled: true
532 src_factor_rgb: .src_alpha
533 dst_factor_rgb: .one_minus_src_alpha
534 }
535 }
536 pipdesc.colors[0] = color_state
537
538 pipdesc.depth = gfx.DepthState{
539 write_enabled: true
540 compare: .less_equal
541 }
542 pipdesc.cull_mode = .back
543
544 app.pip_3d = sgl.make_pipeline(&pipdesc)
545
546 // create chessboard texture 256*256 RGBA
547 w := 256
548 h := 256
549 sz := w * h * 4
550 tmp_txt := unsafe { malloc(sz) }
551 mut i := 0
552 for i < sz {
553 unsafe {
554 y := (i >> 0x8) >> 5 // 8 cell
555 x := (i & 0xFF) >> 5 // 8 cell
556 // upper left corner
557 if x == 0 && y == 0 {
558 tmp_txt[i] = u8(0xFF)
559 tmp_txt[i + 1] = u8(0)
560 tmp_txt[i + 2] = u8(0)
561 tmp_txt[i + 3] = u8(0xFF)
562 }
563 // low right corner
564 else if x == 7 && y == 7 {
565 tmp_txt[i + 0] = u8(0)
566 tmp_txt[i + 1] = u8(0xFF)
567 tmp_txt[i + 2] = u8(0)
568 tmp_txt[i + 3] = u8(0xFF)
569 } else {
570 col := if ((x + y) & 1) == 1 { 0xFF } else { 128 }
571 tmp_txt[i + 0] = u8(col) // red
572 tmp_txt[i + 1] = u8(col) // green
573 tmp_txt[i + 2] = u8(col) // blue
574 tmp_txt[i + 3] = u8(0xFF) // alpha
575 }
576 i += 4
577 }
578 }
579 app.texture, app.sampler = create_texture(w, h, tmp_txt)
580 unsafe { free(tmp_txt) }
581
582 // glsl
583 init_cube_glsl(mut app)
584 app.init_flag = true
585}
586
587/******************************************************************************
588* event
589******************************************************************************/
590fn my_event_manager(mut ev gg.Event, mut app App) {
591 if ev.typ == .mouse_move {
592 app.mouse_x = int(ev.mouse_x)
593 app.mouse_y = int(ev.mouse_y)
594 }
595 if ev.typ == .touches_began || ev.typ == .touches_moved {
596 if ev.num_touches > 0 {
597 touch_point := ev.touches[0]
598 app.mouse_x = int(touch_point.pos_x)
599 app.mouse_y = int(touch_point.pos_y)
600 }
601 }
602}
603
604fn main() {
605 // App init
606 mut app := &App{}
607
608 mut a := [5]int{}
609 a[0] = 2
610 println(a)
611
612 app.gg = gg.new_context(
613 width: win_width
614 height: win_height
615 create_window: true
616 window_title: '3D Cube Demo'
617 user_data: app
618 bg_color: bg_color
619 frame_fn: frame
620 init_fn: my_init
621 event_fn: my_event_manager
622 )
623
624 app.ticks = time.ticks()
625 app.gg.run()
626}
627