basic world text
authorhgn <hgodden00@gmail.com>
Tue, 21 Dec 2021 07:30:02 +0000 (07:30 +0000)
committerhgn <hgodden00@gmail.com>
Tue, 21 Dec 2021 07:30:02 +0000 (07:30 +0000)
15 files changed:
fishladder.c
fishladder_resources.h
sound/win.ogg [new file with mode: 0644]
sound/y0.ogg
sound/y1.ogg
sound/y2.ogg
sound/y3.ogg
sound/y4.ogg
sound/y5.ogg
sound/y6.ogg
sound/y7.ogg
sound/y8.ogg
textures/ubuntu.png
vg/vg_audio.h
vg/vg_m.h

index fcdd58d4fe014c5d4ae3de204315e036e7a29af6..9a567df86c7874e6f65b3cc3a6228a33a1e8ed21 100644 (file)
@@ -132,6 +132,34 @@ struct mesh
        u32 elements;
 };
 
+struct
+{
+       GLuint vao;
+       GLuint vbo;
+       GLuint ebo;
+       
+       u32 
+               title_start, title_count,
+               desc_start, desc_count,
+               score_start, score_count,
+               time_start, time_count
+       ;
+       
+       #pragma pack(push,1)
+       struct vector_glyph_vert
+       {
+               v2f co;
+               v2f uv;
+               
+               u32 colour;
+       } 
+       *buffer;
+       #pragma pack(pop)
+       
+       u16 *indices;
+}
+text_buffers;
+
 struct world
 {
 #pragma pack(push,1)
@@ -145,7 +173,6 @@ struct world
        *data;
 #pragma pack(pop)
        
-       
        int initialzed;
        
        int sim_run, max_runs;
@@ -479,6 +506,94 @@ static void map_reclassify( v2i start, v2i end, int update_texbuffer )
        }
 }
 
+static u32 gen_text_buffer( const char *str, struct sdf_font *font, v2f origin, float size, u32 start )
+{
+       u32 count = 0;
+
+       v2f cursor;
+       v2f invUv;
+       v2_copy( origin, cursor );
+       
+       float invScale = (size / (float)font->size);
+       invUv[0] = 1.0f / (float)font->width;
+       invUv[1] = 1.0f / (float)font->height;
+       
+       const char *_c = str;
+       char c;
+       while( (c = *(_c ++)) )
+       {
+               if( c == '\n' )
+               {
+                       cursor[1] += size * 1.25f;
+                       cursor[0] = origin[0];
+               }
+               else if( c >= 32 && c <= 126 )
+               {
+                       struct sdf_char *pch = &font->characters[ c - ' ' ];
+                       struct vector_glyph_vert *vt = &text_buffers.buffer[ count * 4 ];
+                       u16 *ind = &text_buffers.indices[ count * 6 ];
+                       
+                       // Emit quad
+                       v2f p0; v2f uv0;
+                       v2f p1; v2f uv1;
+                       
+                       v2_muladds( cursor, (v2f){ pch->originX, -pch->originY }, -invScale, p0 );
+                       v2_muladds( p0, (v2f){ pch->w, -pch->h }, invScale, p1 );
+                       
+                       v2_mul( (v2f){ pch->uvx, pch->uvy }, invUv, uv0 );                      
+                       v2_muladd( uv0, (v2f){ pch->w, pch->h }, invUv, uv1 );
+                       
+                       v2_copy( p0, vt[0].co );
+                       v2_copy( uv0, vt[0].uv );
+                       vt[0].colour = 0xffffffff;
+                       
+                       v2_copy( (v2f){ p0[0], p1[1] }, vt[1].co );
+                       v2_copy( (v2f){ uv0[0], uv1[1] }, vt[1].uv );
+                       vt[1].colour = 0xffffffff;
+                       
+                       v2_copy( p1, vt[2].co );
+                       v2_copy( uv1, vt[2].uv );
+                       vt[2].colour = 0xffffffff;
+                       
+                       v2_copy( (v2f){ p1[0], p0[1] }, vt[3].co );
+                       v2_copy( (v2f){ uv1[0], uv0[1] }, vt[3].uv );
+                       vt[3].colour = 0xffffffff;
+                       
+                       // Emit indices
+                       ind[0] = count*4;
+                       ind[1] = count*4+1;
+                       ind[2] = count*4+2;
+                       ind[3] = count*4;
+                       ind[4] = count*4+2;
+                       ind[5] = count*4+3;
+                       
+                       cursor[0] += (float)pch->advance * invScale;
+                       count ++;
+               }
+       }
+       
+       glBindVertexArray( text_buffers.vao );
+       
+       glBindBuffer( GL_ARRAY_BUFFER, text_buffers.vbo );
+       glBufferSubData( GL_ARRAY_BUFFER, 
+                       start*4*sizeof( struct vector_glyph_vert ), 
+                       count*4*sizeof( struct vector_glyph_vert ), 
+                       text_buffers.buffer 
+       );
+       
+       glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, text_buffers.ebo );
+       glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, start*6*sizeof(u16), count*6*sizeof( u16 ), text_buffers.indices );
+       
+       return count;
+}
+
+static void gen_level_text( struct cmp_level *pLevel )
+{
+       text_buffers.title_count = gen_text_buffer( pLevel->title, &font_Ubuntu, (v2f){ 0.0f, 0.0f }, 1.0f, text_buffers.title_start );
+       text_buffers.desc_count = gen_text_buffer( pLevel->description, &font_Ubuntu, (v2f){ 0.0f, 0.0f }, 0.5f, text_buffers.desc_start );
+       text_buffers.desc_count = 0;
+}
+
 static int map_load( const char *str, const char *name )
 {
        //TODO: It may be worthwhile, at this point, to switch to binary encoding for save data
@@ -1044,7 +1159,10 @@ static void career_load(void)
                        if( lvl->serial_id == encoded.in_map )
                        {
                                if( console_changelevel( 1, &lvl->map_name ) )
+                               {
                                        world.pCmpLevel = lvl;
+                                       gen_level_text( world.pCmpLevel );
+                               }
                        }
                }
        }
