Browse Source

font rasterizer, example scene, null tex func, new sourparse

IverMartinson 5 months ago
parent
commit
eadd51ec7a

+ 2 - 1
.vscode/settings.json

@@ -9,7 +9,8 @@
         "initializer_list": "c",
         "initializer_list": "c",
         "utility": "c",
         "utility": "c",
         "compare": "c",
         "compare": "c",
-        "rasteriver.h": "c"
+        "rasteriver.h": "c",
+        "custom_types.h": "c"
     },
     },
     "OpenCL.explorer.localizedProperties": false,
     "OpenCL.explorer.localizedProperties": false,
     "C_Cpp.default.compilerPath": "/bin/gcc"
     "C_Cpp.default.compilerPath": "/bin/gcc"

BIN
build/librasteriver.so


BIN
build/libsourparse.so


BIN
build/main.bin


BIN
compiled_libs/librasteriver.so


BIN
compiled_libs/libsourparse.so


+ 3 - 1
readme.md

@@ -59,4 +59,6 @@ To run the binary, it needs to be in the same folder as librasteriver.so (if you
 - [x] tileable textures
 - [x] tileable textures
 - [ ] UI elements (just images? text? custom text rasterizer? buttons?)
 - [ ] UI elements (just images? text? custom text rasterizer? buttons?)
 - [ ] Documentation
 - [ ] Documentation
-- [ ] text rasterizer for UI
+- [x] text rasterizer for UI [NOTE: its for any texture in general]
+- [ ] texture masking; greyscale texture is used to filter out parts of another image. All white = keep the pixel, all black = make it transparent
+- [x] add request empty texture

+ 2 - 0
src/headers/functions.h

@@ -19,5 +19,7 @@ void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f posi
 void RI_draw_line(RI_texture *target_texture, RI_vector_2 point_a, RI_vector_2 point_b, uint32_t color);
 void RI_draw_line(RI_texture *target_texture, RI_vector_2 point_a, RI_vector_2 point_b, uint32_t color);
 RI_vector_2f v2_to_2f(RI_vector_2 v);
 RI_vector_2f v2_to_2f(RI_vector_2 v);
 RI_vector_2 v2f_to_2(RI_vector_2f v);
 RI_vector_2 v2f_to_2(RI_vector_2f v);
+void RI_clear_texture(RI_texture *target_texture);
+RI_texture* RI_request_empty_texture(RI_vector_2 resolution);
 
 
 #endif
 #endif

+ 26 - 2
src/headers/sourparse.h

@@ -3,16 +3,36 @@
 
 
 #include "stdint.h"
 #include "stdint.h"
 
 
+typedef struct {
+    int16_t ascender;
+    int16_t descender;
+    int16_t line_gap;
+    uint16_t advance_max_width;
+    int16_t min_left_side_bearing;
+    int16_t min_right_side_bearing;
+    int16_t x_max_extent;
+    int16_t carat_slope_rise;
+    int16_t carat_slope_run;
+    int16_t carat_offset;
+    int16_t metric_data_format;
+    uint16_t number_of_h_metrics;
+} SP_hhea_table;
+
+typedef struct {
+    uint16_t advance_width;
+    int16_t left_side_bearing;
+} SP_long_hor_metric;
+
 typedef struct {
 typedef struct {
     int scale_x, scale01, scale10, scale_y;
     int scale_x, scale01, scale10, scale_y;
     int glyph_index;
     int glyph_index;
     int16_t arg1, arg2;
     int16_t arg1, arg2;
-    uint16_t flags;
 } SP_component;
 } SP_component;
 
 
 typedef struct {
 typedef struct {
     int *x_coords, *y_coords, *contour_end_indicies; 
     int *x_coords, *y_coords, *contour_end_indicies; 
     int number_of_points, number_of_contours, number_of_components;
     int number_of_points, number_of_contours, number_of_components;
+    int advance_width;
     uint8_t *flags;
     uint8_t *flags;
     int16_t x_min, y_min, x_max, y_max;
     int16_t x_min, y_min, x_max, y_max;
     SP_component *components;
     SP_component *components;
@@ -21,10 +41,14 @@ typedef struct {
 
 
 typedef struct {
 typedef struct {
     int current_byte, number_of_glyphs, *glyph_offsets; 
     int current_byte, number_of_glyphs, *glyph_offsets; 
-    uint16_t *unicode_to_glyph_indicies, units_per_em;
+    uint16_t *unicode_to_glyph_indicies;
+    float units_per_em;
     uint8_t *buffer;
     uint8_t *buffer;
     SP_glyph *glyphs;
     SP_glyph *glyphs;
     int16_t index_to_loca_format;
     int16_t index_to_loca_format;
+    SP_long_hor_metric *h_metrics;
+    SP_hhea_table hhea_table;
+    int16_t *left_side_bearings;
 } SP_font;
 } SP_font;
 
 
 SP_font* SP_load_font(char *filename);
 SP_font* SP_load_font(char *filename);

+ 34 - 67
src/launch_program/main.c

@@ -1,7 +1,9 @@
 #include "../headers/rasteriver.h"
 #include "../headers/rasteriver.h"
 
 
 int main(){
 int main(){
-    SP_font *font = SP_load_font("fonts/CalSans-Regular.ttf");
+    SP_font *comic_sans = SP_load_font("fonts/ComicSans-Regular.ttf");
+    SP_font *cal_sans = SP_load_font("fonts/CalSans-Regular.ttf");
+    SP_font *QwitcherGrypen = SP_load_font("fonts/QwitcherGrypen-Bold.ttf");
     
     
     // get RasterIver context
     // get RasterIver context
     RasterIver *ri = RI_get_ri();
     RasterIver *ri = RI_get_ri();
@@ -14,79 +16,32 @@ int main(){
     int running = 1;
     int running = 1;
 
 
     // data for loading files
     // data for loading files
-    char *filenames[] = {"objects/unit_cube.obj", "objects/cow-nonormals.obj", "objects/test_guy.obj", "objects/unit_plane.obj"};
-    RI_texture_creation_data texture_creation_info[4] = {{"textures/bill_mcdinner.png", {0, 0}}, {"textures/this is the floor.png", {0, 0}}, {"textures/test_guy_texture.png", {0, 0}}, {"textures/THIS IS THE WALL.png", {0, 0}}};
-    
+    char *filenames[] = {"objects/unit_plane.obj"};
+
     // requesting assets
     // requesting assets
-    RI_mesh* meshes = RI_request_meshes(4, filenames, 0);
-    RI_texture* textures = RI_request_textures(4, texture_creation_info);
-    RI_material* materials = RI_request_materials(4);
-    RI_actor* actors = RI_request_actors(4);
+    RI_mesh* meshes = RI_request_meshes(1, filenames, 0);
+    RI_material* materials = RI_request_materials(1);
+    RI_actor* actors = RI_request_actors(1);
     RI_scene* scenes = RI_request_scenes(1);
     RI_scene* scenes = RI_request_scenes(1);
 
 
     RI_scene* scene = &scenes[0];
     RI_scene* scene = &scenes[0];
 
 
     // meshes
     // meshes
-    RI_mesh* unit_plane_mesh = &meshes[3];
-    RI_mesh* test_object_mesh = &meshes[0];
-
-    // textures
-    RI_texture* test_object_texture = &textures[0];
-    RI_texture* floor_texture = &textures[1];
-    RI_texture* wall_texture = &textures[3];
+    RI_mesh* text_plane_mesh = &meshes[0];
 
 
     // materials
     // materials
-    RI_material* floor_material = &materials[0];
-    floor_material->flags = RI_MATERIAL_HAS_TEXTURE | RI_MATERIAL_DOUBLE_SIDED | RI_MATERIAL_USE_UV_LOOP_MULTIPLIER;
-    floor_material->texture_reference = floor_texture;
-    floor_material->albedo = 0xFFFFFFFF;
-    floor_material->uv_loop_multiplier = (RI_vector_2f){25, 25};
-
-    RI_material* wall_material = &materials[1];
-    wall_material->flags = RI_MATERIAL_DOUBLE_SIDED | RI_MATERIAL_HAS_TEXTURE | RI_MATERIAL_USE_UV_RENDER_RESOLUTION;
-    wall_material->albedo = 0xFF7777FF;
-    wall_material->texture_reference = wall_texture;
-    wall_material->texture_render_size = (RI_vector_2f){25, 50};
-
-    RI_material* test_object_material = &materials[2];
-    test_object_material->flags = RI_MATERIAL_HAS_TEXTURE;
-    test_object_material->texture_reference = test_object_texture;
-    test_object_material->albedo = 0xFFFFFFF;
-    test_object_material->wireframe_width = 0.1;
-
-    RI_material* screen_material = &materials[3];
-    screen_material->flags = RI_MATERIAL_HAS_TEXTURE | RI_MATERIAL_DOUBLE_SIDED;
-    screen_material->texture_reference = ri->frame_buffer;
-    screen_material->albedo = 0xFFFFFFFF;
+    RI_material* text_plane_material = &materials[0];
+    text_plane_material->flags = RI_MATERIAL_HAS_TEXTURE | RI_MATERIAL_DOUBLE_SIDED;
+    text_plane_material->texture_reference = RI_request_empty_texture((RI_vector_2){400, 400});
+    text_plane_material->albedo = 0xFFFFFFFF;
 
 
     // actors
     // actors
-    RI_actor* floor = &actors[2];
-    floor->material_reference = floor_material;
-    floor->mesh_reference = unit_plane_mesh;
-    floor->transform.scale = (RI_vector_3f){1000, 100, 1000};
-    floor->transform.position = (RI_vector_3f){0, -100, 200};
-    floor->transform.rotation = (RI_vector_4f){0, 1, 0, 0};
-
-    RI_actor* wall = &actors[1];
-    wall->material_reference = wall_material;
-    wall->mesh_reference = unit_plane_mesh;
-    wall->transform.scale = (RI_vector_3f){100, 100, 100};
-    wall->transform.position = (RI_vector_3f){0, 0, 300};
-    wall->transform.rotation = (RI_vector_4f){0.70710678, 0.70710678, 0, 0};
-
-    RI_actor* test_object = &actors[0];
-    test_object->material_reference = test_object_material;
-    test_object->mesh_reference = test_object_mesh;
-    test_object->transform.scale = (RI_vector_3f){2, 2, 2};
-    test_object->transform.position = (RI_vector_3f){-50, 100, 100};
-    test_object->transform.rotation = (RI_vector_4f){0, 1, 0, 0};
-
-    RI_actor* screen = &actors[3];
-    screen->material_reference = screen_material;
-    screen->mesh_reference = unit_plane_mesh;
-    screen->transform.scale = (RI_vector_3f){50, 50, 50};
-    screen->transform.position = (RI_vector_3f){0, 0, 250};
-    screen->transform.rotation = (RI_vector_4f){0, 1, 0, 0};
+    RI_actor* text_plane = &actors[0];
+    text_plane->material_reference = text_plane_material;
+    text_plane->mesh_reference = text_plane_mesh;
+    text_plane->transform.scale = (RI_vector_3f){50, 50, 50};
+    text_plane->transform.position = (RI_vector_3f){100, 50, 400};
+    text_plane->transform.rotation = (RI_vector_4f){0, 1, 0, 0};
 
 
     RI_add_actors_to_scene(1, actors, scene);
     RI_add_actors_to_scene(1, actors, scene);
 
 
@@ -100,15 +55,27 @@ int main(){
     scene->antialiasing_subsample_resolution = 8;
     scene->antialiasing_subsample_resolution = 8;
     scene->flags = RI_SCENE_DONT_USE_AA;
     scene->flags = RI_SCENE_DONT_USE_AA;
     
     
+    RI_clear_texture(text_plane_material->texture_reference);
+
+    RI_render_text(comic_sans, text_plane_material->texture_reference, (RI_vector_2f){0, 0}, 0xFFFFFFFF, 2, 80, "WOWWWW!!!11!!");
+    RI_render_text(cal_sans, text_plane_material->texture_reference, (RI_vector_2f){0, 200}, 0xFFFFFFFF, 2, 80, "Wow!!");
+    RI_render_text(QwitcherGrypen, text_plane_material->texture_reference, (RI_vector_2f){0, 300}, 0xFFFFFFFF, 2, 80, "WOW!!!!");    
+
     while (running){
     while (running){
+        RI_euler_rotation_to_quaternion(&text_plane->transform.rotation, (RI_vector_3f){-1.5, ri->frame / 10.0, 0});
+
         RI_render(scene, ri->frame_buffer, 1);
         RI_render(scene, ri->frame_buffer, 1);
         
         
-        RI_render_text(font, ri->frame_buffer, (RI_vector_2f){50, 200}, 0xFFFFFFFF, 10, 300, "A");
-        
+        RI_render_text(comic_sans, ri->frame_buffer, (RI_vector_2f){00, 250}, 0xFFFFFFFF, 2, 80, "I love Comic Sans");
+        RI_render_text(cal_sans, ri->frame_buffer, (RI_vector_2f){00, 350}, 0xFFFFFFFF, 2, 80, "I love Cal Sans");
+        RI_render_text(QwitcherGrypen, ri->frame_buffer, (RI_vector_2f){00, 450}, 0xFFFFFFFF, 2, 80, "I love Qwitcher Grypen");
+
         RI_tick();
         RI_tick();
 
 
         ++ri->frame;
         ++ri->frame;
     }
     }
 
 
-    SP_free_font(font);
+    SP_free_font(comic_sans);
+    SP_free_font(cal_sans);
+    SP_free_font(QwitcherGrypen);
 }
 }

+ 84 - 42
src/library/rasteriver.c

@@ -161,6 +161,21 @@ void written_RI_free(void *__ptr, const char *caller, int line){
     free(__ptr);
     free(__ptr);
 }
 }
 
 
+RI_texture* RI_request_empty_texture(RI_vector_2 resolution){
+    RI_texture *new_texture = RI_malloc(sizeof(RI_texture));
+
+    new_texture->image_buffer = RI_malloc(sizeof(uint32_t) * resolution.x * resolution.y);
+    new_texture->resolution = resolution;
+
+    return new_texture;
+}
+
+void RI_clear_texture(RI_texture *target_texture){
+    for (int i = 0; i < target_texture->resolution.x * target_texture->resolution.y; ++i){
+        target_texture->image_buffer[i] = 0x00000000;
+    }
+}
+
 void RI_draw_line(RI_texture *target_texture, RI_vector_2 point_a, RI_vector_2 point_b, uint32_t color){
 void RI_draw_line(RI_texture *target_texture, RI_vector_2 point_a, RI_vector_2 point_b, uint32_t color){
     int num_pixels = distance_2(point_a, point_b);
     int num_pixels = distance_2(point_a, point_b);
     
     
@@ -197,25 +212,25 @@ void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size,
     for (int contour = 0; contour < glyph->number_of_contours; ++contour){
     for (int contour = 0; contour < glyph->number_of_contours; ++contour){
         // if we are at contour 0, point_start is 0.
         // if we are at contour 0, point_start is 0.
         // if contour is > 0 but != 0, point_start is equal to the previous index
         // if contour is > 0 but != 0, point_start is equal to the previous index
-        int point_start = contour > 0 ? glyph->contour_end_indicies[contour - 1] : 0;
+        int point_start = contour > 0 ? (glyph->contour_end_indicies[contour - 1] + 1) : 0;
 
 
         int point_offset = point_start;
         int point_offset = point_start;
 
 
         // find first on-curve point because the first point isn't always on the curves
         // find first on-curve point because the first point isn't always on the curves
-        while (!(glyph->flags[point_offset] & 1)){
-            point_offset++;
-        }
+        // while (!(glyph->flags[point_offset] & 1)){
+            // point_offset++;
+        // }
 
 
-        for (int point = 0; point < glyph->contour_end_indicies[contour]; ++point){
-            if (new_point_count == allocated_new_points){
+        for (int point = 0; point <= glyph->contour_end_indicies[contour] + 1 - point_start; ++point){
+            if (new_point_count + 1 >= allocated_new_points){
                 allocated_new_points += 20;
                 allocated_new_points += 20;
 
 
                 new_points = RI_realloc(new_points, sizeof(RI_vector_2f) * allocated_new_points);
                 new_points = RI_realloc(new_points, sizeof(RI_vector_2f) * allocated_new_points);
             }
             }
             
             
-            int cur = (point + point_offset) % glyph->contour_end_indicies[contour];
-            int next = (point + point_offset + 1) % glyph->contour_end_indicies[contour];
-            
+            int cur = (point % (glyph->contour_end_indicies[contour] + 1 - point_start) + point_offset);
+            int next = ((point + 1) % (glyph->contour_end_indicies[contour] + 1 - point_start) + point_offset);
+
             new_points[new_point_count].x = (float)glyph->x_coords[cur] / units_per_em * size + position.x;
             new_points[new_point_count].x = (float)glyph->x_coords[cur] / units_per_em * size + position.x;
             new_points[new_point_count].y = (float)glyph->y_coords[cur] / units_per_em * size + position.y;
             new_points[new_point_count].y = (float)glyph->y_coords[cur] / units_per_em * size + position.y;
 
 
@@ -230,47 +245,58 @@ void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size,
         }
         }
 
 
         contour_ends[contour] = new_point_count;
         contour_ends[contour] = new_point_count;
-        debug("%d", new_point_count);
     }
     }
     
     
     allocated_new_points = new_point_count;
     allocated_new_points = new_point_count;
 
 
-    for (int y = (int)((float)glyph->y_min / (float)units_per_em * size) + position.y; y < (int)((float)glyph->y_max / (float)units_per_em * size) + position.y; ++y){
-        for (int x = (int)((float)glyph->x_min / (float)units_per_em * size) + position.x; x < (int)((float)glyph->x_max / (float)units_per_em * size) + position.x; ++x){
-            int intersections = 0;
-            
-            for (int contour = 0; contour < glyph->number_of_contours; ++contour){
-                int p_start = contour_ends[contour > 0 ? contour - 1 : 0];
-                int p_end = contour_ends[contour];
-
-                for (int point = 0; point < p_end - p_start; point += 2){
-                    RI_vector_2f point_a = new_points[p_start + point % (p_end - p_start)];
-                    RI_vector_2f point_b = new_points[p_start + (point + 1) % (p_end - p_start)];
-                    RI_vector_2f point_c = new_points[p_start + (point + 2) % (p_end - p_start)];
+    // maybe make multiple arrays that are lists of lines in increments of y values so that we dont have to check every line even if its above the pixel (the ray only goes to the right)
 
 
-                    RI_vector_2f prev_point = new_points[p_start + point % p_end];
+    RI_vector_2f *lines = RI_malloc(sizeof(RI_vector_2f) * (new_point_count / 2) * (bezier_resolution <= 1 ? 2 : bezier_resolution) + 30);
 
 
-                    for (int i = 0; i < bezier_resolution; ++i){
-                        float w = (float)(i + 1) / (float)bezier_resolution;
-
-                        RI_draw_line(target_texture, v2f_to_2(point_a), v2f_to_2(point_c), 0xFF77FF77);
+    for (int contour = 0; contour < glyph->number_of_contours; ++contour){
+        int p_start = (contour > 0 ? contour_ends[contour - 1] : 0);
+        int p_end = contour_ends[contour];
 
 
-                        RI_vector_2f bez_point; vector_2f_bezier_interpolate(point_a, point_b, point_c, &bez_point, w);
+        for (int point = p_start; point < p_end - 2; point += 2){
+            RI_vector_2f point_a = new_points[point];
+            RI_vector_2f point_b = new_points[(point + 1)];
+            RI_vector_2f point_c = new_points[(point + 2)];
+            
+            RI_vector_2f prev_point = new_points[point];
 
 
-                        if(intersects(prev_point, bez_point, (RI_vector_2f){x, y})) intersections++; 
+            for (int i = 0; i < bezier_resolution; ++i){
+                float w = (float)(i + 1) / (float)bezier_resolution;
+                
+                RI_vector_2f bez_point; 
                 
                 
-                        RI_tick();
+                if (bezier_resolution <= 1) bez_point = point_c;
+                else vector_2f_bezier_interpolate(point_a, point_b, point_c, &bez_point, w);
 
 
-                        int x;
+                lines[point + i] = prev_point;
+                lines[point + i + 1] = bez_point;
 
 
-                        for (int _ = 0; _ < 10000000; _++)x = 10000*10000*_*_*_*_*_;
-                        
-                        prev_point = bez_point;
-                    }
-                }
+                prev_point = bez_point;
             }
             }
+        }
+    }
+
+    for (int y = fmax((int)((float)glyph->y_min / (float)units_per_em * size) + position.y, 0.0); y < fmin((int)((float)glyph->y_max / (float)units_per_em * size) + position.y, target_texture->resolution.y); ++y){
+        for (int x = fmax((int)((float)glyph->x_min / (float)units_per_em * size) + position.x, 0.0); x < fmin((int)((float)glyph->x_max / (float)units_per_em * size) + position.x, target_texture->resolution.x); ++x){
+            int intersections = 0;
             
             
-            // if (intersections % 2 != 0) target_texture->image_buffer[y * target_texture->resolution.x + x] = color;
+            for (int contour = 0; contour < glyph->number_of_contours; ++contour){
+                int p_start = (contour > 0 ? contour_ends[contour - 1] : 0);
+                int p_end = contour_ends[contour];
+        
+                for (int point = p_start; point < p_end - 2; point += 2){ 
+            for (int i = 0; i < bezier_resolution; ++i){
+
+                    if(intersects(lines[point + i], lines[point + i + 1], (RI_vector_2f){x, y})) intersections++; 
+                            }  
+                                      }
+            }
+
+            if (intersections % 2 != 0) target_texture->image_buffer[y * target_texture->resolution.x + x] = color;
         }
         }
     }
     }
 
 
@@ -281,26 +307,42 @@ void render_glyph(RI_texture *target_texture, RI_vector_2f position, float size,
 void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, float size, char *text){
 void RI_render_text(SP_font *font, RI_texture *target_texture, RI_vector_2f position, uint32_t color, int bezier_resolution, float size, char *text){
     int character_count = strlen(text);
     int character_count = strlen(text);
     
     
+    int current_advance_width = 0;
+    RI_vector_2f glyph_position = position;
+
     for (int character_i = 0; character_i < character_count; ++character_i){
     for (int character_i = 0; character_i < character_count; ++character_i){
         int glyph = font->unicode_to_glyph_indicies[text[character_i]];
         int glyph = font->unicode_to_glyph_indicies[text[character_i]];
         
         
+        if (glyph >= font->number_of_glyphs) glyph = 0;
+        
         SP_glyph *current_glyph = &font->glyphs[glyph];
         SP_glyph *current_glyph = &font->glyphs[glyph];
         
         
+        glyph_position.x = position.x + font->h_metrics[glyph].left_side_bearing / font->units_per_em * size;
+        
         if (current_glyph->number_of_contours > 0){
         if (current_glyph->number_of_contours > 0){
-            render_glyph(target_texture, position, size, color, bezier_resolution, (int)font->units_per_em, current_glyph);
+            render_glyph(target_texture, glyph_position, size, color, bezier_resolution, font->units_per_em, current_glyph);
+        }
+        else if (current_glyph->number_of_contours == 0){
+            // do nothing, glyph is empty
         }
         }
         else {
         else {
             for (int k = 0; k < current_glyph->number_of_components; k++){
             for (int k = 0; k < current_glyph->number_of_components; k++){
                 int c_glyph = current_glyph->components[k].glyph_index;
                 int c_glyph = current_glyph->components[k].glyph_index;
                 
                 
-                int offset_x = (int)current_glyph->components[k].arg1;
-                int offset_y = (int)current_glyph->components[k].arg2;
+                float offset_x = (float)current_glyph->components[k].arg1;
+                float offset_y = (float)current_glyph->components[k].arg2;
+
+                glyph_position.x += offset_x / font->units_per_em * size;
+                glyph_position.y += offset_y / font->units_per_em * size;
+                
+                render_glyph(target_texture, glyph_position, size, color, bezier_resolution, font->units_per_em, &font->glyphs[c_glyph]);
                 
                 
-                render_glyph(target_texture, position, size, color, bezier_resolution, (int)font->units_per_em, &font->glyphs[c_glyph]);
+                glyph_position.x -= offset_x / font->units_per_em * size;
+                glyph_position.y -= offset_y / font->units_per_em * size;
             }
             }
         }
         }
         
         
-        position.x += 50;
+        position.x += (float)font->h_metrics[glyph].advance_width / font->units_per_em * size;
     }
     }
 }
 }