2021-02-12 02:42:10 +03:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
2021-02-15 16:40:28 +03:00
* Sokol 3 d cube multishader demo
2021-02-12 02:42:10 +03:00
*
* Copyright ( c ) 2021 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 :
2021-04-08 03:11:41 +03:00
* - download the sokol shader convertor tool from https : //github.com/floooh/sokol-tools-bin
*
2021-02-15 16:40:28 +03:00
* - compile the . glsl shared file with :
* linux : sokol - shdc -- input rt_glsl_puppy . glsl -- output rt_glsl_puppy . h -- slang glsl330
sokol - shdc -- input rt_glsl_march . glsl -- output rt_glsl_march . h -- slang glsl330
* windows : sokol - shdc . exe -- input rt_glsl_puppy . glsl -- output rt_glsl_puppy . h -- slang glsl330
* sokol - shdc . exe -- input rt_glsl_march . glsl -- output rt_glsl_march . h -- slang glsl330
2021-02-12 02:42:10 +03:00
*
* -- slang parameter can be :
* - glsl330 : desktop GL
* - glsl100 : GLES2 / WebGL
* - glsl300es : GLES3 / WebGL2
* - hlsl4 : D3D11
* - hlsl5 : D3D11
* - metal_macos : Metal on macOS
* - metal_ios : Metal on iOS device
* - metal_sim : Metal on iOS simulator
* - wgpu : WebGPU
*
* you can have multiple platforms at the same time passing parameters like this : -- slang glsl330 : hlsl5 : metal_macos
* for further infos have a look at the sokol shader tool docs .
*
* TODO :
* - frame counter
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
import gg
2021-02-15 16:40:28 +03:00
import gg . m4
2021-02-12 02:42:10 +03:00
import gx
2021-02-17 08:57:25 +03:00
// import math
2021-02-12 02:42:10 +03:00
import sokol . sapp
import sokol . gfx
import sokol . sgl
import time
2021-02-15 16:40:28 +03:00
// GLSL Include and functions
#flag -I @VROOT/.
# include "rt_glsl_march.h" #Please use sokol-shdc to generate the necessary rt_glsl_march.h file from rt_glsl_march.glsl (see the instructions at the top of this file)
# include "rt_glsl_puppy.h" #Please use sokol-shdc to generate the necessary rt_glsl_puppy.h file from rt_glsl_puppy.glsl (see the instructions at the top of this file)
2021-04-07 21:39:23 +03:00
fn C . rt_march_shader_desc ( gfx . Backend ) & C . sg_shader_desc
fn C . rt_puppy_shader_desc ( gfx . Backend ) & C . sg_shader_desc
2021-02-15 16:40:28 +03:00
2021-02-12 02:42:10 +03:00
const (
win_width = 800
win_height = 800
bg_color = gx . white
)
struct App {
mut :
2021-02-17 08:57:25 +03:00
gg & gg . Context
texture C . sg_image
init_flag bool
frame_count int
2021-02-18 12:11:26 +03:00
mouse_x int = - 1
mouse_y int = - 1
mouse_down bool
2021-02-12 02:42:10 +03:00
// glsl
2021-02-18 12:11:26 +03:00
cube_pip_glsl C . sg_pipeline
cube_bind C . sg_bindings
2021-02-17 08:57:25 +03:00
pipe map [ string ] C . sg_pipeline
bind map [ string ] C . sg_bindings
2021-02-12 02:42:10 +03:00
// time
2021-02-17 08:57:25 +03:00
ticks i64
2021-02-12 02:42:10 +03:00
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Texture functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2021-02-17 08:57:25 +03:00
fn create_texture ( w int , h int , buf byteptr ) C . sg_image {
2021-02-12 02:42:10 +03:00
sz := w * h * 4
mut img_desc := C . sg_image_desc {
2021-02-17 08:57:25 +03:00
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 : & byte ( 0 )
2021-02-12 02:42:10 +03:00
d3d11_texture : 0
}
// comment if .dynamic is enabled
2021-04-07 21:39:23 +03:00
img_desc . data . subimage [ 0 ] [ 0 ] = C . sg_range {
2021-02-17 08:57:25 +03:00
ptr : buf
2021-04-07 21:39:23 +03:00
size : size_t ( sz )
2021-02-12 02:42:10 +03:00
}
sg_img := C . sg_make_image ( & img_desc )
return sg_img
}
2021-02-17 08:57:25 +03:00
fn destroy_texture ( sg_img C . sg_image ) {
2021-02-12 02:42:10 +03:00
C . sg_destroy_image ( sg_img )
}
// Use only if usage: .dynamic is enabled
2021-02-17 08:57:25 +03:00
fn update_text_texture ( sg_img C . sg_image , w int , h int , buf byteptr ) {
2021-02-12 02:42:10 +03:00
sz := w * h * 4
2021-04-07 21:39:23 +03:00
mut tmp_sbc := C . sg_image_data { }
tmp_sbc . subimage [ 0 ] [ 0 ] = C . sg_range {
2021-02-12 02:42:10 +03:00
ptr : buf
2021-04-07 21:39:23 +03:00
size : size_t ( sz )
2021-02-12 02:42:10 +03:00
}
C . sg_update_image ( sg_img , & tmp_sbc )
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Draw functions
2021-02-18 12:11:26 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2021-02-17 08:57:25 +03:00
Cube vertex buffer with packed vertex formats for color and texture coords .
2021-02-12 02:42:10 +03:00
Note that a vertex format which must be portable across all
backends must only use the normalized integer formats
( BYTE4N , UBYTE4N , SHORT2N , SHORT4N ) , which can be converted
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 s u p p o r t i n t e g e r v e r t e x s h a d e r i n p u t s .
* /
struct Vertex_t {
2021-02-17 08:57:25 +03:00
x f32
y f32
z f32
color u32
// u u16 // for compatibility with D3D11
// v u16 // for compatibility with D3D11
u f32
v f32
2021-02-15 16:40:28 +03:00
}
2021-02-12 02:42:10 +03:00
2021-02-15 16:40:28 +03:00
// march shader init
fn init_cube_glsl_m ( mut app App ) {
2021-02-17 08:57:25 +03:00
// cube vertex buffer
// d := u16(32767) // for compatibility with D3D11, 32767 stand for 1
2021-02-12 02:42:10 +03:00
d := f32 ( 1.0 )
c := u32 ( 0xFFFFFF_FF ) // color RGBA8
2021-02-17 08:57:25 +03:00
vertices := [
2021-02-18 12:11:26 +03:00
// Face 0
Vertex_t { - 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
Vertex_t { 1.0 , - 1.0 , - 1.0 , c , d , 0 } ,
2021-03-25 18:53:13 +03:00
Vertex_t { 1.0 , 1.0 , - 1.0 , c , d , d } ,
Vertex_t { - 1.0 , 1.0 , - 1.0 , c , 0 , d } ,
2021-02-18 12:11:26 +03:00
// Face 1
Vertex_t { - 1.0 , - 1.0 , 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 2
Vertex_t { - 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 3
Vertex_t { 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 4
Vertex_t { - 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 5
Vertex_t { - 1.0 , 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-12 02:42:10 +03:00
]
mut vert_buffer_desc := C . sg_buffer_desc { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & vert_buffer_desc , 0 , sizeof ( vert_buffer_desc ) ) }
2021-04-07 21:39:23 +03:00
vert_buffer_desc . size = size_t ( vertices . len * int ( sizeof ( Vertex_t ) ) )
vert_buffer_desc . data = C . sg_range {
ptr : vertices . data
size : size_t ( vertices . len * int ( sizeof ( Vertex_t ) ) )
}
2021-02-17 08:57:25 +03:00
vert_buffer_desc . @ type = . vertexbuffer
vert_buffer_desc . label = ' c u b e - v e r t i c e s ' . str
2021-02-12 02:42:10 +03:00
vbuf := gfx . make_buffer ( & vert_buffer_desc )
2021-02-15 16:40:28 +03:00
2021-02-18 12:11:26 +03:00
/* create an index buffer for the cube */
2021-02-12 02:42:10 +03:00
indices := [
2021-02-18 12:11:26 +03:00
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 ,
2021-02-12 02:42:10 +03:00
16 , 17 , 18 , 16 , 18 , 19 ,
22 , 21 , 20 , 23 , 22 , 20
2021-02-18 12:11:26 +03:00
* /
2021-02-12 02:42:10 +03:00
]
2021-02-15 16:40:28 +03:00
2021-02-12 02:42:10 +03:00
mut index_buffer_desc := C . sg_buffer_desc { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & index_buffer_desc , 0 , sizeof ( index_buffer_desc ) ) }
2021-04-07 21:39:23 +03:00
index_buffer_desc . size = size_t ( indices . len * int ( sizeof ( u16 ) ) )
index_buffer_desc . data = C . sg_range {
ptr : indices . data
size : size_t ( indices . len * int ( sizeof ( u16 ) ) )
}
2021-02-17 08:57:25 +03:00
index_buffer_desc . @ type = . indexbuffer
index_buffer_desc . label = ' c u b e - i n d i c e s ' . str
2021-02-12 02:42:10 +03:00
ibuf := gfx . make_buffer ( & index_buffer_desc )
2021-02-15 16:40:28 +03:00
2021-02-17 08:57:25 +03:00
// create shader
2021-04-07 21:39:23 +03:00
shader := gfx . make_shader ( C . rt_march_shader_desc ( C . sg_query_backend ( ) ) )
2021-02-12 02:42:10 +03:00
mut pipdesc := C . sg_pipeline_desc { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & pipdesc , 0 , sizeof ( pipdesc ) ) }
2021-02-12 02:42:10 +03:00
pipdesc . layout . buffers [ 0 ] . stride = int ( sizeof ( Vertex_t ) )
2021-02-15 16:40:28 +03:00
// the constants [C.ATTR_vs_m_pos, C.ATTR_vs_m_color0, C.ATTR_vs_m_texcoord0] are generated by sokol-shdc
2021-02-18 12:11:26 +03:00
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
2021-02-17 08:57:25 +03:00
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
2021-02-15 16:40:28 +03:00
2021-02-12 02:42:10 +03:00
pipdesc . shader = shader
pipdesc . index_type = . uint16
2021-02-15 16:40:28 +03:00
2021-04-07 21:39:23 +03:00
pipdesc . depth = C . sg_depth_state {
write_enabled : true
compare : gfx . CompareFunc ( C . SG_COMPAREFUNC_LESS_EQUAL )
2021-02-12 02:42:10 +03:00
}
2021-04-07 21:39:23 +03:00
pipdesc . cull_mode = . back
2021-02-17 08:57:25 +03:00
pipdesc . label = ' g l s l _ s h a d e r p i p e l i n e ' . str
2021-02-15 16:40:28 +03:00
mut bind := C . sg_bindings { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & bind , 0 , sizeof ( bind ) ) }
2021-02-15 16:40:28 +03:00
bind . vertex_buffers [ 0 ] = vbuf
2021-02-17 08:57:25 +03:00
bind . index_buffer = ibuf
2021-02-15 16:40:28 +03:00
bind . fs_images [ C . SLOT_tex ] = app . texture
app . bind [ ' m a r c h ' ] = bind
app . pipe [ ' m a r c h ' ] = gfx . make_pipeline ( & pipdesc )
2021-02-17 08:57:25 +03:00
println ( ' G L S L M a r c h i n i t D O N E ! ' )
2021-02-12 02:42:10 +03:00
}
2021-02-15 16:40:28 +03:00
// putty shader init
fn init_cube_glsl_p ( mut app App ) {
2021-02-17 08:57:25 +03:00
// cube vertex buffer
// d := u16(32767) // for compatibility with D3D11, 32767 stand for 1
2021-02-15 16:40:28 +03:00
d := f32 ( 1.0 )
c := u32 ( 0xFFFFFF_FF ) // color RGBA8
2021-02-17 08:57:25 +03:00
vertices := [
2021-02-18 12:11:26 +03:00
// Face 0
Vertex_t { - 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
Vertex_t { 1.0 , - 1.0 , - 1.0 , c , d , 0 } ,
2021-03-25 18:53:13 +03:00
Vertex_t { 1.0 , 1.0 , - 1.0 , c , d , d } ,
Vertex_t { - 1.0 , 1.0 , - 1.0 , c , 0 , d } ,
2021-02-18 12:11:26 +03:00
// Face 1
Vertex_t { - 1.0 , - 1.0 , 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 2
Vertex_t { - 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 3
Vertex_t { 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 4
Vertex_t { - 1.0 , - 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-18 12:11:26 +03:00
// Face 5
Vertex_t { - 1.0 , 1.0 , - 1.0 , c , 0 , 0 } ,
2021-03-25 18:53:13 +03:00
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 } ,
2021-02-15 16:40:28 +03:00
]
mut vert_buffer_desc := C . sg_buffer_desc { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & vert_buffer_desc , 0 , sizeof ( vert_buffer_desc ) ) }
2021-04-07 21:39:23 +03:00
vert_buffer_desc . size = size_t ( vertices . len * int ( sizeof ( Vertex_t ) ) )
vert_buffer_desc . data = C . sg_range {
ptr : vertices . data
size : size_t ( vertices . len * int ( sizeof ( Vertex_t ) ) )
}
2021-02-17 08:57:25 +03:00
vert_buffer_desc . @ type = . vertexbuffer
vert_buffer_desc . label = ' c u b e - v e r t i c e s ' . str
2021-02-15 16:40:28 +03:00
vbuf := gfx . make_buffer ( & vert_buffer_desc )
2021-02-18 12:11:26 +03:00
/* create an index buffer for the cube */
2021-02-15 16:40:28 +03:00
indices := [
2021-02-18 12:11:26 +03:00
/ *
u16 ( 0 ) , 1 , 2 , 0 , 2 , 3 ,
2021-02-15 16:40:28 +03:00
6 , 5 , 4 , 7 , 6 , 4 ,
8 , 9 , 10 , 8 , 10 , 11 ,
2021-02-18 12:11:26 +03:00
* /
u16 ( 14 ) , 13 , 12 , 15 , 14 , 12 ,
16 , 17 , 18 , 16 , 18 , 19 ,
22 , 21 , 20 , 23 , 22 , 20
2021-02-15 16:40:28 +03:00
]
mut index_buffer_desc := C . sg_buffer_desc { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & index_buffer_desc , 0 , sizeof ( index_buffer_desc ) ) }
2021-04-07 21:39:23 +03:00
index_buffer_desc . size = size_t ( indices . len * int ( sizeof ( u16 ) ) )
index_buffer_desc . data = C . sg_range {
ptr : indices . data
size : size_t ( indices . len * int ( sizeof ( u16 ) ) )
}
2021-02-17 08:57:25 +03:00
index_buffer_desc . @ type = . indexbuffer
index_buffer_desc . label = ' c u b e - i n d i c e s ' . str
2021-02-15 16:40:28 +03:00
ibuf := gfx . make_buffer ( & index_buffer_desc )
2021-02-17 08:57:25 +03:00
// create shader
2021-04-07 21:39:23 +03:00
shader := gfx . make_shader ( C . rt_puppy_shader_desc ( C . sg_query_backend ( ) ) )
2021-02-15 16:40:28 +03:00
mut pipdesc := C . sg_pipeline_desc { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & pipdesc , 0 , sizeof ( pipdesc ) ) }
2021-02-15 16:40:28 +03:00
pipdesc . layout . buffers [ 0 ] . stride = int ( sizeof ( Vertex_t ) )
// the constants [C.ATTR_vs_p_pos, C.ATTR_vs_p_color0, C.ATTR_vs_p_texcoord0] are generated by sokol-shdc
2021-02-18 12:11:26 +03:00
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
2021-02-17 08:57:25 +03:00
// pipdesc.layout.attrs[C.ATTR_vs_p_texcoord0].format = .short2n // u,v as u16
2021-02-15 16:40:28 +03:00
pipdesc . shader = shader
pipdesc . index_type = . uint16
2021-04-07 21:39:23 +03:00
pipdesc . depth = C . sg_depth_state {
write_enabled : true
compare : gfx . CompareFunc ( C . SG_COMPAREFUNC_LESS_EQUAL )
2021-02-15 16:40:28 +03:00
}
2021-04-07 21:39:23 +03:00
pipdesc . cull_mode = . back
2021-02-17 08:57:25 +03:00
pipdesc . label = ' g l s l _ s h a d e r p i p e l i n e ' . str
2021-02-15 16:40:28 +03:00
mut bind := C . sg_bindings { }
2021-02-17 08:57:25 +03:00
unsafe { C . memset ( & bind , 0 , sizeof ( bind ) ) }
2021-02-15 16:40:28 +03:00
bind . vertex_buffers [ 0 ] = vbuf
2021-02-17 08:57:25 +03:00
bind . index_buffer = ibuf
2021-02-15 16:40:28 +03:00
bind . fs_images [ C . SLOT_tex ] = app . texture
app . bind [ ' p u p p y ' ] = bind
app . pipe [ ' p u p p y ' ] = gfx . make_pipeline ( & pipdesc )
2021-02-17 08:57:25 +03:00
println ( ' G L S L P u p p y i n i t D O N E ! ' )
2021-02-15 16:40:28 +03:00
}
2021-04-07 21:39:23 +03:00
[ inline ]
2021-02-18 12:11:26 +03:00
fn vec4 ( x f32 , y f32 , z f32 , w f32 ) m4 . Vec4 {
return m4 . Vec4 { e : [ x , y , z , w ] ! }
}
2021-02-17 08:57:25 +03:00
fn calc_tr_matrices ( w f32 , h f32 , rx f32 , ry f32 , in_scale f32 ) m4 . Mat4 {
2021-02-18 12:11:26 +03:00
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 ) )
2021-02-15 16:40:28 +03:00
view_proj := view * proj
2021-02-18 12:11:26 +03:00
rxm := m4 . rotate ( m4 . rad ( rx ) , vec4 ( f32 ( 1 ) , 0 , 0 , 0 ) )
rym := m4 . rotate ( m4 . rad ( ry ) , vec4 ( f32 ( 0 ) , 1 , 0 , 0 ) )
2021-02-15 16:40:28 +03:00
2021-02-18 12:11:26 +03:00
model := rym * rxm
scale_m := m4 . scale ( vec4 ( in_scale , in_scale , in_scale , 1 ) )
2021-02-15 16:40:28 +03:00
2021-02-18 12:11:26 +03:00
res := ( scale_m * model ) * view_proj
2021-02-15 16:40:28 +03:00
return res
}
// march triangles draw
2021-02-17 08:57:25 +03:00
fn draw_cube_glsl_m ( app App ) {
2021-02-12 02:42:10 +03:00
if app . init_flag == false {
return
}
2021-02-28 00:11:26 +03:00
ws := gg . window_size_real_pixels ( )
2021-02-12 02:42:10 +03:00
ratio := f32 ( ws . width ) / ws . height
2021-02-17 08:57:25 +03:00
dw := f32 ( ws . width / 2 )
2021-02-12 02:42:10 +03:00
dh := f32 ( ws . height / 2 )
2021-02-15 16:40:28 +03:00
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 [ ' m a r c h ' ] )
gfx . apply_bindings ( app . bind [ ' m a r c h ' ] )
// Uniforms
2021-02-18 12:11:26 +03:00
// *** vertex shadeer uniforms ***
2021-02-15 16:40:28 +03:00
// passing the view matrix as uniform
// res is a 4x4 matrix of f32 thus: 4*16 byte of size
2021-04-07 21:39:23 +03:00
vs_uniforms_range := C . sg_range {
ptr : & tr_matrix
size : size_t ( 4 * 16 )
}
gfx . apply_uniforms ( C . SG_SHADERSTAGE_VS , C . SLOT_vs_params_m , & vs_uniforms_range )
2021-02-15 16:40:28 +03:00
2021-02-18 12:11:26 +03:00
// *** fragment shader uniforms ***
2021-02-15 16:40:28 +03:00
time_ticks := f32 ( time . ticks ( ) - app . ticks ) / 1000
mut tmp_fs_params := [
2021-02-17 08:57:25 +03:00
f32 ( ws . width ) ,
2021-02-18 12:11:26 +03:00
ws . height * ratio , // x,y resolution to pass to FS
2021-02-17 08:57:25 +03:00
0 ,
2021-02-18 12:11:26 +03:00
0 , // dont send mouse position
2021-02-17 08:57:25 +03:00
/* app.mouse_x, // mouse x */
/* ws.height - app.mouse_y*2, // mouse y scaled */
2021-02-18 12:11:26 +03:00
time_ticks , // time as f32
app . frame_count , // frame count
2021-02-17 08:57:25 +03:00
0 ,
2021-02-18 12:11:26 +03:00
0 // padding bytes , see "fs_params" struct paddings in rt_glsl.h
2021-02-15 16:40:28 +03:00
] !
2021-04-07 21:39:23 +03:00
fs_uniforms_range := C . sg_range {
ptr : & tmp_fs_params
size : size_t ( sizeof ( tmp_fs_params ) )
}
gfx . apply_uniforms ( C . SG_SHADERSTAGE_FS , C . SLOT_fs_params_p , & fs_uniforms_range )
2021-02-15 16:40:28 +03:00
// 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw
gfx . draw ( 0 , ( 3 * 2 ) * 3 , 1 )
}
// puppy triangles draw
2021-02-17 08:57:25 +03:00
fn draw_cube_glsl_p ( app App ) {
2021-02-15 16:40:28 +03:00
if app . init_flag == false {
return
}
2021-02-28 00:11:26 +03:00
ws := gg . window_size_real_pixels ( )
2021-02-15 16:40:28 +03:00
ratio := f32 ( ws . width ) / ws . height
2021-02-17 08:57:25 +03:00
dw := f32 ( ws . width / 2 )
2021-02-15 16:40:28 +03:00
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 )
2021-02-12 02:42:10 +03:00
// apply the pipline and bindings
2021-02-15 16:40:28 +03:00
gfx . apply_pipeline ( app . pipe [ ' p u p p y ' ] )
gfx . apply_bindings ( app . bind [ ' p u p p y ' ] )
2021-02-12 02:42:10 +03:00
// Uniforms
2021-02-18 12:11:26 +03:00
// *** vertex shadeer uniforms ***
2021-02-12 02:42:10 +03:00
// passing the view matrix as uniform
// res is a 4x4 matrix of f32 thus: 4*16 byte of size
2021-04-07 21:39:23 +03:00
vs_uniforms_range := C . sg_range {
ptr : & tr_matrix
size : size_t ( 4 * 16 )
}
gfx . apply_uniforms ( C . SG_SHADERSTAGE_VS , C . SLOT_vs_params_p , & vs_uniforms_range )
2021-02-15 16:40:28 +03:00
2021-02-18 12:11:26 +03:00
// *** fragment shader uniforms ***
2021-02-12 02:42:10 +03:00
time_ticks := f32 ( time . ticks ( ) - app . ticks ) / 1000
mut tmp_fs_params := [
2021-02-17 08:57:25 +03:00
f32 ( ws . width ) ,
2021-02-18 12:11:26 +03:00
ws . height * ratio , // x,y resolution to pass to FS
2021-02-17 08:57:25 +03:00
0 ,
2021-02-18 12:11:26 +03:00
0 , // dont send mouse position
2021-02-17 08:57:25 +03:00
/* app.mouse_x, // mouse x */
/* ws.height - app.mouse_y*2, // mouse y scaled */
2021-02-18 12:11:26 +03:00
time_ticks , // time as f32
app . frame_count , // frame count
2021-02-17 08:57:25 +03:00
0 ,
2021-02-18 12:11:26 +03:00
0 // padding bytes , see "fs_params" struct paddings in rt_glsl.h
2021-02-12 02:42:10 +03:00
] !
2021-04-07 21:39:23 +03:00
fs_uniforms_range := C . sg_range {
ptr : & tmp_fs_params
size : size_t ( sizeof ( tmp_fs_params ) )
}
gfx . apply_uniforms ( C . SG_SHADERSTAGE_FS , C . SLOT_fs_params_p , & fs_uniforms_range )
2021-02-15 16:40:28 +03:00
2021-02-12 02:42:10 +03:00
// 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw
2021-02-15 16:40:28 +03:00
gfx . draw ( 0 , ( 3 * 2 ) * 3 , 1 )
}
2021-02-17 08:57:25 +03:00
fn draw_start_glsl ( app App ) {
2021-02-15 16:40:28 +03:00
if app . init_flag == false {
return
}
2021-02-28 00:11:26 +03:00
ws := gg . window_size_real_pixels ( )
2021-02-17 08:57:25 +03:00
// ratio := f32(ws.width) / ws.height
// dw := f32(ws.width / 2)
// dh := f32(ws.height / 2)
2021-02-15 16:40:28 +03:00
gfx . apply_viewport ( 0 , 0 , ws . width , ws . height , true )
}
2021-02-17 08:57:25 +03:00
fn draw_end_glsl ( app App ) {
2021-02-12 02:42:10 +03:00
gfx . end_pass ( )
gfx . commit ( )
}
fn frame ( mut app App ) {
2021-02-28 00:11:26 +03:00
ws := gg . window_size_real_pixels ( )
2021-02-12 02:42:10 +03:00
// clear
mut color_action := C . sg_color_attachment_action {
action : gfx . Action ( C . SG_ACTION_CLEAR )
2021-04-07 21:39:23 +03:00
value : C . sg_color {
r : 0.0
g : 0.0
b : 0.0
a : 1.0
}
2021-02-12 02:42:10 +03:00
}
mut pass_action := C . sg_pass_action { }
pass_action . colors [ 0 ] = color_action
gfx . begin_default_pass ( & pass_action , ws . width , ws . height )
2021-02-15 16:40:28 +03:00
2021-02-17 08:57:25 +03:00
/ *
2021-02-12 02:42:10 +03:00
// glsl cube
2021-02-15 16:40:28 +03:00
if app . frame_count % 1 == 1 {
draw_cube_glsl_m ( app )
} else {
draw_cube_glsl_p ( app )
}
2021-02-17 08:57:25 +03:00
* /
2021-02-15 16:40:28 +03:00
draw_start_glsl ( app )
2021-02-17 08:57:25 +03:00
draw_cube_glsl_m ( app )
draw_cube_glsl_p ( app )
2021-02-15 16:40:28 +03:00
draw_end_glsl ( app )
2021-02-12 02:42:10 +03:00
app . frame_count ++
2021-02-15 16:40:28 +03:00
}
2021-02-12 02:42:10 +03:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 := C . sgl_desc_t {
max_vertices : 50 * 65536
}
sgl . setup ( & sgl_desc )
// create chessboard texture 256*256 RGBA
w := 256
h := 256
sz := w * h * 4
2021-02-15 16:40:28 +03:00
tmp_txt := unsafe { malloc ( sz ) }
2021-02-12 02:42:10 +03:00
mut i := 0
for i < sz {
unsafe {
2021-02-17 08:57:25 +03:00
y := ( i >> 0x8 ) >> 5 // 8 cell
x := ( i & 0xFF ) >> 5 // 8 cell
2021-02-12 02:42:10 +03:00
// upper left corner
2021-02-17 08:57:25 +03:00
if x == 0 && y == 0 {
2021-02-18 12:11:26 +03:00
tmp_txt [ i + 0 ] = byte ( 0xFF )
2021-02-17 08:57:25 +03:00
tmp_txt [ i + 1 ] = byte ( 0 )
tmp_txt [ i + 2 ] = byte ( 0 )
tmp_txt [ i + 3 ] = byte ( 0xFF )
2021-02-12 02:42:10 +03:00
}
// low right corner
2021-02-17 08:57:25 +03:00
else if x == 7 && y == 7 {
2021-02-18 12:11:26 +03:00
tmp_txt [ i + 0 ] = byte ( 0 )
2021-02-17 08:57:25 +03:00
tmp_txt [ i + 1 ] = byte ( 0xFF )
tmp_txt [ i + 2 ] = byte ( 0 )
tmp_txt [ i + 3 ] = byte ( 0xFF )
2021-02-12 02:42:10 +03:00
} else {
2021-02-17 08:57:25 +03:00
col := if ( ( x + y ) & 1 ) == 1 { 0xFF } else { 128 }
2021-02-18 12:11:26 +03:00
tmp_txt [ i + 0 ] = byte ( col ) // red
tmp_txt [ i + 1 ] = byte ( col ) // green
tmp_txt [ i + 2 ] = byte ( col ) // blue
2021-02-17 08:57:25 +03:00
tmp_txt [ i + 3 ] = byte ( 0xFF ) // alpha
2021-02-12 02:42:10 +03:00
}
i += 4
}
}
2021-02-15 16:40:28 +03:00
app . texture = create_texture ( w , h , tmp_txt )
unsafe { free ( tmp_txt ) }
2021-02-12 02:42:10 +03:00
// glsl
2021-02-15 16:40:28 +03:00
init_cube_glsl_m ( mut app )
init_cube_glsl_p ( mut app )
2021-02-12 02:42:10 +03:00
app . init_flag = true
}
fn cleanup ( mut app App ) {
gfx . shutdown ( )
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2021-02-18 12:11:26 +03:00
* events handling
2021-02-12 02:42:10 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2021-02-17 08:57:25 +03:00
fn my_event_manager ( mut ev gg . Event , mut app App ) {
if ev . typ == . mouse_down {
2021-02-15 16:40:28 +03:00
app . mouse_down = true
}
2021-02-17 08:57:25 +03:00
if ev . typ == . mouse_up {
2021-02-15 16:40:28 +03:00
app . mouse_down = false
}
if app . mouse_down == true && ev . typ == . mouse_move {
2021-02-12 02:42:10 +03:00
app . mouse_x = int ( ev . mouse_x )
app . mouse_y = int ( ev . mouse_y )
}
if ev . typ == . touches_began || ev . typ == . touches_moved {
if ev . num_touches > 0 {
touch_point := ev . touches [ 0 ]
app . mouse_x = int ( touch_point . pos_x )
app . mouse_y = int ( touch_point . pos_y )
}
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Main
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2021-02-18 12:11:26 +03:00
[ console ] // is needed for easier diagnostics on windows
2021-02-17 08:57:25 +03:00
fn main ( ) {
2021-02-12 02:42:10 +03:00
// App init
mut app := & App {
gg : 0
}
2021-02-17 08:57:25 +03:00
app . gg = gg . new_context (
width : win_width
height : win_height
use_ortho : true // This is needed for 2D drawing
2021-02-12 02:42:10 +03:00
create_window : true
2021-02-18 12:11:26 +03:00
window_title : ' 3 D D u a l s h a d e r C u b e - c l i c k a n d r o t a t e w i t h t h e m o u s e '
2021-02-17 08:57:25 +03:00
user_data : app
bg_color : bg_color
frame_fn : frame
init_fn : my_init
cleanup_fn : cleanup
event_fn : my_event_manager
)
2021-02-12 02:42:10 +03:00
2021-02-15 16:40:28 +03:00
app . ticks = time . ticks ( )
2021-02-12 02:42:10 +03:00
app . gg . run ( )
}