@@ -1768,6 +1886,10 @@ void vg_update(void)
                                                {
                                                        career_pass_level( world.pCmpLevel, world.score, 1 );
                                                }
+                                               
+                                               sfx_set_play( &audio_tones, &audio_system_balls_extra, 9 );
+                                               failure_this_frame = 0;
+                                               success_this_frame = 0;
                                        }
                                }
                                else
@@ -2187,6 +2309,7 @@ static void level_selection_buttons(void)
                if( console_changelevel( 1, &switch_level_to->map_name ) )
                {
                        world.pCmpLevel = switch_level_to;
+                       gen_level_text( world.pCmpLevel );
                }
        }
 }
@@ -2397,6 +2520,18 @@ void vg_render(void)
        
        level_selection_buttons();
        
+       // TEXT ELEMENTS
+       // ========================================================================================================
+       SHADER_USE( shader_sdf );
+       glBindVertexArray( text_buffers.vao );
+       glUniformMatrix3fv( SHADER_UNIFORM( shader_sdf, "uPv" ), 1, GL_FALSE, (float *)vg_pv );
+       
+       vg_tex2d_bind( &tex_ubuntu, 0 );
+       glUniform1i( SHADER_UNIFORM( shader_sdf, "uTexGlyphs" ), 0 );
+       
+       glDrawElements( GL_TRIANGLES, text_buffers.title_count*6, GL_UNSIGNED_SHORT, (void*)( text_buffers.title_start*6*sizeof(u16) ) );
+       glDrawElements( GL_TRIANGLES, text_buffers.desc_count*6, GL_UNSIGNED_SHORT, (void*)( text_buffers.desc_start*6*sizeof(u16) ) );
+       
        // WIRES
        // ========================================================================================================
        //glDisable(GL_BLEND);
@@ -3393,6 +3528,88 @@ void vg_start(void)
        
        resource_load_main();
        
