ui gpu clipping
authorhgn <hgodden00@gmail.com>
Sun, 5 Dec 2021 16:57:05 +0000 (16:57 +0000)
committerhgn <hgodden00@gmail.com>
Sun, 5 Dec 2021 16:57:05 +0000 (16:57 +0000)
fishladder.c
fishladder_resources.h
maps/level0.map
textures/ascii.png
vg/vg.h
vg/vg_console.h
vg/vg_ui.h

index 74a39ce4de1bcd955e8c5db78b89b5ca3e6222b9..842bb64846d0af9facf5900e45aa24ad58841134 100644 (file)
@@ -23,9 +23,9 @@
                        Reverse order
                
                New things to program:
-                       UI text element renderer (SDF)
-                       Particle system thing for ball collision
-                       Level descriptions / titles
+                       UI text element renderer (SDF)                          DONE(sorta)
+                       Particle system thing for ball collision        
+                       Level descriptions / titles                                     HALF
                        Row Gridlines for I/O
                        Play button / Speed controller
                        
@@ -355,7 +355,7 @@ struct world
        
        int num_fishes;
        
-       char map_name[128];
+       char map_name[64];
        struct career_level *ptr_career_level;
        
        u32 score;
@@ -402,9 +402,9 @@ static int map_load( const char *str, const char *name )
        // Scan for width
        for(;; world.w ++)
        {
-               if( str[world.w] == ';' )
+               if( c[world.w] == ';' )
                        break;
-               else if( !str[world.w] )
+               else if( !c[world.w] )
                {
                        vg_error( "Unexpected EOF when parsing level\n" );
                        return 0;
@@ -1965,6 +1965,27 @@ void vg_render(void)
        }
        
        
+       // Level title
+       ui_begin( &ui_global_ctx, 512, 256 );
+       
+       ui_global_ctx.override_colour = 0xff9a8a89;
+       //ui_text( &ui_global_ctx, world.map_title, 6, 0 );
+       ui_global_ctx.override_colour = 0xffffffff;
+       
+       ui_resolve( &ui_global_ctx );
+       
+       m3x3f world_text;
+       m3x3_copy( vg_pv, world_text );
+       m3x3_translate( world_text, (v3f){ 1.55f, 1.9f, 0.0f } );
+       m3x3_rotate( world_text, VG_PIf*0.5f );
+       m3x3_scale( world_text, (v3f){0.01f,-0.01f,0.01f} );
+       
+       ui_draw( &ui_global_ctx, world_text );
+       
+       // Main
+       // =========================================================================================
+       
+       use_mesh( &world.tile );
        SHADER_USE( shader_tile_main );
 
        m2x2f subtransform;
@@ -2311,12 +2332,49 @@ void vg_render(void)
                level_ui_space[1] -= 0.01f;
                draw_numbers( level_ui_space, i );
        }
-       
-       //use_mesh( &world.numbers );
-       //draw_numbers( (v3f){ 0.0f, -0.5f, 0.1f }, 128765 );
 }
 
 void vg_ui(void)
 {
+       ui_global_ctx.cursor[0] = 0;
+       ui_global_ctx.cursor[1] = 0;
+       ui_global_ctx.cursor[2] = 256;
+
+       ui_fill_y( &ui_global_ctx );
        
+       ui_new_node( &ui_global_ctx );
+       {
+               ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, 0xff5577ff );
+               
+               ui_text( &ui_global_ctx, "MARBLE COMPUTING", 4, 0 );
+               
+               ui_global_ctx.cursor[1] += 45;
+               ui_global_ctx.cursor[3] = 709;
+               
+               // Level scroll view
+               ui_new_node( &ui_global_ctx );
+               {
+                       ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, 0xffff7729 );
+                       ui_set_clip( &ui_global_ctx, ui_global_ctx.cursor );
+                       
+                       ui_global_ctx.cursor[3] = 50;
+                       ui_global_ctx.cursor[2] = 240;
+                       
+                       for( int i = 0; i < vg_list_size(cmp_levels_basic); i ++ )
+                       {
+                               struct cmp_level *lvl_info = &cmp_levels_basic[i];
+                       
+                               ui_new_node( &ui_global_ctx );
+                               {
+                                       ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, i&0x1?0xff23fce45:0xff8722f8 );
+                                       ui_text( &ui_global_ctx, lvl_info->title, 3, 0 );
+                               }
+                               ui_end_down( &ui_global_ctx );
+                       }
+                       
+                       ui_release_clip( &ui_global_ctx );
+               }
+               ui_end_down( &ui_global_ctx );
+       }
+       ui_end( &ui_global_ctx );
 }
