From: Brendan Hansen Date: Mon, 8 Nov 2021 02:23:57 +0000 (-0600) Subject: added drawing line primitives X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=b2e8c010f3af312100a186d3865a91d433c46fd1;p=heartbreak.git added drawing line primitives --- diff --git a/include/gfx.h b/include/gfx.h index 712880f..44075f0 100644 --- a/include/gfx.h +++ b/include/gfx.h @@ -51,6 +51,11 @@ typedef struct ImmediateColor { f32 r, g, b, a; } ImmediateColor; +typedef enum ImmediateMode { + IMMEDIATE_MODE_TRIANGLES = 1, + IMMEDIATE_MODE_LINES = 2, +} ImmediateMode; + typedef struct ImmediateVertex { f32 x, y; f32 u, v; @@ -66,6 +71,7 @@ typedef struct ImmediateRenderer { u32 tris_vertex_count; ImmediateColor current_color; + ImmediateMode current_mode; Shader tris_shader; GLint tris_vertex_array; @@ -86,6 +92,7 @@ typedef struct ImmediateRenderer { void gfx_immediate_renderer_init(ImmediateRenderer *ir, bh_allocator allocator); void gfx_immediate_renderer_flush(ImmediateRenderer *ir); +void gfx_immediate_renderer_set_primitive_mode(ImmediateRenderer *ir, ImmediateMode mode); void gfx_immediate_renderer_set_color(ImmediateRenderer *ir, ImmediateColor color); void gfx_immediate_renderer_push_vertex(ImmediateRenderer *ir, f32 x, f32 y, f32 u, f32 v); void gfx_immediate_renderer_push_triangle(ImmediateRenderer *ir, diff --git a/src/gfx.c b/src/gfx.c index 3c0ee21..3a36e16 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -256,6 +256,7 @@ void gfx_immediate_renderer_init(ImmediateRenderer *ir, bh_allocator allocator) gfx_image_unbind(ir); + ir->current_mode = IMMEDIATE_MODE_TRIANGLES; ir->current_color = (ImmediateColor) { 1, 1, 1, 1 }; ir->world_transform_dirty = 1; @@ -271,14 +272,29 @@ void gfx_immediate_renderer_flush(ImmediateRenderer *ir) { gfx_immediate_renderer_update_world_transform(ir); + static const GLint primitives[] = { + 0, + GL_TRIANGLES, + GL_LINES, + }; + GLint primitive = primitives[ir->current_mode]; + glUseProgram(ir->tris_shader.program); glBindVertexArray(ir->tris_vertex_array); - glDrawArrays(GL_TRIANGLES, 0, ir->tris_vertex_count); + glDrawArrays(primitive, 0, ir->tris_vertex_count); glBindVertexArray(-1); ir->tris_vertex_count = 0; } +void gfx_immediate_renderer_set_primitive_mode(ImmediateRenderer *ir, ImmediateMode mode) { + if (ir->current_mode != mode && ir->tris_vertex_count > 0) { + gfx_immediate_renderer_flush(ir); + } + + ir->current_mode = mode; +} + void gfx_immediate_renderer_set_color(ImmediateRenderer *ir, ImmediateColor color) { ir->current_color = color; diff --git a/src/heartbreak_graphics.c b/src/heartbreak_graphics.c index 6d85b11..3212b41 100644 --- a/src/heartbreak_graphics.c +++ b/src/heartbreak_graphics.c @@ -33,117 +33,219 @@ HEARTBREAK_DEF(set_color, (WASM_F32,WASM_F32,WASM_F32,WASM_F32), ()) { HEARTBREAK_DEF(rectangle, (WASM_I32,WASM_F32,WASM_F32,WASM_F32,WASM_F32), ()) { gfx_image_unbind(&renderer); - // @TODO: Use fill mode + + i32 mode = params->data[0].of.i32; + if (mode == 1) gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_TRIANGLES); + if (mode == 2) gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_LINES); f32 x = params->data[1].of.f32; f32 y = params->data[2].of.f32; f32 w = params->data[3].of.f32; f32 h = params->data[4].of.f32; - gfx_immediate_renderer_push_triangle(&renderer, - x, y, 0, 0, - x + w, y, 0, 0, - x + w, y + h, 0, 0); + if (mode == 1) { + gfx_immediate_renderer_push_triangle(&renderer, + x, y, 0, 0, + x + w, y, 0, 0, + x + w, y + h, 0, 0); - gfx_immediate_renderer_push_triangle(&renderer, - x, y, 0, 0, - x + w, y + h, 0, 0, - x, y + h, 0, 0); + gfx_immediate_renderer_push_triangle(&renderer, + x, y, 0, 0, + x + w, y + h, 0, 0, + x, y + h, 0, 0); + + } else if (mode == 2) { + gfx_immediate_renderer_push_vertex(&renderer, x, y, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, x + w, y, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, x + w, y, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, x + w, y + h, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, x + w, y + h, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, x, y + h, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, x, y + h, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, x, y, 0, 0); + } return NULL; } HEARTBREAK_DEF(circle, (WASM_I32, WASM_F32, WASM_F32, WASM_F32, WASM_I32), ()) { gfx_image_unbind(&renderer); - // @TODO: Use fill mode - f32 x = params->data[1].of.f32; - f32 y = params->data[2].of.f32; - f32 r = params->data[3].of.f32; - i32 segments = params->data[4].of.i32; + i32 mode = params->data[0].of.i32; + if (mode == 1) { + gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_TRIANGLES); - f32 cx1 = x + r; - f32 cy1 = y; - f32 cx2 = x + cos(PI * 2 / segments) * r; - f32 cy2 = y + sin(PI * 2 / segments) * r; - f32 cx3, cy3; + f32 x = params->data[1].of.f32; + f32 y = params->data[2].of.f32; + f32 r = params->data[3].of.f32; + i32 segments = params->data[4].of.i32; - fori (i, 2, segments) { - cx3 = x + cos(i * PI * 2 / segments) * r; - cy3 = y + sin(i * PI * 2 / segments) * r; + f32 cx1 = x + r; + f32 cy1 = y; + f32 cx2 = x + cos(PI * 2 / segments) * r; + f32 cy2 = y + sin(PI * 2 / segments) * r; + f32 cx3, cy3; - gfx_immediate_renderer_push_triangle(&renderer, - cx1, cy1, 0, 0, - cx2, cy2, 0, 0, - cx3, cy3, 0, 0); + fori (i, 2, segments) { + cx3 = x + cos(i * PI * 2 / segments) * r; + cy3 = y + sin(i * PI * 2 / segments) * r; - cx2 = cx3; - cy2 = cy3; - } + gfx_immediate_renderer_push_triangle(&renderer, + cx1, cy1, 0, 0, + cx2, cy2, 0, 0, + cx3, cy3, 0, 0); - return NULL; -} + cx2 = cx3; + cy2 = cy3; + } -HEARTBREAK_DEF(ellipse, (WASM_I32, WASM_F32, WASM_F32, WASM_F32, WASM_F32, WASM_I32), ()) { - gfx_image_unbind(&renderer); - // @TODO: Use fill mode + } else if (mode == 2) { + gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_LINES); - f32 x = params->data[1].of.f32; - f32 y = params->data[2].of.f32; - f32 r1 = params->data[3].of.f32; - f32 r2 = params->data[4].of.f32; - i32 segments = params->data[5].of.i32; + f32 x = params->data[1].of.f32; + f32 y = params->data[2].of.f32; + f32 r = params->data[3].of.f32; + i32 segments = params->data[4].of.i32; - f32 cx1 = x + r1; - f32 cy1 = y; - f32 cx2 = x + cos(PI * 2 / segments) * r1; - f32 cy2 = y + sin(PI * 2 / segments) * r2; - f32 cx3, cy3; + f32 cx1 = x + r; + f32 cy1 = y; + f32 cx2, cy2; - fori (i, 2, segments) { - cx3 = x + cos(i * PI * 2 / segments) * r1; - cy3 = y + sin(i * PI * 2 / segments) * r2; + fori (i, 1, segments + 1) { + cx2 = x + cos(i * PI * 2 / segments) * r; + cy2 = y + sin(i * PI * 2 / segments) * r; - gfx_immediate_renderer_push_triangle(&renderer, - cx1, cy1, 0, 0, - cx2, cy2, 0, 0, - cx3, cy3, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, cx1, cy1, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, cx2, cy2, 0, 0); - cx2 = cx3; - cy2 = cy3; + cx1 = cx2; + cy1 = cy2; + } } return NULL; } -HEARTBREAK_DEF(arc, (WASM_I32, WASM_F32, WASM_F32, WASM_F32, WASM_F32, WASM_F32, WASM_I32), ()) { +HEARTBREAK_DEF(ellipse, (WASM_I32, WASM_F32, WASM_F32, WASM_F32, WASM_F32, WASM_I32), ()) { gfx_image_unbind(&renderer); - // @TODO: Use fill mode - f32 x = params->data[1].of.f32; - f32 y = params->data[2].of.f32; - f32 r = params->data[3].of.f32; - f32 a1 = params->data[4].of.f32; - f32 a2 = params->data[5].of.f32; - f32 segments = params->data[6].of.i32; - - f32 cx1 = x; - f32 cy1 = y; - f32 cx2 = x + cos(a1 + 0 * (a2 - a1) / segments) * r; - f32 cy2 = y + sin(a1 + 0 * (a2 - a1) / segments) * r; - f32 cx3, cy3; + i32 mode = params->data[0].of.i32; + if (mode == 1) { + gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_TRIANGLES); + f32 x = params->data[1].of.f32; + f32 y = params->data[2].of.f32; + f32 r1 = params->data[3].of.f32; + f32 r2 = params->data[4].of.f32; + i32 segments = params->data[5].of.i32; + + f32 cx1 = x + r1; + f32 cy1 = y; + f32 cx2 = x + cos(PI * 2 / segments) * r1; + f32 cy2 = y + sin(PI * 2 / segments) * r2; + f32 cx3, cy3; + + fori (i, 2, segments) { + cx3 = x + cos(i * PI * 2 / segments) * r1; + cy3 = y + sin(i * PI * 2 / segments) * r2; + + gfx_immediate_renderer_push_triangle(&renderer, + cx1, cy1, 0, 0, + cx2, cy2, 0, 0, + cx3, cy3, 0, 0); + + cx2 = cx3; + cy2 = cy3; + } + + } else if (mode == 2) { + gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_LINES); + f32 x = params->data[1].of.f32; + f32 y = params->data[2].of.f32; + f32 r1 = params->data[3].of.f32; + f32 r2 = params->data[4].of.f32; + i32 segments = params->data[5].of.i32; + + f32 cx1 = x + r1; + f32 cy1 = y; + f32 cx2, cy2; + + fori (i, 1, segments + 1) { + cx2 = x + cos(i * PI * 2 / segments) * r1; + cy2 = y + sin(i * PI * 2 / segments) * r2; + + gfx_immediate_renderer_push_vertex(&renderer, cx1, cy1, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, cx2, cy2, 0, 0); + + cx1 = cx2; + cy1 = cy2; + } + } - fori (i, 1, segments + 1) { - cx3 = x + cos(a1 + i * (a2 - a1) / segments) * r; - cy3 = y + sin(a1 + i * (a2 - a1) / segments) * r; + return NULL; +} - gfx_immediate_renderer_push_triangle(&renderer, - cx1, cy1, 0, 0, - cx2, cy2, 0, 0, - cx3, cy3, 0, 0); +HEARTBREAK_DEF(arc, (WASM_I32, WASM_F32, WASM_F32, WASM_F32, WASM_F32, WASM_F32, WASM_I32), ()) { + gfx_image_unbind(&renderer); - cx2 = cx3; - cy2 = cy3; + i32 mode = params->data[0].of.i32; + if (mode == 1) { + gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_TRIANGLES); + f32 x = params->data[1].of.f32; + f32 y = params->data[2].of.f32; + f32 r = params->data[3].of.f32; + f32 a1 = params->data[4].of.f32; + f32 a2 = params->data[5].of.f32; + f32 segments = params->data[6].of.i32; + + f32 cx1 = x; + f32 cy1 = y; + f32 cx2 = x + cos(a1 + 0 * (a2 - a1) / segments) * r; + f32 cy2 = y + sin(a1 + 0 * (a2 - a1) / segments) * r; + f32 cx3, cy3; + + fori (i, 1, segments + 1) { + cx3 = x + cos(a1 + i * (a2 - a1) / segments) * r; + cy3 = y + sin(a1 + i * (a2 - a1) / segments) * r; + + gfx_immediate_renderer_push_triangle(&renderer, + cx1, cy1, 0, 0, + cx2, cy2, 0, 0, + cx3, cy3, 0, 0); + + cx2 = cx3; + cy2 = cy3; + } + + } else if (mode == 2) { + gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_LINES); + + f32 x = params->data[1].of.f32; + f32 y = params->data[2].of.f32; + f32 r = params->data[3].of.f32; + f32 a1 = params->data[4].of.f32; + f32 a2 = params->data[5].of.f32; + f32 segments = params->data[6].of.i32; + + f32 cx1 = x + cos(a1 + 0 * (a2 - a1) / segments) * r; + f32 cy1 = y + sin(a1 + 0 * (a2 - a1) / segments) * r; + f32 cx2, cy2; + + gfx_immediate_renderer_push_vertex(&renderer, x, y, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, cx1, cy1, 0, 0); + + fori (i, 1, segments + 1) { + cx2 = x + cos(a1 + i * (a2 - a1) / segments) * r; + cy2 = y + sin(a1 + i * (a2 - a1) / segments) * r; + + gfx_immediate_renderer_push_vertex(&renderer, cx1, cy1, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, cx2, cy2, 0, 0); + + cx1 = cx2; + cy1 = cy2; + } + + gfx_immediate_renderer_push_vertex(&renderer, x, y, 0, 0); + gfx_immediate_renderer_push_vertex(&renderer, cx1, cy1, 0, 0); } return NULL; @@ -233,6 +335,7 @@ HEARTBREAK_DEF(image_draw, (WASM_I64, WASM_F32, WASM_F32, WASM_F32, WASM_F32), ( if (w < 0) w = img->width; if (h < 0) h = img->height; + gfx_immediate_renderer_set_primitive_mode(&renderer, IMMEDIATE_MODE_TRIANGLES); gfx_image_bind(&renderer, img, 0); gfx_immediate_renderer_push_triangle(&renderer, diff --git a/src/heartbreak_system.c b/src/heartbreak_system.c index 0967775..5465e62 100644 --- a/src/heartbreak_system.c +++ b/src/heartbreak_system.c @@ -14,24 +14,20 @@ HB_EVENT(wheelmoved, (WASM_F32, WASM_F32)) \ HB_EVENT(resize, (WASM_I32, WASM_I32)) \ -#define HB_EVENT(name, pt) static wasm_func_t *__heartbreak_event_##name; -HEARTBREAK_EVENTS -#undef HB_EVENT - typedef struct HeartbreakEventType { const char* name; - wasm_func_t** func; + wasm_func_t* func; WasmValkindBuffer params; } HeartbreakEventType; -#define HB_EVENT(name, pt) static HeartbreakEventType __heartbreak_event_type_##name = { #name, &__heartbreak_event_##name, _VALS pt }; +#define HB_EVENT(name, pt) static HeartbreakEventType __heartbreak_event_type_##name = { #name, NULL, _VALS pt }; HEARTBREAK_EVENTS #undef HB_EVENT #define HEARTBREAK_EVENT_CALL(name, ...) __heartbreak_event_call(&__heartbreak_event_type_##name, __VA_ARGS__); void __heartbreak_event_call(HeartbreakEventType *ev, ...) { - if (*ev->func == NULL) return; + if (ev->func == NULL) return; va_list args; va_start(args, ev); @@ -49,7 +45,7 @@ void __heartbreak_event_call(HeartbreakEventType *ev, ...) { } } - const wasm_trap_t* trap = wasm_func_call(*ev->func, &wasm_args, &wasm_results); + const wasm_trap_t* trap = wasm_func_call(ev->func, &wasm_args, &wasm_results); if (trap) { wasm_message_t msg; wasm_trap_message(trap, &msg); @@ -96,8 +92,8 @@ static void __glfw_scroll_callback(GLFWwindow *w, f64 xoff, f64 yoff) { } typedef struct HeartbreakEventLink { - const char *name; - wasm_func_t **func; + const char *name; + HeartbreakEventType *ev; } HeartbreakEventLink; HEARTBREAK_DEF(init, (), (WASM_I32)) { @@ -136,7 +132,7 @@ HEARTBREAK_DEF(init, (), (WASM_I32)) { glfwGetWindowSize(glfw_window, &width, &height); gfx_immediate_renderer_update_window_size(&renderer, (f32) width, (f32) height); - #define HB_EVENT(name, pt) { "__heartbreak_" #name, &__heartbreak_event_##name }, + #define HB_EVENT(name, pt) { "__heartbreak_" #name, &__heartbreak_event_type_##name }, static HeartbreakEventLink events[] = { HEARTBREAK_EVENTS { NULL } @@ -147,7 +143,7 @@ HEARTBREAK_DEF(init, (), (WASM_I32)) { HeartbreakEventLink* ev = events; while (ev->name) { tmp_extern = wasm_extern_lookup_by_name(wasm_module, wasm_instance, ev->name); - if (tmp_extern) *ev->func = wasm_extern_as_func(tmp_extern); + if (tmp_extern) ev->ev->func = wasm_extern_as_func(tmp_extern); ev++; } diff --git a/tests/simp.onyx b/tests/simp.onyx index c32bf46..4c8020b 100644 --- a/tests/simp.onyx +++ b/tests/simp.onyx @@ -81,7 +81,7 @@ draw :: () { hb.graphics.setColor(0, 1, 0); hb.graphics.rectangle(.Fill, 0, 0, 100, 100); hb.graphics.setColor(1, 1, 0); - hb.graphics.rectangle(.Fill, 100, 100, 200, 100); + hb.graphics.rectangle(.Line, 100, 100, 200, 100); mx, my := hb.input.mouseGetPos(); hb.graphics.push(); @@ -89,7 +89,7 @@ draw :: () { hb.graphics.rotate(t); hb.graphics.translate(~~ mx, ~~ my); hb.graphics.setColor(1, 0, 0); - hb.graphics.ellipse(.Fill, 0, 0, 25, 15 + 10 * math.sin(t)); + hb.graphics.ellipse(.Line, 0, 0, 25, 15 + 10 * math.sin(t)); hb.graphics.pop(); hb.graphics.setColor(1, 1, 1, 1); @@ -106,8 +106,11 @@ draw :: () { hb.graphics.rectangle(.Fill, w - 100, h - 100, 100, 100); hb.graphics.setColor(0, 0, 1); - hb.graphics.arc(.Fill, 300, 300, 100, math.PI / 4, math.PI * 7 / 4); + hb.graphics.arc(.Line, 300, 300, 100, math.PI / 4, math.PI * 7 / 4); hb.graphics.setColor(0, 1, 1); - hb.graphics.print("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+`~[{}]\|<,>./?'\";:", 100, 100, 200 + math.sin(t) * 100); + hb.graphics.print("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+`~[{}]\|<,>./?'\";:", 400, 100, 200 + math.sin(t) * 100); + + hb.graphics.setColor(1, 1, 1); + hb.graphics.circle(.Line, 200, 500, 100, 100); }