项目作者: BertilBraun

项目描述 :
3D Game Engine Framework
高级语言: C++
项目地址: git://github.com/BertilBraun/Oath3D.git
创建时间: 2019-01-10T16:46:03Z
项目社区:https://github.com/BertilBraun/Oath3D

开源协议:MIT License

下载


Oath3D

3D Game Engine Framework WIP

Design:

Everything is wrapped in a namespace OATH. In it there are namespaces for all major differences.

  1. namespace OATH {
  2. namespace Comp
  3. namespace App
  4. namespace LOGGER
  5. namespace Physic
  6. namespace WINDOW
  7. namespace System
  8. namespace Render
  9. namespace EVENT
  10. }

States are the base of the engine. You push and pop States as you please and once all are poped the game ends.
You can start the engine’s main loop by calling runLoop<>(args), pushing a state to the engine and starting the main game loop.

  1. #include "Test.h"
  2. void main() {
  3. LOG("STARTED");
  4. OATH::APP::Application app("Test", 1600, 1000);
  5. app.runLoop<OATH::TestState>(&app);
  6. }

States are implementing a StateBase which provides overridable functions for updating, rendering, and init and shutdown.

  1. class StateBase {
  2. StateBase(APP::Application* app, APP::StateBase* parent = nullptr);
  3. virtual ~StateBase() = default;
  4. virtual void update(float deltaTime) = 0;
  5. virtual void render() = 0;
  6. virtual void onOpen() {};
  7. virtual void onClose() {};
  8. virtual void onResume() {};
  9. public:
  10. Physic::World* world;
  11. ECS::Manager ecs;
  12. ECS::SystemList rendering, updatelist;
  13. protected:
  14. APP::Application* app;
  15. APP::StateBase* parent;
  16. };

A basic example can be seen here, showing off some of the stuff this engine has to feature.

  1. class TestState : public APP::StateBase {
  2. public:
  3. TestState(APP::Application* app, APP::StateBase* parent = nullptr) :
  4. APP::StateBase(app, parent)
  5. {
  6. Skybox sky("Skybox/");
  7. ecs.makeEntity(sky);
  8. AmbientLight alight(0.1f);
  9. ecs.makeEntity(alight);
  10. DirectionalLight dlight(vec3(1), 0.1f, 0.9f, vec3(0.2, -0.8, -0.2));
  11. ecs.makeEntity(dlight);
  12. PointLight pLight(vec3(1, 0, 0), 1, 1.2f, 0, 0, 0.3f);
  13. ecs.makeEntity(pLight)->pos(vec3(0, 5, 0));
  14. SpotLight sLight(vec3(0, 0, 1), 2, 2.2f, 0.5, 0.5, 0.5, vec3(0, 0, 1), 20);
  15. ecs.makeEntity(sLight);
  16. Asset sponza("Sponza/sponza.obj");
  17. ecs.makeEntity(sponza)->scale(vec3(0.1)).rot(vec3(0, 0, 180));
  18. AnimatedAsset anim("CharacterRunning.dae");
  19. ecs.makeEntity(anim)/*->pos(vec3(10, 0, 0)).rot(vec3(0, 0, 90))*/;
  20. Camera cam(true);
  21. Reciever r;
  22. FreeMove move(5);
  23. FreeLook look;
  24. look.rot = vec2(50, 30);
  25. ecs.makeEntity(cam, look, move, r);
  26. }
  27. void update(float deltaTime) override {
  28. }
  29. vec3 p, f, u;
  30. void render(float deltaTime) override {
  31. ImGui::Begin("WINDOW");
  32. ImGui::SliderFloat3("UP", glm::value_ptr(u), 0, 1);
  33. ImGui::SliderFloat3("POS", glm::value_ptr(p), -50, 50);
  34. ImGui::SliderFloat3("TARGET", glm::value_ptr(f), 0, 1);
  35. ImGui::End();
  36. }
  37. };