index 023c329d4f2ec2ff04a93f66343288d7e845c225..da8b8ea2052b31275b22735697b7924168351468 100644 (file)
@@ -6,7 +6,7 @@ vg_tex2d tex_tile_detail = { .path = "textures/tile_overlays.qoi" };
 vg_tex2d tex_wood =                    { .path = "textures/wood.qoi" };
 vg_tex2d tex_background =      { .path = "textures/background.qoi" };
 vg_tex2d tex_ball_noise =  { .path = "textures/bnoise.qoi" };
-vg_tex2d tex_monofur   =  { .path = "textures/ascii.qoi" };
+vg_tex2d tex_monofur   =  { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
 
 vg_tex2d *texture_list[] = { &tex_tile_detail, &tex_tile_data, &tex_wood, &tex_background, &tex_ball_noise, &tex_monofur };
 
@@ -95,7 +95,7 @@ static void resource_load_main(void)
        // Textures
        vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
        
-       ui_override_font( tex_monofur.name, 3 );
+       ui_override_font( tex_monofur.name, 7 );
        
        // Audio
        sfx_set_init( &audio_tile_mod, NULL );
@@ -543,3 +543,224 @@ u32 const MESH_NUMBERS_OFFSETS[][2] =
                vg_list_size( MESH_NUMBER_9 ) / MESH_NUMBER_DIVISOR
        }
 };
