@@ -7,141 +7,141 @@ pub mod shared_data;
7
7
8
8
// Compute optimal grid layout (rows, cols) for cell count while attempting to keep the aspect ratio close to the provided aspect ratio.
9
9
fn optimal_grid ( cell_count : usize , aspect : Vec2 ) -> ( usize , usize ) {
10
- // Handle edge cases for 0 or 1 cells.
11
- if cell_count == 0 {
12
- return ( 0 , 0 ) ;
13
- }
14
- if cell_count == 1 {
15
- return ( 1 , 1 ) ;
16
- }
17
-
18
- // The target aspect ratio (width / height). Add a small epsilon to avoid division by zero.
19
- let target_aspect = aspect. x / ( aspect. y + f32:: EPSILON ) ;
20
-
21
- let mut best_layout = ( 1 , cell_count) ;
22
- let mut min_aspect_diff = f32:: INFINITY ;
23
-
24
- // Iterate through all possible row counts from 1 to cell_count.
25
- // This is a simple and robust way to find the global optimum.
26
- for rows in 1 ..=cell_count {
27
- // Calculate the number of columns needed to fit all cells for the current row count.
28
- // This is equivalent to `ceil(cell_count / rows)`.
29
- let cols = cell_count. div_ceil ( rows) ;
30
-
31
- // The aspect ratio of the current grid layout.
32
- let grid_aspect = cols as f32 / rows as f32 ;
33
-
34
- // Calculate the difference from the target aspect ratio.
35
- let diff = ( grid_aspect - target_aspect) . abs ( ) ;
36
-
37
- // If this layout is better than the best one we've found so far, update it.
38
- if diff < min_aspect_diff {
39
- min_aspect_diff = diff;
40
- best_layout = ( rows, cols) ;
41
- }
10
+ // Handle edge cases for 0 or 1 cells.
11
+ if cell_count == 0 {
12
+ return ( 0 , 0 ) ;
13
+ }
14
+ if cell_count == 1 {
15
+ return ( 1 , 1 ) ;
16
+ }
17
+
18
+ // The target aspect ratio (width / height). Add a small epsilon to avoid division by zero.
19
+ let target_aspect = aspect. x / ( aspect. y + f32:: EPSILON ) ;
20
+
21
+ let mut best_layout = ( 1 , cell_count) ;
22
+ let mut min_aspect_diff = f32:: INFINITY ;
23
+
24
+ // Iterate through all possible row counts from 1 to cell_count.
25
+ // This is a simple and robust way to find the global optimum.
26
+ for rows in 1 ..=cell_count {
27
+ // Calculate the number of columns needed to fit all cells for the current row count.
28
+ // This is equivalent to `ceil(cell_count / rows)`.
29
+ let cols = cell_count. div_ceil ( rows) ;
30
+
31
+ // The aspect ratio of the current grid layout.
32
+ let grid_aspect = cols as f32 / rows as f32 ;
33
+
34
+ // Calculate the difference from the target aspect ratio.
35
+ let diff = ( grid_aspect - target_aspect) . abs ( ) ;
36
+
37
+ // If this layout is better than the best one we've found so far, update it.
38
+ if diff < min_aspect_diff {
39
+ min_aspect_diff = diff;
40
+ best_layout = ( rows, cols) ;
42
41
}
42
+ }
43
43
44
- best_layout
44
+ best_layout
45
45
}
46
46
47
47
#[ inline( always) ]
48
48
#[ must_use]
49
49
pub fn fs ( constants : & ShaderConstants , mut frag_coord : Vec2 ) -> Vec4 {
50
- let resolution = vec3 ( constants. width as f32 , constants. height as f32 , 0.0 ) ;
51
- let time = constants. time ;
52
- let mut mouse = vec4 (
53
- constants. drag_end_x ,
54
- constants. drag_end_y ,
55
- constants. drag_start_x ,
56
- constants. drag_start_y ,
50
+ let resolution = vec3 ( constants. width as f32 , constants. height as f32 , 0.0 ) ;
51
+ let time = constants. time ;
52
+ let mut mouse = vec4 (
53
+ constants. drag_end_x ,
54
+ constants. drag_end_y ,
55
+ constants. drag_start_x ,
56
+ constants. drag_start_y ,
57
+ ) ;
58
+ if mouse != Vec4 :: ZERO {
59
+ mouse. y = resolution. y - mouse. y ;
60
+ mouse. w = resolution. y - mouse. w ;
61
+ }
62
+ if constants. mouse_left_pressed != 1 {
63
+ mouse. z *= -1.0 ;
64
+ }
65
+ if constants. mouse_left_clicked != 1 {
66
+ mouse. w *= -1.0 ;
67
+ }
68
+
69
+ frag_coord. x %= resolution. x ;
70
+ frag_coord. y = resolution. y - frag_coord. y % resolution. y ;
71
+
72
+ let shader_count = shaders:: SHADER_DEFINITIONS . len ( ) ;
73
+
74
+ let shader_index;
75
+ let shader_input: ShaderInput ;
76
+ let shader_output = & mut ShaderResult { color : Vec4 :: ZERO } ;
77
+
78
+ if constants. grid_mode == 0 {
79
+ shader_input = ShaderInput {
80
+ resolution,
81
+ time,
82
+ frag_coord,
83
+ mouse,
84
+ } ;
85
+ shader_index = constants. shader_to_show as usize ;
86
+ } else {
87
+ // Render all shaders in a grid layout
88
+ // ignore shader_to_show
89
+ let ( rows, cols) = optimal_grid ( shader_count, vec2 ( resolution. x , resolution. y ) ) ;
90
+
91
+ let cell_width = resolution. x / cols as f32 ;
92
+ let cell_height = resolution. y / rows as f32 ;
93
+
94
+ #[ expect( clippy:: cast_sign_loss) ]
95
+ let col = ( frag_coord. x / cell_width) . floor ( ) as usize ;
96
+ #[ expect( clippy:: cast_sign_loss) ]
97
+ let row = ( frag_coord. y / cell_height) . floor ( ) as usize ;
98
+ shader_index = row + col * rows;
99
+
100
+ let cell_resolution = vec3 ( cell_width, cell_height, 0.0 ) ;
101
+ let cell_frag_coord = vec2 (
102
+ ( col as f32 ) . mul_add ( -cell_width, frag_coord. x ) ,
103
+ ( row as f32 ) . mul_add ( -cell_height, frag_coord. y ) ,
57
104
) ;
58
- if mouse != Vec4 :: ZERO {
59
- mouse. y = resolution. y - mouse. y ;
60
- mouse. w = resolution. y - mouse. w ;
61
- }
62
- if constants. mouse_left_pressed != 1 {
63
- mouse. z *= -1.0 ;
64
- }
65
- if constants. mouse_left_clicked != 1 {
66
- mouse. w *= -1.0 ;
67
- }
68
-
69
- frag_coord. x %= resolution. x ;
70
- frag_coord. y = resolution. y - frag_coord. y % resolution. y ;
71
-
72
- let shader_count = shaders:: SHADER_DEFINITIONS . len ( ) ;
73
-
74
- let shader_index;
75
- let shader_input: ShaderInput ;
76
- let shader_output = & mut ShaderResult { color : Vec4 :: ZERO } ;
77
-
78
- if constants. grid_mode == 0 {
79
- shader_input = ShaderInput {
80
- resolution,
81
- time,
82
- frag_coord,
83
- mouse,
84
- } ;
85
- shader_index = constants. shader_to_show as usize ;
86
- } else {
87
- // Render all shaders in a grid layout
88
- // ignore shader_to_show
89
- let ( rows, cols) = optimal_grid ( shader_count, vec2 ( resolution. x , resolution. y ) ) ;
90
-
91
- let cell_width = resolution. x / cols as f32 ;
92
- let cell_height = resolution. y / rows as f32 ;
93
-
94
- #[ expect( clippy:: cast_sign_loss) ]
95
- let col = ( frag_coord. x / cell_width) . floor ( ) as usize ;
96
- #[ expect( clippy:: cast_sign_loss) ]
97
- let row = ( frag_coord. y / cell_height) . floor ( ) as usize ;
98
- shader_index = row + col * rows;
99
-
100
- let cell_resolution = vec3 ( cell_width, cell_height, 0.0 ) ;
101
- let cell_frag_coord = vec2 (
102
- ( col as f32 ) . mul_add ( -cell_width, frag_coord. x ) ,
103
- ( row as f32 ) . mul_add ( -cell_height, frag_coord. y ) ,
104
- ) ;
105
- let cell_mouse = mouse / vec4 ( cols as f32 , rows as f32 , cols as f32 , rows as f32 ) ;
106
-
107
- shader_input = ShaderInput {
108
- resolution : cell_resolution,
109
- time,
110
- frag_coord : cell_frag_coord,
111
- mouse : cell_mouse,
112
- } ;
113
- }
114
-
115
- if shader_index < shader_count {
116
- shaders:: render_shader ( shader_index as u32 , & shader_input, shader_output) ;
117
- } else {
118
- // If the shader index is out of bounds, just return a default color
119
- shader_output. color = Vec4 :: new ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
120
- }
121
-
122
- let color = shader_output. color ;
123
- Vec3 :: powf ( color. truncate ( ) , 2.2 ) . extend ( color. w )
105
+ let cell_mouse = mouse / vec4 ( cols as f32 , rows as f32 , cols as f32 , rows as f32 ) ;
106
+
107
+ shader_input = ShaderInput {
108
+ resolution : cell_resolution,
109
+ time,
110
+ frag_coord : cell_frag_coord,
111
+ mouse : cell_mouse,
112
+ } ;
113
+ }
114
+
115
+ if shader_index < shader_count {
116
+ shaders:: render_shader ( shader_index as u32 , & shader_input, shader_output) ;
117
+ } else {
118
+ // If the shader index is out of bounds, just return a default color
119
+ shader_output. color = Vec4 :: new ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
120
+ }
121
+
122
+ let color = shader_output. color ;
123
+ Vec3 :: powf ( color. truncate ( ) , 2.2 ) . extend ( color. w )
124
124
}
125
125
126
126
#[ allow( unused_attributes) ]
127
127
#[ spirv( fragment) ]
128
128
pub fn main_fs (
129
- #[ spirv( frag_coord) ] in_frag_coord : Vec4 ,
130
- #[ spirv( push_constant) ] constants : & ShaderConstants ,
131
- output : & mut Vec4 ,
129
+ #[ spirv( frag_coord) ] in_frag_coord : Vec4 ,
130
+ #[ spirv( push_constant) ] constants : & ShaderConstants ,
131
+ output : & mut Vec4 ,
132
132
) {
133
- let frag_coord = vec2 ( in_frag_coord. x , in_frag_coord. y ) ;
134
- let color = fs ( constants, frag_coord) ;
135
- * output = color;
133
+ let frag_coord = vec2 ( in_frag_coord. x , in_frag_coord. y ) ;
134
+ let color = fs ( constants, frag_coord) ;
135
+ * output = color;
136
136
}
137
137
138
138
#[ allow( unused_attributes) ]
139
139
#[ spirv( vertex) ]
140
140
pub fn main_vs ( #[ spirv( vertex_index) ] vert_idx : i32 , #[ spirv( position) ] builtin_pos : & mut Vec4 ) {
141
- // Create a "full screen triangle" by mapping the vertex index.
142
- // ported from https://www.saschawillems.de/blog/2016/08/13/vulkan-tutorial-on-rendering-a-fullscreen-quad-without-buffers/
143
- let uv = vec2 ( ( ( vert_idx << 1 ) & 2 ) as f32 , ( vert_idx & 2 ) as f32 ) ;
144
- let pos = 2.0 * uv - Vec2 :: ONE ;
141
+ // Create a "full screen triangle" by mapping the vertex index.
142
+ // ported from https://www.saschawillems.de/blog/2016/08/13/vulkan-tutorial-on-rendering-a-fullscreen-quad-without-buffers/
143
+ let uv = vec2 ( ( ( vert_idx << 1 ) & 2 ) as f32 , ( vert_idx & 2 ) as f32 ) ;
144
+ let pos = 2.0 * uv - Vec2 :: ONE ;
145
145
146
- * builtin_pos = pos. extend ( 0.0 ) . extend ( 1.0 ) ;
146
+ * builtin_pos = pos. extend ( 0.0 ) . extend ( 1.0 ) ;
147
147
}
0 commit comments