From 65d448aad0e6c792b1adba1272efef73b31c4885 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 24 Oct 2025 18:33:36 -0700 Subject: Consolidate renderers --- src/renderer/imm_renderer.c | 192 ------------------------------ src/renderer/imm_renderer_impl.h | 43 ------- src/renderer/renderer.c | 246 --------------------------------------- src/renderer/renderer_impl.h | 25 ---- 4 files changed, 506 deletions(-) delete mode 100644 src/renderer/imm_renderer.c delete mode 100644 src/renderer/imm_renderer_impl.h delete mode 100644 src/renderer/renderer.c delete mode 100644 src/renderer/renderer_impl.h (limited to 'src/renderer') diff --git a/src/renderer/imm_renderer.c b/src/renderer/imm_renderer.c deleted file mode 100644 index b3af7e8..0000000 --- a/src/renderer/imm_renderer.c +++ /dev/null @@ -1,192 +0,0 @@ -#include "imm_renderer_impl.h" - -#include -#include -#include -#include - -#include - -#include -#include // memcpy - -bool gfx_imm_make(Imm* 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(Imm* 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(Imm* 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(Imm* 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(Imm* 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( - Imm* 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(Imm* renderer, const vec3 verts[3]) { - gfx_imm_draw_triangles(renderer, verts, 1); -} - -void gfx_imm_draw_aabb2(Imm* 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(Imm* 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(Imm* 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(Imm* renderer, vec4 colour) { - assert(renderer); - assert(renderer->shader); - - gfx_imm_flush(renderer); - - gfx_set_vec4_uniform(renderer->shader, "Colour", colour); -} diff --git a/src/renderer/imm_renderer_impl.h b/src/renderer/imm_renderer_impl.h deleted file mode 100644 index d87b910..0000000 --- a/src/renderer/imm_renderer_impl.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include - -#include - -#include -#include - -typedef struct Geometry Geometry; -typedef struct GfxCore GfxCore; -typedef struct IBL IBL; -typedef struct LLR LLR; -typedef struct Material Material; -typedef struct ShaderProgram ShaderProgram; -typedef struct Texture Texture; - -/// Immediate mode renderer. -/// -/// Currently, the immediate mode renderer can only draw up to a maximum number -/// of primitives per frame. It does not adjust this number dynamically. Keeps -/// things simple while the extra complexity is not needed. -/// TODO: Flush the buffer when it reaches its maximum size to remove this -/// constraint. -typedef struct Imm { - GfxCore* gfxcore; - LLR* llr; - - ShaderProgram* shader; // Immediate-mode shader program for primitives. - Geometry* triangles; - size_t num_triangle_verts; // Number of triangle verts this frame. - // TODO: wireframe rendering. - struct { - bool wireframe : 1; - } flags; - vec3 triangle_verts[GFX_IMM_MAX_NUM_TRIANGLES * 3]; -} Imm; - -/// Create a new immediate mode renderer. -bool gfx_imm_make(Imm*, GfxCore*, LLR*); - -/// Destroy the immediate mode renderer. -void gfx_imm_destroy(Imm*); diff --git a/src/renderer/renderer.c b/src/renderer/renderer.c deleted file mode 100644 index 7797c83..0000000 --- a/src/renderer/renderer.c +++ /dev/null @@ -1,246 +0,0 @@ -#include "renderer_impl.h" - -#include "llr/llr_impl.h" -#include "memory.h" -#include "scene/animation_impl.h" -#include "scene/camera_impl.h" -#include "scene/model_impl.h" -#include "scene/node_impl.h" -#include "scene/object_impl.h" -#include "scene/scene_impl.h" - -#include -#include -#include - -#include - -#include - -bool gfx_renderer_make(Renderer* renderer, LLR* llr, GfxCore* gfxcore) { - assert(renderer); - assert(llr); - assert(gfxcore); - - renderer->gfxcore = gfxcore; - renderer->llr = llr; - - return true; -} - -void gfx_renderer_destroy(Renderer* renderer) { - if (!renderer) { - return; - } - assert(renderer->gfxcore); - GfxCore* gfxcore = renderer->gfxcore; - if (renderer->shaders.debug) { - gfx_destroy_shader_program(gfxcore, &renderer->shaders.debug); - } - if (renderer->shaders.normals) { - gfx_destroy_shader_program(gfxcore, &renderer->shaders.normals); - } - if (renderer->shaders.normal_mapped_normals) { - gfx_destroy_shader_program( - gfxcore, &renderer->shaders.normal_mapped_normals); - } - if (renderer->shaders.tangents) { - gfx_destroy_shader_program(gfxcore, &renderer->shaders.tangents); - } -} - -static ShaderProgram* load_shader(Renderer* renderer, RenderSceneMode mode) { - assert(renderer); - -#define LOAD_AND_RETURN(pShader, constructor) \ - { \ - if (!pShader) { \ - pShader = constructor(renderer->gfxcore); \ - } \ - assert(pShader); \ - return pShader; \ - } - - switch (mode) { - case RenderDefault: - return 0; - case RenderDebug: - LOAD_AND_RETURN(renderer->shaders.debug, gfx_make_debug3d_shader); - case RenderNormals: - LOAD_AND_RETURN(renderer->shaders.normals, gfx_make_view_normals_shader); - case RenderNormalMappedNormals: - LOAD_AND_RETURN( - renderer->shaders.normal_mapped_normals, - gfx_make_view_normal_mapped_normals_shader); - case RenderTangents: - LOAD_AND_RETURN(renderer->shaders.tangents, gfx_make_view_tangents_shader); - } - assert(false); - return 0; -} - -// static void log_matrix(const mat4* m) { -// for (int row = 0; row < 4; ++row) { -// LOGI("[ %5.2f, %5.2f, %5.2f, %5.2f ]", m->val[0][row], m->val[1][row], -// m->val[2][row], m->val[3][row]); -// } -// } - -typedef struct RenderState { - GfxCore* gfxcore; - LLR* llr; - Renderer* renderer; - ShaderProgram* shader; // Null to use scene shaders. - const Scene* scene; - const Anima* anima; -} RenderState; - -static void draw_children( - RenderState* state, const mat4* node_transform, const SceneNode* node); - -/// Draw the scene recursively. -static void draw_recursively( - RenderState* state, mat4 parent_transform, const SceneNode* node) { - assert(state); - const mat4 node_transform = mat4_mul(parent_transform, node->transform); - - // Anima. - if (node->type == AnimaNode) { - // Save the anima so that we can animate objects. - state->anima = gfx_get_node_anima(node); - - draw_children(state, &node_transform, node); - } - // Activate light. - else if (node->type == LightNode) { - Light* light = mem_get_light(node->light); - assert(light); - gfx_llr_push_light(state->llr, light); - { - draw_children(state, &node_transform, node); - } - gfx_llr_pop_light(state->llr); - } - // Model. - else if (node->type == ModelNode) { - const Model* model = gfx_get_node_model(node); - const SceneNode* root = mem_get_node(model->root); - draw_recursively(state, parent_transform, root); - draw_children(state, &node_transform, node); - } - // Render object. - else if (node->type == ObjectNode) { - const SceneObject* object = mem_get_object(node->object); - assert(object); - - // TODO: Here we would frustum-cull the object. - - // A model/anima can have many skeletons. We need to animate the given - // object using its skeleton, not just any skeleton of the anima. - if (object->skeleton.val) { - const Skeleton* skeleton = mem_get_skeleton(object->skeleton); - gfx_llr_set_skeleton(state->llr, state->anima, skeleton); - } - - const mat4 model_matrix = node_transform; - - for (mesh_link_idx mesh_link_index = object->mesh_link; - mesh_link_index.val;) { - const MeshLink* mesh_link = mem_get_mesh_link(mesh_link_index); - mesh_link_index = mesh_link->next; - - const Mesh* mesh = mem_get_mesh(mesh_link->mesh); - if (!mesh) { - continue; - } - - // TODO: Here we would frustum-cull the mesh. The AABB would have to be - // transformed by the model matrix. Rotation would make the AABB - // relatively large, but still, the culling would be conservative. - - ShaderProgram* shader = state->shader ? state->shader : mesh->shader; - gfx_llr_set_shader(state->llr, shader); - gfx_llr_set_model_matrix(state->llr, &model_matrix); - gfx_llr_render_mesh(state->llr, mesh); - } - - if (object->skeleton.val) { - gfx_llr_clear_skeleton(state->llr); - } - - draw_children(state, &node_transform, node); - } else { - draw_children(state, &node_transform, node); - } -} - -/// Draw the node's children. -static void draw_children( - RenderState* state, const mat4* node_transform, const SceneNode* node) { - // Render children recursively. - for (node_idx child_index = node->child; child_index.val;) { - const SceneNode* child = mem_get_node(child_index); - draw_recursively(state, *node_transform, child); - child_index = child->next; - } -} - -void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) { - assert(renderer); - assert(params); - assert(params->scene); - - ShaderProgram* const shader = load_shader(renderer, params->mode); - - const Scene* scene = params->scene; - const SceneCamera* camera = params->camera; - GfxCore* const gfxcore = renderer->gfxcore; - - int x, y, width, height; - gfx_get_viewport(gfxcore, &x, &y, &width, &height); - const R aspect = (R)width / (R)height; - - RenderState state = { - .gfxcore = gfxcore, - .llr = renderer->llr, - .renderer = renderer, - .shader = shader, - .scene = scene}; - - gfx_llr_set_camera(renderer->llr, &camera->camera); - gfx_llr_set_aspect(renderer->llr, aspect); - draw_recursively(&state, mat4_id(), scene->root); -} - -static void update_rec(SceneNode* node, const SceneCamera* camera, R t) { - assert(node); - assert(camera); - - const NodeType node_type = gfx_get_node_type(node); - - // TODO: Models do not need to be animated if they are not visible to the - // camera. - if (node_type == AnimaNode) { - Anima* anima = gfx_get_node_anima_mut(node); - gfx_update_animation(anima, (R)t); - } else if (node_type == ModelNode) { - Model* model = gfx_get_node_model_mut(node); - SceneNode* root = gfx_get_model_root_mut(model); - update_rec(root, camera, t); - } - - // Children. - SceneNode* child = gfx_get_node_child_mut(node); - while (child) { - update_rec(child, camera, t); - child = gfx_get_node_sibling_mut(child); - } -} - -void gfx_update(Scene* scene, const SceneCamera* camera, R t) { - assert(scene); - assert(camera); - - SceneNode* node = gfx_get_scene_root(scene); - update_rec(node, camera, t); -} diff --git a/src/renderer/renderer_impl.h b/src/renderer/renderer_impl.h deleted file mode 100644 index 7395915..0000000 --- a/src/renderer/renderer_impl.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -#include - -typedef struct LLR LLR; -typedef struct ShaderProgram ShaderProgram; - -typedef struct Renderer { - GfxCore* gfxcore; - LLR* llr; - struct { - ShaderProgram* debug; - ShaderProgram* normals; - ShaderProgram* normal_mapped_normals; - ShaderProgram* tangents; - } shaders; -} Renderer; - -/// Create a new renderer. -bool gfx_renderer_make(Renderer*, LLR*, GfxCore*); - -/// Destroy the renderer. -void gfx_renderer_destroy(Renderer*); -- cgit v1.2.3