Skip to content

Game engine framework using DirectX 11, Direct2D, DirectWrite, Qt, FBX SDK, ImGui/ImGuizmo and PhysX

Notifications You must be signed in to change notification settings

sfederic/VEngine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VEngine

image

Build/Usage Notes

Helpful Fork [#3] to build using premake. Thanks to https://github.com/ignite720

  • Visual Studio 2022 17.10
  • Blender 3.4

Packages

DirectXTK (directxtk_desktop_win10) ver. 2021.8.2.1 - https://github.com/microsoft/DirectXTK

Third Party Libraries:

(The ImGui libs are already included in the repo)

Helpful Extensions

Overview

The techincal outset of the engine was to keep it simple and mostly in C++ with minimal use of other programming languages. That means usage of the C++ standard library and attempted usage of modern C++ concepts.

Below is a quick outline of various concepts the engine uses, from game object component models, rendering and asset workflows.

Game Object Model

Actors

The engine uses an Actor/Component model similar to Unity and Unreal. The inspiration came from Rare's presentation on Actor Ticks in UE4 in Sea of Thieves

An inherited actor will be defined with a system via a macro.

struct Enemy : Actor
{
    //essentially defines 'inline static ActorSystem<Enemy> system;'
    ACTOR_SYSTEM(Enemy);

    void Tick(float deltaTime) override;
};

Actor Systems

Both Actors and Components have Systems. A system essentially looks like:

template <typename ActorType>
struct ActorSystem : IActorSystem
{
    std::vector<ActorType*> actors;

    void Tick(float deltaTime) override
    {
        for(auto actor : actors)
        {
            actor->Tick(deltaTime);
        }
    }
}

Worlds

A 'World' is the current view of the scene on-screen. Each World will have lists of the currently active Actor and Component systems.

struct World
{
    std::vector<IActorSystem*> actorSystems;
    std::vector<IComponentSystem*> componentSystems;

    void Tick(float deltaTime)
    {
        TickAllActorSystems(deltaTime);
        TickAllComponentSystems(deltaTime)
    }
}

Actor and Component Properties

For serialisiation, Actors and Components define their properties to be fetched at run-time.

struct Enemy : Actor
{
    int attack = 5;
    
    Properties GetProps() override
    {
        Properties props = Actor::GetProps();
        props.Add<int>("Attack", &attack);
        return props;
    }
}

Properties is a collection of Propertys. VEngine uses the typeid() from Properties::Add<T>() to infer the type.

struct Property
{
    std::optional<std::type_info> type;
    void* value;
}

struct Properties
{
    std::map<std::string, Property> propertyMap;

    template <typename T>
    void Add(std::string propertyName, T* propertyValue)
    {
        Property property;
        property.type = typeid(T);
        property.value = propertyValue;

        propertyMap.emplace(propertyName, property);
    }
}

Serialisation

Using Properties, serialisation infers property types by checking for a matching typeid().

void Serialiser::Serialise(Properties& properties)
{
    for (Property& property : properties)
    {
        if (property.type == typeid(int))
        {
            SerialiseInt<int>(property.value);    
        }
    }
}

World Save File

Files with the .vmap extension describe the layout of a level in-game. Below is an example of the text format to show how properties map to values.

Enemy  //This type name fetches the appropriate system (in this case an Actor class of 'Enemy').
13     //This is how many instances of the class to create.
Attack //Property name.
16     //Property value.
next   //Move onto the next Enemy instance...
Attack
3

Rendering

VEngine uses DirectX 11 for 3D/2D rendering and DirectWrite + Direct2D for in-game UI.

FBX Importing

VEngine uses the official FBX SDK to import models and animations. While not very robust, details can be gleamed at

Game UI

For in-game UI, an immediate approach is used. An example in-game widget would be declared like so:

struct EnemyText : Widget
{
    std::string text;

    void Draw() override
    {
        Layout layout = AlignLayoutByScreenPercent(0.1, 0.9, 0.1, 0.2);
        DrawText(text, layout);
    }
}

Physically Based Shading

Implementations were inspired by EA's Frostbite engine.

Global Illumination

VEngine uses a simple Global Illumination technique using light probes spread around a level uniformly. Leveraging the DirectXSH spherical harmonics library, each probe takes a cubemap snapshot of its surroundings an encodes it using spherical harmonics. Static meshes are assigned an index into the light probe map built up, while dynamic meshes find their closest probe and apply its colours per vertex normal.

References for this system were mainly taken from Bluepoint's Shadow of the Colossus and Sonic Unleashed.

Skeletal Animation (FBX) with Blender Workflow

To import skeletal .fbx animations via Blender:

  • Add an Armature and bone structure to a mesh in Blender

image

  • hit Ctrl+P to parent the mesh to the armature and automate the weights

image

  • Record the poses using the Timeline and Dope Sheet -> Action Editor windows

image

  • Use the Non-Linear Animation window to organise animations

image

  • Export as an FBX with these settings, including all animations

image

Setup Skeletal mesh in code

Note that a seperate .vmesh file of the mesh is needed without animations baked in (but with the same bone structure as the animations), assigned as the mesh of a SkeletalMeshComponent, where then the imported FBX animations are linked to.

For example:

class AnimCube : public Actor
{
public:
	AnimCube()
    {
        skeletalMesh = CreateComponent("Skeleton", SkeletalMeshComponent("anim_cube.vmesh", "texture jpg"));
        rootComponent = skeletalMesh;
    }

    void Start() override
    {
        skeletalMesh->PlayAnimation("move");
    }

private:
	SkeletalMeshComponent* skeletalMesh = nullptr;
}

References and Helpful Links

Below is a collection of the most influential articles, tutorials, talks and concepts for development of the engine over time.

Game Object Component Models

Global Illumination

Navigation

FBX SDK

Audio

Cameras

Animation

Mesh Slicing

Dialog Editor

Editor UI Design

Transform Gizmo

Shadow Mapping