#include "imm_renderer_impl.h" #include #include #include #include #include #include #include // memcpy bool gfx_imm_make(ImmRenderer* renderer, GfxCore* gfxcore, LLR* llr) { assert(renderer); assert(gfxcore); assert(llr); const size_t num_triangle_verts = GFX_IMM_MAX_NUM_TRIANGLES * 3; renderer->gfxcore = gfxcore; renderer->llr = llr; renderer->triangles = gfx_make_geometry( gfxcore, &(GeometryDesc){.type = Triangles, .buffer_usage = BufferDynamic, .num_verts = num_triangle_verts, .positions3d = (BufferView3d){ .size_bytes = num_triangle_verts * sizeof(vec3)}}); if (!renderer->triangles) { goto cleanup; } renderer->shader = gfx_make_immediate_mode_shader(gfxcore); if (!renderer->shader) { goto cleanup; } gfx_imm_set_colour(renderer, vec4_make(0.0f, 0.0f, 0.0f, 1.0f)); return true; cleanup: gfx_imm_destroy(renderer); return false; } void gfx_imm_destroy(ImmRenderer* renderer) { assert(renderer); assert(renderer->gfxcore); if (renderer->triangles) { gfx_destroy_geometry(renderer->gfxcore, &renderer->triangles); // TODO: Could also destroy the geometry's buffers here. } if (renderer->shader) { gfx_destroy_shader_program(renderer->gfxcore, &renderer->shader); } } void gfx_imm_flush(ImmRenderer* renderer) { assert(renderer); if (renderer->num_triangle_verts > 0) { gfx_update_geometry( renderer->triangles, &(GeometryDesc){ .num_verts = renderer->num_triangle_verts, .positions3d = (BufferView3d){ .data = renderer->triangle_verts, .size_bytes = renderer->num_triangle_verts * sizeof(vec3)} }); gfx_llr_render_geometry(renderer->llr, renderer->triangles); renderer->num_triangle_verts = 0; } } void gfx_imm_start(ImmRenderer* renderer) { assert(renderer); // Shader uniforms are applied lazily. // TODO: In the event that gfx_activate_shader_program() activates uniforms // automatically for convenience, call an overload here that doesn't do so. // gfx_activate_shader_program(renderer->shader); gfx_llr_set_shader(renderer->llr, renderer->shader); } void gfx_imm_end(ImmRenderer* renderer) { assert(renderer); gfx_imm_flush(renderer); // gfx_deactivate_shader_program(renderer->shader); gfx_llr_set_shader(renderer->llr, 0); } void gfx_imm_draw_triangles( ImmRenderer* renderer, const vec3 verts[], size_t num_triangles) { assert(renderer); assert(verts); const size_t new_verts = num_triangles * 3; assert( renderer->num_triangle_verts + new_verts < (GFX_IMM_MAX_NUM_TRIANGLES * 3)); memcpy( renderer->triangle_verts + renderer->num_triangle_verts, verts, new_verts * sizeof(vec3)); renderer->num_triangle_verts += new_verts; } void gfx_imm_draw_triangle(ImmRenderer* renderer, const vec3 verts[3]) { gfx_imm_draw_triangles(renderer, verts, 1); } void gfx_imm_draw_aabb2(ImmRenderer* renderer, aabb2 box) { assert(renderer); // clang-format off const vec3 verts[4] = { vec3_make(box.min.x, box.min.y, 0), // 3 ---- 2 vec3_make(box.max.x, box.min.y, 0), // | | vec3_make(box.max.x, box.max.y, 0), // | | vec3_make(box.min.x, box.max.y, 0)}; // 0 ---- 1 // clang-format on #define tri(i0, i1, i2) verts[i0], verts[i1], verts[i2] const vec3 tris[6] = {tri(0, 1, 2), tri(0, 2, 3)}; #undef tri gfx_imm_draw_triangles(renderer, tris, 2); } void gfx_imm_draw_aabb3(ImmRenderer* renderer, aabb3 box) { assert(renderer); // clang-format off const vec3 vertices[8] = { vec3_make(box.min.x, box.min.y, box.max.z), // 7 ----- 6 vec3_make(box.max.x, box.min.y, box.max.z), // / /| vec3_make(box.max.x, box.max.y, box.max.z), // 3 ----- 2 | vec3_make(box.min.x, box.max.y, box.max.z), // | | | vec3_make(box.min.x, box.min.y, box.min.z), // | 4 ----- 5 vec3_make(box.max.x, box.min.y, box.min.z), // |/ |/ vec3_make(box.max.x, box.max.y, box.min.z), // 0 ----- 1 vec3_make(box.min.x, box.max.y, box.min.z)}; // clang-format on gfx_imm_draw_box3(renderer, vertices); } void gfx_imm_draw_box3(ImmRenderer* renderer, const vec3 vertices[8]) { assert(renderer); assert(vertices); // 7 ----- 6 // / /| // 3 ----- 2 | // | | | // | 4 ----- 5 // |/ |/ // 0 ----- 1 #define tri(i0, i1, i2) vertices[i0], vertices[i1], vertices[i2] const vec3 tris[36] = { // Front. tri(0, 1, 2), tri(0, 2, 3), // Right. tri(1, 5, 6), tri(1, 6, 2), // Back. tri(5, 4, 7), tri(5, 7, 6), // Left. tri(4, 0, 03), tri(4, 3, 7), // Top. tri(3, 2, 6), tri(3, 6, 7), // Bottom. tri(0, 4, 5), tri(0, 5, 1)}; gfx_imm_draw_triangles(renderer, tris, 12); } void gfx_imm_set_colour(ImmRenderer* renderer, vec4 colour) { assert(renderer); assert(renderer->shader); gfx_imm_flush(renderer); gfx_set_vec4_uniform(renderer->shader, "Colour", colour); }