+
+struct cmp_level
+{
+       const char *map_name;
+       const char *title;
+       const char *description;
+       
+       int serial_id;
+};
+
+struct cmp_level cmp_levels_tutorials[] = 
+{
+       {
+               .title = "PRINCIPLE 1",
+               .map_name = "cmp_t01",
+               .description = "Utilize basic transport methods",
+               
+               .serial_id = 0
+       },
+       {
+               .title = "PRINCIPLE 2",
+               .map_name = "cmp_t02",
+               .description = "Utilize the twisty turny(TM) piece",
+               
+               .serial_id = 1
+       },
+       {
+               .title = "PRINCIPLE 3",
+               .map_name = "cmp_t03",
+               .description = "Merge transport into one",
+               
+               .serial_id = 2
+       },
+       {
+               .title = "PRINCIPLE 4",
+               .map_name = "cmp_t04",
+               .description = "Some stages require multiple runs to succeed in order to pass",
+               
+               .serial_id = 12
+       }
+};
+
+struct cmp_level cmp_levels_basic[] =
+{
+       {
+               .title = "SUBDIVISION 1",
+               .map_name = "cmp_b01",
+               .description = "Simple maths, branching required.",
+               
+               .serial_id = 3
+       },
+       {
+               .title = "SUBDIVISION 2",
+               .map_name = "cmp_b02",
+               .description = "Simple maths. Futher.",
+
+               .serial_id = 4
+       },
+       {
+               .title = "RESTRUCTURE",
+               .map_name = "cmp_b03",
+               .description = "Not so simple swap",
+               
+               .serial_id = 5
+       },
+       {
+               .title = "SERIALIZE",
+               .map_name = "cmp_b04",
+               .description = "Merge and sort",
+               
+               .serial_id = 6
+       },
+       {
+               .title = "PATTERNS 1",
+               .map_name = "cmp_b05",
+               .description = "Replicate",
+               
+               .serial_id = 7
+       },
+       {
+               .title = "PATTERNS 2",
+               .map_name = "cmp_b06",
+               .description = "Replicate MORE",
+               
+               .serial_id = 8
+       },
+       {
+               .title = "MIGHTY CONSUMER",
+               .map_name = "cmp_b07",
+               .description = "Build a greedy system",
+               
+               .serial_id = 9
+       },
+       {
+               .title = "ENCRYPTED 1",
+               .map_name = "cmp_b08",
+               .description = "Some configurations may not be valid",
+
+               .serial_id = 10
+       },
+       {
+               .title = "REVERSE",
+               .map_name = "cmp_b09",
+               .description = "Reverse the incoming order. Always length 4",
+               
+               .serial_id = 11
+       },
+       {
+               .title = "PRINCIPLE 5",
+               .map_name = "cmp_b10",
+               .description = 
+                       "The competent engineers among you may have already\n" 
+                       "spotted and utilized these parts of the system\n"
+                       "\n"
+                       "We forgot to include the relevant principle tasks\n"
+                       "as part of your training package, you will now be\n"
+                       "tasked to complete them",
+
+               .serial_id = 15
+       },
+       {
+               .title = "ROUTING PROBLEM",
+               .map_name = "cmp_routing",
+               .description = 
+                       "Things can get a little chaotic on tight boards,\n"
+                       "Do your best to utilize principle 5 to get the job\n"
+                       "done.",
+               
+               .serial_id = 16
+       },
+       {
+               .title = "PRINCIPLE 6",
+               .map_name = "cmp_b11",
+               .description =
+                       "While hovering over a simple tile peice, right click\n"
+                       "and drag to start creating a wire. These can be\n"
+                       "connected to the left, or right recieving pins of a\n"
+                       "Twisty Turny(TM) peice.\n"
+                       "\n"
+                       "Once connected, the Twisty Turny(TM) will no longer\n"
+                       "'flip flop' as marbles run through them, but instead\n"
+                       "be set to left or right rotating only. As indicated\n"
+                       "by the status arrow beneath them\n"
+                       "\n"
+                       "When the left or right slot is triggered, the Twisty\n"
+                       "Turny(TM) will switch modes according to that input.\n"
+                       "\n"
+                       "Trigger wires apply instantaneously, however if both\n"
+                       "the left and right inputs are recieved at the same\n"
+                       "time, this results in no operation being performed,\n"
+                       "and no state changes take place in the Twisty Turny(TM)\n",
+
+                       .serial_id = 17
+       },
+       {
+               .title = "NOT GATE",
+               .map_name = "cmp_not",
+               .description = 
+                       "Test your knowledge of triggers, build an 'NOT GATE'\n"
+                       "emulated by marble logic.",
+               
+               .serial_id = 18
+       },
+       {
+               .title = "AND GATE",
+               .map_name = "cmp_and",
+               .description = 
+                       "A slightly more complicated gate, but shouldn't be\n"
+                       "too difficult for your skillset.",
+               
+               .serial_id = 19
+       },
+       {
+               .title = "QUALIFICATION PROJECT",
+               .map_name = "cmp_grad",
+               .description =
+                       "There's no instructions here, resolve and complete this\n"
+                       "task to qualify yourself as an official marble engineer",
+               .serial_id = 20
+       }
+};
+
+struct cmp_level cmp_levels_grad[] =
+{
+       {
+               .title = "SORT",
+               .map_name = "cmp_i01",
+               .description = 
+                       "Device a scheme to filter and sort the inputs. If you\n"
+                       "believe you lack the tools required to solve this one,\n"
+                       "take a harder look at the inputs.",
+               
+               .serial_id = 13
+       },
+       {
+               .title = "THIRDS",
+               .map_name = "cmp_i02",
+               .description = 
+                       "Spit your inputs up into a third of its value\n"
+                       "Is this possible? -HG",
+               
+               .serial_id = 14
+       },
+       {
+               .title = "XOR CHIP",
+               .map_name = "cmp_xor",
+               .description = 
+                       "Significantly more complicated than an AND or NOT gate,\n"
+                       "but possible.",
+               .serial_id = 21
+       },
+       {
+               .title = "SECRET CODE",
+               .map_name = "cmp_secret",
+               .description = 
+                       "Only one input should send an unlock signal marble to\n"
+                       "the output.\n"
+                       "The code: 100110",
+               .serial_id = 22
+       }
+};
index e5dc41006708678125847e49579dcc3f85528223..a30aab959705311fe180a019d2948dfab1473240 100644 (file)
@@ -1,3 +1,4 @@
+PRINCIPLE 1
 #########;
 ###-#####;acac
 ##     ##;
