circle :: (mode: FillMode, x, y, r: f32, segments: i32 = 24) -> void #foreign "heartbreak" "graphics_circle" ---
ellipse :: (mode: FillMode, x, y, r1, r2: f32, segments: i32 = 24) -> void #foreign "heartbreak" "graphics_ellipse" ---
arc :: (mode: FillMode, x, y, r, a1, a2: f32, segments: i32 = 24) -> void #foreign "heartbreak" "graphics_arc" ---
-print :: (text: str, x, y: f32) -> void #foreign "heartbreak" "graphics_print" ---
+print :: (text: str, x, y: f32, max_width: f32 = -1) -> void #foreign "heartbreak" "graphics_print" ---
//
// Transforms
//
-origin :: () -> void #foreign "heartbreak" "graphics_origin" ---
-translate :: (x, y: f32) -> void #foreign "heartbreak" "graphics_translate" ---
-scale :: (x, y: f32) -> void #foreign "heartbreak" "graphics_scale" ---
-shear :: (x, y: f32) -> void #foreign "heartbreak" "graphics_shear" ---
+origin :: () -> void #foreign "heartbreak" "graphics_origin" ---
+translate :: (x, y: f32) -> void #foreign "heartbreak" "graphics_translate" ---
+scale :: (x, y: f32) -> void #foreign "heartbreak" "graphics_scale" ---
+shear :: (x, y: f32) -> void #foreign "heartbreak" "graphics_shear" ---
rotate :: (angle: f32) -> void #foreign "heartbreak" "graphics_rotate" ---
-push :: () -> void #foreign "heartbreak" "graphics_push" ---
-pop :: () -> void #foreign "heartbreak" "graphics_pop" ---
+push :: () -> void #foreign "heartbreak" "graphics_push" ---
+pop :: () -> void #foreign "heartbreak" "graphics_pop" ---
//
// Objects
"\n"
"void main() {\n"
" gl_Position = u_view * vec4((u_world * vec3(a_vertex, 1)).xy, 0, 1);\n"
-" v_color = a_color * u_color;\n"
+" v_color = a_color;\n"
" v_texture = a_texture;\n"
"}";
}
static void gfx_immediate_renderer_update_world_transform(ImmediateRenderer *ir) {
+ if (!ir->world_transform_dirty) return;
+
// TODO: Speed this process up either but changing mat3 to be a mat4x3 or something...
f32* d = bh_arr_last(ir->world_transforms).data;
f32 dumb_way_of_converting_a_matrix[] = {
glBindBuffer(GL_UNIFORM_BUFFER, ir->matrix_block_buffer);
glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof(f32), 12 * sizeof(f32), dumb_way_of_converting_a_matrix);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ ir->world_transform_dirty = 0;
}
void gfx_immediate_renderer_init(ImmediateRenderer *ir, bh_allocator allocator) {
gfx_image_unbind(ir);
ir->current_color = (ImmediateColor) { 1, 1, 1, 1 };
- ir->last_world_transforms_count = 0;
+ ir->world_transform_dirty = 1;
ir->active_font = gfx_font_load(ir, "/usr/share/fonts/nerd-fonts-complete/TTF/mononoki-Regular Nerd Font Complete Mono.ttf", 32.0f);
}
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(ImmediateVertex) * ir->tris_vertex_count, ir->tris_vertex_data);
glBindBuffer(GL_ARRAY_BUFFER, -1);
- glUseProgram(ir->tris_shader.program);
- if (bh_arr_length(ir->world_transforms) != ir->last_world_transforms_count) {
- gfx_immediate_renderer_update_world_transform(ir);
- }
+ gfx_immediate_renderer_update_world_transform(ir);
+ glUseProgram(ir->tris_shader.program);
glBindVertexArray(ir->tris_vertex_array);
glDrawArrays(GL_TRIANGLES, 0, ir->tris_vertex_count);
glBindVertexArray(-1);
ir->tris_vertex_count = 0;
- ir->last_world_transforms_count = bh_arr_length(ir->world_transforms);
}
void gfx_immediate_renderer_set_color(ImmediateRenderer *ir, ImmediateColor color) {
ir->current_color = color;
+
+ glBindBuffer(GL_UNIFORM_BUFFER, ir->matrix_block_buffer);
+ glBufferSubData(GL_UNIFORM_BUFFER, sizeof(f32) * (16 + 12), 4 * sizeof(f32), &color);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void gfx_immediate_renderer_push_vertex(ImmediateRenderer *ir, f32 x, f32 y, f32 u, f32 v) {
ir->tris_vertex_count += 3;
}
-void gfx_immediate_renderer_render_text(ImmediateRenderer *ir, f32 x, f32 y, char* msgptr, i32 msglen) {
+void gfx_immediate_renderer_render_text(ImmediateRenderer *ir, f32 x, f32 y, char* msgptr, i32 msglen, f32 max_width) {
if (ir->tris_vertex_count > 0) gfx_immediate_renderer_flush(ir);
stbtt_aligned_quad* quads = (stbtt_aligned_quad *) alloca(msglen * sizeof(stbtt_aligned_quad));
i32 quad_num = 0;
+ f32 origx = x;
+
while (msglen--) {
stbtt_GetPackedQuad(ir->active_font->char_data,
FONT_INTERNAL_IMAGE_SIZE, FONT_INTERNAL_IMAGE_SIZE,
*msgptr - ir->active_font->first_character,
&x, &y, &quads[quad_num], 0);
+ if (max_width > 0 && x - origx >= max_width) {
+ x = origx;
+ y += ir->active_font->size;
+
+ stbtt_GetPackedQuad(ir->active_font->char_data,
+ FONT_INTERNAL_IMAGE_SIZE, FONT_INTERNAL_IMAGE_SIZE,
+ *msgptr - ir->active_font->first_character,
+ &x, &y, &quads[quad_num], 0);
+ }
+
msgptr++, quad_num++;
}
glBindTexture(GL_TEXTURE_2D, ir->active_font->texture);
glUseProgram(ir->font_shader.program);
glUniform1i(ir->font_shader.texture_uniform, 1);
+
+ gfx_immediate_renderer_update_world_transform(ir);
glBindVertexArray(ir->font_vertex_array);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (void *) 0, quad_num);
glBindVertexArray(-1);
gfx_immediate_renderer_flush(ir);
mat3 new_top = bh_arr_last(ir->world_transforms);
bh_arr_push(ir->world_transforms, new_top);
+
+ ir->world_transform_dirty = 1;
}
void gfx_immediate_renderer_pop_state(ImmediateRenderer *ir) {
gfx_immediate_renderer_flush(ir);
bh_arr_pop(ir->world_transforms);
+
+ ir->world_transform_dirty = 1;
}
void gfx_immediate_renderer_origin(ImmediateRenderer *ir) {
gfx_immediate_renderer_flush(ir);
mat3* top = &bh_arr_last(ir->world_transforms);
mat3_identity(top);
+
+ ir->world_transform_dirty = 1;
}
void gfx_immediate_renderer_translate(ImmediateRenderer *ir, f32 dx, f32 dy) {
mat3_mul(&new_top, bh_arr_last(ir->world_transforms), trans);
bh_arr_last(ir->world_transforms) = new_top;
+ ir->world_transform_dirty = 1;
}
void gfx_immediate_renderer_scale(ImmediateRenderer *ir, f32 sx, f32 sy) {
mat3_mul(&new_top, bh_arr_last(ir->world_transforms), scale);
bh_arr_last(ir->world_transforms) = new_top;
+ ir->world_transform_dirty = 1;
}
void gfx_immediate_renderer_rotate(ImmediateRenderer *ir, f32 angle) {
mat3_mul(&new_top, bh_arr_last(ir->world_transforms), rotate);
bh_arr_last(ir->world_transforms) = new_top;
+ ir->world_transform_dirty = 1;
}
void gfx_immediate_renderer_shear(ImmediateRenderer *ir, f32 kx, f32 ky) {
mat3_mul(&new_top, bh_arr_last(ir->world_transforms), shear);
bh_arr_last(ir->world_transforms) = new_top;
+ ir->world_transform_dirty = 1;
}
font->first_character = FONT_FIRST_CHAR;
font->last_character = FONT_FIRST_CHAR + FONT_CHAR_COUNT - 1;
font->char_data = font_char_data;
+ font->size = (f32) font_size;
return font;
}