Features:

  • Fully functional ECS

    • Systems

      • Update based on Component Types
        ```c++
        class CameraSystem : public ECS::System {
        public:
        CameraSystem() {

        addComponentType(Camera::ID);
        addComponentType(FreeLook::ID, ECS::FLAG_OPTIONAL);
        addComponentType(FreeMove::ID, ECS::FLAG_OPTIONAL);
        }

      // This function gets called for every entity which has all of the Components nescessary for this system

      void updateComponents(float delta, ECS::Entity entity, ECS::BaseComponent* components) override

      1. Camera* camera = (Camera*)components[0];
      2. FreeLook* freeLook = (FreeLook*)components[1];
      3. FreeMove* freeMove = (FreeMove*)components[2];
      4. if (freeLook)
      5. UpdateFreeLook(camera, freeLook);
      6. if (freeMove)
      7. UpdateFreeMove(delta, entity, camera, freeMove);

      }
      };

      1. - Components
      2. - pure data (basically)
      3. - own ID per type
      4. - owning entity
      5. ```c++
      6. struct Camera : public ECS::Component<Camera> {
      7. vec3 forward;
      8. vec3 right;
      9. vec3 up;
      10. mat4 view;
      11. mat4 proj;
      12. };
      • Entity
        1. bool enabled = true;
        2. Entity* parent = nullptr;
        3. String tag = "";
        4. Vector<Entity*> childs;
        5. Vector<Script*> scripts;
        6. Vector<std::pair<ComponentID, IndexInData>> components;
        7. Transform transform;
    • usage
      ```c++
      ECS::Manager ecs; // Controls all entity’s systems and listeners and updates on call of void updateSystems(SystemList& systems, float delta);

ECS::SystemList rendering, mainlist;

mainlist.addSystem(new CameraSystem());
rendering.addSystem(new AssertRenderer());
rendering.addSystem(new AnimationRenderer());

ecs.addListener(new CameraListener());
ecs.addListener(new AssetListener());

Asset asset(“Earth/earth.obj”, ASSET::DONT_RENDER_MESH1 | ASSET::DONT_RENDER_MESH2); // Asset is a Component

ECS::Entity* entity = ecs.makeEntity(asset); // Manager creates entity and adds all components passed into the function to the entity
// entity can be used to update transforms, or add children to be stacked in the scene tree

for (int i : range(0, 100)) {
ecs.updateSystems(mainlist, 0.1f);
ecs.updateSystems(rendering, 0.1f);
}

  1. Sceene Tree:
  2. - the entities in the sceene can have children. Children, sofar, inherit all transforms of its parents and add their own onto that.
  3. ```c++
  4. void addChild(Entity* e); // adds child to 'this' entity, further on it inherits its transform

Physics:

  • by adding a ‘RigidBody’ and / or a ‘Collider’, a entity gets added to the physics world.
    it then gets updated every physics frame with the specified parameters.

    • Collider

      • Bounding Box, specified by a vec3 halfExtends
      • Sphere, specified by a radius
      • Capsule, specified by a radius and a height
    • RigidBody

      • btRigidBodyConstructionInfo

Events:

  • Create Dispatcher, add Subscriber to Dispatcher with String as an EventType on which it gets updated.
    A Subscriber is a owner, which will be used to call on data, and a function which gets called once the EventType gets dispatched

    1. void TestFunc(void* sender, void* data) {
    2. LOG("CALLED");
    3. }
    4. EVENT::Dispatcher dispatcher;
    5. EVENT::Subscriber* sub = new EVENT::Subscriber(this, EVENT_FUNC_CAST(&TestFunc));
    6. dispatcher.AddEventSubscriber("TEST", sub);
    7. dispatcher.AddEventSubscriber("COLLISION", this, &TestFunc);
    8. dispatcher.DispatchEvent("TEST", this);

    Window:

    1. Window window("NAME", WIDTH, HEIGHT);`

    Resource Manager:

    • stores Textures, Models, Aniamtions
    • releases all Data after nothing uses the Data anymore

    • loading Models using Assimp

Render:

  1. - Hotloading Shaders
  2. Deffered
  3. rendering
  4. shading
  5. shadows
  6. lights
  7. directional
  8. point
  9. cone
  10. static / dynamic / no shadow mapping
  11. Optimisation
  12. Frustum culling
  13. LOD

Sound:
loading of wav files
emitter component updating sound
reciever component

Assets:
loading with assimp
static Assets
Animations
interpolation between animations
interpolation between keyframes

RoadMap:

Complete refactoring

  1. - Assets
  2. - ECS

ECS

  1. - https://www.youtube.com/watch?v=FmPZG4ETcMc after 1.05h

Use new Event System from one of my repos

Post Processing

  1. - Gamma correction
  2. - Object motion blur
  3. - Bloom
  4. - SSAO
  5. - Antialiasing
  6. - Lens flare
  7. - God ray's
  8. - Screen Space Reflections

Shadows

  1. - Point Light shadow mapping

Extras

  1. - Terrain (CDLOD)
  2. - Water
  3. - Grass
  4. - https://github.com/songrun/SeamAwareDecimater

Fixes

  1. - Particle systems
  2. - Cascaded shadow mapping
  3. - Normal mapping
  4. - Parallax mapping
  5. - Texture Free
  6. - Frustum Culling

Dependencies:

  1. assimp
  2. Bullet
  3. GLFW
  4. glm
  5. ImGui
  6. stb_image