gs_quad_batch.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #ifndef __GS_QUAD_BATCH_H__
  2. #define __GS_QUAD_BATCH_H__
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #include "base/gs_engine.h"
  7. #include "graphics/gs_graphics.h"
  8. #include "graphics/gs_mesh.h"
  9. #include "math/gs_math.h"
  10. _force_inline
  11. const char* __gs_default_quad_batch_vertex_src()
  12. {
  13. return "#version 330 core\n"
  14. "layout(location = 0) in vec3 a_pos;\n"
  15. "layout(location = 1) in vec2 a_uv;\n"
  16. "layout(location = 2) in vec4 a_color;\n"
  17. "uniform mat4 u_model;\n"
  18. "uniform mat4 u_view;\n"
  19. "uniform mat4 u_proj;\n"
  20. "out vec2 uv;\n"
  21. "out vec4 color;\n"
  22. "void main()\n"
  23. "{\n"
  24. " gl_Position = u_proj * u_view * u_model * vec4(a_pos, 1.0);\n"
  25. " uv = a_uv;\n"
  26. " color = a_color;\n"
  27. "}";
  28. }
  29. #define gs_quad_batch_default_vertex_src\
  30. __gs_default_quad_batch_vertex_src()
  31. _force_inline
  32. const char* __gs_default_quad_batch_frag_src()
  33. {
  34. return "#version 330 core\n"
  35. "uniform sampler2D u_tex;\n"
  36. "in vec2 uv;\n"
  37. "in vec4 color;\n"
  38. "out vec4 frag_color;\n"
  39. "void main()\n"
  40. "{\n"
  41. " frag_color = color * texture(u_tex, uv);\n"
  42. "}";
  43. }
  44. #define gs_quad_batch_default_frag_src\
  45. __gs_default_quad_batch_frag_src()
  46. typedef struct gs_quad_batch_t
  47. {
  48. gs_byte_buffer raw_vertex_data;
  49. gs_mesh_t mesh;
  50. gs_resource( gs_material ) material;
  51. } gs_quad_batch_t;
  52. // Default quad vertex structure
  53. // Define your own to match custom materials
  54. typedef struct gs_quad_batch_default_vert_t
  55. {
  56. gs_vec3 position;
  57. gs_vec2 uv;
  58. gs_vec4 color;
  59. } gs_quad_batch_default_vert_t;
  60. typedef struct gs_quad_batch_vert_into_t
  61. {
  62. gs_dyn_array( gs_vertex_attribute_type ) layout;
  63. } gs_quad_batch_vert_info_t;
  64. // Generic api for submitting custom data for a quad batch
  65. /*
  66. Quad Batch API
  67. * Common functionality for quad batch
  68. * To define CUSTOM functionality, override specific function and information for API:
  69. - gs_quad_batch_i.shader: gs_resource( gs_shader )
  70. * Default shader used for quad batch material
  71. * Define custom vertex/fragment source and then set this shader to construct materials for batches
  72. - gs_quad_batch_i.vert_info: gs_quad_batch_vert_info_t
  73. * Holds a gs_dyn_array( gs_vertex_attribute_type ) for the vertex layout
  74. * Initialized by default
  75. * Reset this layout and then pass in custom vertex information for your custom shader and mesh layout
  76. - gs_quad_batch_i.add: func
  77. * This function requires certain parameters, and you can override this functionality with your specific data
  78. for adding information into the batch
  79. * vertex_data: void*
  80. - all the data used for your add function
  81. * data_size: usize
  82. - total size of data
  83. * I hope to make this part of the interface nicer in the future, but for now, this'll have to do.
  84. */
  85. typedef struct gs_quad_batch_i
  86. {
  87. gs_quad_batch_t ( * new )( gs_resource( gs_material ) );
  88. void ( * begin )( gs_quad_batch_t* );
  89. void ( * end )( gs_quad_batch_t* );
  90. void ( * add )( gs_quad_batch_t*, void* quad_data, usize data_size );
  91. void ( * submit )( gs_resource( gs_command_buffer ), gs_quad_batch_t* );
  92. void ( * free )( gs_quad_batch_t* );
  93. void ( * set_layout )( struct gs_quad_batch_i* api, void* layout, usize layout_size );
  94. void ( * set_shader )( struct gs_quad_batch_i* api, gs_resource( gs_shader ) );
  95. gs_resource( gs_shader ) shader;
  96. gs_quad_batch_vert_info_t vert_info;
  97. } gs_quad_batch_i;
  98. _force_inline
  99. gs_quad_batch_t __gs_quad_batch_default_new( gs_resource( gs_material ) mat )
  100. {
  101. gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
  102. gs_quad_batch_t qb = {0};
  103. qb.raw_vertex_data = gs_byte_buffer_new();
  104. qb.material = mat;
  105. // Calculate layout size from layout
  106. void* layout = (void*)gfx->quad_batch_i->vert_info.layout;
  107. u32 layout_count = gs_dyn_array_size( gfx->quad_batch_i->vert_info.layout );
  108. // The data for will be empty for now
  109. qb.mesh.vbo = gfx->construct_vertex_buffer( layout, layout_count, NULL, 0 );
  110. return qb;
  111. }
  112. _force_inline
  113. void __gs_quad_batch_default_begin( gs_quad_batch_t* batch )
  114. {
  115. // Reset position of vertex data
  116. gs_byte_buffer_clear( &batch->raw_vertex_data );
  117. batch->mesh.vertex_count = 0;
  118. }
  119. typedef struct gs_default_quad_info_t
  120. {
  121. gs_vqs transform;
  122. gs_vec4 uv;
  123. gs_vec4 color;
  124. } gs_default_quad_info_t;
  125. _force_inline
  126. void __gs_quad_batch_add_raw_vert_data( gs_quad_batch_t* qb, void* data, usize data_size )
  127. {
  128. gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
  129. gs_quad_batch_i* qbi = gfx->quad_batch_i;
  130. // Calculate layout size from layout
  131. void* layout = (void*)qbi->vert_info.layout;
  132. u32 layout_count = gs_dyn_array_size( qbi->vert_info.layout );
  133. // Calculate vert size
  134. usize vert_size = gfx->calculate_vertex_size_in_bytes( layout, layout_count );
  135. // In here, you need to know how to read/structure your data to parse the package
  136. u32 vert_count = data_size / vert_size;
  137. gs_byte_buffer_bulk_write( &qb->raw_vertex_data, data, data_size );
  138. qb->mesh.vertex_count += vert_count;
  139. }
  140. _force_inline
  141. void __gs_quad_batch_default_add( gs_quad_batch_t* qb, void* quad_info_data, usize quad_info_data_size )
  142. {
  143. gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
  144. gs_default_quad_info_t* quad_info = (gs_default_quad_info_t*)(quad_info_data);
  145. if ( !quad_info ) {
  146. gs_assert( false );
  147. }
  148. gs_vqs transform = quad_info->transform;
  149. gs_vec4 uv = quad_info->uv;
  150. gs_vec4 color = quad_info->color;
  151. // Add as many vertices as you want into the batch...should I perhaps just call this a triangle batch instead?
  152. // For now, no rotation (just position and scale)
  153. gs_mat4 model = gs_vqs_to_mat4( &transform );
  154. gs_vec3 _tl = (gs_vec3){-0.5f, -0.5f, 0.f};
  155. gs_vec3 _tr = (gs_vec3){ 0.5f, -0.5f, 0.f};
  156. gs_vec3 _bl = (gs_vec3){-0.5f, 0.5f, 0.f};
  157. gs_vec3 _br = (gs_vec3){ 0.5f, 0.5f, 0.f};
  158. gs_vec4 position = {0};
  159. gs_quad_batch_default_vert_t tl = {0};
  160. gs_quad_batch_default_vert_t tr = {0};
  161. gs_quad_batch_default_vert_t bl = {0};
  162. gs_quad_batch_default_vert_t br = {0};
  163. // Top Left
  164. position = gs_mat4_mul_vec4( model, (gs_vec4){_tl.x, _tl.y, _tl.z, 1.0f} );
  165. position = gs_vec4_scale( position, 1.0f / position.w );
  166. tl.position = (gs_vec3){position.x, position.y, position.z};
  167. tl.uv = (gs_vec2){uv.x, uv.y};
  168. tl.color = color;
  169. // Top Right
  170. position = gs_mat4_mul_vec4( model, (gs_vec4){_tr.x, _tr.y, _tr.z, 1.0f} );
  171. position = gs_vec4_scale( position, 1.0f / position.w );
  172. tr.position = (gs_vec3){position.x, position.y, position.z};
  173. tr.uv = (gs_vec2){uv.z, uv.y};
  174. tr.color = color;
  175. // Bottom Left
  176. position = gs_mat4_mul_vec4( model, (gs_vec4){_bl.x, _bl.y, _bl.z, 1.0f} );
  177. position = gs_vec4_scale( position, 1.0f / position.w );
  178. bl.position = (gs_vec3){position.x, position.y, position.z};
  179. bl.uv = (gs_vec2){uv.x, uv.w};
  180. bl.color = color;
  181. // Bottom Right
  182. position = gs_mat4_mul_vec4( model, (gs_vec4){_br.x, _br.y, _br.z, 1.0f} );
  183. position = gs_vec4_scale( position, 1.0f / position.w );
  184. br.position = (gs_vec3){position.x, position.y, position.z};
  185. br.uv = (gs_vec2){uv.z, uv.w};
  186. br.color = color;
  187. gs_quad_batch_default_vert_t verts[] = {
  188. tl, br, bl, tl, tr, br
  189. };
  190. __gs_quad_batch_add_raw_vert_data( qb, verts, sizeof(verts) );
  191. }
  192. _force_inline
  193. void __gs_quad_batch_default_end( gs_quad_batch_t* batch )
  194. {
  195. gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
  196. gfx->update_vertex_buffer_data( batch->mesh.vbo, batch->raw_vertex_data.buffer, batch->raw_vertex_data.size );
  197. }
  198. _force_inline
  199. void __gs_quad_batch_default_free( gs_quad_batch_t* batch )
  200. {
  201. // Free byte buffer
  202. gs_byte_buffer_free( &batch->raw_vertex_data );
  203. }
  204. _force_inline
  205. void __gs_quad_batch_default_submit( gs_resource( gs_command_buffer ) cb, gs_quad_batch_t* batch )
  206. {
  207. gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
  208. // Bind material shader
  209. gfx->bind_material_shader( cb, batch->material );
  210. // Not liking this too much...
  211. gfx->bind_material_uniforms( cb, batch->material );
  212. // Bind quad batch mesh vbo
  213. gfx->bind_vertex_buffer( cb, batch->mesh.vbo );
  214. // Draw
  215. gfx->draw( cb, 0, batch->mesh.vertex_count );
  216. }
  217. _force_inline
  218. void __gs_quad_batch_i_set_layout( gs_quad_batch_i* api, void* layout, usize layout_size )
  219. {
  220. gs_dyn_array_clear( api->vert_info.layout );
  221. u32 count = layout_size / sizeof(gs_vertex_attribute_type);
  222. gs_for_range_i( count )
  223. {
  224. gs_dyn_array_push( api->vert_info.layout, ((gs_vertex_attribute_type*)layout)[i] );
  225. }
  226. }
  227. _force_inline
  228. void __gs_quad_batch_i_set_shader( gs_quad_batch_i* api, gs_resource( gs_shader ) shader )
  229. {
  230. gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
  231. // Free previous shader
  232. gfx->free_shader( api->shader );
  233. api->shader = shader;
  234. }
  235. _force_inline
  236. gs_quad_batch_i __gs_quad_batch_i_new()
  237. {
  238. gs_quad_batch_i api = {0};
  239. api.begin = &__gs_quad_batch_default_begin;
  240. api.end = &__gs_quad_batch_default_end;
  241. api.add = &__gs_quad_batch_default_add;
  242. api.begin = &__gs_quad_batch_default_begin;
  243. api.new = &__gs_quad_batch_default_new;
  244. api.free = &__gs_quad_batch_default_free;
  245. api.submit = &__gs_quad_batch_default_submit;
  246. api.set_layout = &__gs_quad_batch_i_set_layout;
  247. api.set_shader = &__gs_quad_batch_i_set_shader;
  248. api.vert_info.layout = gs_dyn_array_new( gs_vertex_attribute_type );
  249. gs_dyn_array_push( api.vert_info.layout, gs_vertex_attribute_float3 ); // Position
  250. gs_dyn_array_push( api.vert_info.layout, gs_vertex_attribute_float2 ); // UV
  251. gs_dyn_array_push( api.vert_info.layout, gs_vertex_attribute_float4 ); // Color
  252. return api;
  253. }
  254. #ifdef __cplusplus
  255. }
  256. #endif // c++
  257. #endif // __GS_QUAD_BATCH_H__