From 175c72557b21f356e295a6f8a4acd91b7e744bef Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 24 Oct 2025 15:40:40 -0700 Subject: Consolidate LLR into a single file. --- CMakeLists.txt | 3 -- README.md | 14 +++++- include/gfx/llr/light.h | 30 ------------ include/gfx/llr/llr.h | 68 ++++++++++++++++++++++++++ include/gfx/llr/material.h | 26 ---------- include/gfx/llr/mesh.h | 23 --------- src/asset/model.c | 3 +- src/llr/light.c | 42 ---------------- src/llr/light_impl.h | 25 ---------- src/llr/llr.c | 117 +++++++++++++++++++++++++++++++++++++++++++-- src/llr/llr_impl.h | 31 ++++++++++++ src/llr/material.c | 57 ---------------------- src/llr/material_impl.h | 15 ------ src/llr/mesh.c | 24 ---------- src/llr/mesh_impl.h | 9 ---- src/memory.c | 4 +- src/renderer/renderer.c | 3 +- src/scene/node.c | 2 +- src/scene/node_impl.h | 3 ++ src/scene/object.c | 2 +- src/util/skyquad.c | 4 +- 21 files changed, 234 insertions(+), 271 deletions(-) delete mode 100644 include/gfx/llr/light.h delete mode 100644 include/gfx/llr/material.h delete mode 100644 include/gfx/llr/mesh.h delete mode 100644 src/llr/light.c delete mode 100644 src/llr/light_impl.h delete mode 100644 src/llr/material.c delete mode 100644 src/llr/material_impl.h delete mode 100644 src/llr/mesh.c delete mode 100644 src/llr/mesh_impl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index de5f0dd..cda7b1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,9 +50,6 @@ add_library(gfx SHARED src/core/shader.c src/core/texture.c src/llr/llr.c - src/llr/light.c - src/llr/material.c - src/llr/mesh.c src/memory.c src/renderer/imm_renderer.c src/renderer/renderer.c diff --git a/README.md b/README.md index 491761d..3a30ee4 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The `Gfx` object represents the graphics subsystem and is at the center of the library's high-level API. The `Gfx` object exposes a render backend (`GfxCore`) and a `Renderer`, and allows the caller to create `Scene`s. -### Render Backend +### Render Backend ("Core") The render backend (`GfxCore`) is a thin abstraction layer over low-level graphics APIs like OpenGL or Vulkan. It holds GPU resources such as geometry, @@ -43,7 +43,17 @@ manage resource lifetime. ### Low-level Renderer -`ImmRenderer` is a low-level, immediate mode renderer. +The low-level renderer (`LLR`) provides a low-level, immediate-mode interface +on top of the render backend. It understands higher-level concepts to make +rendering more convenient (object, mesh, material, light, camera, etc), but is +still relatively low-level and does not understand any particular scene data +structure. + +### Immediate-mode Renderer + +The immediate-mode renderer (`Imm`) provides an API to define and render +geometry procedurally and on the spot. It should be reserved for debug or +not-performance-intensive rendering. ### Scene diff --git a/include/gfx/llr/light.h b/include/gfx/llr/light.h deleted file mode 100644 index 132e344..0000000 --- a/include/gfx/llr/light.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -typedef struct Texture Texture; - -typedef struct Light Light; - -/// Light type. -typedef enum LightType { EnvironmentLightType } LightType; - -/// Describes an environment light. -typedef struct EnvironmentLightDesc { - const Texture* environment_map; -} EnvironmentLightDesc; - -/// Describes a light. -typedef struct LightDesc { - LightType type; - union { - EnvironmentLightDesc environment; - } light; -} LightDesc; - -/// Create a light. -Light* gfx_make_light(const LightDesc*); - -/// Destroy the light. -/// -/// The light is conveniently removed from the scene graph and its parent scene -/// node is destroyed. -void gfx_destroy_light(Light**); diff --git a/include/gfx/llr/llr.h b/include/gfx/llr/llr.h index f84b3fb..6d78a50 100644 --- a/include/gfx/llr/llr.h +++ b/include/gfx/llr/llr.h @@ -1,5 +1,8 @@ #pragma once +#include +#include + #include #include #include @@ -11,9 +14,74 @@ typedef struct Material Material; typedef struct Mesh Mesh; typedef struct ShaderProgram ShaderProgram; typedef struct Skeleton Skeleton; +typedef struct Texture Texture; typedef struct LLR LLR; +// ----------------------------------------------------------------------------- +// Data structures. + +/// Light type. +typedef enum LightType { EnvironmentLightType } LightType; + +/// Describes an environment light. +typedef struct EnvironmentLightDesc { + const Texture* environment_map; +} EnvironmentLightDesc; + +/// Describes a light. +typedef struct LightDesc { + LightType type; + union { + EnvironmentLightDesc environment; + } light; +} LightDesc; + +/// Describes a material. +/// +/// TODO: It doesn't hold the shader program anymore...It's in the Mesh. +/// A material holds a shader program and a set of shader-specific uniform +/// variables. Two materials can share the same shader, but shader parameters +/// generally give two materials a different appearance. +typedef struct MaterialDesc { + ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL]; + int num_uniforms; +} MaterialDesc; + +/// Describes a mesh. +typedef struct MeshDesc { + const Geometry* geometry; + const Material* material; + ShaderProgram* shader; +} MeshDesc; + +/// Create a light. +Light* gfx_make_light(const LightDesc*); + +/// Destroy the light. +/// +/// The light is conveniently removed from the scene graph and its parent scene +/// node is destroyed. +void gfx_destroy_light(Light**); + +/// Create a material. +Material* gfx_make_material(const MaterialDesc*); + +/// Destroy the material. +/// +/// The caller must make sure that no Mesh points to the given Material. +/// For a safe purge of unused resources, see scene_purge(). +void gfx_destroy_material(Material**); + +/// Create a mesh. +Mesh* gfx_make_mesh(const MeshDesc*); + +/// Destroy the mesh. +/// +/// The caller must make sure that no SceneObject points to the given Mesh. +/// For a safe purge of unused resources, see scene_purge(). +void gfx_destroy_mesh(Mesh**); + // ----------------------------------------------------------------------------- // Low-level rendering. diff --git a/include/gfx/llr/material.h b/include/gfx/llr/material.h deleted file mode 100644 index 9ebf9b3..0000000 --- a/include/gfx/llr/material.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -typedef struct Material Material; - -/// Describes a material. -/// -/// TODO: It doesn't hold the shader program anymore...It's in the Mesh. -/// A material holds a shader program and a set of shader-specific uniform -/// variables. Two materials can share the same shader, but shader parameters -/// generally give two materials a different appearance. -typedef struct MaterialDesc { - ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL]; - int num_uniforms; -} MaterialDesc; - -/// Create a material. -Material* gfx_make_material(const MaterialDesc*); - -/// Destroy the material. -/// -/// The caller must make sure that no Mesh points to the given Material. -/// For a safe purge of unused resources, see scene_purge(). -void gfx_destroy_material(Material**); diff --git a/include/gfx/llr/mesh.h b/include/gfx/llr/mesh.h deleted file mode 100644 index 0d3b4d4..0000000 --- a/include/gfx/llr/mesh.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -typedef struct Geometry Geometry; -typedef struct Material Material; -typedef struct ShaderProgram ShaderProgram; - -typedef struct Mesh Mesh; - -/// Describes a mesh. -typedef struct MeshDesc { - const Geometry* geometry; - const Material* material; - ShaderProgram* shader; -} MeshDesc; - -/// Create a mesh. -Mesh* gfx_make_mesh(const MeshDesc*); - -/// Destroy the mesh. -/// -/// The caller must make sure that no SceneObject points to the given Mesh. -/// For a safe purge of unused resources, see scene_purge(). -void gfx_destroy_mesh(Mesh**); diff --git a/src/asset/model.c b/src/asset/model.c index 0c57470..96d200f 100644 --- a/src/asset/model.c +++ b/src/asset/model.c @@ -84,8 +84,7 @@ #include "asset/texture.h" #include "gfx/core.h" #include "gfx/gfx.h" -#include "gfx/llr/material.h" -#include "gfx/llr/mesh.h" +#include "gfx/llr/llr.h" #include "gfx/scene/animation.h" #include "gfx/scene/camera.h" #include "gfx/scene/node.h" diff --git a/src/llr/light.c b/src/llr/light.c deleted file mode 100644 index 0fa1522..0000000 --- a/src/llr/light.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "light_impl.h" - -#include "memory.h" -#include "scene/node_impl.h" - -#include - -static void make_environment_light( - Light* light, const EnvironmentLightDesc* desc) { - assert(light); - assert(desc); - light->type = EnvironmentLightType; - light->environment.environment_map = desc->environment_map; -} - -Light* gfx_make_light(const LightDesc* desc) { - assert(desc); - - Light* light = mem_alloc_light(); - - switch (desc->type) { - case EnvironmentLightType: - make_environment_light(light, &desc->light.environment); - break; - default: - log_error("Unhandled light type"); - gfx_destroy_light(&light); - return 0; - } - - return light; -} - -void gfx_destroy_light(Light** light) { - assert(light); - if (*light) { - if ((*light)->parent.val) { - gfx_del_node((*light)->parent); - } - mem_free_light(light); - } -} diff --git a/src/llr/light_impl.h b/src/llr/light_impl.h deleted file mode 100644 index 5ec8145..0000000 --- a/src/llr/light_impl.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -#include "scene/types.h" - -typedef struct Texture Texture; - -/// An environment light. -typedef struct EnvironmentLight { - const Texture* environment_map; - const Texture* irradiance_map; // Renderer implementation. - const Texture* prefiltered_environment_map; // Renderer implementation. - int max_reflection_lod; // Mandatory when prefiltered_environment_map is - // given. -} EnvironmentLight; - -/// A scene light. -typedef struct Light { - LightType type; - union { - EnvironmentLight environment; - }; - node_idx parent; // Parent SceneNode. -} Light; diff --git a/src/llr/llr.c b/src/llr/llr.c index 25cdf9f..a1b37be 100644 --- a/src/llr/llr.c +++ b/src/llr/llr.c @@ -1,14 +1,14 @@ -#include "light_impl.h" #include "llr_impl.h" -#include "mesh_impl.h" -#include "llr/material_impl.h" +#include "memory.h" #include "scene/animation_impl.h" +#include "scene/node_impl.h" #include #include #include +#include static const int IRRADIANCE_MAP_WIDTH = 1024; static const int IRRADIANCE_MAP_HEIGHT = 1024; @@ -17,6 +17,117 @@ static const int PREFILTERED_ENVIRONMENT_MAP_HEIGHT = 128; static const int BRDF_INTEGRATION_MAP_WIDTH = 512; static const int BRDF_INTEGRATION_MAP_HEIGHT = 512; +static void make_environment_light( + Light* light, const EnvironmentLightDesc* desc) { + assert(light); + assert(desc); + light->type = EnvironmentLightType; + light->environment.environment_map = desc->environment_map; +} + +Light* gfx_make_light(const LightDesc* desc) { + assert(desc); + + Light* light = mem_alloc_light(); + + switch (desc->type) { + case EnvironmentLightType: + make_environment_light(light, &desc->light.environment); + break; + default: + log_error("Unhandled light type"); + gfx_destroy_light(&light); + return 0; + } + + return light; +} + +void gfx_destroy_light(Light** light) { + assert(light); + if (*light) { + if ((*light)->parent.val) { + gfx_del_node((*light)->parent); + } + mem_free_light(light); + } +} + +static void material_make(Material* material, const MaterialDesc* desc) { + assert(material); + assert(desc); + assert(desc->num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL); + material->num_uniforms = desc->num_uniforms; + for (int i = 0; i < desc->num_uniforms; ++i) { + material->uniforms[i] = desc->uniforms[i]; + } +} + +Material* gfx_make_material(const MaterialDesc* desc) { + assert(desc); + Material* material = mem_alloc_material(); + material_make(material, desc); + return material; +} + +void gfx_destroy_material(Material** material) { mem_free_material(material); } + +static void set_uniform(ShaderProgram* prog, const ShaderUniform* uniform) { + switch (uniform->type) { + case UniformTexture: + gfx_set_texture_uniform(prog, uniform->name.str, uniform->value.texture); + break; + case UniformMat4: + gfx_set_mat4_uniform(prog, uniform->name.str, &uniform->value.mat4); + break; + case UniformVec3: + gfx_set_vec3_uniform(prog, uniform->name.str, uniform->value.vec3); + break; + case UniformVec4: + gfx_set_vec4_uniform(prog, uniform->name.str, uniform->value.vec4); + break; + case UniformFloat: + gfx_set_float_uniform(prog, uniform->name.str, uniform->value.scalar); + break; + case UniformMat4Array: + gfx_set_mat4_array_uniform( + prog, uniform->name.str, uniform->value.array.values, + uniform->value.array.count); + break; + } +} + +/// Activate the material. +/// +/// This configures the shader uniforms that are specific to the material. +static void gfx_material_activate( + ShaderProgram* shader, const Material* material) { + assert(material); + for (int i = 0; i < material->num_uniforms; ++i) { + const ShaderUniform* uniform = &material->uniforms[i]; + set_uniform(shader, uniform); + } +} + +static void mesh_make(Mesh* mesh, const MeshDesc* desc) { + assert(mesh); + assert(desc); + assert(desc->geometry); + assert(desc->material); + assert(desc->shader); + mesh->geometry = desc->geometry; + mesh->material = desc->material; + mesh->shader = desc->shader; +} + +Mesh* gfx_make_mesh(const MeshDesc* desc) { + Mesh* mesh = mem_alloc_mesh(); + mesh_make(mesh, desc); + return mesh; +} + +void gfx_destroy_mesh(Mesh** mesh) { mem_free_mesh(mesh); } + /// Initialize renderer state for IBL. static bool init_ibl(LLR* renderer) { assert(renderer); diff --git a/src/llr/llr_impl.h b/src/llr/llr_impl.h index 3f6a68f..6318ee0 100644 --- a/src/llr/llr_impl.h +++ b/src/llr/llr_impl.h @@ -3,6 +3,8 @@ #include #include +#include "scene/types.h" + #include #include @@ -17,6 +19,35 @@ typedef struct Material Material; typedef struct ShaderProgram ShaderProgram; typedef struct Texture Texture; +/// An environment light. +typedef struct EnvironmentLight { + const Texture* environment_map; + const Texture* irradiance_map; // Renderer implementation. + const Texture* prefiltered_environment_map; // Renderer implementation. + int max_reflection_lod; // Mandatory when prefiltered_environment_map is + // given. +} EnvironmentLight; + +/// A scene light. +typedef struct Light { + LightType type; + union { + EnvironmentLight environment; + }; + node_idx parent; // Parent SceneNode. +} Light; + +typedef struct Material { + ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL]; + int num_uniforms; +} Material; + +typedef struct Mesh { + const Geometry* geometry; + const Material* material; + ShaderProgram* shader; // TODO: Move this back to Material? +} Mesh; + /// Immediate mode renderer. /// /// The renderer caches state changes in memory and only programs the underlying diff --git a/src/llr/material.c b/src/llr/material.c deleted file mode 100644 index f09dd3f..0000000 --- a/src/llr/material.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "material_impl.h" - -#include "memory.h" - -#include - -static void material_make(Material* material, const MaterialDesc* desc) { - assert(material); - assert(desc); - assert(desc->num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL); - material->num_uniforms = desc->num_uniforms; - for (int i = 0; i < desc->num_uniforms; ++i) { - material->uniforms[i] = desc->uniforms[i]; - } -} - -Material* gfx_make_material(const MaterialDesc* desc) { - assert(desc); - Material* material = mem_alloc_material(); - material_make(material, desc); - return material; -} - -void gfx_destroy_material(Material** material) { mem_free_material(material); } - -static void set_uniform(ShaderProgram* prog, const ShaderUniform* uniform) { - switch (uniform->type) { - case UniformTexture: - gfx_set_texture_uniform(prog, uniform->name.str, uniform->value.texture); - break; - case UniformMat4: - gfx_set_mat4_uniform(prog, uniform->name.str, &uniform->value.mat4); - break; - case UniformVec3: - gfx_set_vec3_uniform(prog, uniform->name.str, uniform->value.vec3); - break; - case UniformVec4: - gfx_set_vec4_uniform(prog, uniform->name.str, uniform->value.vec4); - break; - case UniformFloat: - gfx_set_float_uniform(prog, uniform->name.str, uniform->value.scalar); - break; - case UniformMat4Array: - gfx_set_mat4_array_uniform( - prog, uniform->name.str, uniform->value.array.values, - uniform->value.array.count); - break; - } -} - -void gfx_material_activate(ShaderProgram* shader, const Material* material) { - assert(material); - for (int i = 0; i < material->num_uniforms; ++i) { - const ShaderUniform* uniform = &material->uniforms[i]; - set_uniform(shader, uniform); - } -} diff --git a/src/llr/material_impl.h b/src/llr/material_impl.h deleted file mode 100644 index 2b7cd89..0000000 --- a/src/llr/material_impl.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -typedef struct ShaderProgram ShaderProgram; - -typedef struct Material { - ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL]; - int num_uniforms; -} Material; - -/// Activate the material. -/// -/// This configures the shader uniforms that are specific to the material. -void gfx_material_activate(ShaderProgram* shader, const Material* material); diff --git a/src/llr/mesh.c b/src/llr/mesh.c deleted file mode 100644 index 5f9e5d0..0000000 --- a/src/llr/mesh.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "mesh_impl.h" - -#include "memory.h" - -#include - -static void mesh_make(Mesh* mesh, const MeshDesc* desc) { - assert(mesh); - assert(desc); - assert(desc->geometry); - assert(desc->material); - assert(desc->shader); - mesh->geometry = desc->geometry; - mesh->material = desc->material; - mesh->shader = desc->shader; -} - -Mesh* gfx_make_mesh(const MeshDesc* desc) { - Mesh* mesh = mem_alloc_mesh(); - mesh_make(mesh, desc); - return mesh; -} - -void gfx_destroy_mesh(Mesh** mesh) { mem_free_mesh(mesh); } diff --git a/src/llr/mesh_impl.h b/src/llr/mesh_impl.h deleted file mode 100644 index a997d5b..0000000 --- a/src/llr/mesh_impl.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -typedef struct Mesh { - const Geometry* geometry; - const Material* material; - ShaderProgram* shader; // TODO: Move this back to Material? -} Mesh; diff --git a/src/memory.c b/src/memory.c index 59bf8ca..39ae6ea 100644 --- a/src/memory.c +++ b/src/memory.c @@ -2,9 +2,7 @@ #include -#include "llr/light_impl.h" -#include "llr/material_impl.h" -#include "llr/mesh_impl.h" +#include "llr/llr_impl.h" #include "scene/animation_impl.h" #include "scene/camera_impl.h" #include "scene/model_impl.h" diff --git a/src/renderer/renderer.c b/src/renderer/renderer.c index 6bcf5cc..7797c83 100644 --- a/src/renderer/renderer.c +++ b/src/renderer/renderer.c @@ -1,7 +1,6 @@ #include "renderer_impl.h" -#include "llr/light_impl.h" -#include "llr/mesh_impl.h" +#include "llr/llr_impl.h" #include "memory.h" #include "scene/animation_impl.h" #include "scene/camera_impl.h" diff --git a/src/scene/node.c b/src/scene/node.c index 9d45aa7..b7cf467 100644 --- a/src/scene/node.c +++ b/src/scene/node.c @@ -2,7 +2,7 @@ #include "animation_impl.h" #include "camera_impl.h" -#include "llr/light_impl.h" +#include "llr/llr_impl.h" #include "memory.h" #include "model_impl.h" #include "object_impl.h" diff --git a/src/scene/node_impl.h b/src/scene/node_impl.h index c79f252..d43ae1e 100644 --- a/src/scene/node_impl.h +++ b/src/scene/node_impl.h @@ -13,6 +13,9 @@ /// together form a strict tree hierarchy and not a more general DAG. typedef struct SceneNode { NodeType type; + // TODO: Inline the actual object here and get rid of the indirection and the + // extra pools? The "scene camera" is kind of a useless data structure, for + // example. union { anima_idx anima; camera_idx camera; diff --git a/src/scene/object.c b/src/scene/object.c index e985fd5..3b2d498 100644 --- a/src/scene/object.c +++ b/src/scene/object.c @@ -2,7 +2,7 @@ #include -#include "llr/mesh_impl.h" +#include "llr/llr_impl.h" #include "memory.h" #include "node_impl.h" diff --git a/src/util/skyquad.c b/src/util/skyquad.c index 094de67..847bc91 100644 --- a/src/util/skyquad.c +++ b/src/util/skyquad.c @@ -1,9 +1,7 @@ #include #include -#include -#include -#include +#include #include #include #include -- cgit v1.2.3