From 1ec46bead3cf87971a2329f9ef4ddde5a0c48325 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 4 Jul 2025 10:27:06 -0700 Subject: Clarify doc --- src/llr/llr_impl.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/llr/llr_impl.h (limited to 'src/llr/llr_impl.h') diff --git a/src/llr/llr_impl.h b/src/llr/llr_impl.h new file mode 100644 index 0000000..5ccabd1 --- /dev/null +++ b/src/llr/llr_impl.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include + +#include +#include + +#include +#include + +typedef struct Geometry Geometry; +typedef struct GfxCore GfxCore; +typedef struct IBL IBL; +typedef struct Material Material; +typedef struct ShaderProgram ShaderProgram; +typedef struct Texture Texture; + +/// Immediate mode renderer. +/// +/// The renderer caches state changes in memory and only programs the underlying +/// shader program when a draw call is issued and if anything has changed. This +/// keeps the number of graphics API calls to a minimum, but requires tracking +/// state changes. The 'changed' booleans below fulfill this purpose, and +/// indicate whether a given state has changed since the last draw call. +/// +/// The renderer must combine state changes accordingly. For example, if only +/// the lights have changed, then it is sufficient to update light uniforms in +/// the current shader program. On the other hand, if the shader program has +/// changed, then the renderer must reconfigure it from scratch and set light +/// uniforms, camera uniforms, etc. +/// +/// Note that the shader program API has its own level of caching as well, so +/// reconfiguration at the level of the renderer does not result in the +/// worst-case set of graphics API calls. +/// +/// 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 ImmRenderer { + GfxCore* gfxcore; + + vec3 camera_position; + mat4 view; // Camera view matrix. + mat4 projection; // Camera projection matrix. + bool camera_changed; // Whether the camera parameters have changed. + + // ------------------------------------------- + // Immediate-mode rendering of scene elements. + + IBL* ibl; + Texture* brdf_integration_map; + + ShaderProgram* shader; // Active shader. Not owned. + bool shader_changed; // Whether the shader has changed. + + // Lights are not const because environment lights store lazily-computed + // irradiance maps. + Light* lights[IMM_MAX_NUM_LIGHTS]; // Lights stack. + int num_lights; // Number of lights enabled at a given point in time. It + // points to one past the top of the stack. + bool lights_changed; // Whether the lights have changed. + + bool skeleton_changed; + size_t num_joints; + mat4 joint_matrices[GFX_MAX_NUM_JOINTS]; + + // --------------------------------------- + // Immediate-mode rendering of primitives. + + ShaderProgram* imm_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[IMM_MAX_NUM_TRIANGLES * 3]; + + // ------------- + // Matrix stack. + + // The matrix stack contains pre-multiplied matrices. + // It is also never empty. The top of the stack is an identity matrix when the + // stack is "empty" from the user's perspective. + mat4 matrix_stack[IMM_MAX_NUM_MATRICES]; + int stack_pointer; // Points to the top of the stack. +} ImmRenderer; + +/// Create a new immediate mode renderer. +bool gfx_imm_make(ImmRenderer*, GfxCore*); + +/// Destroy the immediate mode renderer. +void gfx_imm_destroy(ImmRenderer*); + +/// Flush draw commands. +void gfx_imm_flush(ImmRenderer*); -- cgit v1.2.3