+       // Create text buffers
+       {
+               // Work out the counts for each 'segment'
+               u32 desc_max_size = 0, title_max_size = 0, 
+                       score_max_size = 10,
+                       time_max_size = 10
+               ;
+               
+               for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
+               {
+                       struct serializable_set *set = &career_serializable[i];
+                       for( int j = 0; j < set->count; j ++ )
+                       {
+                               struct cmp_level *lvl = &set->pack[j];
+                               
+                               desc_max_size = VG_MAX( desc_max_size, strlen( lvl->description ) );
+                               title_max_size = VG_MAX( title_max_size, strlen( lvl->title ) );
+                       }
+               }
+               
+               // Full buffer
+               u32 total_characters = 
+                       title_max_size +
+                       desc_max_size +
+                       score_max_size +
+                       time_max_size;
+       
+               u32 total_faces = total_characters * 2,
+                       total_vertices = total_characters * 4,
+                       total_indices = total_faces * 3;
+
+               // Working buffer               
+               u32 work_buffer_total_chars = 
+                       VG_MAX( VG_MAX( desc_max_size, title_max_size ), VG_MAX( score_max_size, time_max_size ) );
+               u32 total_work_faces = work_buffer_total_chars * 2,
+                       total_work_vertices = work_buffer_total_chars * 4,
+                       total_work_indices = total_work_faces * 3;
+
+               text_buffers.title_count = 0;
+               text_buffers.desc_count = 0;
+               text_buffers.score_count = 0;
+               text_buffers.time_count = 0;
+               
+               // Calculate offsets
+               text_buffers.title_start = 0;
+               text_buffers.desc_start = title_max_size;
+               text_buffers.score_start = text_buffers.desc_start + desc_max_size;
+               text_buffers.time_start = text_buffers.score_start + score_max_size;
+       
+               // Opengl
+               glGenVertexArrays(1, &text_buffers.vao);
+               glGenBuffers( 1, &text_buffers.vbo );
+               glGenBuffers( 1, &text_buffers.ebo );
+               glBindVertexArray( text_buffers.vao );
+               
+               glBindBuffer( GL_ARRAY_BUFFER, text_buffers.vbo );
+               glBufferData( GL_ARRAY_BUFFER, total_vertices * sizeof( struct vector_glyph_vert ), NULL, GL_DYNAMIC_DRAW );
+
+               glBindVertexArray( text_buffers.vao );
+               
+               glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, text_buffers.ebo );
+               glBufferData( GL_ELEMENT_ARRAY_BUFFER, total_indices * sizeof( u16 ), NULL, GL_DYNAMIC_DRAW );
+               
+               u32 const stride = sizeof( struct vector_glyph_vert );
+               
+               // XY
+               glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, stride, (void *)offsetof( struct vector_glyph_vert, co ) );
+               glEnableVertexAttribArray( 0 );
+               
+               // UV
+               glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, stride, (void *)offsetof( struct vector_glyph_vert, uv ) );
+               glEnableVertexAttribArray( 1 );
+               
+               // COLOUR
+               glVertexAttribPointer( 2, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (void *)offsetof( struct vector_glyph_vert, colour ) );
+               glEnableVertexAttribArray( 2 );
+               
+               // Offline memory
+               text_buffers.buffer = (struct vector_glyph_vert *)malloc( total_work_vertices * sizeof(struct vector_glyph_vert) );
+               text_buffers.indices = (u16*)malloc( total_work_indices * sizeof(u16) );
+       }
+       
        // Restore gamestate
        career_local_data_init();
        career_load();
@@ -3404,6 +3621,13 @@ void vg_free(void)
        console_save_map( 0, NULL );
        career_serialize();
 
+       glDeleteVertexArrays( 1, &text_buffers.vao );
+       glDeleteBuffers( 1, &text_buffers.vbo );
+       glDeleteBuffers( 1, &text_buffers.ebo );
+       
+       free( text_buffers.buffer );
+       free( text_buffers.indices );
+
        resource_free_main();
 
        glDeleteTextures( 1, &world.background_data );
index 4cdd8943018ab2b2c33c8dc662e2a9d36a914508..431c8d83611c9b1e21277060d86e3e6ee22bd4ac 100644 (file)
@@ -198,7 +198,8 @@ sound/y4.ogg\0\
 sound/y5.ogg\0\
 sound/y6.ogg\0\
 sound/y7.ogg\0\
-sound/y8.ogg\0"
+sound/y8.ogg\0\
+sound/win.ogg\0"
 };
 
 // One two or three layers of rolling noise
@@ -572,6 +573,40 @@ SHADER_DEFINE( shader_buttons,
        UNIFORMS({ "uPv", "uOffset", "uTexMain", "uColour" })
 )
 
