#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*);