index 523184d9efd2bcca9d566063d0b644b8cbc0a822..adf296e710e80a64f2bb1468a6b3997ad23e552a 100644 (file)
Binary files a/textures/ascii.png and b/textures/ascii.png differ
diff --git a/vg/vg.h b/vg/vg.h
index c792527fce16a2c2ed6086f79965f19017578dae..cdcf431555158d07289fcd75577550e3a7b2c504 100644 (file)
--- a/vg/vg.h
+++ b/vg/vg.h
@@ -255,7 +255,7 @@ static void vg_init( int argc, char *argv[], const char *window_name )
                                vg_debugtools_draw();
                                
                                ui_resolve( &ui_global_ctx );
-                               ui_draw( &ui_global_ctx );
+                               ui_draw( &ui_global_ctx, NULL );
                        }
                        
                        glfwSwapBuffers( vg_window );
index 48dee1a4a0fbd36d4f625fdab7c0f25dfc9da7f4..febe54af68d55186be0e7339eb09553f5c18ce88 100644 (file)
@@ -177,6 +177,9 @@ static void execute_console_input( const char *cmd )
                        {
                                temp[i] = '\0';
                                in_token = 0;
+                               
+                               if( arg_count == vg_list_size( args ) )
+                                       break;
                        }
                        else
                        {
index 56ece6b85d75fb7897e7b8cfbf593ec54a62c28b..a2cc77057af0da407c4681fe83333acdbd3a5570 100644 (file)
@@ -6,16 +6,22 @@ SHADER_DEFINE( shader_ui,
        "layout (location=0) in vec2 a_co;"                     // i16, i16, .. ?
        "layout (location=1) in vec2 a_uv;"                     // i8, i8
        "layout (location=2) in vec4 a_colour;" // u32
+       "layout (location=3) in vec4 a_clip;"           // i16, i16, i16, i16
        "uniform mat3 uPv;"
        ""
        "out vec2 aTexCoords;"
        "out vec4 aColour;"
+       "out vec2 aWsp;"
+       "out vec4 aClip;"
        ""
        "void main()"
        "{"
                "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );"
-               "aTexCoords = a_uv * 0.01388888888;"
+               "aTexCoords = a_uv * 0.0078125;"
                "aColour = a_colour;"
+               
+               "aWsp = a_co;"
+               "aClip = a_clip;"
        "}",
        
        // FRAGMENT
@@ -25,10 +31,15 @@ SHADER_DEFINE( shader_ui,
        "in vec2 aTexCoords;"
        "in vec4 aColour;"
        ""
+       "in vec2 aWsp;"
+       "in vec4 aClip;"
+       ""
        "void main()"
        "{"
+               "float clip_blend = step( aWsp.x, aClip.z ) * step( aWsp.y, aClip.w ) * step( aClip.x, aWsp.x ) * step( aClip.y, aWsp.y );"
+       
                "vec4 glyph = texture( uTexGlyphs, aTexCoords );"
-               "FragColor = aColour * vec4( 1.0, 1.0, 1.0, glyph.r );"
+               "FragColor = aColour * vec4( 1.0, 1.0, 1.0, glyph.r * clip_blend );"
        "}"
        ,
        UNIFORMS({ "uPv", "uTexGlyphs" })
@@ -61,17 +72,21 @@ struct ui_ctx
        #pragma pack(push,1)
        struct ui_vert
        {
-               ui_px co[2];
-               u8 uv[2];
-               u32 colour;
+               ui_px co[2];    //32 4
+               u8 uv[2];               //16 2
+               u32 colour;             //32 4
+               ui_rect clip;   //64 8
        }
        *verts;
        #pragma pack(pop)
        
+       u32 override_colour;
+       
        u32 num_verts;
        u16 *indices;
        u32 num_indices;
        
+       ui_rect clipping;
        ui_rect cursor;
        u32 stack_count;
        u32 capture_mouse_id;
@@ -172,7 +187,7 @@ static void ui_default_init(void)
                u32 const stride = sizeof( struct ui_vert );
                
                // XY
-               glVertexAttribPointer( 0, 2, GL_UNSIGNED_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, co ) );
+               glVertexAttribPointer( 0, 2, GL_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, co ) );
                glEnableVertexAttribArray( 0 );
                
                // UV
@@ -182,6 +197,10 @@ static void ui_default_init(void)
                // COLOUR
                glVertexAttribPointer( 2, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (void *)offsetof( struct ui_vert, colour ) );
                glEnableVertexAttribArray( 2 );
+               
+               // CLIPPING
+               glVertexAttribPointer( 3, 4, GL_SHORT, GL_FALSE, stride, (void *)offsetof( struct ui_vert, clip ) );
+               glEnableVertexAttribArray( 3 );
        }
        
        // Initialize default context
