- Moved OpenGL library wrapper into platform

- Finished reorganizing PLANNING.md
This commit is contained in:
2025-08-05 16:14:00 -04:00
parent 4a3639ecb4
commit 0f721f57ea
22 changed files with 794 additions and 1045 deletions

View File

@@ -69,6 +69,7 @@ add_library(fennec STATIC
include/fennec/containers/map.h include/fennec/containers/map.h
include/fennec/containers/optional.h include/fennec/containers/optional.h
include/fennec/containers/pair.h include/fennec/containers/pair.h
include/fennec/containers/rdtree.h
include/fennec/containers/set.h include/fennec/containers/set.h
include/fennec/containers/tuple.h include/fennec/containers/tuple.h
@@ -192,8 +193,6 @@ add_library(fennec STATIC
# EXTRA SOURCES ======================================================================================================== # EXTRA SOURCES ========================================================================================================
${FENNEC_EXTRA_SOURCES} ${FENNEC_EXTRA_SOURCES}
include/fennec/renderers/interface/renderer.h
include/fennec/containers/rdtree.h
include/fennec/scene/scene.h include/fennec/scene/scene.h
include/fennec/scene/component.h include/fennec/scene/component.h
include/fennec/core/system.h include/fennec/core/system.h

View File

@@ -39,12 +39,9 @@ if(FENNEC_GRAPHICS_WANT_EGL)
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::EGL) list(APPEND FENNEC_LINK_LIBRARIES OpenGL::EGL)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1) list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1)
list(APPEND FENNEC_EXTRA_SOURCES list(APPEND FENNEC_EXTRA_SOURCES
include/fennec/renderers/opengl/lib/fwd.h include/fennec/platform/opengl/lib/fwd.h
include/fennec/renderers/opengl/lib/enum.h include/fennec/platform/opengl/lib/enum.h
include/fennec/renderers/opengl/lib/buffer.h include/fennec/platform/opengl/lib/buffer.h
include/fennec/renderers/opengl/modern.h
include/fennec/renderers/opengl/fallback.h
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
) )

View File

@@ -48,7 +48,7 @@ PROJECT_NAME = fennec
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = PROJECT_NUMBER = 1.0.2
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a

View File

@@ -1,188 +0,0 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_INTERFACE_RENDERER_H
#define FENNEC_RENDERERS_INTERFACE_RENDERER_H
#include <fennec/containers/dynarray.h>
#include <fennec/lang/types.h>
#include <fennec/langproc/strings/cstring.h>
#include <fennec/math/matrix.h>
#include <fennec/math/scalar.h>
#include <fennec/math/ext/quaternion.h>
/*
* Some ramblings on deciding what objects are needed to support the features in PLANNING.md
*
*
* Definitions:
* Static Mesh -> A mesh whose number of vertices and attributes does not change after creation
* Object -> A static mesh instance
* Skeletal Mesh -> A static mesh with support for skinned rigs
* Animation -> A set of keys for a skeletal mesh
* Puppet -> A skeletal mesh instance
* Static Object -> An object whose transform does not change after scene start
* Dynamic Object -> An object whose transform can change after scene start, all puppets must be dynamic objects
* Static Light -> A light whose transform does not change after scene start. Other attributes may change, which will
* be specified per light
* Dynamic Light -> A light whose transform can change after scene start, including all attributes
*
* Static mesh rendering
* Skeletal mesh rendering
* Lights with or without shadows (PCSS for soft shadowing)
* - Sun Light
* - Skybox
* - Point Light
* - Spotlight
* - Area light
* Post-Processing
*
* Materials
*/
namespace fennec
{
class renderer3d {
public:
// These refer to assets
// texture -> 8-bit type, 24-bit id (256, 16,777,216)
// mesh -> 32-bit id (4,294,967,296)
// skeleton -> 32-bit id (4,294,967,296)
// animation -> 32-bit id (4,294,967,296)
// shader -> 32-bit id (4,294,967,296)
// model -> 8-bit flag, 24-bit id (8, 16,777,216)
// puppet -> 32-bit id (4,294,967,296)
// light -> 8-bit type, 24-bit id (256, 16,777,216)
// material -> 32-bit id (4,294,967,296)
// TYPEDEFS & CONSTANTS ================================================================================================
using uid_t = uint32_t;
static constexpr uid_t null = -1;
static constexpr uint_t max_bone_weights = 8;
// ENUMS ===============================================================================================================
enum format_ : uint8_t {
format_r = 0,
format_rg,
format_rgb,
format_rgba,
format_shadow, // TODO: decide whether end-users may create shadow buffers
format_count,
format_last = format_count - 1,
};
enum texture_ : uint8_t {
texture_2d = 0,
texture_3d,
texture_cubemap,
};
enum light_ : uint8_t {
light_sun = 0,
light_sky,
light_point,
light_spot,
light_area,
};
enum iterp_ : uint8_t {
iterp_step = 0,
iterp_linear,
iterp_spherical,
iterp_cubic,
};
// STRUCTURES ==========================================================================================================
struct mesh_vertex {
vec3 location;
vec3 normal;
vec3 tangent;
vec2 uv;
};
struct skin_vertex {
vec3 location;
vec3 normal;
vec3 tangent;
vec2 uv;
uint32_t bones[max_bone_weights];
uint32_t weights[max_bone_weights];
};
struct bone {
mat4 localSpace; // I was going to use quaternions, but Assimp, glTF, FBX, Unity, Unreal, and Godot all use matrices
};
struct skeleton {
mat4 root;
uint boneStart, boneEnd; // APIs job to figure out how to store bones, should be in a SSBO regardless of API
};
// Wrapper for animation keys
template<typename ValueT>
struct key {
double time;
ValueT val;
uint8_t mode;
};
// Wrapper for a track, essentially the keyframes for a single bone
struct track {
uint posStart, posEnd; // APIs job to figure out how to store keys, should be in a SSBO regardless of API
uint rotStart, rotEnd;
uint sclStart, sclEnd;
};
struct animation {
uint trkStart, trkEnd; // APIs job to figure out how to store tracks, should be in a SSBO regardless of API
};
// FUNCTIONS ===========================================================================================================
virtual uid_t create_mesh(const dynarray<uint32_t>& indices, const dynarray<mesh_vertex>& vertices) = 0;
virtual void release_mesh(uid_t id);
// TODO: virtual uid_t create_skeleton()
// TODO: virtual uid_t create_shader()
virtual uid_t create_texture(uint8_t type, uint8_t format, bool hdr) = 0;
virtual void release_texture(uid_t);
// TODO: virtual uid_t create_light()
virtual ~renderer3d() = default;
private:
};
}
#endif // FENNEC_RENDERERS_INTERFACE_RENDERER_H

View File

@@ -1,38 +0,0 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_OPENGL_FALLBACK_H
#define FENNEC_RENDERERS_OPENGL_FALLBACK_H
/*
* This should be implemented using the OpenGL ES 3.2 profile
* https://registry.khronos.org/OpenGL/specs/es/3.2/es_spec_3.2.pdf
*
* Requires the following:
* OpenGL ES 3.2 / OpenGL 4.3 OR
* - ARB_compute_shader
* - ARB_shader_image_load_store
* - ARB_shader_storage_buffer_object
* - ARB_texture_cube_map_array
* - ARB_texture_storage
* - EXT_texture_array
*
* This will support all mobile devices since 2012
*/
#endif // FENNEC_RENDERERS_OPENGL_FALLBACK_H

View File

