· 5 years ago · Jul 24, 2020, 11:08 PM
1#include <gs.h>
2
3/*===================
4// Useful Defines
5===================*/
6
7#define char_buffer( name, size )\
8 char name[size];\
9 memset(name, 0, size);
10
11#define v4( _x, _y, _z, _w )\
12 (gs_vec4){ _x, _y, _z, _w }
13
14#define v3( _x, _y, _z )\
15 (gs_vec3){ _x, _y, _z }
16
17#define v2( _x, _y )\
18 (gs_vec2){ _x, _y }
19
20#define color( _r, _g, _b, _a )\
21 (gs_color){ _r, _g, _b, _a }
22
23/*===================
24// Material
25===================*/
26
27typedef gs_resource( gs_texture ) gs_texture_resource;
28
29#define gs_uniform_decl( T, name )\
30 typedef struct gs_uniform_##name##_t\
31 {\
32 gs_resource( gs_uniform ) handle;\
33 T value;\
34 u32 slot;\
35 } gs_uniform_##name##_t;
36
37gs_uniform_decl( gs_texture_resource, texture );
38gs_uniform_decl( gs_mat4, mat4 );
39gs_uniform_decl( gs_vec4, vec4 );
40gs_uniform_decl( gs_vec3, vec3 );
41gs_uniform_decl( gs_vec2, vec2 );
42gs_uniform_decl( float, float );
43gs_uniform_decl( int, int );
44
45gs_slot_array_decl( gs_uniform_texture_t );
46gs_slot_array_decl( gs_uniform_mat4_t );
47gs_slot_array_decl( gs_uniform_vec4_t );
48gs_slot_array_decl( gs_uniform_vec3_t );
49gs_slot_array_decl( gs_uniform_vec2_t );
50gs_slot_array_decl( gs_uniform_float_t );
51gs_slot_array_decl( gs_uniform_int_t );
52
53typedef struct gs_uniform_block_t
54{
55 gs_slot_array( gs_uniform_texture_t ) uniform_texture;
56 gs_slot_array( gs_uniform_mat4_t ) uniform_mat4;
57 gs_slot_array( gs_uniform_vec4_t ) uniform_vec4;
58 gs_slot_array( gs_uniform_vec3_t ) uniform_vec3;
59 gs_slot_array( gs_uniform_vec2_t ) uniform_vec2;
60 gs_slot_array( gs_uniform_float_t ) uniform_float;
61 gs_slot_array( gs_uniform_int_t ) uniform_int;
62 gs_hash_table( u64, u32 ) uniform_ids; // -> go from name to id
63} gs_uniform_block_t;
64
65gs_uniform_block_t gs_uniform_block_new()
66{
67 gs_uniform_block_t block = {0};
68 block.uniform_texture = gs_slot_array_new( gs_uniform_texture_t );
69 block.uniform_mat4 = gs_slot_array_new( gs_uniform_mat4_t );
70 block.uniform_vec4 = gs_slot_array_new( gs_uniform_vec4_t );
71 block.uniform_vec3 = gs_slot_array_new( gs_uniform_vec3_t );
72 block.uniform_vec2 = gs_slot_array_new( gs_uniform_vec2_t );
73 block.uniform_float = gs_slot_array_new( gs_uniform_float_t );
74 block.uniform_int = gs_slot_array_new( gs_uniform_int_t );
75 block.uniform_ids = gs_hash_table_new( u64, u32 );
76
77 return block;
78}
79
80// Could be something as simple as this?...
81typedef struct gs_material_t
82{
83 gs_resource( gs_shader ) shader;
84 gs_uniform_block_t uniforms;
85} gs_material_t;
86
87#define __gs_material_uniform_new( mat, __type, handle, hash, v, slot )\
88 do {\
89 gs_uniform_##__type##_t uniform;\
90 uniform.handle = handle;\
91 uniform.value = v;\
92 uniform.slot = slot;\
93 u32 id = gs_slot_array_insert( mat->uniforms.uniform_##__type, uniform );\
94 gs_hash_table_insert( mat->uniforms.uniform_ids, hash_id, id );\
95 } while (0);
96
97#define __gs_material_uniform_set_existing( mat, __type, hash, v, slot )\
98 do {\
99 u32 idx = gs_hash_table_get( mat->uniforms.uniform_ids, hash_id );\
100 gs_uniform_##__type##_t* uniform = &gs_slot_array_get( mat->uniforms.uniform_##__type, idx );\
101 uniform->value = v;\
102 uniform->slot = slot;\
103 } while (0);
104
105void __gs_material_set_uniform_internal( gs_material_t* mat, gs_uniform_type T, const char* name, void* value, u32 slot )
106{
107 gs_graphics_i* __gfx = gs_engine_instance()->ctx.graphics;
108 u64 hash_id = gs_hash_str_64( name );
109
110 /* Insert if not exists */
111 if ( !gs_hash_table_exists( mat->uniforms.uniform_ids, hash_id ) )
112 {
113 /* For now, just construct uniform */
114 gs_resource( gs_uniform ) handle = __gfx->construct_uniform( mat->shader, name, T );
115 switch ( T )
116 {
117 case gs_uniform_type_sampler2d: __gs_material_uniform_new( mat, texture, handle, hash_id, *(gs_resource(gs_texture)*)value, slot ); break;
118 case gs_uniform_type_mat4: __gs_material_uniform_new( mat, mat4, handle, hash_id, *(gs_mat4*)value, slot ); break;
119 case gs_uniform_type_vec4: __gs_material_uniform_new( mat, vec4, handle, hash_id, *(gs_vec4*)value, slot ); break;
120 case gs_uniform_type_vec3: __gs_material_uniform_new( mat, vec3, handle, hash_id, *(gs_vec3*)value, slot ); break;
121 case gs_uniform_type_vec2: __gs_material_uniform_new( mat, vec2, handle, hash_id, *(gs_vec2*)value, slot ); break;
122 case gs_uniform_type_float: __gs_material_uniform_new( mat, float, handle, hash_id, *(f32*)value, slot ); break;
123 case gs_uniform_type_int: __gs_material_uniform_new( mat, int, handle, hash_id, *(s32*)value, slot ); break;
124 }
125 }
126 else
127 {
128 switch ( T )
129 {
130 case gs_uniform_type_sampler2d: __gs_material_uniform_set_existing( mat, texture, hash_id, *(gs_resource(gs_texture)*)value, slot ); break;
131 case gs_uniform_type_mat4: __gs_material_uniform_set_existing( mat, mat4, hash_id, *(gs_mat4*)value, slot ); break;
132 case gs_uniform_type_vec4: __gs_material_uniform_set_existing( mat, vec4, hash_id, *(gs_vec4*)value, slot ); break;
133 case gs_uniform_type_vec3: __gs_material_uniform_set_existing( mat, vec3, hash_id, *(gs_vec3*)value, slot ); break;
134 case gs_uniform_type_vec2: __gs_material_uniform_set_existing( mat, vec2, hash_id, *(gs_vec2*)value, slot ); break;
135 case gs_uniform_type_float: __gs_material_uniform_set_existing( mat, float, hash_id, *(f32*)value, slot ); break;
136 case gs_uniform_type_int: __gs_material_uniform_set_existing( mat, int, hash_id, *(s32*)value, slot ); break;
137 }
138 }
139}
140
141#define gs_material_set_uniform( mat, uniform_type, name, value_type, value, slot )\
142 do {\
143 value_type __v = (value);\
144 __gs_material_set_uniform_internal( mat, uniform_type, name, &__v, slot );\
145 } while(0)
146
147gs_material_t gs_material_t_new( gs_resource( gs_shader ) shader )
148{
149 // I'd like a way to establish uniform blocks here automatically based on the shader, but that's fine for now...
150 gs_material_t mat = {0};
151 mat.shader = shader;
152 mat.uniforms = gs_uniform_block_new();
153 return mat;
154}
155
156#define __gs_material_bind_uniforms( cb, mat, T )\
157 do {\
158 gs_for_range_i( gs_slot_array_size( mat->uniforms.uniform_##T ) )\
159 {\
160 gs_uniform_##T##_t* uniform = &mat->uniforms.uniform_##T##.data[i];\
161 gfx->bind_uniform( cb, uniform->handle, &uniform->value );\
162 }\
163 } while(0)
164
165void gs_material_bind( gs_resource( gs_command_buffer ) cb, gs_material_t* mat )
166{
167 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
168
169 // Bind standard uniforms
170 __gs_material_bind_uniforms( cb, mat, mat4 );
171 __gs_material_bind_uniforms( cb, mat, vec4 );
172 __gs_material_bind_uniforms( cb, mat, vec3 );
173 __gs_material_bind_uniforms( cb, mat, vec2 );
174 __gs_material_bind_uniforms( cb, mat, float );
175 __gs_material_bind_uniforms( cb, mat, int );
176
177 // Bind textures
178 gs_for_range_i( gs_slot_array_size( mat->uniforms.uniform_texture ) )
179 {
180 gs_uniform_texture_t* uniform = &mat->uniforms.uniform_texture.data[i];
181 gfx->bind_texture( cb, uniform->handle, uniform->value, uniform->slot );
182 }
183}
184
185/*===================
186// Mesh
187===================*/
188
189typedef struct gs_mesh_t
190{
191 gs_resource( gs_vertex_buffer ) vbo;
192 u32 vertex_count;
193} gs_mesh_t;
194
195gs_mesh_t gs_mesh_t_new( gs_vertex_attribute_type* layout_data, u32 layout_size, void* v_data, usize v_data_size )
196{
197 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
198 gs_mesh_t mesh = {0};
199 mesh.vbo = gfx->construct_vertex_buffer( layout_data, layout_size, v_data, v_data_size );
200 mesh.vertex_count = v_data_size / sizeof(f32);
201 return mesh;
202}
203
204/*===================
205// Renderable
206===================*/
207
208typedef struct gs_renderable_t
209{
210 gs_mesh_t mesh; // Should be an asset handle
211 gs_material_t material;
212 gs_vqs transform;
213} gs_renderable_t;
214
215void gs_renderable_submit( gs_resource( gs_command_buffer ) cb, gs_renderable_t* renderable )
216{
217 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
218 gfx->bind_vertex_buffer( cb, renderable->mesh.vbo );
219 gfx->draw( cb, 0, renderable->mesh.vertex_count );
220}
221
222gs_renderable_t gs_renderable_new()
223{
224 gs_renderable_t renderable = {0};
225 renderable.transform = gs_vqs_default();
226 return renderable;
227}
228
229/*===================
230// Asset Subsystem
231===================*/
232
233// Hash table declaration for u64 hashed string id to texture id
234gs_hash_table_decl( u64, gs_texture_resource, gs_hash_u64, gs_hash_key_comp_std_type );
235
236typedef struct asset_subsystem_t
237{
238 gs_hash_table( u64, gs_texture_resource ) textures;
239} asset_subsystem_t;
240
241asset_subsystem_t asset_subsystem_new()
242{
243 asset_subsystem_t assets = {0};
244 assets.textures = gs_hash_table_new( u64, gs_texture_resource );
245 return assets;
246}
247
248void qualified_name_from_file( const char* file_path, char* buffer, usize sz )
249{
250 // Get file name
251 char_buffer(file_name, 256);
252 gs_util_get_file_name( file_name, sizeof(file_name), file_path );
253
254 // Remove / from file name
255 char_buffer(fnq, 256);
256 gs_util_string_remove_character( file_name, fnq, sizeof(fnq), '/' );
257
258 // Then get parent directory
259 char_buffer(dir, 256);
260 gs_util_get_dir_from_file( dir, sizeof(dir), file_path );
261
262 // Need to format parent directory now (remove all dots)
263 char_buffer(qd, 256);
264 gs_util_string_remove_character( dir, qd, sizeof(qd), '.' );
265
266 // Now need to replace all '/' with '.'
267 char_buffer(d, 256);
268 gs_util_string_replace( qd, d, sizeof(d), '/', '.' );
269
270 // Now need to combine file name with qualified directory
271 char_buffer(qual, 256);
272 gs_snprintf( qual, sizeof(qual), "%s%s", d, fnq );
273
274 // Then need to remove the first 8 characters of string (.assets.)
275 gs_util_string_substring( qual, buffer, sz, 8, gs_string_length( qual ) );
276
277 gs_println( "qualified name: %s", buffer );
278}
279
280void asset_subsystem_load_texture_from_file( asset_subsystem_t* assets, const char* file_path )
281{
282 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
283 gs_platform_i* platform = gs_engine_instance()->ctx.platform;
284
285 char_buffer(qualified_name, 256);
286 qualified_name_from_file( file_path, qualified_name, sizeof(qualified_name) );
287
288 // We'll assert if the file doesn't exist
289 gs_assert(platform->file_exists(file_path));
290
291 // Load texture from file and pass into description format
292 gs_texture_parameter_desc desc = gs_texture_parameter_desc_default();
293 desc.texture_wrap_s = gs_clamp_to_edge;
294 desc.texture_wrap_t = gs_clamp_to_edge;
295 desc.generate_mips = false;
296 desc.min_filter = gs_nearest;
297 desc.mag_filter = gs_nearest;
298
299 desc.data = gfx->load_texture_data_from_file( file_path, true, desc.texture_format, &desc.width,
300 &desc.height, &desc.num_comps );
301
302 // Construct GPU texture
303 gs_resource( gs_texture ) tex = gfx->construct_texture( desc );
304
305 // Free texture data
306 gs_free(desc.data);
307
308 // Insert texture into assets
309 gs_hash_table_insert( assets->textures, gs_hash_str_64( qualified_name ), tex );
310}
311
312gs_resource( gs_texture ) asset_subsystem_get_texture( asset_subsystem_t* assets, const char* name )
313{
314 u64 key = gs_hash_str_64( name );
315 if ( gs_hash_table_exists( assets->textures, key ) ) {
316
317 return gs_hash_table_get( assets->textures, key );
318 }
319
320 return (gs_resource( gs_texture )){0};
321}
322
323//========================================================================
324
325/*=============
326// Quad Batch
327==============*/
328
329const char* v_qb_src = "\n"
330"#version 110\n"
331"in vec3 a_pos;\n"
332"in vec2 a_uv;\n"
333"uniform mat4 u_model;\n"
334"uniform mat4 u_view;\n"
335"uniform mat4 u_proj;\n"
336"varying vec2 uv;\n"
337"void main()\n"
338"{\n"
339" gl_Position = u_proj * u_view * u_model * vec4(a_pos, 1.0);\n"
340" uv = a_uv;\n"
341"}";
342
343const char* f_qb_src = "\n"
344"#version 110\n"
345"uniform sampler2D u_tex;"
346"varying vec2 uv;\n"
347"void main()\n"
348"{\n"
349" gl_FragColor = texture2D(u_tex, uv);\n"
350"}";
351
352typedef struct gs_quad_batch_t
353{
354 gs_byte_buffer raw_vertex_data;
355 gs_mesh_t mesh;
356 gs_material_t material;
357} gs_quad_batch_t;
358
359// Generic api for submitting custom data for a quad batch
360typedef struct gs_quad_batch_api
361{
362 gs_quad_batch_t ( * new )();
363 void ( * begin )( gs_quad_batch_t* );
364 void ( * end )( gs_quad_batch_t* );
365 void ( * add )( gs_quad_batch_t*, void* vertex_data, usize data_size );
366 void ( * submit )( gs_resource( gs_command_buffer ), gs_quad_batch_t*, void* submit_data );
367 void ( * free )( gs_quad_batch_t* );
368} gs_quad_batch_api;
369
370// Custom Quad Batch API implementation
371typedef struct quad_vert_t
372{
373 gs_vec3 position;
374 gs_vec2 uv;
375} quad_vert_t;
376
377typedef struct quad_batch_submit_data_t
378{
379 gs_mat4 proj_mtx;
380 gs_mat4 view_mtx;
381 gs_resource( gs_uniform ) u_view;
382 gs_resource( gs_uniform ) u_proj;
383 gs_resource( gs_uniform ) u_model;
384} quad_batch_submit_data_t;
385
386gs_quad_batch_t __gs_quad_batch_new( gs_material_t mat )
387{
388 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
389
390 gs_quad_batch_t qb = {0};
391 qb.raw_vertex_data = gs_byte_buffer_new();
392 qb.material = mat;
393
394 // Vertex data layout for a sprite vertex
395 gs_vertex_attribute_type layout[] = {
396
397 gs_vertex_attribute_float3, // Position
398 gs_vertex_attribute_float2 // UV
399 };
400 // Count of our vertex attribute array
401 u32 layout_count = sizeof( layout ) / sizeof( gs_vertex_attribute_type );
402
403 // The data for will be empty for now
404 qb.mesh.vbo = gfx->construct_vertex_buffer( layout, layout_count, NULL, 0 );
405
406 return qb;
407}
408
409void __gs_quad_batch_begin( gs_quad_batch_t* batch )
410{
411 // Reset position of vertex data
412 gs_byte_buffer_clear( &batch->raw_vertex_data );
413 batch->mesh.vertex_count = 0;
414}
415
416void __gs_quad_batch_add( gs_quad_batch_t* batch, void* data, usize data_size )
417{
418 // In here, you need to know how to read/structure your data to parse the package
419 u32 vert_count = data_size / sizeof(quad_vert_t);
420 gs_byte_buffer_bulk_write( &batch->raw_vertex_data, data, data_size );
421 batch->mesh.vertex_count += vert_count;
422}
423
424void __gs_quad_batch_end( gs_quad_batch_t* batch )
425{
426 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
427 gfx->update_vertex_buffer_data( batch->mesh.vbo, batch->raw_vertex_data.buffer, batch->raw_vertex_data.size );
428}
429
430void __gs_quad_batch_free( gs_quad_batch_t* batch )
431{
432 // Free byte buffer
433 gs_byte_buffer_free( &batch->raw_vertex_data );
434}
435
436void __gs_quad_batch_submit( gs_resource( gs_command_buffer ) cb, gs_quad_batch_t* batch, void* submit_data )
437{
438 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
439
440 // Bind material shader
441 gfx->bind_shader( cb, batch->material.shader );
442
443 quad_batch_submit_data_t* sd = (quad_batch_submit_data_t*)submit_data;
444 gs_mat4 model = gs_mat4_identity();
445 gs_material_set_uniform( &batch->material, gs_uniform_type_mat4, "u_model", gs_mat4, model, 0 );
446 gs_material_set_uniform( &batch->material, gs_uniform_type_mat4, "u_view", gs_mat4, sd->view_mtx, 0 );
447 gs_material_set_uniform( &batch->material, gs_uniform_type_mat4, "u_proj", gs_mat4, sd->proj_mtx, 0 );
448
449 // Bind material
450 gs_material_bind( cb, &batch->material );
451
452 // Bind quad batch mesh vbo
453 gfx->bind_vertex_buffer( cb, batch->mesh.vbo );
454
455 // Draw
456 gfx->draw( cb, 0, batch->mesh.vertex_count );
457}
458
459gs_quad_batch_api __gs_construct_quad_batch_api()
460{
461 gs_quad_batch_api api = {0};
462 api.begin = &__gs_quad_batch_begin;
463 api.end = &__gs_quad_batch_end;
464 api.add = &__gs_quad_batch_add;
465 api.begin = &__gs_quad_batch_begin;
466 api.new = &__gs_quad_batch_new;
467 api.free = &__gs_quad_batch_free;
468 api.submit = &__gs_quad_batch_submit;
469 return api;
470}
471
472void gs_quad_batch_add( gs_quad_batch_api* api, gs_quad_batch_t* qb, gs_vqs transform, gs_vec4 uv )
473{
474 // For now, no rotation (just position and scale)
475 gs_mat4 model = gs_vqs_to_mat4( &transform );
476
477 gs_vec3 _tl = v3(-0.5f, -0.5f, 0.f);
478 gs_vec3 _tr = v3( 0.5f, -0.5f, 0.f);
479 gs_vec3 _bl = v3(-0.5f, 0.5f, 0.f);
480 gs_vec3 _br = v3( 0.5f, 0.5f, 0.f);
481 gs_vec4 position = {0};
482 quad_vert_t tl = {0};
483 quad_vert_t tr = {0};
484 quad_vert_t bl = {0};
485 quad_vert_t br = {0};
486
487 // Top Left
488 position = gs_mat4_mul_vec4( model, v4(_tl.x, _tl.y, _tl.z, 1.0f) );
489 position = gs_vec4_scale( position, 1.0f / position.w );
490 tl.position = v3(position.x, position.y, position.z);
491 tl.uv = v2(uv.x, uv.y);
492
493 // Top Right
494 position = gs_mat4_mul_vec4( model, v4(_tr.x, _tr.y, _tr.z, 1.0f) );
495 position = gs_vec4_scale( position, 1.0f / position.w );
496 tr.position = v3(position.x, position.y, position.z);
497 tr.uv = v2(uv.z, uv.y);
498
499 // Bottom Left
500 position = gs_mat4_mul_vec4( model, v4(_bl.x, _bl.y, _bl.z, 1.0f) );
501 position = gs_vec4_scale( position, 1.0f / position.w );
502 bl.position = v3(position.x, position.y, position.z);
503 bl.uv = v2(uv.x, uv.w);
504
505 // Bottom Right
506 position = gs_mat4_mul_vec4( model, v4(_br.x, _br.y, _br.z, 1.0f) );
507 position = gs_vec4_scale( position, 1.0f / position.w );
508 br.position = v3(position.x, position.y, position.z);
509 br.uv = v2(uv.z, uv.w);
510
511 api->add( qb, &tl, sizeof(tl) );
512 api->add( qb, &br, sizeof(br) );
513 api->add( qb, &bl, sizeof(bl) );
514 api->add( qb, &tl, sizeof(tl) );
515 api->add( qb, &tr, sizeof(tr) );
516 api->add( qb, &br, sizeof(br) );
517}
518
519/*
520 Quad Vertex Definition (can this be user defined)? Possibly? Just need to pass
521
522 Would like to be able to have a definition and utilities that could be used with custom user materials and vertex definitions
523 But not sure that's a possibility
524
525 Quad batch (single material)
526 typedef struct gs_quad_batch_t
527 {
528 gs_material_t material;
529 } gs_quad_batch_t;
530
531 quad_batch_begin();
532 quad_batch_end();
533 quad_batch_submit();
534*/
535
536/*======================
537// Sprite Batch Material
538======================*/
539
540const char* v_sb_src = "\n"
541"#version 110\n"
542"in vec2 a_pos;\n"
543"in vec2 a_uv;\n"
544"in vec4 a_color;\n"
545"uniform mat4 u_model;\n"
546"uniform mat4 u_view;\n"
547"uniform mat4 u_proj;\n"
548"varying vec2 uv;\n"
549"varying vec4 color;\n"
550"void main()\n"
551"{\n"
552" gl_Position = u_proj * u_view * u_model * vec4(a_pos, 0.0, 1.0);\n"
553" uv = a_uv;\n"
554" color = a_color;\n"
555"}";
556
557const char* f_sb_src = "\n"
558"#version 110\n"
559"uniform sampler2D u_tex;"
560"uniform vec4 u_color;"
561"varying vec2 uv;\n"
562"varying vec4 color;\n"
563"void main()\n"
564"{\n"
565" gl_FragColor = u_color * texture2D(u_tex, uv);\n"
566"}";
567
568// Globals
569_global gs_resource( gs_vertex_buffer ) g_vbo = {0};
570_global gs_resource( gs_index_buffer ) g_ibo = {0};
571_global gs_resource( gs_command_buffer ) g_cb = {0};
572_global gs_resource( gs_shader ) g_shader = {0};
573_global gs_resource( gs_uniform ) u_model = {0};
574_global gs_resource( gs_uniform ) u_view = {0};
575_global gs_resource( gs_uniform ) u_proj = {0};
576_global gs_resource( gs_uniform ) u_tex = {0};
577_global gs_resource( gs_texture ) g_tex = {0};
578_global asset_subsystem_t g_assets = {0};
579_global gs_camera g_camera = {0};
580_global gs_material_t g_mat0 = {0};
581_global gs_material_t g_mat1 = {0};
582_global gs_mesh_t g_quad = {0};
583_global gs_renderable_t g_rend0 = {0};
584_global gs_renderable_t g_rend1 = {0};
585
586_global gs_quad_batch_api g_qb_api = {0};
587_global gs_quad_batch_t g_qb = {0};
588_global gs_resource( gs_shader ) g_qb_shader = {0};
589_global gs_material_t g_qb_mat = {0};
590
591const char* v_src = "\n"
592"#version 110\n"
593"in vec2 a_pos;\n"
594"in vec2 a_uv;\n"
595"uniform mat4 u_model;\n"
596"uniform mat4 u_view;\n"
597"uniform mat4 u_proj;\n"
598"varying vec2 uv;\n"
599"void main()\n"
600"{\n"
601" gl_Position = u_proj * u_view * u_model * vec4(a_pos, 0.0, 1.0);\n"
602" uv = a_uv;\n"
603"}";
604
605const char* f_src = "\n"
606"#version 110\n"
607"uniform sampler2D u_tex;"
608"uniform vec4 u_color;"
609"varying vec2 uv;\n"
610"void main()\n"
611"{\n"
612" gl_FragColor = u_color * texture2D(u_tex, uv);\n"
613"}";
614
615// Forward Decls.
616gs_result app_init(); // Use to init your application
617gs_result app_update(); // Use to update your application
618gs_result app_shutdown(); // Use to shutdown your appliaction
619
620int main( int argc, char** argv )
621{
622 gs_application_desc app = {0};
623 app.window_title = "AssetSystem";
624 app.window_width = 800;
625 app.window_height = 600;
626 app.init = &app_init;
627 app.update = &app_update;
628 app.shutdown = &app_shutdown;
629
630 // Construct internal instance of our engine
631 gs_engine* engine = gs_engine_construct( app );
632
633 // Run the internal engine loop until completion
634 gs_result res = engine->run();
635
636 // Check result of engine after exiting loop
637 if ( res != gs_result_success )
638 {
639 gs_println( "Error: Engine did not successfully finish running." );
640 return -1;
641 }
642
643 gs_println( "Gunslinger exited successfully." );
644
645 return 0;
646}
647
648// Here, we'll initialize all of our application data, which in this case is our graphics resources
649gs_result app_init()
650{
651 // Cache instance of graphics/platform apis from engine
652 gs_graphics_i* gfx = gs_engine_instance()->ctx.graphics;
653 gs_platform_i* platform = gs_engine_instance()->ctx.platform;
654
655 // Construct command buffer ( the command buffer is used to allow for immediate drawing at any point in our program )
656 g_cb = gfx->construct_command_buffer();
657
658 // Construct asset subsystem
659 g_assets = asset_subsystem_new();
660
661 // Construct shader from our source above
662 g_shader = gfx->construct_shader( v_src, f_src );
663
664 // Construct uniform for shader
665 u_view = gfx->construct_uniform( g_shader, "u_view", gs_uniform_type_mat4 );
666 u_model = gfx->construct_uniform( g_shader, "u_model", gs_uniform_type_mat4 );
667 u_proj = gfx->construct_uniform( g_shader, "u_proj", gs_uniform_type_mat4 );
668 u_tex = gfx->construct_uniform( g_shader, "u_tex", gs_uniform_type_sampler2d );
669
670 // Vertex data layout for our mesh
671 gs_vertex_attribute_type layout[] = {
672
673 gs_vertex_attribute_float2, // Position
674 gs_vertex_attribute_float2 // UV
675 };
676
677 // Count of our vertex attribute array
678 u32 layout_count = sizeof( layout ) / sizeof( gs_vertex_attribute_type );
679
680 // Vertex data for quad
681 f32 v_data[] =
682 {
683 // Positions UVs
684 -0.5f, -0.5f, 0.0f, 0.0f, // Top Left
685 0.5f, -0.5f, 1.0f, 0.0f, // Top Right
686 -0.5f, 0.5f, 0.0f, 1.0f, // Bottom Left
687 0.5f, 0.5f, 1.0f, 1.0f // Bottom Right
688 };
689
690 f32 quad_v_data[] =
691 {
692 // Positions UVs
693 -0.5f, -0.5f, 0.0f, 0.0f, // Top Left
694 0.5f, 0.5f, 1.0f, 1.0f, // Bottom Right
695 -0.5f, 0.5f, 0.0f, 1.0f, // Bottom Left
696 -0.5f, -0.5f, 0.0f, 0.0f, // Top Left
697 0.5f, -0.5f, 1.0f, 0.0f, // Top Right
698 0.5f, 0.5f, 1.0f, 1.0f // Bottom Right
699 };
700
701 u32 i_data[] = {
702
703 0, 3, 2, // First Triangle
704 0, 1, 3 // Second Triangle
705 };
706
707 // Construct vertex and index buffers
708 g_vbo = gfx->construct_vertex_buffer( layout, layout_count, v_data, sizeof(v_data) );
709 g_ibo = gfx->construct_index_buffer( i_data, sizeof(i_data) );
710
711 // Construct quad
712 g_quad = gs_mesh_t_new( layout, layout_count, quad_v_data, sizeof(quad_v_data) );
713
714 // This is a descriptor for our texture. It includes various metrics, such as the width, height, texture format,
715 // and holds the actual uncompressed texture data for the texture. After using it for loading a raw texture
716 // from file, it's the responsibility of the user to free the data.
717 // gs_texture_parameter_desc desc = gs_texture_parameter_desc_default();
718
719 // Get appropriate file path for our texture (depending on where the app is running from)
720 const char* tfp = platform->file_exists("./assets/gs.png") ? "./assets/gs.png" : "./../assets/gs.png";
721 gs_assert(platform->file_exists(tfp)); // We'll assert if the file doesn't exist
722
723 // Load texture from file into asset subsystem
724 asset_subsystem_load_texture_from_file( &g_assets, tfp );
725
726 tfp = platform->file_exists("./assets/mario.png") ? "./assets/mario.png" : "./../assets/mario.png";
727 gs_assert(platform->file_exists(tfp)); // We'll assert if the file doesn't exist
728
729 asset_subsystem_load_texture_from_file( &g_assets, tfp );
730
731 // Grab texture
732 g_tex = asset_subsystem_get_texture( &g_assets, "gs" );
733
734 // Construct camera parameters
735 g_camera.transform = gs_vqs_default();
736 g_camera.transform.position = (gs_vec3){0.f, 0.f, -1.f};
737 g_camera.fov = 60.f;
738 g_camera.near_plane = 0.1f;
739 g_camera.far_plane = 1000.f;
740 g_camera.ortho_scale = 2.f;
741 g_camera.proj_type = gs_projection_type_orthographic;
742
743 gs_vec4 color = v4(1.f, 0.f, 0.f, 1.f);
744
745 // Setup materials
746 g_mat0 = gs_material_t_new( g_shader );
747 gs_material_set_uniform( &g_mat0, gs_uniform_type_sampler2d, "u_tex", gs_resource( gs_texture ), g_tex, 0 );
748 gs_material_set_uniform( &g_mat0, gs_uniform_type_vec4, "u_color", gs_vec4, v4(1.f, 0.f, 0.f, 1.f), 0 );
749
750 // Setup materials
751 g_mat1 = gs_material_t_new( g_shader );
752 gs_material_set_uniform( &g_mat1, gs_uniform_type_sampler2d, "u_tex", gs_resource( gs_texture ), asset_subsystem_get_texture( &g_assets, "mario" ), 0 );
753 gs_material_set_uniform( &g_mat1, gs_uniform_type_vec4, "u_color", gs_vec4, v4(1.f, 1.f, 1.f, 1.f), 0 );
754
755 g_rend0 = gs_renderable_new();
756 g_rend0.mesh = g_quad;
757 g_rend0.material = g_mat0;
758 g_rend0.transform.position = v3(-2.f, 0.f, 0.f);
759
760 g_rend1 = gs_renderable_new();
761 g_rend1.mesh = g_quad;
762 g_rend1.material = g_mat1;
763 g_rend1.transform.position = v3(2.f, 0.f, 0.f);
764
765 // Construct quad batch api and link up function pointers
766 g_qb_api = __gs_construct_quad_batch_api();
767
768 g_qb_shader = gfx->construct_shader( v_qb_src, f_qb_src );
769 g_qb_mat = gs_material_t_new( g_qb_shader );
770 gs_material_set_uniform( &g_qb_mat, gs_uniform_type_sampler2d, "u_tex", gs_resource( gs_texture ), asset_subsystem_get_texture( &g_assets, "mario" ), 0 );
771 g_qb = g_qb_api.new( g_qb_mat );
772
773 return gs_result_success;
774}
775
776gs_result app_update()
777{
778 // Grab global instance of engine
779 gs_engine* engine = gs_engine_instance();
780
781 // Platform api
782 gs_platform_i* platform = engine->ctx.platform;
783
784 // If we press the escape key, exit the application
785 if ( platform->key_pressed( gs_keycode_esc ) )
786 {
787 return gs_result_success;
788 }
789
790 const f32 dt = platform->time.delta;
791 const f32 t = platform->elapsed_time();
792
793 /*=================
794 // Camera controls
795 ==================*/
796
797 if ( platform->key_down( gs_keycode_q ) ) {
798 g_camera.ortho_scale += 0.1f;
799 }
800 if ( platform->key_down( gs_keycode_e ) ) {
801 g_camera.ortho_scale -= 0.1f;
802 }
803
804 if (platform->key_down(gs_keycode_a)) {
805 g_camera.transform.position.x -= 0.1f;
806 }
807 if (platform->key_down(gs_keycode_d)) {
808 g_camera.transform.position.x += 0.1f;
809 }
810 if (platform->key_down(gs_keycode_w)) {
811 g_camera.transform.position.y += 0.1f;
812 }
813 if (platform->key_down(gs_keycode_s)) {
814 g_camera.transform.position.y -= 0.1f;
815 }
816
817 // Add some stuff to the quad batch
818 g_qb_api.begin( &g_qb );
819 {
820 gs_for_range_i( 10000 )
821 {
822 gs_vqs xform = gs_vqs_default();
823 xform.position = v3(i, 0.f, 0.f);
824 gs_vec4 uv = v4(0.f, 0.f, 1.f, 1.f);
825 gs_quad_batch_add( &g_qb_api, &g_qb, xform, uv );
826 }
827 }
828 g_qb_api.end( &g_qb );
829
830 /*===============
831 // Render scene
832 ================*/
833
834 // Graphics api instance
835 gs_graphics_i* gfx = engine->ctx.graphics;
836
837 // Main window size
838 gs_vec2 ws = platform->window_size( platform->main_window() );
839
840 // Set clear color and clear screen
841 f32 clear_color[4] = { 0.2f, 0.2f, 0.2f, 1.f };
842 gfx->set_view_clear( g_cb, clear_color );
843 gfx->set_view_port( g_cb, ws.x, ws.y );
844 gfx->set_depth_enabled( g_cb, false );
845 gfx->set_blend_mode( g_cb, gs_blend_mode_src_alpha, gs_blend_mode_one_minus_src_alpha );
846
847 // Create model/view/projection matrices from camera
848 gs_mat4 view_mtx = gs_camera_get_view( &g_camera );
849 gs_mat4 proj_mtx = gs_camera_get_projection( &g_camera, ws.x, ws.y );
850 gs_mat4 model_mtx = gs_mat4_scale((gs_vec3){1.f, 1.f, 1.f});
851
852 quad_batch_submit_data_t sd = {0};
853 sd.view_mtx = view_mtx;
854 sd.proj_mtx = proj_mtx;
855 sd.u_model = u_model;
856 sd.u_proj = u_proj;
857 sd.u_view = u_view;
858
859 // Need to submit quad batch
860 g_qb_api.submit( g_cb, &g_qb, &sd );
861
862 // gs_resource( gs_shader ) cur_shader = g_rend0.material.shader;
863
864 // // For each renderable in scene
865 // // Bind material if necessary
866 // // Bind mesh if necessary
867 // // Bind material uniforms if necessary
868 // // Submit renderable
869
870 // // Sort renderables by shader program
871 // // if ( cur_shader.id != g_rend0.material.shader.id )
872 // {
873 // model_mtx = gs_vqs_to_mat4(&g_rend0.transform);
874
875 // // Bind shader
876 // gfx->bind_shader( g_cb, g_rend0.material.shader );
877
878 // // Bind matrix uniforms
879 // gfx->bind_uniform( g_cb, u_proj, &proj_mtx );
880 // gfx->bind_uniform( g_cb, u_view, &view_mtx );
881 // gfx->bind_uniform( g_cb, u_model, &model_mtx );
882 // }
883
884 // // Bind uniforms for material
885 // gs_material_bind( g_cb, &g_rend0.material );
886
887 // // Submit renderable mesh
888 // gs_renderable_submit( g_cb, &g_rend0 );
889
890 // // if ( cur_shader.id != g_rend1.material.shader.id )
891 // {
892 // model_mtx = gs_vqs_to_mat4(&g_rend1.transform);
893
894 // // Bind shader
895 // gfx->bind_shader( g_cb, g_rend1.material.shader );
896
897 // // Bind matrix uniforms
898 // gfx->bind_uniform( g_cb, u_proj, &proj_mtx );
899 // gfx->bind_uniform( g_cb, u_view, &view_mtx );
900 // gfx->bind_uniform( g_cb, u_model, &model_mtx );
901 // }
902
903 // // Bind uniforms for material
904 // gs_material_bind( g_cb, &g_rend1.material );
905
906 // // Submit renderable mesh
907 // gs_renderable_submit( g_cb, &g_rend1 );
908
909 // Submit command buffer for rendering
910 gfx->submit_command_buffer( g_cb );
911
912 return gs_result_in_progress;
913}
914
915gs_result app_shutdown()
916{
917 gs_println( "Goodbye, Gunslinger." );
918 return gs_result_success;
919}
920
921/*
922 Simple 2d game
923
924 Sprite batch
925 Asset system for textures
926
927 // Add sprites to batch during play
928 // Update renderable mesh with sprite batch mesh
929*/
930
931/*
932
933// Keep arrays for various uniform types?
934
935typedef gs_uniform_block_t
936{
937 gs_slot_array( gs_uniform_texture ) uniform_texture;
938 gs_slot_array( gs_uniform_mat4 ) uniform_mat4;
939 gs_slot_array( gs_uniform_vec4 ) uniform_vec4;
940 gs_slot_array( gs_uniform_vec3 ) uniform_vec3;
941 gs_slot_array( gs_uniform_vec2 ) uniform_vec2;
942 gs_slot_array( gs_uniform_float ) uniform_float;
943 gs_hash_table( u64, u32 ) uniform_ids; -> go from name to id
944} gs_uniform_block_t;
945
946
947// Could do a byte buffer for uniform information... Uniform block could come from shader itself
948typedef gs_uniform_block_t
949{
950 gs_hash_table( u64, u32 ) data_offsets; // Used for being able to actually set the data in the buffer
951 hash table for offsets into data (based on name)
952 data block
953 to upload all uniforms, rip through data and upload to bound shader
954} gs_uniform_block_t;
955
956material_set_uniform( name, value )\
957 if (exists(hash_str_64(name))) {
958 data_offset = gs_hash_table_get(data_offsets, hash_str_64(name));
959 cur_position = data_block.position;
960 data_block.position = data_offset;
961 write( type, value , data_block );
962 data_block.position = cur_position;
963 }
964
965
966typedef gs_material_t
967{
968 gs_resource( gs_shader ) shader;
969 gs_uniform_block_t uniforms;
970} gs_material_t;
971
972// Need inputs for the material to bind to shader
973typedef gs_material_t
974{
975 gs_resource( gs_shader ) shader;
976 gs_hash_table( u32, gs_uniform_texture ) uniform_texture; -> wasted space
977 gs_hash_table( u32, gs_uniform_vec4 ) uniform_vec4;
978 gs_hash_table( u32, gs_uniform_vec3 ) uniform_vec3;
979 gs_hash_table( u32, gs_uniform_vec2 ) uniform_vec2;
980 gs_hash_table( u32, gs_uniform_float ) uniform_float;
981 gs_hash_table( u32, gs_uniform_mat4 ) uniform_mat4;
982} gs_material_t;
983
984// Need a way to keep up with uniforms, of course
985gs_shader_t
986{
987} gs_shader;
988
989
990*/