@@ -204,7 +223,7 @@ static void ui_default_free(void)
        free( ui_global_ctx.indices );
 }
 
-static void ui_draw( ui_ctx *ctx )
+static void ui_draw( ui_ctx *ctx, m3x3f view_override )
 {
        glBindVertexArray( ui_vao );
        
@@ -221,9 +240,16 @@ static void ui_draw( ui_ctx *ctx )
        SHADER_USE( shader_ui );
        
        m3x3f view = M3X3_IDENTITY;
-       m3x3_translate( view, (v3f){ -1.0f, 1.0f, 0.0f } );
-       m3x3_scale( view, (v3f){ 1.0f/((float)vg_window_x*0.5f), -1.0f/((float)vg_window_y*0.5f), 1.0f } );
-       glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1, GL_FALSE, (float *)view );
+       
+       if( !view_override )
+       {
+               view_override = view;
+       
+               m3x3_translate( view, (v3f){ -1.0f, 1.0f, 0.0f } );
+               m3x3_scale( view, (v3f){ 1.0f/((float)vg_window_x*0.5f), -1.0f/((float)vg_window_y*0.5f), 1.0f } );
+       }
+       
+       glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1, GL_FALSE, (float *)view_override );
        
        glActiveTexture( GL_TEXTURE0 );
        glBindTexture( GL_TEXTURE_2D, ui_glyph_texture );
@@ -394,6 +420,22 @@ static void ui_capture_mouse( ui_ctx *ctx, u32 id )
        }
 }
 
+static void ui_set_clip( ui_ctx *ctx, ui_rect clip )
+{
+       ctx->clipping[0] = clip[0];
+       ctx->clipping[1] = clip[1];
+       ctx->clipping[2] = clip[0] + clip[2];
+       ctx->clipping[3] = clip[1] + clip[3];
+}
+
+static void ui_release_clip( ui_ctx *ctx )
+{
+       ctx->clipping[0] = -32000;
+       ctx->clipping[1] = -32000;
+       ctx->clipping[2] =  32000;
+       ctx->clipping[3] =  32000;
+}
+
 // Drawing
 // ===========================================================================================================
 
