A cross-platform C++ SDK for simplified 3D rendering with OpenGL.
- Easy Model Loading - Load OBJ models with textures using Assimp
- Shader Management - Load GLSL shaders from files
- Camera System - Perspective and orthographic cameras with built-in input controls
- Async Loading - Non-blocking model loading for responsive applications
- Render Queue - Flexible rendering pipeline with per-object shader support
- Post-Processing Support - Add support for post-processing effects (bloom, HDR, etc.)
- PBR (Physically Based Rendering) - Implement PBR material system for realistic lighting
- Transparent Texture Rendering - Support for rendering transparent textures with proper blending
- Shadow Mapping - Add dynamic shadow rendering capabilities
- Skybox Support - Add cubemap-based skybox rendering for environment backgrounds
Model created by Meshy AI
#include <Figura/GraphicsEngine.h>
#include <iostream>
#include <thread>
#include <chrono>
int main()
{
// Window configuration
fgr::WindowProperties props;
props.width = 800;
props.height = 600;
props.tittle = "FiguraSDK Example";
props.OpenGLContextVersionMajor = 4;
props.OpenGLContextVersionMinor = 6;
// Initialize the graphics engine
fgr::GraphicsEngine engine(props);
// Create a default shader
auto shader = std::make_shared<fgr::Shader>();
shader->Load("../../shaders/default/default.vert", "../../shaders/default/default.frag");
engine.ConfigureDefaultShader(shader);
// Create a default perspective camera
fgr::PerspectiveAttribs attribs = { 60.f, 800.f / 600.f, 0.1f, 100.f };
auto camera = std::make_shared<fgr::PerspectiveCamera>(attribs);
camera->set_position({ 0,0,5 });
engine.ConfigureCamera(camera);
// Load a model
auto model = std::make_shared<fgr::Model>();
model->LoadAsync("../assets/Meshy_AI_Fortress_Cannon_Cart_0206220959_texture.obj");
model->set_position({ 0.f, 0.f, -5.f });
// Main render loop
while (engine.IsWindowOpen())
{
// Rotate the model slowly
model->rotate(glm::vec3(0.f, 1.f, 0.f), 1.f);
// Get camera movement
engine.GetCameraMovement();
// Add model to render queue
fgr::RenderItem item;
item.model = model;
engine.AppendRenderQueue(item);
// Render all queued items
engine.Render();
// Update window (swap buffers, poll events)
engine.UpdateWindow();
}
return 0;
}
Build with CMake:
cd FiguraSDK
cmake -B out -DCMAKE_BUILD_TYPE=Release
cmake --build out --config ReleaseFiguraSDK must be linked with the following libraries:
link_libraries(
"opengl32.lib"
"FiguraSDK.lib"
"assimp-vc143-mt.lib"
)Note
Precompiled libraries for Linux are not included. You must download or compile them yourself for Linux builds.
FiguraSDK/
├── include/Figura/ # Header files
├── source/ # Implementation files
├── examples/ # Example applications
├── shaders/ # GLSL shader files
├── lib/ # Library build output
└── Additional Licenses/
The main engine class that manages the rendering pipeline, window, and resources.
GraphicsEngine(WindowProperties properties)- Initialize the graphics engine with window properties
void ConfigureDefaultShader(std::shared_ptr<Shader> shader)- Set the default shader used for rendering when no custom shader is specifiedvoid ConfigureCamera(std::shared_ptr<Camera> camera)- Set the active camera for the scene
void GetCameraMovement()- Process keyboard and mouse input for camera movement (WASD, Space, Ctrl, Right Mouse)
void AppendRenderQueue(RenderItem item)- Add a render item to the queue for the current framevoid ClearRenderQueue()- Clear all items from the render queuevoid Render()- Render all queued items to the screen
bool IsWindowOpen()- Check if the window is still openvoid UpdateWindow(glm::vec4 surface_color = glm::vec4(0.f, 0.f, 0.f, 1.f))- Swap buffers and poll events (call once per frame)surface_color- Optional RGBA clear color for the background (default: black)
Abstract base class for cameras. Use PerspectiveCamera or OrthoCamera to create instances.
void set_position(glm::vec3 pos)- Set camera position in world spacevoid face(glm::vec3 target)- Point the camera at a target position
glm::vec3 get_position()- Get current camera positionglm::vec3 get_oreintation()- Get camera orientation vector
Perspective projection camera. Inherits from Camera.
PerspectiveCamera(PerspectiveAttribs attribs)- Create with perspective projection settings
struct PerspectiveAttribs {
float fov; // Field of view in degrees
float aspect; // Aspect ratio (width/height)
float near; // Near clipping plane
float far; // Far clipping plane
};Orthographic projection camera. Inherits from Camera.
OrthoCamera(OrthographicAttribs attribs)- Create with orthographic projection settings
struct OrthographicAttribs {
float left, right; // Horizontal bounds
float bottom, top; // Vertical bounds
float near, far; // Near and far clipping planes
};Represents a 3D model composed of one or more meshes.
void Load(std::string file)- Load a 3D model synchronously from file (blocks until complete)void LoadAsync(std::string file)- Load a 3D model asynchronously (non-blocking, loads in background)static model_data LoadModelData(std::string file)- Load model data without creating GPU resources (for custom loading)
void set_position(glm::vec3 position)- Set model position in world spacevoid scale(float v)- Scale the model uniformly by factorvvoid rotate(glm::vec3 v, float angle)- Rotate model around axisvbyangleradians
glm::vec3 get_position()- Get current model position
A specialized model class for rendering 2D textured planes (sprites). Inherits from Model.
Model2D(const char* texture_path)- Create a 2D plane with the specified texturetexture_path- Path to the texture image file
All transform methods from Model are available (set_position, scale, rotate, etc.).
Manages GLSL shader programs.
void Load(const char* vertex_shader_file, const char* fragment_shader_file, const char* geometry_shader_file = nullptr)- Load and compile shaders from filesvertex_shader_file- Path to vertex shader filefragment_shader_file- Path to fragment shader filegeometry_shader_file- Optional path to geometry shader file
Note
Shaders must follow the uniform and attribute naming conventions documented in the Shader Requirements section.
struct WindowProperties {
int width; // Window width in pixels
int height; // Window height in pixels
const char* tittle; // Window title
int frames_per_second; // Target FPS (default: 30)
GLint OpenGLContextVersionMajor; // OpenGL major version (default: 4)
GLint OpenGLContextVersionMinor; // OpenGL minor version (default: 6)
};struct RenderItem {
std::shared_ptr<Shader> shader; // Custom shader (nullptr uses default)
std::shared_ptr<Model> model; // Model to render
};struct Vertex {
float position[3]; // Vertex position (x, y, z)
float color[4]; // Vertex color (r, g, b, a)
float texture_coordinates[3]; // Texture coordinates (u, v, w)
float normal[3]; // Normal vector (x, y, z)
float tangent[3]; // Tangent vector (x, y, z)
float bittangent[3]; // Bitangent vector (x, y, z)
};When creating custom shaders for FiguraSDK, your shaders must adhere to specific uniform names, texture bindings, and vertex attribute locations that the engine expects. This ensures proper communication between the engine and your shader programs.
| Uniform Name | Type | Description |
|---|---|---|
modelMatrix |
mat4 |
Model transformation matrix |
viewMatrix |
mat4 |
View (camera) matrix |
projectionMatrix |
mat4 |
Projection matrix |
normalMatrix |
mat4 |
Normal transformation matrix (for lighting calculations) |
| Binding | Uniform Name | Description |
|---|---|---|
0 |
albedo_map |
Albedo/diffuse color texture |
1 |
normal_map |
Normal map for bump mapping |
2 |
metallic_map |
Metallic texture (PBR) |
2 |
roughness_map |
Roughness texture (PBR) |
2 |
ao_map |
Ambient occlusion map |
Note
Multiple textures can share the same binding point if they are not used simultaneously in the shader.
| Location | Attribute Name | Type | Description |
|---|---|---|---|
0 |
local_space_ver_pos |
vec3 |
Vertex position in local space |
2 |
ver_texture_coords |
vec2 |
Texture coordinates |
3 |
local_space_ver_normal |
vec3 |
Vertex normal in local space |
4 |
local_space_ver_tangent |
vec3 |
Vertex tangent in local space |
5 |
local_space_ver_bittangent |
vec3 |
Vertex bitangent in local space |
See default.vert for the complete default vertex shader:
#version 460 core
layout (location = 0) in vec3 local_space_ver_pos;
layout (location = 2) in vec2 ver_texture_coords;
layout (location = 3) in vec3 local_space_ver_normal;
layout (location = 4) in vec3 local_space_ver_tangent;
layout (location = 5) in vec3 local_space_ver_bittangent;
out VERTEX_DATA
{
vec3 world_space_frag_pos;
vec3 world_space_ver_normal;
vec3 world_space_ver_tangent;
vec3 world_space_ver_bittangent;
vec2 ver_texture_coordinates;
} ver_out;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 normalMatrix;
void main() {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(local_space_ver_pos,1.0);
ver_out.ver_texture_coordinates = ver_texture_coords;
ver_out.world_space_ver_normal = mat3(normalMatrix) * local_space_ver_normal;
ver_out.world_space_ver_tangent = mat3(normalMatrix) * local_space_ver_tangent;
ver_out.world_space_ver_bittangent = mat3(normalMatrix) * local_space_ver_bittangent;
ver_out.world_space_frag_pos = vec3(modelMatrix * vec4(local_space_ver_pos,1.0));
}See default.frag for the complete default fragment shader:
#version 460 core
layout (binding = 0) uniform sampler2D albedo_map;
layout (binding = 1) uniform sampler2D normal_map;
layout (binding = 2) uniform sampler2D metallic_map;
layout (binding = 2) uniform sampler2D roughness_map;
layout (binding = 2) uniform sampler2D ao_map;
in VERTEX_DATA
{
vec3 world_space_frag_pos;
vec3 world_space_ver_normal;
vec3 world_space_ver_tangent;
vec3 world_space_ver_bittangent;
vec2 ver_texture_coordinates;
} frag_in;
out vec4 frag_color;
void main() {
frag_color = vec4(texture(albedo_map, frag_in.ver_texture_coordinates).rgb, 1.0f);
}See Additional Licenses folder for third-party library licenses.
This project was developed with the help of LearnOpenGL, an excellent resource for learning modern OpenGL programming. If you are curious about computer graphics and specifically OpenGL it is highly advised that you check it out.