@@ -1,38 +0,0 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_OPENGL_MODERN_H
#define FENNEC_RENDERERS_OPENGL_MODERN_H
/*
*
* Requires the following:
* OpenGL 4.6 OR
* - ARB_buffer_storage
* - ARB_compute_shader
* - ARB_multi_draw_indirect
* - ARB_shader_draw_parameters
* - ARB_shader_image_load_store
* - ARB_texture_cube_map_array
* - ARB_texture_storage
* - EXT_texture_array
*
* This will support >91.31% of devices on Steam, including all Desktop GPUs and iGPUs since 2012
*/
#endif // FENNEC_RENDERERS_OPENGL_MODERN_H

64
planning/2D_GRAPHICS.md Normal file
View File

@@ -0,0 +1,64 @@
# 2D Graphics (`gfx2d`)
## Table of Contents
<!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [2D Graphics (`gfx2d`)](#2d-graphics-gfx2d)
* [Table of Contents](#table-of-contents)
* [Introduction](#introduction)
* [Structures (`gfx2d`)](#structures-gfx2d)
<!-- TOC -->
## Introduction
&ensp; This system handles the rendering of 2D meshes and textures.
Links:
- https://en.wikipedia.org/wiki/Quadtree
- https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-25-rendering-vector-art-gpu
### Structures (`gfx2d`)
For the 2d rendering framework, Materials need to be rendered independently because we have
no size constraints for images. This disallows us from using a meta-shader like in
the 3d rendering framework.
```c++
struct Object
{
vec2 location, scale; // A matrix would be 36 bytes, this is instead 20 bytes
float rotation;
}
```
- BVH
- Quadtree
- Leaf Size and Tree Depth should be calculated by the scene, constraints are as follows:
- Min Object Size
- Max Object Size
- Scene Center
- Scene Edge
- Insertions and Updates are done on the CPU
- Nodes
- Start Index 32-bits
- Object Count 32-bits
- Objects
- Buffer of Object IDs grouped by Octree Node
- Culling
- Starting at each Octree Leaf, traverse upwards.
- Insert Visible Leaf IDs
- Track using atomic buffer
- Generate the Command Buffer for Culled Meshes from the Visible Leaf Buffer
- Count Materials
- Count Meshes per Material
- Generate the Culled Object Buffer by copying objects from the Object Buffer
- Adjust Buffer Size using the counts
- Insert using another atomic buffer
- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate.
This will allow us to sort objects as they are created. We can still bulk render each z-index,
with meshes and objects being grouped by material.

211
planning/3D_GRAPHICS.md Normal file
View File

@@ -0,0 +1,211 @@
# 3D Graphics (`gfx3d`)
## Table of Contents
<!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [3D Graphics (`gfx3d`)](#3d-graphics-gfx3d)
* [Table of Contents](#table-of-contents)
* [Introduction](#introduction)
* [Structures](#structures)
* [Stages](#stages)
<!-- TOC -->
## Introduction
&ensp; This system handles the rendering of 3D meshes, materials, lights, and post-processing
effects.
**DirectX will never have official support.**
If you would like to make a fork, have at it, but know that I will hold a deep disdain for you.
The graphics pipeline will have a buffer with a list of objects and their rendering data.
This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes.
The buffers will be optimized by scene prediction.
This involves tracking the meshes and textures directly and indirectly used by a scene.
A callback function in the graphics system for scene loading can do this.
Materials and Lighting models will be run via a shader metaprogram to make the pipeline independent of this aspect.
This allows the GPU to draw every single deferred rendered mesh in a single draw call for each stage of the renderer.
Specifications for debugging views via early breaks are included in the stages.
Links:
- https://en.wikipedia.org/wiki/Octree
- https://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study/
- https://learnopengl.com/PBR/Lighting
- https://learnopengl.com/PBR/IBL/Diffuse-irradiance
- https://en.wikipedia.org/wiki/Schlick%27s_approximation
- https://pixelandpoly.com/ior.html
- https://developer.download.nvidia.com/SDK/10/opengl/screenshots/samples/dual_depth_peeling.html
## Structures
Object Structure. The mesh is implicit data.
```c++
struct Object
{
vec3 location, scale; // A matrix would be 64 bytes, this is instead 28 bytes
quat rotation;
uint32 material, lighting;
}
```
Textures for 3D rendering are stored in various buffers with sizes of powers of 2.
Ratios of `1:1` and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection.
UVs may be transformed to use a `2:1` as if it were `1:2`.
Cubemaps and 3D textures may only be `1:1`, I would be concerned if you are using any other ratio.
- 8-Bit R Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RG Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RGB Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RGBA Texture `4096, 2048, 1024, 512` (8)
- 8-Bit R Cubemap `1024, 512, 256, 128` (4)
- 8-Bit RGB Cubemap `1024, 512, 256, 128` (4)
* 16-Bit HDR R Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR RGB Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR RGBA Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR R Cubemap `1024, 512, 256, 128` (4)
* 16-Bit HDR RGB Cubemap `1024, 512, 256, 128` (4)
- 16-Bit Shadow Texture `4096, 2048, 1024, 512` (8)
- 16-Bit Shadow Cubemap `2048, 1024, 512, 256` (4)
* 8-Bit 3D R Texture `256, 128, 64, 32` (4)
* 8-Bit 3D RGB Texture `256, 128, 64, 32` (4)
* 16-Bit 3D HDR R Texture `256, 128, 64, 32` (4)
* 16-Bit 3D HDR RGB Texture `256, 128, 64, 32` (4)
Documentation should provide guidelines on categories of Art Assets and the resolution of textures to use.
Textures are identified by a 32-bit integer.
- `8 bits` &rarr; the texture buffer
- `24 bits` &rarr; the layer in the buffer
Artists should be informed on the texture structure of the engine and its limitations.
However, these principles should be followed in other game engines as these are
guided by what is most efficient for typical GPU hardware.
Materials are, for the most part, user-defined. Documentation should make the user aware of this.
Material buffers will be a sequence of the Material Struct instances.
They will at the very least contain the id of their shader.
Types of materials:
- Surface (Vertex & Fragment)
- Opaque / Masked
- Translucent (Forward)
- Volume (Path Traced Volumetrics / Forward)
- Light (Lighting Model)
- Post-Process
## Stages
This is the set of stages for the graphics pipeline that runs every frame:
Unless otherwise specified, each stage will be run on the GPU.
- BVH
- Octree `(8 Bpn, 64 bpn) [6-Layers ≈ 2.1MB]`
- Leaf Size and Tree Depth should be calculated by the scene, constraints are as follows:
- Min Object Size
- Max Object Size
- Scene Center
- Scene Edge
- Buffer has implicit locations due to the tree having 8 children.
- Insertions and Updates are done on the CPU
- Nodes
- Start Index `int32`
- Object Count `int32`
- Objects
- Buffer of Object IDs grouped by Octree Node
- Leaf Culling
- Starting at each Octree Leaf, traverse upwards.
- Insert Visible Leaf IDs
- Track using atomic buffer
- Generate the Command Buffer for Culled Mesh LODs from the Visible Leaf Buffer
- Track counts using atomic buffers
- To avoid double counting due to the construction of the Octree output, we have some options
- Ignore Leaf Instances based on occurrences of the mesh in the surrounding 8 Quadtree Leaves. This would require
a bias towards a specific corner of the filter.
- Perform a preprocessing step on the CPU to erase duplicate elements and fix the buffer continuity.
- Let the duplicates be rendered.
- Generate the Culled Object Buffer with the respective object IDs
- Adjust Buffer Size using the counts
- Insert by reusing the count buffer, clipped to only contain used meshes
Debug View: Object ID, Mesh ID, LOD
- Visibility
- Buffer `(15 Bpp, 120 bpp) [1920x1080] ≈ 39.4MB`
- Depth Buffer &rarr; `D24`
- Visibility Info &rarr; `RGB32I`
- R = Object ID
- G = Mesh ID
- B = Material ID
- Regenerate the Command Buffer for Visible Mesh LODs
- Regenerate the Culled Object Buffer
Debug View: Visibility Buffer
* G-Buffer Pass `(17 Bpp, 136 bpp) [1920x1080] ≈ 35.3MB`
* Depth - Stencil &rarr; `D24_S8`
* S &rarr; used to represent the lighting model.
* Diffuse &rarr; `RGBA8`
* A &rarr; Ambient Occlusion
* Emission &rarr; `RGB8`
* Normal &rarr; `RGB8`
* Specular &rarr; `RGB8`
* R &rarr; Roughness
* G &rarr; Specularity (sometimes called the Metallicness)
* B &rarr; Index of Refraction (IOR)
Debug View: Depth, Stencil, Diffuse, Emission, Normal, Specularity
- Generate Dynamic Shadows
- Generate Dynamic Reflections (Optional)
- SSAO (Optional)
- Deferred Lighting Pass `(10 Bpp, 80 bpp) [1920x1080] ≈ 2 x 16.3MB + 8.3MB ≈ 24.6MB`
- Depth Buffer &rarr; `D24`
- Lighting Buffer &rarr; `RGB16` w/ Mipmapping
- Stencil Buffer $rarr; `S8`
- Apply Lighting Model
Debug View: Shadows, Reflections, SSAO, Deferred Lighting
We can combine all of these into one framebuffer:
- Depth - Stencil &rarr; `D24_S8`
- Visibility Info &rarr; `RGB32I`
- Diffuse &rarr; `RGBA8`
- Emission &rarr; `RGB8`
- Normal &rarr; `RGB8`
- Specular &rarr; `RGB8`
- Lighting Buffer &rarr; `RGB16` w/ Mipmapping
- One more slot left open for another
* Forward Pass
* BVH, Same as Above
* LOD Selection, Same as Above
* Translucent Materials
* Dual Depth Peeling
Debug View: Forward Mask
- Post Processing
- Depth of Field (Optional)
- When enabled, the Visiblity Buffer, G-Buffer, and Deferred Lighting Pass will be double layered.
- At this point the Lighting Buffers will be Flattened
- Bloom (Optional) &rarr; Mipmap Blurring `(6Bpp, 48bpp) [1920x1080] ≈ 16.3MB`
- Tonemapping (Optional)
- HDR Correction

48
planning/3D_PHYSICS.md Normal file
View File

@@ -0,0 +1,48 @@
# 3D Physics (`physics3d`)
## Table of Contents
<!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [3D Physics (`physics3d`)](#3d-physics-physics3d)
* [Table of Contents](#table-of-contents)
* [Introduction](#introduction)
* [System Layout](#system-layout)
<!-- TOC -->
## Introduction
&ensp; This system will handle newtonian physics for 3D rigid and soft-bodies. This should include
articulated skeletal systems, particle physics, and soft-body physics. The following soft-body systems
will be supported with the associated implementation; elastics with finite element simulation, cloth
physics with position-based dynamics, oceans with iWave, 3D fluid dynamics with smoothed-particle
hydrodynamics, 2D surface fluid dynamics with force-based dynamics.
## System Layout
* Rigid Body Physics
* Newtonian Physics and Collision Resolution
* Articulated Skeletal Systems
* Inverse Kinematics
* Stiff Rods
- Particle Physics
* Soft Body Physics
* Elastics &rarr; Finite Element Simulation
* Cloth &rarr; Position-Based Dynamics
* Water
* Oceans &rarr; iWave
* Reasoning: iWave provides interactive lightweight fluid dynamics suitable for flat planes of water.
<br><br>
* 3D Fluid Dynamics &rarr; Smoothed-Particle Hydrodynamics
* Reasoning: This is the simplest method for simulating 3D bodies of water. This should exclusively be
used for small scale simulations where self-interactive fluids are necessary. I.E. pouring water into
a glass.
<br><br>
* 2D Surface Fluid Dynamics &rarr; Force-Based Dynamics
* Reasoning: This model, like iWave, provides lightweight interactive fluid dynamics, but is more easily
adapted to flowing surfaces such as streams and rivers.

View File

@@ -0,0 +1,29 @@
# Artifical Intelligence (`ai`)
## Table of Contents
## Introduction
&ensp; This system implements pathing and decision systems for general-purpose traditional
artifical intelligence algorithms. This library will not support Machine-Learning Artificial
Intelligence (ML/AI). This artificial intelligence method only differs in static generation
between 2D and 3D. The solvers are dimension independent since they work on a graph.
## General Process
### Static
- generate a static navigation graph (sometimes called a NavMesh)
### Tick
* resolve dynamic blockers
* update paths using dijkstra's algorithm
* apply rigid-body forces with constraints
The update loop for artificial intelligence should only update every `n` ticks. Where
`n <= k`, with `k` being the tick rate of the physics engine.

View File

@@ -3,15 +3,53 @@
## Table of Contents ## Table of Contents
<!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [Containers Library](#containers-library-containers)
* [Table of Contents](#table-of-contents)
* [Introduction](#introduction)
* [Implementation](#implementation)
* [C++ Standard Template Library](#c-standard-template-library)
* [fennec](#fennec)
<!-- TOC -->
## Introduction ## Introduction
&ensp; This library contains headers and classes that implement common data &ensp; This library contains headers and classes that implement common data
structures. The contents are restricted to the Containers Library of the C++ structures. The contents include the Containers Library of the C++ Standard
Standard Library and Template Library. Library and Template Library.
## Implementation ## Implementation
### C++ Standard Template Library
| Symbol | Implemented | Passed |
|:-------------------------------------|:-----------:|:------:|
| pair | ✔ | ✔ |
| tuple | ⭕ | ❌ |
| optional | ✔ | ✔ |
| variant | ❌ | ❌ |
| any | ❌ | ❌ |
| bitset | ❌ | ❌ |
| array | ✔ | ✔ |
| dynarray (`std::vector`) | ✔ | ✔ |
| list | ✔ | ✔ |
| set (`std::unordered_set`) | ✔ | ✔ |
| ordered_set (`std::set`) | ✔ | ✔ |
| map (`std::unordered_map`) | ✔ | ✔ |
| ordered_map (`std::map`) | ✔ | ✔ |
| multiset (`std::unordered_multiset`) | ✔ | ✔ |
| ordered_multiset (`std::multiset`) | ✔ | ✔ |
| multimap (`std::unordered_multimap`) | ✔ | ✔ |
| ordered_multimap (`std::multimap`) | ✔ | ✔ |
### fennec
| Symbol | Implemented | Passed |
|:--------|:-----------:|:------:|
| graph | ✔ | ✔ |
| rd_tree | ✔ | ✔ |

View File

@@ -52,11 +52,20 @@ be achieved using events at different stages of those engines that are on-demand
&ensp; Many subpages of these documents will contain tables that use symbols to &ensp; Many subpages of these documents will contain tables that use symbols to
denote implementation and testing progress. The symbols are defined below. denote implementation and testing progress. The symbols are defined below.
| Symbol | Meaning | | Symbol | Meaning | Notes |
|:-------:|:------------------------| |:------:|:------------------------|:----------------------------------------------------------|
| ✔ | Completed | | ✔ | Completed | Complete implementation and all tests passing. |
| | Partial | | | Partial | Partial implementation and all tests implemented passing. |
| | Unimplemented / Failing | | | Untested | Not tested |
| ❌ | Unimplemented / Failing | Not implemented or any test is failing. |
| Implemented / Passed | ✔ | ⭕ | ❓ | ❌ |
|:--------------------:|--------------------------------------------------------------------|-------------------------------------------------------------------------------|---------|-----------------|
| ✔ | Implemented and Passing | Invalid | Invalid | Not Implemented |
| ⭕ | Implemented and Partial Testing with all implemented tests passing | Partial Implementation and Partial Testing with all implemented tests passing | Invalid | Not Implemented |
| ❓ | Implemented and Untested | Partial Implementation and Untested | Invalid | Not Implemented |
| ❌ | Implemented and Any Test is Failing | Partial Implementation and any test is Failing | Invalid | Not Implemented |
## Libraries ## Libraries

View File

@@ -5,7 +5,7 @@
<!-- TOC --> <!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec) * [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [C++ Language Library (`lang`)](#c-language-library-lang) * [C++ Language Library](#c-language-library-lang)
* [Table of Contents](#table-of-contents) * [Table of Contents](#table-of-contents)
* [Introduction](#introduction) * [Introduction](#introduction)
* [Implementation](#implementation) * [Implementation](#implementation)
@@ -27,7 +27,7 @@
## Introduction ## Introduction
&ensp; This library contains headers and classes related to the C++ language. The &ensp; This library contains headers and classes related to the C++ language. The
contents of this library are restricted to the Language Support, Diagnostics, and contents of this library include the Language Support, Diagnostics, and
Metaprogramming libraries of the C++ Standard Library and Template Library. Metaprogramming libraries of the C++ Standard Library and Template Library.
See: See:

131
planning/ENGINE.md Normal file
View File

@@ -0,0 +1,131 @@
# fennec
## Table of Contents
<!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [fennec](#fennec)
* [Table of Contents](#table-of-contents)
* [Introduction](#introduction)
* [Systems](#systems)
* [Events](#events)
* [Scene](#scene)
* [Scripts](#scripts)
* [AI](#ai)
* [Physics](#physics)
* [Graphics](#graphics)
* [Audio](#audio)
* [Core Game Loop](#core-game-loop)
* [Tick](#tick)
* [Frame](#frame)
<!-- TOC -->
## Introduction
&ensp; This file outlines the core engine structure and all necessary systems for
the engine to run.
## Systems
This section outlines core systems to the engine and brief overviews.
### Events
&ensp; fennec will be largely event based, the system should be able to handle multiple
event types without having any type-specific code. There will be a few categories of events,
predominantly on-demand and delayed events. On-demand events are fired immediately, which is
useful for events related to graphics and audio. Delayed events are fired at the next tick or
after a certain period of time, this is useful for physics events which can't be handled
immediately without potentially harming the state of the physics engine. Events should be
optionally able to be handled with multithreading.
### Scene
&ensp; The core structure of the engine and its levels will be a scene hierarchy. The hierarchy
will be implemented using a rooted-directed tree (rdtree, not to be confused with rbtree).
Each element in the tree will be a node with a name and some very basic flags. Component
dependent behaviour *must* be handled in systems to avoid the overhead of an object-oriented
scene hierarchy. This is predominantly caused by the recursive nature of parsing an object-
oriented scene hierarchy where each node records its children and updates them accordingly.
### Scripts
&ensp; Scripts won't be handled the same way scripts are in other engines, they will be translated
as a system which will be data-oriented. This is to reduce the overhead of the object-oriented
approach in C++ while maintaining the appearance of being object-oriented.
### AI
&ensp; AI will be a fairly multi-parted system as we need to handle different use-cases.
The first use case is characters that can "walk" and "jump" on surfaces. The second use-case
is characters that "fly" in some manner. The static path generation will be the only difference
between 2D and 3D.
### Physics
&ensp; Physics, like other systems, will be separated into 2D and 3D specific implementations.
This system should be able to handle both Newtonian Rigid-Bodies and Soft-Bodies. The 2D
and 3D systems should be able to co-exist but not interact. This is for such cases where one
might decide to have a minigame with physics enabled in a 2D environment.
### Graphics
&ensp; Graphics, like other systems, will be separated into 2D and 3D specific implementations.
Graphics will exist on a separate thread that handles "frames" vs "ticks," see definitions below
for more information. From an abstract, the graphics system should be able to handle static models,
dynamic models, skeletons, materials, lights, lighting models, and post-processing effects.
### Audio
&ensp; Audio may actually be implemented generically since the principles of spatial audio apply
identically in both 2D and 3D. The only thing that may change for 2D is which axis is "up" and which
axis is "forwards," for example side-scrollers vs top-down. However, this does not mandate specific
implementations and rather just aliases which axis is "up." The X-axis can always be "left" and "right"
while the Y axis may be interpreted as "up" or "forwards." Audio also won't be handled in the same
manner as other systems which have explicit ticks and frames.
## Core Game Loop
&ensp; The core game loop is divided into Ticks and Frames. Ticks represent updates in the engine
state while Frames represent the generation of the visual output of the engine.
### Tick
- **Update**
- Events
- Scripts
- AI
- **Physics**
- Newtonian Commit
- Apply Forces (Updates Accelerations)
- Acceleration (Updates Velocities)
- Apply Velocities (Updates Position and Rotation)
- Constraint Resolution
- Collision Detection
- Collision Resolution
- Collision Response
- Calculate Forces & Velocities
- Queue events for next tick
### Frame
- **Physics**
- Physics Interpolation
- **Graphics**
- [2D Graphics](./2D_GRAPHICS.md#2d-graphics-gfx2d)
- Generate 3D Mask
- [3D Graphics](./3D_GRAPHICS.md#3d-graphics-gfx3d)

View File

@@ -0,0 +1,248 @@
# Language Processing Library (`langproc`)
## Table of Contents
<!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [Language Processing Library (`langproc`)](#language-processing-library-langproc)
* [Table of Contents](#table-of-contents)
* [Introduction](#introduction)
* [String Analysis (`langproc/strings`)](#string-analysis-langprocstrings)
* [Implementation](#implementation)
* [File System (`filesystem`)](#file-system-filesystem)
* [Implementation](#implementation-1)
<!-- TOC -->
## Introduction
&ensp; This library contains implementations of headers and classes related to processing
languages. This includes; ascii/utf8/utf16 string processing, file formats, machine language,
and programming languages.
&ensp; fennec should be able to process documentation in files, the main ways it will support
this is through Doxygen and LaTeX. Consider including binaries with releases.
## String Analysis (`langproc/strings`)
&ensp; fennec reimplements the C++ Strings Library as a submodule of this library. This
is because C++ `std::string` has a lot of overhead. I would say that `std::string`
is a Jeep, while `fennec::string` is an F2 Car, if that analogy makes any sense. i.e.
`std::string` offers a lot of use cases, but is slower, while an F2 Car is barebones and
highly performant on the right surface.
### Implementation
| Symbol | Implemented | Passed |
|:---------|:-----------:|:------:|
| cstring | ✔ | ✔ |
| string | ✔ | ✔ |
| wcstring | ✔ | ✔ |
| wstring | ✔ | ✔ |
## File System (`filesystem`)
&ensp; fennec *does not* reimplement the C++ I/O Library. What it does do
is create C++ classes that handle file streams, directory streams, and file paths.
### Implementation
| Symbol | Implemented | Passed |
|:----------|:-----------:|:------:|
| path | ✔ | ✔ |
| file | ✔ | ✔ |
| directory | ❌ | ❌ |
## Interpreter (`langproc/interpret`)
&ensp; This submodule will contain classes for interpreting data, particularly
through parsers. We will need to be able to do the following things to achieve
support for files that adhere to a certain specification. Here are some concepts
that will need to be implemented as classes:
### Reading
- Tokenization
- Useful for text-based formats
- Data Parser
- Useful for binary-based formats
- Lexical Analysis
- Necessary for Syntax Coloring
- Syntax Analysis
- Necessary for Syntax Coloring
- Semantic Analysis
- Necessary for Code Completion
- Intermediate Code Generation
- Necessary for any custom programming language in fennec
- Target Code Generation / Optimization?
- Necessary for any custom programming language that needs to compile to binary
### Writing
&ensp; The writers will be responsible for writing data as a specific format. I.E. converting
data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/utf16).
- Writer
- Binary Writer
## Formats (`langproc/formats`)
&ensp; This submodule will contain classes for processing a variety of file formats.
### Serialization
| Symbol | Implemented | Passed |
|:-------|:-----------:|:------:|
| JSON | ❌ | ❌ |
| HTML | ❌ | ❌ |
| XML | ❌ | ❌ |
| YAML | ❌ | ❌ |
### Configuration
| Symbol | Implemented | Passed |
|:-------|:-----------:|:------:|
| INI | ❌ | ❌ |
| TOML | ❌ | ❌ |
### Documents
| Symbol | Implemented | Passed |
|:---------|:-----------:|:------:|
| ODF | ❌ | ❌ |
| Markdown | ❌ | ❌ |
| PDF | ❌ | ❌ |
### Spreadsheets & Tables
| Symbol | Implemented | Passed |
|:---------|:-----------:|:------:|
| ODS | ❌ | ❌ |
| CSV | ❌ | ❌ |
### Audio Formats
| Symbol | Implemented | Passed |
|:---------|:-----------:|:------:|
| MP3 | ❌ | ❌ |
| WAV | ❌ | ❌ |
| AAC | ❌ | ❌ |
### Graphics Formats
#### Raster Textures
| Symbol | Implemented | Passed |
|:-------|:-----------:|:------:|
| BMP | ❌ | ❌ |
| DDS | ❌ | ❌ |
| JPG | ❌ | ❌ |
| PNG | ❌ | ❌ |
| TIFF | ❌ | ❌ |
#### Vector Graphics
| Symbol | Implemented | Passed |
|:-------|:-----------:|:------:|
| OTF | ❌ | ❌ |
| SVG | ❌ | ❌ |
| TTF | ❌ | ❌ |
#### 3D Model Formats
&ensp; unfortunately, most formats are esoteric due to copyright/trademark/etc.
I will be using assimp for the time being, below is a list of formats supported
by assimp.
| Symbol | Implemented | Passed |
|:----------------|:-----------:|:------:|
| 3D | ❌ | ❌ |
| 3DS | ❌ | ❌ |
| 3MF | ❌ | ❌ |
| AC | ❌ | ❌ |
| AC3D | ❌ | ❌ |
| ACC | ❌ | ❌ |
| AMJ | ❌ | ❌ |
| ASE | ❌ | ❌ |
| ASK | ❌ | ❌ |
| B3D | ❌ | ❌ |
| BVH | ❌ | ❌ |
| CSM | ❌ | ❌ |
| COB | ❌ | ❌ |
| DAE/Collada | ❌ | ❌ |
| DXF | ❌ | ❌ |
| ENFF | ❌ | ❌ |
| FBX | ❌ | ❌ |
| glTF 1.0 + GLB | ❌ | ❌ |
| glTF 2.0 | ❌ | ❌ |
| HMB | ❌ | ❌ |
| IFC-STEP | ❌ | ❌ |
| IQM | ❌ | ❌ |
| IRR / IRRMESH | ❌ | ❌ |
| LWO | ❌ | ❌ |
| LWS | ❌ | ❌ |
| LXO | ❌ | ❌ |
| M3D | ❌ | ❌ |
| MD2 | ❌ | ❌ |
| MD3 | ❌ | ❌ |
| MD5 | ❌ | ❌ |
| MDC | ❌ | ❌ |
| MDL | ❌ | ❌ |
| MESH / MESH.XML | ❌ | ❌ |
| MOT | ❌ | ❌ |
| MS3D | ❌ | ❌ |
| NDO | ❌ | ❌ |
| NFF | ❌ | ❌ |
| OBJ | ❌ | ❌ |
| OFF | ❌ | ❌ |
| OGEX | ❌ | ❌ |
| PLY | ❌ | ❌ |
| PMX | ❌ | ❌ |
| PRJ | ❌ | ❌ |
| Q3O | ❌ | ❌ |
| Q3S | ❌ | ❌ |
| RAW | ❌ | ❌ |
| SCN | ❌ | ❌ |
| SIB | ❌ | ❌ |
| SMD | ❌ | ❌ |
| STP | ❌ | ❌ |
| STL | ❌ | ❌ |
| TER | ❌ | ❌ |
| UC | ❌ | ❌ |
| USD | ❌ | ❌ |
| VTA | ❌ | ❌ |
| X | ❌ | ❌ |
| X3D | ❌ | ❌ |
| XGL | ❌ | ❌ |
| ZGL | ❌ | ❌ |
#### Video Formats
| Symbol | Implemented | Passed |
|:-------|:-----------:|:------:|
| MP4 | ❌ | ❌ |
| AVI | ❌ | ❌ |
| MPG | ❌ | ❌ |
| MOV | ❌ | ❌ |

View File

@@ -5,7 +5,7 @@
<!-- TOC --> <!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec) * [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [Memory Library (`memory`)](#memory-library-memory) * [Memory Library](#memory-library-memory)
* [Table of Contents](#table-of-contents) * [Table of Contents](#table-of-contents)
* [Introduction](#introduction) * [Introduction](#introduction)
* [Implementation](#implementation) * [Implementation](#implementation)
@@ -15,7 +15,7 @@
## Introduction ## Introduction
&ensp; This library contains headers and classes related to memory allocation and &ensp; This library contains headers and classes related to memory allocation and
management in C++. The contents are restricted to the Memory Management Library of management in C++. The contents include the Memory Management Library of
the C++ Standard Library and Template Library. This pulls some functions from the the C++ Standard Library and Template Library. This pulls some functions from the
C stdlib and either wraps them or aliases them. C stdlib and either wraps them or aliases them.

View File

@@ -1,761 +0,0 @@
# Planning Documentation for fennec
## Table of Contents
1. [Introduction](#introduction)
2. [TODO](#todo)
1. [Security Ramblings](#file-security-ramblings)
2. [Platform Support](#platform--api-support)
3. [C++ Language](#c-language-library-lang)
4. [Math Library](#math-library-math)
5. [Memory Library](#memory-library-memory)
6. [Containers Library](#containers-library-containers)
7. [Format Processing](#format-processing-langproc)
8. [Core](#core-core)
1. [Tick](#tick)
2. [Frame](#frame)
9. [Platform Support Layer](#platform-support-layer-platform)
10. [Scene](#scene-scene)
11. [2D Graphics](#2d-graphics-gfx2d)
12. [3D Graphics](#3d-graphics-gfx3d)
1. [Structures](#structures-gfx3d)
2. [Stages](#stages-gfx3d)
13. [3D Physics](#3d-physics-physics3d)
14. [Artificial Intelligence](#artificial-intelligence-ai)
## Introduction
This file serves as a general planning document for engine structure, systems, pipelines, and implementation.
Implementations of core engine systems should strive to be `O(1)` in implementations,
both in terms of runtime and memory performance. This is obviously not a realistic goal,
so rather than the goal requiring the entire engine to be `O(1)`, we should more specifically look
at achieving `O(1)` performance on hot paths. I distinctly use 'strive' and 'goal' as different concepts, where designs
should *strive* to accommodate function implementations for `O(1)`, however the specifics of the implementation might not always
be able to achieve that, so the end *goal* is that hot paths should be `O(1)`.
Functions should be highly verbose and any bugprone or erroneous behaviour should throw
assertions. **DO NOT USE EXCEPTIONS**.
System implementations should be independent of architecture or platforms. i.e. the code of the graphics system should
not care if OpenGL or Vulkan is used and should not use any direct calls to OpenGL or Vulkan.
The engine should not care about the types of objects loaded from a so/dll. In fact, most of the code should
be type independent. Any shared information among a collection of objects should be held either implicitly or explicitly
in the super-class. It will be the responsibility of the linked code to initialize and cleanup the objects related to it.
This principle should extend to the submodules of the engine.
It is also best to avoid objects having behaviour that is not defined by the system they are in. There are some exceptions
in extensions or mods and should be given configurability and programmability within those systems and their stages.
This however can be achieved using events at different stages of those engines that are on-demand.
## TODO
- 2D Graphics (`gfx2d`)
- 2D Physics (`physics2d`)
- 2D & 3D Audio (`audio`)
### File Security Ramblings:
Windows is starting to piss me off, so I am considering dropping official support for MSVC. MinGW and Cygwin
will still work for compiling on Windows if this ends up being the case. The reason for this is that there are
*a lot* of platform dependent security issues. MinGW and Cygwin wrap Linux and glibc headers for Windows, which would
push the security onus onto the compiler and end-user.
The biggest blocker at the moment in terms of this is the filesystem. If we want to implement a filesystem that
is safe across platforms, stdc++ *and* iso libc have no guarantees about the safety of their functions.
The crux of this issue falls at the following specific behaviour:
- User selects an existing file to write to
- Application interface confirms overwrite action
- Application writes to the file after confirmation
A threat actor can introduce a malicious file or symlink to the file that was attempted access between the check and
usage of the file. This is called TOCTOU (time of check, time of use).
This issue can be solved using `fopen("<file>", "a+")` and `ftell`, however this specific behaviour is not intuitive to
those first learning how to work with file systems. We can attempt to abstract this away with another wrapper, or simply
write the file structure to handle this behaviour properly. The downside to this method overall is that it will break
common conventions of how humans interpret filesystems and the related control flow logic. What we can do is force the
`'+'` flag to always be present for write operations, and raise an error when desired, if the file is not empty. This
unfortunately would have the downside of being unable to open a file as write only.
Using `"wx"` in this instance would not be sufficient since it would require a second call to fopen, which would
create the conditions for the TOCTOU error described above.
Another issue arises when we are parsing a directory tree. The best we can do is take ownership of the directory that
is opened as the root. However, this requires `dirent.h` which is not implemented in MSVC. A custom implementation of
`dirent.h` may be written for MSVC, however this is one of the few things I am not willing to outsource to another
library. Developing our own implementation would take a non-insignificant amount of time, between writing the library,
debugging it, and testing for vulnerabilities. As stated above, this implementation is native to MinGW and Cygwin,
so we would not have to entirely drop support for Windows. However, MSVC is the most widely used compiler for Windows
applications and is native to Visual Studio and VSCode.
What is probably the best solution is to wrap everything in a file interface that does not allow the direct setting of
these flags. Then we set our own usage type for the file that informs which flags should be used.
We need to be able to handle the following types of files:
- Assets, such as scenes, audio, textures, metadata, meshes, etc.
- Save files, setting files, etc.
One of the nice things about the assets is that they are guaranteed to be read-only once an application is installed
on the computer of the end-user. Therefore, this issue only arises with save files and custom file formats.
When the editor is run, all these files should be opened in read/write mode.
Naming conventions should exist for the types of files and how they are read. For example, in release mode,
most assets should be opened once, and then closed immediately. However, this does not make sense for formats
that are continuous and too large to be kept around in memory, such as video formats.
Perhaps the following conventions:
- Static Asset
- Stream Asset
- Resource
We can turn this into an object-oriented approach by having different formats inherit these base types. We may still
have a base file type that wraps C functionality, but discourage developers from using the interface.
We could also declare the file interface extern so that only internal files know the implementation. However, I would
not be satisfied by doing this since it would prevent developers from implementing custom file type implementations.
Conserving memory is not really an issue here as long as we are smart about our implementation. Files should only be
open when necessary and be closed when it is no longer necessary to have them open. Data should be streamed unless the
all the data in the file is required.
When built in release mode, we also need to pack static assets into some sort of archive that is mountable to reduce
disk space consumption of a program.
I was considering encryption for archives, however it does not make much sense. Assuming someone intends to pirate the
game, there is not much stopping them from running the files. I will add Steam support at some point which would allow
you to use Steam's DRM to prevent the executable from being run. Otherwise, there is no point in attempting to encrypt
game files. Even Unreal PAK files can be cracked in seconds, and even if I managed to write something that cannot be
trivially cracked locally, you can scrape most assets from the GPU and Audio Card.
I have managed to solve the specific case provided at the top of this section, which was done by wrapping C I/O calls
into a file wrapper. This wrapper can handle a few different mode flags and has specific conditions for the flags. See
the documentation for `fennec/langproc/io/file.h` for more info.
One question remains unanswered on this front; should a read/write file open as `r+` or `a+`. `rewind` is slightly faster
than `fseek(SEEK_END)`, however for the case of save files and editor assets, `r+` makes more sense from a usage perspective
Directories remain an issue, with `dirent.h` being the only sensible option at time of writing. The issue with using
`dirent.h` boils back down to security issues on Windows. However, the only option is to write a custom implementation
for MSVC.
### Platform & API Support
I have decided to forgo SDL, this is so the engine can provide specific support for specific platforms.
Also, SDL implements a lot of things that will need to be implemented specifically for the engine, so only the window
management would be used.
Platform support will be implemented in the following order:
- Linux/BSD
- Wayland
- OpenGL (EGL) ✔
- XKB
- PulseAudio
- Vulkan
- X11
- ALSA
- Vulkan
- Microsoft Windows
- XInput
- OpenGL (WGL)
- WASAPI
- Vulkan
- Android
- OpenGL ES
- AAudio
- openslES
- macOS/iOS
- cocoa
- OpenGL
- Core Audio
- Vulkan
- Metal
Linux Wayland will be implemented first. Once setup, the core engine will be implemented and tested on top of Wayland.
Once the engine is in a stable state, then support for other platforms will be resumed.
Most consoles will never get official platform support due to NDAs which conflict with the principles of this engine.
fennec will avoid using proprietary libraries except when strictly necessary, such as support for Windows and MacOS.
fennec will interact with any drivers required for the listed operating systems above, even if proprietary.
## C++ Language Library (`lang`)
Implement header files for standard functions relating to the C++ Language.
So far this is implemented on an as-needed basis. A full implementation should be worked on continuously.
## Math Library (`math`)
Implement math functions according to the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
"Extensions" has a different meaning here. Extensions for the math library are any functions that are not defined within
the Specification.
Additional extensions should be implemented to provide standard definitions for functions predominantly related
to Linear Algebra, Mathematical Analysis, and more specifically Discrete Analysis. Additional extensions will be
implemented on an as-needed basis.
## Memory Library (`memory`)
Implement headers related to memory allocation in C++.
* Smart Pointers
* Unique Pointer
* Shared Pointer
- Memory Allocation
- Allocation
-
## Containers Library (`containers`)
All containers of the [C++ Standard Library](https://cppreference.com/w/cpp/container.html) should be implemented.
Here are essential data-structures not specified in the C++ stdlib:
- Graph &rarr; AI `graph`
- Necessary for 2D and 3D navigation.
- Rooted Directed Tree &rarr; Scene `rd_tree`
- Defines the scene structure.
## Language Processing (`langproc`)
This library contains information for any data that is formatted. This includes basic string formats, file formats,
and eventually programming languages
fennec should be able to use Doxygen and LaTeX externally. Consider including binaries with releases.
### Notes
* String Analysis (`langproc/strings`)
* Search
* Manipulation
* Delimiting
* Regex
- File Formats (`langproc/formats`)
- Serialization
- JSON
- HTML
- XML
- YAML
- Configuration
- INI
- TOML
- Documents
- ODF
- Markdown
- PDF
- Spreadsheets & Tables
- ODS
- CSV
- Audio Formats
- MP3
- WAV
- AAC
- Graphics Formats
- Textures
- BMP
- DDS
- JPG
- PNG
- TIFF
- Vectors
- OTF
- SVG
- TTF
- Models
unfortunately, most formats are esoteric due to copyright/trademark/etc. I will be using assimp for the
time being, below is a list of formats supported by assimp.
- 3D
- 3DS
- 3MF
- AC
- AC3D
- ACC
- AMJ
- ASE
- ASK
- B3D
- BVH
- CSM
- COB
- DAE/Collada
- DXF
- ENFF
- FBX
- glTF 1.0 + GLB
- glTF 2.0
- HMB
- IFC-STEP
- IQM
- IRR / IRRMESH
- LWO
- LWS
- LXO
- M3D
- MD2
- MD3
- MD5
- MDC
- MDL
- MESH / MESH.XML
- MOT
- MS3D
- NDO
- NFF
- OBJ
- OFF
- OGEX
- PLY
- PMX
- PRJ
- Q3O
- Q3S
- RAW
- SCN
- SIB
- SMD
- STP
- STL
- TER
- UC
- USD
- VTA
- X
- X3D
- XGL
- ZGL
- Video Formats
- MP4
- AVI
- MPG
- MOV
**TODO LATER**
* Compilation (`langproc/code`)
* Lexical Analysis
* Syntax Analysis
* Semantic Analysis
* Intermediate Code Generation
* Optimization
* Target Code Generation
## Core (`core`)
This will be the core of the engine.
- Event System
- Most events will fire at the start of the next tick, especially those related to physics and input.
- Events for graphics or audio should propagate immediately.
- Events for stages should also propagate immediately, this is to support extensions and mods.
- Core Engine Loop
- System Manager
- Ticks vs. Frames
The following systems are not essential to the core engine, but are instead major systems that should be defined
in their operation order:
### Tick
- **Update**
- Events
- Scripts
- AI
- **Physics**
- Newtonian Commit
- Apply Forces (Updates Accelerations)
- Acceleration (Updates Velocities)
- Apply Velocities (Updates Position and Rotation)
- Constraint Resolution
- Collision Detection
- Collision Resolution
- Collision Response
- Calculate Forces & Velocities
- Queue events for next tick
### Frame
- **Physics**
- Physics Interpolation
- **Graphics**
- [2D Graphics](#2d-graphics-gfx2d)
- Generate 3D Mask
- [3D Graphics](#3d-graphics-gfx3d)
- **Audio**
## Platform Support Layer (`platform`)
This is the core part of platform support for fennec. All necessary drivers
and OS specific functionality will be wrapped up nicely into these interfaces.
See implementation order [here](#platform--api-support)
## Scene (`scene`)
* In-Array Directed Tree
* Elegant method for providing `O(1)` insertions and `O(log(n))` deletions.
* Bounding Volume Hierarchy
* Octree
## 2D Graphics (`gfx2d`)
Links:
- https://en.wikipedia.org/wiki/Quadtree
- https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-25-rendering-vector-art-gpu
Object Structure. The mesh is implicit data.
### Structures (`gfx2d`)
For the 2d rendering framework, Materials need to be rendered independently because we have
no size constraints for images. This disallows us from using a meta-shader like in
the 3d rendering framework.
```c++
struct Object
{
vec2 location, scale; // A matrix would be 36 bytes, this is instead 20 bytes
float rotation;
}
```
- BVH
- Quadtree
- Leaf Size and Tree Depth should be calculated by the scene, constraints are as follows:
- Min Object Size
- Max Object Size
- Scene Center
- Scene Edge
- Insertions and Updates are done on the CPU
- Nodes
- Start Index 32-bits
- Object Count 32-bits
- Objects
- Buffer of Object IDs grouped by Octree Node
- Culling
- Starting at each Octree Leaf, traverse upwards.
- Insert Visible Leaf IDs
- Track using atomic buffer
- Generate the Command Buffer for Culled Meshes from the Visible Leaf Buffer
- Count Materials
- Count Meshes per Material
- Generate the Culled Object Buffer by copying objects from the Object Buffer
- Adjust Buffer Size using the counts
- Insert using another atomic buffer
- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate.
This will allow us to sort objects as they are created. We can still bulk render each z-index,
with meshes and objects being grouped by material.
## 3D Graphics (`gfx3d`)
Links:
- https://en.wikipedia.org/wiki/Octree
- https://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study/
- https://learnopengl.com/PBR/Lighting
- https://learnopengl.com/PBR/IBL/Diffuse-irradiance
- https://en.wikipedia.org/wiki/Schlick%27s_approximation
- https://pixelandpoly.com/ior.html
- https://developer.download.nvidia.com/SDK/10/opengl/screenshots/samples/dual_depth_peeling.html
**DirectX will never have official support.**
If you would like to make a fork, have at it, but know that I will hold a deep disdain for you.
The graphics pipeline will have a buffer with a list of objects and their rendering data.
This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes.
The buffers will be optimized by scene prediction.
This involves tracking the meshes and textures directly and indirectly used by a scene.
A callback function in the graphics system for scene loading can do this.
Materials and Lighting models will be run via a shader metaprogram to make the pipeline independent of this aspect.
This allows the GPU to draw every single deferred rendered mesh in a single draw call for each stage of the renderer.
Specifications for debugging views via early breaks are included in the stages.
There will be three profiles for OpenGL implementation:
- modern
- fallback
- legacy
All profiles will have the same feature set, however their implementations will differ.
The modern context will use up-to-date features to get as much performance out of the pipeline as
possible.
### Structures (`gfx3d`)
Object Structure. The mesh is implicit data.
```c++
struct Object
{
vec3 location, scale; // A matrix would be 64 bytes, this is instead 28 bytes
quat rotation;
uint32 material, lighting;
}
```
Textures for 3D rendering are stored in various buffers with sizes of powers of 2.
Ratios of `1:1` and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection.
UVs may be transformed to use a `2:1` as if it were `1:2`.
Cubemaps and 3D textures may only be `1:1`, I would be concerned if you are using any other ratio.
- 8-Bit R Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RG Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RGB Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RGBA Texture `4096, 2048, 1024, 512` (8)
- 8-Bit R Cubemap `1024, 512, 256, 128` (4)
- 8-Bit RGB Cubemap `1024, 512, 256, 128` (4)
* 16-Bit HDR R Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR RGB Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR RGBA Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR R Cubemap `1024, 512, 256, 128` (4)
* 16-Bit HDR RGB Cubemap `1024, 512, 256, 128` (4)
- 16-Bit Shadow Texture `4096, 2048, 1024, 512` (8)
- 16-Bit Shadow Cubemap `2048, 1024, 512, 256` (4)
* 8-Bit 3D R Texture `256, 128, 64, 32` (4)
* 8-Bit 3D RGB Texture `256, 128, 64, 32` (4)
* 16-Bit 3D HDR R Texture `256, 128, 64, 32` (4)
* 16-Bit 3D HDR RGB Texture `256, 128, 64, 32` (4)
Documentation should provide guidelines on categories of Art Assets and the resolution of textures to use.
Textures are identified by a 32-bit integer.
- `8 bits` &rarr; the texture buffer
- `24 bits` &rarr; the layer in the buffer
Artists should be informed on the texture structure of the engine and its limitations.
However, these principles should be followed in other game engines as these are
guided by what is most efficient for typical GPU hardware.
Materials are, for the most part, user-defined. Documentation should make the user aware of this.
Material buffers will be a sequence of the Material Struct instances.
They will at the very least contain the id of their shader.
Types of materials:
- Surface (Vertex & Fragment)
- Opaque / Masked
- Translucent (Forward)
- Volume (Path Traced Volumetrics / Forward)
- Light (Lighting Model)
- Post-Process
### Stages (`gfx3d`)
This is the set of stages for the graphics pipeline that runs every frame:
Unless otherwise specified, each stage will be run on the GPU.
- BVH
- Octree `(8 Bpn, 64 bpn) [6-Layers ≈ 2.1MB]`
- Leaf Size and Tree Depth should be calculated by the scene, constraints are as follows:
- Min Object Size
- Max Object Size
- Scene Center
- Scene Edge
- Buffer has implicit locations due to the tree having 8 children.
- Insertions and Updates are done on the CPU
- Nodes
- Start Index `int32`
- Object Count `int32`
- Objects
- Buffer of Object IDs grouped by Octree Node
- Leaf Culling
- Starting at each Octree Leaf, traverse upwards.
- Insert Visible Leaf IDs
- Track using atomic buffer
- Generate the Command Buffer for Culled Mesh LODs from the Visible Leaf Buffer
- Track counts using atomic buffers
- To avoid double counting due to the construction of the Octree output, we have some options
- Ignore Leaf Instances based on occurrences of the mesh in the surrounding 8 Quadtree Leaves. This would require
a bias towards a specific corner of the filter.
- Perform a preprocessing step on the CPU to erase duplicate elements and fix the buffer continuity.
- Let the duplicates be rendered.
- Generate the Culled Object Buffer with the respective object IDs
- Adjust Buffer Size using the counts
- Insert by reusing the count buffer, clipped to only contain used meshes
Debug View: Object ID, Mesh ID, LOD
- Visibility
- Buffer `(15 Bpp, 120 bpp) [1920x1080] ≈ 39.4MB`
- Depth Buffer &rarr; `D24`
- Visibility Info &rarr; `RGB32I`
- R = Object ID
- G = Mesh ID
- B = Material ID
- Regenerate the Command Buffer for Visible Mesh LODs
- Regenerate the Culled Object Buffer
Debug View: Visibility Buffer
* G-Buffer Pass `(17 Bpp, 136 bpp) [1920x1080] ≈ 35.3MB`
* Depth - Stencil &rarr; `D24_S8`
* S &rarr; used to represent the lighting model.
* Diffuse &rarr; `RGBA8`
* A &rarr; Ambient Occlusion
* Emission &rarr; `RGB8`
* Normal &rarr; `RGB8`
* Specular &rarr; `RGB8`
* R &rarr; Roughness
* G &rarr; Specularity (sometimes called the Metallicness)
* B &rarr; Index of Refraction (IOR)
Debug View: Depth, Stencil, Diffuse, Emission, Normal, Specularity
- Generate Dynamic Shadows
- Generate Dynamic Reflections (Optional)
- SSAO (Optional)
- Deferred Lighting Pass `(10 Bpp, 80 bpp) [1920x1080] ≈ 2 x 16.3MB + 8.3MB ≈ 24.6MB`
- Depth Buffer &rarr; `D24`
- Lighting Buffer &rarr; `RGB16` w/ Mipmapping
- Stencil Buffer $rarr; `S8`
- Apply Lighting Model
Debug View: Shadows, Reflections, SSAO, Deferred Lighting
We can combine all of these into one framebuffer:
- Depth - Stencil &rarr; `D24_S8`
- Visibility Info &rarr; `RGB32I`
- Diffuse &rarr; `RGBA8`
- Emission &rarr; `RGB8`
- Normal &rarr; `RGB8`
- Specular &rarr; `RGB8`
- Lighting Buffer &rarr; `RGB16` w/ Mipmapping
- One more slot left open for another
* Forward Pass
* BVH, Same as Above
* LOD Selection, Same as Above
* Translucent Materials
* Dual Depth Peeling
Debug View: Forward Mask
- Post Processing
- Depth of Field (Optional)
- When enabled, the Visiblity Buffer, G-Buffer, and Deferred Lighting Pass will be double layered.
- At this point the Lighting Buffers will be Flattened
- Bloom (Optional) &rarr; Mipmap Blurring `(6Bpp, 48bpp) [1920x1080] ≈ 16.3MB`
- Tonemapping (Optional)
- HDR Correction
## 3D Physics `(physics3d)`
Links:
- https://www.researchgate.net/publication/264839743_Simulating_Ocean_Water
- https://arxiv.org/pdf/2109.00104
- https://www.youtube.com/watch?v=rSKMYc1CQHE
- https://tflsguoyu.github.io/webpage/pdf/2013ICIA.pdf
- https://animation.rwth-aachen.de/publication/0557/
- https://github.com/InteractiveComputerGraphics/PositionBasedDynamics?tab=readme-ov-file
- https://www.cs.umd.edu/class/fall2019/cmsc828X/LEC/PBD.pdf
Systems
* Rigid Body Physics
* Newtonian Physics and Collision Resolution
* Articulated Skeletal Systems
* Inverse Kinematics
* Stiff Rods
- Particle Physics
* Soft Body Physics
* Elastics &rarr; Finite Element Simulation
* Cloth &rarr; Position-Based Dynamics
* Water
* Oceans &rarr; iWave
* Reasoning: iWave provides interactive lightweight fluid dynamics suitable for flat planes of water.
<br><br>
* 3D Fluid Dynamics &rarr; Smoothed-Particle Hydrodynamics
* Reasoning: This is the simplest method for simulating 3D bodies of water. This should exclusively be
used for small scale simulations where self-interactive fluids are necessary. I.E. pouring water into
a glass.
<br><br>
* 2D Fluid Dynamics &rarr; Force-Based Dynamics
* Reasoning: This model, like iWave, provides lightweight interactive fluid dynamics, but is more easily
adapted to flowing surfaces such as streams and rivers.
## Artificial Intelligence (`ai`)
This artificial intelligence method only differs in static generation between 2D and 3D.
The solvers are dimension independent since they work on a graph.
The general process is;
Static:
- generate a static navigation graph (sometimes called a NavMesh)
Update:
* resolve dynamic blockers
* update paths using dijkstra's algorithm
* apply rigid-body forces with constraints
The update loop for artificial intelligence should only update every `n` ticks. Where `n <= k`, with `k` being the
tick rate of the physics engine.