+SHADER_DEFINE( shader_sdf,
+
+       // VERTEX
+       "layout (location=0) in vec2 a_co;"
+       "layout (location=1) in vec2 a_uv;"
+       "layout (location=2) in vec4 a_colour;"
+       "uniform mat3 uPv;"
+       ""
+       "out vec2 aTexCoords;"
+       "out vec4 aColour;"
+       ""
+       "void main()"
+       "{"
+               "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );"
+               "aTexCoords = a_uv;"
+               "aColour = a_colour;"
+       "}",
+       
+       // FRAGMENT
+       "uniform sampler2D uTexGlyphs;"
+       "out vec4 FragColor;"
+       ""
+       "in vec2 aTexCoords;"
+       "in vec4 aColour;"
+       ""
+       "void main()"
+       "{"
+               "vec4 glyph = texture( uTexGlyphs, aTexCoords );"
+               "FragColor = vec4( aColour.rgb, smoothstep( 0.48, 0.52, glyph.r ) * aColour.a );"
+               //"FragColor = glyph;"
+       "}"
+       ,
+       UNIFORMS({ "uPv", "uTexGlyphs" })
+)
 
 void vg_register(void)
 {
@@ -581,6 +616,7 @@ void vg_register(void)
        SHADER_INIT( shader_background );
        SHADER_INIT( shader_wire );
        SHADER_INIT( shader_buttons );
+       SHADER_INIT( shader_sdf );
 }
 
 /*
diff --git a/sound/win.ogg b/sound/win.ogg
new file mode 100644 (file)
index 0000000..b1b4a01
Binary files /dev/null and b/sound/win.ogg differ
index f4735af0019f031279e1423c2b9d3834a137c426..bc03524ba3c49e78a8949a7a01d721b4e54230a0 100644 (file)
Binary files a/sound/y0.ogg and b/sound/y0.ogg differ
index bed449b9e1ce8eaf3bd3505b70f37423fca29717..6955a02c576ccbcf6c587ea01f516bea46450a8a 100644 (file)
Binary files a/sound/y1.ogg and b/sound/y1.ogg differ
index 2994944de8b15a52b6a25be8435b039ecfd9c116..2c3bfdb54290c3c1e6a1edc2c4f0ec38fcdb7904 100644 (file)
Binary files a/sound/y2.ogg and b/sound/y2.ogg differ
index 740ca0a2fbd467d6e1dcc29445466063a2aa9859..62b3f861ee8c361bc3a81f5e85d6463ca8221362 100644 (file)
Binary files a/sound/y3.ogg and b/sound/y3.ogg differ
index 0156c5a505c5dfcec064aa85c3688b7fc7d86a1c..cd2d7acfa1703ea0542ba578853230d678fc36b0 100644 (file)
Binary files a/sound/y4.ogg and b/sound/y4.ogg differ
index 8af3fc622d8b3247e47466a3544c62c5ed07b758..a12fed55a4764920e92279144645b99cb635a4a5 100644 (file)
Binary files a/sound/y5.ogg and b/sound/y5.ogg differ
index f51a778dab22142b41b9d9c85a160cb61be82616..f5da32980167671ba05bb66cfad79aafe13bb07b 100644 (file)
Binary files a/sound/y6.ogg and b/sound/y6.ogg differ
index f7f1cb867838ba36f987c6807c65523fccc6b7b1..694da67236c792b9d21306847c020207b627da80 100644 (file)
Binary files a/sound/y7.ogg and b/sound/y7.ogg differ
index 935503e6004d58aea258ae394000a5dc977856f6..d4d438b465e64da4a6736cf3751ca024441f58db 100644 (file)
Binary files a/sound/y8.ogg and b/sound/y8.ogg differ
index 083432207e55b465ee491d075cdb2e91684d406e..bf15bff114d24e7707c04046d070a795ba7e3c3f 100644 (file)
Binary files a/textures/ubuntu.png and b/textures/ubuntu.png differ
index 35d775621b1bdddd27edb6b948c9425a84834477..e62d5845447e35f09c3e3b6536911a38ff2e3e42 100644 (file)
@@ -26,6 +26,7 @@ struct sfx_vol_control
 struct sfx_system
 {
        sfx_system *persisitent_source;
+       int in_queue;
 
        // Source buffer start
        float *source, *replacement;
@@ -54,7 +55,7 @@ struct sfx_set
        float *main;
        char *sources;
        
-       u32 segments[20];       //from->to,from->to ...
+       u32 segments[32];       //from->to,from->to ...
        u32 numsegments;
        u32 ch;
        u32 flags;
@@ -228,7 +229,7 @@ static int sfx_begin_edit( sfx_system *sys )
 {
        MUTEX_LOCK( sfx_mux_t01 );
        
-       if( sfx_q_len >= SFX_MAX_SYSTEMS )
+       if( sfx_q_len >= SFX_MAX_SYSTEMS && !sys->in_queue )
        {
                MUTEX_UNLOCK( sfx_mux_t01 );
                vg_warn( "Warning: No free space in sound queue\n" );           
@@ -246,8 +247,12 @@ static void sfx_end_edit( sfx_system *sys )
 // Mark change to be uploaded to queue system
 static int sfx_push( sfx_system *sys )
 {
-       // Mark change in queue
-       sfx_q[ sfx_q_len ++ ] = sys;
+       if( !sys->in_queue )
+       {
+               // Mark change in queue
+               sfx_q[ sfx_q_len ++ ] = sys;
+               sys->in_queue = 1;
+       }
        
        MUTEX_UNLOCK( sfx_mux_t01 );
        
@@ -379,6 +384,8 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
                sfx_system *src = sfx_q[sfx_q_len];
                sfx_system *clone;
                
+               src->in_queue = 0;
+               
                // Copy
                clone = sfx_alloc();
                *clone = *src;
@@ -522,8 +529,6 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 // String layout: "sounda.ogg\0soundb.ogg\0soundc.ogg\0\0"
 static void sfx_set_strings( sfx_set *dest, char *strSources, u32 flags, int bAsync )
 {
-       printf( "Init sfx set\n|   start   |    end    |  length   | name \n" );
-
        dest->ch = (flags & SFX_FLAG_STEREO)? 2: 1;
        
        dest->main = NULL;
@@ -556,8 +561,6 @@ static void sfx_set_strings( sfx_set *dest, char *strSources, u32 flags, int bAs
                        
                        dest->segments[ dest->numsegments*2+0 ] = total-samples;
                        dest->segments[ dest->numsegments*2+1 ] = total;
-                       
-                       printf( "| %09u | %09u | %09u | %s\n", total-samples, total, samples, source );
                }
                else
                {
@@ -569,8 +572,6 @@ static void sfx_set_strings( sfx_set *dest, char *strSources, u32 flags, int bAs
                source += len +1;
                dest->numsegments ++;
        }
-       
-       vg_info( "finished, numsegments: %u\n", dest->numsegments );
 }
 
 static void sfx_set_init( sfx_set *dest, char *sources )
index a567092e79b130fa83dfe2234ead19aa95ad4d78..577138fb12e575698d1c941e15958f05a898beeb 100644 (file)
--- a/vg/vg_m.h
+++ b/vg/vg_m.h
@@ -110,7 +110,8 @@ static inline void v2_divs( v2f a, float s, v2f d )
 
 static inline void v2_mul( v2f a, v2f b, v2f d )
 {
-       d[0] = a[0]*b[0]; d[1] = a[1]*b[1];
+       d[0] = a[0]*b[0]; 
+       d[1] = a[1]*b[1];
 }
 
 static inline void v2_div( v2f a, v2f b, v2f d )
@@ -118,9 +119,16 @@ static inline void v2_div( v2f a, v2f b, v2f d )
        d[0] = a[0]/b[0]; d[1] = a[1]/b[1];
 }
 
+static inline void v2_muladd( v2f a, v2f b, v2f s, v2f d )
+{
+       d[0] = a[0]+b[0]*s[0]; 
+       d[1] = a[1]+b[1]*s[1];
+}
+
 static inline void v2_muladds( v2f a, v2f b, float s, v2f d )
 {
-       d[0] = a[0]+b[0]*s; d[1] = a[1]+b[1]*s;
+       d[0] = a[0]+b[0]*s; 
+       d[1] = a[1]+b[1]*s;
 }
 
 static inline float v2_length2( v2f a )