@@ -423,6 +465,11 @@ static struct ui_vert *ui_fill_rect_uv( ui_ctx *ctx, ui_rect rect, u32 colour, u
        u16 ind_start = ctx->num_verts;
        u16 *indices = &ctx->indices[ ctx->num_indices ];
        
+       ui_rect_copy( ctx->clipping, vertices[0].clip );
+       ui_rect_copy( ctx->clipping, vertices[1].clip );
+       ui_rect_copy( ctx->clipping, vertices[2].clip );
+       ui_rect_copy( ctx->clipping, vertices[3].clip );
+       
        indices[0] = ind_start+0;
        indices[1] = ind_start+2;
        indices[2] = ind_start+1;
@@ -439,7 +486,7 @@ static struct ui_vert *ui_fill_rect_uv( ui_ctx *ctx, ui_rect rect, u32 colour, u
 
 static struct ui_vert *ui_fill_rect( ui_ctx *ctx, ui_rect rect, u32 colour )
 {
-       return ui_fill_rect_uv( ctx, rect, colour, (ui_px[4]){ 66, 72-66, 66, 72-66 } );
+       return ui_fill_rect_uv( ctx, rect, colour, (ui_px[4]){ 4,124,4,124 } );
 }
 
 static void ui_text( ui_ctx *ctx, const char *str, ui_px scale, int alignment )
@@ -448,10 +495,10 @@ static void ui_text( ui_ctx *ctx, const char *str, ui_px scale, int alignment )
 
        text_cursor[0] = ctx->cursor[0];
        text_cursor[1] = ctx->cursor[1];
-       text_cursor[2] = 7*scale;
-       text_cursor[3] = 7*scale;
+       text_cursor[2] = scale*8;
+       text_cursor[3] = scale*8;
 
-       u32 current_colour = 0xffffffff;
+       u32 current_colour = ctx->override_colour;
 
        const char *_c = str;
        char c;
@@ -467,13 +514,19 @@ static void ui_text( ui_ctx *ctx, const char *str, ui_px scale, int alignment )
                {
                        u8 glyph_base[2];
                        u8 glyph_index = c - 32;
-                       glyph_base[0] = glyph_index%10;
-                       glyph_base[1] = (glyph_index-glyph_base[0])/10;
+                       glyph_base[0] = glyph_index&0xf;
+                       glyph_base[1] = (glyph_index-glyph_base[0])>>4;
                        
-                       glyph_base[0] *= 7;
-                       glyph_base[1] *= 7;
+                       glyph_base[0] *= 8;
+                       glyph_base[1] *= 8;
                        
-                       ui_fill_rect_uv( ctx, text_cursor, current_colour, (ui_px[4]){glyph_base[0],72-glyph_base[1],glyph_base[0]+7,72-(glyph_base[1]+7)} );
+                       ui_fill_rect_uv( ctx, text_cursor, current_colour, 
+                               (ui_px[4]){
+                                       glyph_base[0],
+                                       128-glyph_base[1],
+                                       glyph_base[0]+8,
+                                       128-(glyph_base[1]+8)
+                               });
                }
                else if( c == '\x1B' )
                {
@@ -510,9 +563,10 @@ static void ui_text( ui_ctx *ctx, const char *str, ui_px scale, int alignment )
                                        break;
                                }
                        }
+                       continue;
                }
                
-               text_cursor[0] += ui_glyph_spacing_x*scale;
+               text_cursor[0] += (ui_glyph_spacing_x*scale)/2;
        }
 }
 
@@ -533,6 +587,8 @@ static void ui_begin( ui_ctx *ctx, ui_px res_x, ui_px res_y )
        
        ctx->num_verts = 0;
        ctx->num_indices = 0;
+       
+       ui_release_clip( ctx );
 }
 
 static void ui_resolve( ui_ctx *ctx )