
<!-- I release these notes into the public domain -->

# 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 lighting;
}
```

Objects are identified with a manually provided type and ID. Object types include:
 - Static (transform does not change after creation)
 - Dynamic (transform changes after creation)
 - Forward Static (object is forward rendered and its transform does not change after creation)

A user should never have to specify these and should be automatically generated by the respective components.


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 


Each Material will have a buffer of Objects so that
each can be rendered in a single draw call.


## Lighting

When Dynamic Lighting is enabled, each light has two textures,
one for static lighting and one for dynamic lighting.


Shadows

 - Directional Light &rarr; 16-bit Shadow Texture `4096`
 - Spotlights        &rarr; 16-bit Shadow Texture `2048`
 - Point Lights      &rarr; 16-bit Shadow Cubemap `1024`
 - Area Lights       &rarr; 16-bit Shadow Texture `2048`


Reflections

 - Light Probe &rarr; 16-bit RGB Cubemap `512, 256`


## 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
  * Specular &rarr; `RGB8`
      * R &rarr; Roughness
      * G &rarr; Specularity (sometimes called the Metallicity)
      * B &rarr; Index of Refraction (IOR)
    * Emission &rarr; `RGB8`
    * Normal &rarr; `RGB8`

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`
- Specular &rarr; `RGB8`
- Emission &rarr; `RGB8`
- Normal &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
