diff --git a/CMakeLists.txt b/CMakeLists.txt index af1819c..88419e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeList.txt : Top-level CMake project file, do global configuration # and include sub-projects here. # -cmake_minimum_required (VERSION 3.8) +cmake_minimum_required (VERSION 3.11) # Enable Hot Reload for MSVC compilers if supported. if (POLICY CMP0141) @@ -9,6 +9,22 @@ if (POLICY CMP0141) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") endif() +include(FetchContent) + +SET(TRACY_ENABLE 1) +SET(TRACY_ON_DEMAND 1) +SET(TRACY_ONLY_LOCALHOST 1) + +FetchContent_Declare( + tracy + GIT_REPOSITORY https://github.com/wolfpld/tracy.git + GIT_TAG v0.11.1 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(tracy) + project ("YuppleMayham") # Include sub-projects. diff --git a/Resources/backgrounds/blue_sky.jpg b/Resources/backgrounds/blue_sky.jpg new file mode 100644 index 0000000..7fbaac2 Binary files /dev/null and b/Resources/backgrounds/blue_sky.jpg differ diff --git a/Resources/backgrounds/blue_sky.png b/Resources/backgrounds/blue_sky.png new file mode 100644 index 0000000..a034568 Binary files /dev/null and b/Resources/backgrounds/blue_sky.png differ diff --git a/Resources/scenes/debugScene.xml b/Resources/scenes/debugScene.xml index 737d164..2ba1a06 100644 --- a/Resources/scenes/debugScene.xml +++ b/Resources/scenes/debugScene.xml @@ -1,6 +1,6 @@ - + diff --git a/Resources/shaders/GL_flat.frag b/Resources/shaders/GL_flat.frag new file mode 100644 index 0000000..eb901fe --- /dev/null +++ b/Resources/shaders/GL_flat.frag @@ -0,0 +1,11 @@ +#version 330 core +in vec2 texCoord; + +out vec4 FragColor; + +uniform sampler2D sprite; + +void main() +{ + FragColor = texture(sprite, texCoord) * vec4(1.0, 0.8, 1.0, 1.0); +} \ No newline at end of file diff --git a/Resources/shaders/GL_flat.vert b/Resources/shaders/GL_flat.vert new file mode 100644 index 0000000..e6ea325 --- /dev/null +++ b/Resources/shaders/GL_flat.vert @@ -0,0 +1,15 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoord; + +out vec2 texCoord; + +uniform mat4 projection; +uniform mat4 view; + +void main() +{ + texCoord = aTexCoord; + gl_Position = projection * vec4(aPos.xyz, 1.0); + +} \ No newline at end of file diff --git a/Resources/shaders/GL_tile.vert b/Resources/shaders/GL_tile.vert index 039f99a..d2da722 100644 --- a/Resources/shaders/GL_tile.vert +++ b/Resources/shaders/GL_tile.vert @@ -9,7 +9,7 @@ layout (location = 6) in vec2 aOriginalSize; layout (location = 7) in mat4 aModel; uniform vec2 uCanvasSize; -uniform mat4 proj; +uniform mat4 projection; uniform mat4 view; out vec2 texCoord; @@ -18,7 +18,7 @@ flat out int textureIndex; void main() { int tilesPerRow = aTilesPerRow; - gl_Position = proj * view * aModel * vec4(aPos, 1.0); + gl_Position = projection * view * aModel * vec4(aPos, 1.0); textureIndex = aTextureIndex; if (aTileIndex != 0) { diff --git a/YuppleMayham/CMakeLists.txt b/YuppleMayham/CMakeLists.txt index 1bddbde..66249ac 100644 --- a/YuppleMayham/CMakeLists.txt +++ b/YuppleMayham/CMakeLists.txt @@ -67,7 +67,12 @@ add_executable (YuppleMayham "include/utility/raycaster.h" "include/utility/ftfont.h" "include/utility/direction.h" - "include/graphics/animation.h" "src/graphics/animation.cpp" "include/utility/logger.h" "src/utility/logger.cpp") + "include/graphics/animation.h" + "src/graphics/animation.cpp" + "include/utility/logger.h" + "src/utility/logger.cpp" + "include/graphics/renderer.h" + "src/graphics/renderer.cpp") add_custom_command(TARGET YuppleMayham PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Resources/ $) @@ -75,6 +80,6 @@ if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET YuppleMayham PROPERTY CXX_STANDARD 20) endif() -target_link_libraries(YuppleMayham SDL2::SDL2main SDL2::SDL2 SDL2_image::SDL2_image tinyxml2 lua_static freetype) +target_link_libraries(YuppleMayham SDL2::SDL2main SDL2::SDL2 SDL2_image::SDL2_image tinyxml2 lua_static freetype Tracy::TracyClient) # TODO: Add tests and install targets if needed. diff --git a/YuppleMayham/include/gameplay/entity.h b/YuppleMayham/include/gameplay/entity.h index 29bdb25..0a91ffd 100644 --- a/YuppleMayham/include/gameplay/entity.h +++ b/YuppleMayham/include/gameplay/entity.h @@ -6,23 +6,22 @@ #include #include -#include "graphics/shader.h" +#include "graphics/renderer.h" class Camera; struct PhysicsComponent; // TODO: Allow speed to be changed and add speed as creation value in XML File! // TODO: Create Entity System that loads entity types and creates them in scene according to name. -class Entity +class Entity : public Drawable { public: - Entity(const std::shared_ptr& shader) : - shader(shader), + Entity(unsigned shaderID) : position(glm::vec3(0.0f)), scale(glm::vec3(1.0f)), rotation(0.0f), speed(20.0f), entityid(SDL_GetTicks()) - {}; + { this->shaderID = shaderID; }; virtual ~Entity() {}; void setPosition(const glm::vec3& position); @@ -44,11 +43,11 @@ public: const bool getIsMoving() const { return isMoving; } const int getEntityID() const { return entityid; } const std::shared_ptr getPhysicsComponent() const { return physics; } - const std::shared_ptr getShader() const { return shader; } + const unsigned getShaderID() const { return shaderID; } // TODO: right now there is no default behavior, but eventually the Entity class will be expanded to handle physics virtual void update(double deltaTime) = 0; - virtual void render(const std::shared_ptr& camera) = 0; + virtual void draw() = 0; protected: glm::vec3 localPosition; @@ -70,8 +69,6 @@ protected: glm::mat4 modelMatrix; void updateModelMatrix(); - - std::shared_ptr shader; }; diff --git a/YuppleMayham/include/gameplay/game.h b/YuppleMayham/include/gameplay/game.h index e507b0c..eef5f6d 100644 --- a/YuppleMayham/include/gameplay/game.h +++ b/YuppleMayham/include/gameplay/game.h @@ -8,6 +8,7 @@ class InputHandler; class Scene; class Text; class ResourceManager; +class Renderer; class GLWindow; enum { @@ -45,6 +46,7 @@ private: std::shared_ptr currentScene; std::shared_ptr inputHandler; std::shared_ptr resourceManager; + std::shared_ptr renderer; std::shared_ptr textHandler; }; diff --git a/YuppleMayham/include/gameplay/gameactor.h b/YuppleMayham/include/gameplay/gameactor.h index 657b939..002c141 100644 --- a/YuppleMayham/include/gameplay/gameactor.h +++ b/YuppleMayham/include/gameplay/gameactor.h @@ -19,16 +19,16 @@ class EventManager; class GameActor : public Entity { public: - GameActor(const std::shared_ptr& shader) : Entity(shader) {} + GameActor(const unsigned shaderID) : Entity(shaderID) {} ~GameActor(); void addComponent(std::shared_ptr component); void pickupWeapon(std::shared_ptr weapon); void hookEventManager(std::shared_ptr eventManager); void update(double deltaTime) override; - void render(const std::shared_ptr& camera) override; + void draw() override; - const std::optional> getHeldWeapon() const; + const std::shared_ptr getHeldWeapon() const; void setRotation(const float& rotation) override; diff --git a/YuppleMayham/include/gameplay/map.h b/YuppleMayham/include/gameplay/map.h index 7bcfc0a..c2797c2 100644 --- a/YuppleMayham/include/gameplay/map.h +++ b/YuppleMayham/include/gameplay/map.h @@ -5,6 +5,7 @@ #include #include "graphics/instancedraw.h" +#include "graphics/renderer.h" class Shader; class Camera; @@ -12,14 +13,14 @@ class ResourceManager; struct MapData; struct TileSetData; -class Map +class Map : public Drawable { public: - Map(std::shared_ptr mapData, const std::shared_ptr& shader, std::shared_ptr resourceManager); + Map(std::shared_ptr mapData, const unsigned shaderID, std::shared_ptr resourceManager); const std::vector> getCollisionMap() const { return collisionMap; } - void render(const std::shared_ptr& camera); + void draw() override; private: void loadMap(); @@ -31,7 +32,6 @@ private: std::vector> tileSetData; std::vector> instanceHandles; - std::shared_ptr shader; std::vector>> tileIds; std::vector> collisionMap; std::vector> tileData; diff --git a/YuppleMayham/include/gameplay/scene.h b/YuppleMayham/include/gameplay/scene.h index d7a5983..e824e85 100644 --- a/YuppleMayham/include/gameplay/scene.h +++ b/YuppleMayham/include/gameplay/scene.h @@ -9,10 +9,13 @@ class Entity; class Camera; class Map; class ResourceManager; +class Renderer; class EventManager; class GameActor; class Line; class PhysicsEngine; +class Sprite; +class Shader; struct SceneData; @@ -27,7 +30,7 @@ public: Scene(SceneType type, std::shared_ptr resources); void update(double deltaTime); - void render(); + void render(std::shared_ptr renderer); std::shared_ptr getPlayer() const; diff --git a/YuppleMayham/include/gameplay/weapons/bullet.h b/YuppleMayham/include/gameplay/weapons/bullet.h index 78bc5d8..7e73b62 100644 --- a/YuppleMayham/include/gameplay/weapons/bullet.h +++ b/YuppleMayham/include/gameplay/weapons/bullet.h @@ -14,14 +14,14 @@ public: Bullet ( const unsigned int owner, - std::shared_ptr shader, + unsigned shaderID, glm::vec3 fireFrom, glm::vec2 direction, float bulletSpeed, float bulletDrop, glm::vec2 bulletSize ) : - Entity(shader), + Entity(shaderID), origin(fireFrom), direction(direction), bulletSpeed(bulletSpeed), @@ -36,7 +36,7 @@ public: void addComponent(std::shared_ptr component); void update(double deltaTime) override; - void render(const std::shared_ptr& camera) override; + void draw() override; float getBulletDrop() const { return bulletDrop; } glm::vec3 getBulletOrigin() const { return origin; } diff --git a/YuppleMayham/include/gameplay/weapons/bulletmanager.h b/YuppleMayham/include/gameplay/weapons/bulletmanager.h index 4d14772..8e33ab5 100644 --- a/YuppleMayham/include/gameplay/weapons/bulletmanager.h +++ b/YuppleMayham/include/gameplay/weapons/bulletmanager.h @@ -22,14 +22,16 @@ public: float bulletSpeed, float bulletDrop, glm::vec2 bulletSize, - const std::shared_ptr& shader, + const unsigned& shaderID, const std::shared_ptr& sprite); void update(double deltaTime); - void render(const std::shared_ptr& camera); + void draw(); void hookEventManager(const std::shared_ptr& eventManager); + const std::vector> getBullets() { return bullets; } + private: std::vector> bullets; std::shared_ptr eventManager; diff --git a/YuppleMayham/include/gameplay/weapons/weapon.h b/YuppleMayham/include/gameplay/weapons/weapon.h index 2c3ce20..4e87c98 100644 --- a/YuppleMayham/include/gameplay/weapons/weapon.h +++ b/YuppleMayham/include/gameplay/weapons/weapon.h @@ -27,7 +27,7 @@ struct WeaponData; class Weapon : public Entity, public std::enable_shared_from_this { public: - Weapon(std::shared_ptr data, const std::shared_ptr& weaponShader, const std::shared_ptr& bulletShader, ResourceManager* resourceManager); + Weapon(std::shared_ptr data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager); void setWielder(const std::shared_ptr& wielder) { this->wielder = wielder; } void toggleInfiniteAmmo() { infiniteAmmo = !infiniteAmmo; } @@ -40,7 +40,7 @@ public: void shoot(); void reload(); void update(double deltaTime); - void render(const std::shared_ptr& camera); + void draw(); struct BulletData { glm::vec3 origin; @@ -65,6 +65,8 @@ public: Weapon::BulletData genBulletData (); void createBullet (const BulletData& data); + const std::shared_ptr& getBulletManager() { return bulletManager; } + private: void adjustWeapon(); @@ -82,7 +84,7 @@ private: // in ms float fireSpeed; glm::vec2 bulletSize; - std::shared_ptr bulletShader; + unsigned bulletShaderID; std::shared_ptr bulletSprite; std::shared_ptr bulletManager; std::shared_ptr eventManager; diff --git a/YuppleMayham/include/graphics/renderer.h b/YuppleMayham/include/graphics/renderer.h new file mode 100644 index 0000000..2499fb4 --- /dev/null +++ b/YuppleMayham/include/graphics/renderer.h @@ -0,0 +1,94 @@ +#ifndef _H_RENDERER_H +#define _H_RENDERER_H + +#include +#include +#include +#include +#include +#include + +class ResourceManager; + +enum class RenderLayer { + Background, + Map, + GameObjects, + Effects, + HUD, + Menu +}; + +using UniformValue = std::variant< + int, + bool, + float, + double, + glm::mat4, + glm::vec2 +>; + +struct Uniform { + std::string name; + UniformValue value; +}; + +class Drawable +{ +public: + virtual void draw() = 0; + const unsigned getShaderID() const { return shaderID; } + const std::vector& getUniforms() { return uniforms; } + const std::vector& getOneShotUniforms() { return oneShotUniforms; } + void clearOneShot() { oneShotUniforms.clear(); } + void clearUniforms() { uniforms.clear(); } +protected: + unsigned shaderID; + template + void editUniform(const std::string& name, T value) + { + uniforms.emplace_back(Uniform {name, value}); + } + + template + void editUniformOnce(const std::string& name, T value) + { + oneShotUniforms.emplace_back(Uniform {name, value}); + } +private: + std::vector uniforms; + std::vector oneShotUniforms; +}; + +class Renderer +{ +public: + Renderer(const std::shared_ptr&); + void clear(); + + void setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view); + void addDrawable(RenderLayer renderLayer, std::shared_ptr drawable); + void removeDrawable(RenderLayer renderLayer, std::shared_ptr drawable); + + void render(); + +private: + std::unordered_map>> layerPool; + std::vector renderingOrder = { + RenderLayer::Background, + RenderLayer::Map, + RenderLayer::GameObjects, + RenderLayer::Effects, + RenderLayer::HUD, + RenderLayer::Menu + }; + + void uploadUniforms(const unsigned shaderID, const std::vector& uniforms); + + glm::mat4 projMat; + glm::mat4 viewMat; + + std::shared_ptr resourceManager; +}; + +#endif \ No newline at end of file diff --git a/YuppleMayham/include/graphics/sprite.h b/YuppleMayham/include/graphics/sprite.h index 139e9a9..730b5c3 100644 --- a/YuppleMayham/include/graphics/sprite.h +++ b/YuppleMayham/include/graphics/sprite.h @@ -24,6 +24,8 @@ public: void bind(); virtual void draw() = 0; + bool loaded() const; + virtual std::shared_ptr clone() const = 0; protected: Texture* texture = nullptr; diff --git a/YuppleMayham/include/utility/resourcemanager.h b/YuppleMayham/include/utility/resourcemanager.h index 559e97c..8e4e704 100644 --- a/YuppleMayham/include/utility/resourcemanager.h +++ b/YuppleMayham/include/utility/resourcemanager.h @@ -6,11 +6,11 @@ #include #include "utility/xmlloader.h" +#include "graphics/shader.h" #include class Sprite; class SpriteAtlas; -class Shader; class Weapon; class Script; class AnimationSet; @@ -37,21 +37,24 @@ public: std::shared_ptr loadAIScript (const std::string& path); std::shared_ptr loadWeaponScript (const std::string& path); - std::shared_ptr loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath); - std::shared_ptr loadWeapon (const std::string& name, std::shared_ptr weaponShader, std::shared_ptr bulletShader); + const unsigned loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath); + std::shared_ptr loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID); std::shared_ptr loadScene (const std::string& id); std::shared_ptr loadAnimationSet(const std::string& name, int entityid = 0); std::shared_ptr loadTileSet (const std::string& name); + Shader* getShaderByID(unsigned int ID); + void clearResources(); ~ResourceManager(); private: - std::unordered_map> sprites; - std::unordered_map> shaders; - std::unordered_map> weapons; - std::unordered_map> scripts; + std::unordered_map> shaders; + std::unordered_map shaderIDs; + std::unordered_map> sprites; + std::unordered_map> weapons; + std::unordered_map> scripts; std::unordered_map>tileSets; //std::unordered_map> entityData; //std::unordered_map> scenes; diff --git a/YuppleMayham/include/utility/xmlloader.h b/YuppleMayham/include/utility/xmlloader.h index 1270baa..06c7650 100644 --- a/YuppleMayham/include/utility/xmlloader.h +++ b/YuppleMayham/include/utility/xmlloader.h @@ -65,6 +65,7 @@ struct TileSetData { struct SceneData { std::string id; std::string type; + std::string bgFile; std::shared_ptr map; std::vector entities; diff --git a/YuppleMayham/src/gameplay/ai.cpp b/YuppleMayham/src/gameplay/ai.cpp index 715c6a3..5505dee 100644 --- a/YuppleMayham/src/gameplay/ai.cpp +++ b/YuppleMayham/src/gameplay/ai.cpp @@ -4,6 +4,8 @@ #include "utility/raycaster.h" #include "utility/script.h" +#include + AI::AI(const std::shared_ptr& actor, const std::shared_ptr& raycaster) : actor(actor), raycaster(raycaster), state(AIState::Idle), diff --git a/YuppleMayham/src/gameplay/entity.cpp b/YuppleMayham/src/gameplay/entity.cpp index 2b9c174..94faaeb 100644 --- a/YuppleMayham/src/gameplay/entity.cpp +++ b/YuppleMayham/src/gameplay/entity.cpp @@ -54,14 +54,11 @@ void Entity::update(double deltaTime) } } -void Entity::render(const std::shared_ptr& camera) +void Entity::draw() { //glm::mat4 mvp = camera->getProjectionMatrix() * camera->getViewMatrix() * modelMatrix; - shader->use(); - shader->setMatrix4f("model", glm::value_ptr(modelMatrix)); - shader->setMatrix4f("projection", glm::value_ptr(camera->getProjectionMatrix())); - shader->setMatrix4f("view", glm::value_ptr(camera->getViewMatrix())); - shader->setBool("flip", flipped); + editUniform("model", modelMatrix); + editUniform("flip", flipped); } void Entity::updateModelMatrix() diff --git a/YuppleMayham/src/gameplay/game.cpp b/YuppleMayham/src/gameplay/game.cpp index 84769fc..a3eb82f 100644 --- a/YuppleMayham/src/gameplay/game.cpp +++ b/YuppleMayham/src/gameplay/game.cpp @@ -50,6 +50,7 @@ bool Game::init() game_state |= GAME_RUNNING; resourceManager = std::make_shared(); + renderer = std::make_shared(resourceManager); textHandler = std::make_shared(); if (!textHandler->loadFonts("fonts")) return false; @@ -88,11 +89,11 @@ void Game::render() if (currentScene) { - currentScene->render(); + currentScene->render(renderer); /*Debug ammo indicator*/ - textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->get()->getMagazine()), glm::vec2(10, 10), 0.5f); + textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->getMagazine()), glm::vec2(10, 10), 0.5f); textHandler->DrawText("comic.ttf", "/", glm::vec2(50, 10), 0.5f); - textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->get()->getAmmo()), glm::vec2(90, 10), 0.5f); + textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->getAmmo()), glm::vec2(90, 10), 0.5f); } window->swap(); diff --git a/YuppleMayham/src/gameplay/gameactor.cpp b/YuppleMayham/src/gameplay/gameactor.cpp index 9b7e39d..6788407 100644 --- a/YuppleMayham/src/gameplay/gameactor.cpp +++ b/YuppleMayham/src/gameplay/gameactor.cpp @@ -14,9 +14,9 @@ void GameActor::addComponent(std::shared_ptr component) components.push_back(component); } -const std::optional> GameActor::getHeldWeapon() const +const std::shared_ptr GameActor::getHeldWeapon() const { - return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? std::nullopt : std::make_optional(weapons[currentWeaponIndex]); + return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? nullptr : weapons[currentWeaponIndex]; } void GameActor::pickupWeapon(std::shared_ptr weapon) @@ -24,9 +24,9 @@ void GameActor::pickupWeapon(std::shared_ptr weapon) weapon->setWielder(std::shared_ptr(this)); weapons.push_back(weapon); // wield the newly picked up weapon. - getHeldWeapon().value()->putaway(); + getHeldWeapon()->putaway(); currentWeaponIndex = weapons.size() - 1; - getHeldWeapon().value()->wield(); + getHeldWeapon()->wield(); } void GameActor::hookEventManager(std::shared_ptr eventManager) @@ -72,9 +72,9 @@ void GameActor::update(double deltaTime) isMoving = false; } -void GameActor::render(const std::shared_ptr& camera) +void GameActor::draw() { - Entity::render(camera); + Entity::draw(); // regular loop through components, but if the component returns true to kill, we erase it. // Components are always assumed to be smart pointers! @@ -83,8 +83,8 @@ void GameActor::render(const std::shared_ptr& camera) component->bind(); component->render(); } - for (auto& weapon : weapons) - weapon->render(camera); + //for (auto& weapon : weapons) + // weapon->draw(); } void GameActor::moveUp() { if (physics) physics->rigidBody.applyForce(glm::vec3( 0.f,-1.f, 0.f), 1500.25f); isMoving = true; } @@ -93,7 +93,7 @@ void GameActor::moveLeft() { if (physics) physics->rigidBody.applyForce(glm::vec void GameActor::moveRight(){ if (physics) physics->rigidBody.applyForce(glm::vec3( 1.f, 0.f, 0.f), 1500.25f); isMoving = true; } // top-down shooter mode controls -void GameActor::fireWeapon()const { if (auto& weapon = getHeldWeapon()) weapon.value()->shoot(); } +void GameActor::fireWeapon()const { if (auto& weapon = getHeldWeapon()) weapon->shoot(); } void GameActor::cycleUpWeapons() { if (!weapons.empty()) { weapons[currentWeaponIndex]->putaway(); diff --git a/YuppleMayham/src/gameplay/map.cpp b/YuppleMayham/src/gameplay/map.cpp index e23bbd7..b5129ea 100644 --- a/YuppleMayham/src/gameplay/map.cpp +++ b/YuppleMayham/src/gameplay/map.cpp @@ -7,11 +7,12 @@ #include -Map::Map(std::shared_ptr mapData, const std::shared_ptr& shader, std::shared_ptr resourceManager) : - shader(shader), +Map::Map(std::shared_ptr mapData, const unsigned shaderID, std::shared_ptr resourceManager) : mapData(mapData), tileIds(mapData->tiles) { + this->shaderID = shaderID; + for (auto& tileSet : mapData->tileSets) tileSetData.push_back(resourceManager->loadTileSet(tileSet.path)); @@ -61,8 +62,7 @@ void Map::loadMap() instanceHandles[layer]->updateInstanceData(tileData[layer]); } glm::vec2 canvasSize = glm::vec2(instanceHandles[0]->getTextureArray()->getWidth(), instanceHandles[0]->getTextureArray()->getHeight()); - shader->use(); - shader->setVec2("uCanvasSize", glm::value_ptr(canvasSize)); + editUniformOnce("uCanvasSize", canvasSize); } void Map::createCollisionMap() @@ -96,11 +96,8 @@ void Map::createCollisionMap() } } -void Map::render(const std::shared_ptr& camera) +void Map::draw() { - shader->use(); - shader->setMatrix4f("proj", glm::value_ptr(camera->getProjectionMatrix())); - shader->setMatrix4f("view", glm::value_ptr(camera->getViewMatrix())); for (int layer = 0; layer < instanceHandles.size(); layer++) { instanceHandles[layer]->draw(); diff --git a/YuppleMayham/src/gameplay/scene.cpp b/YuppleMayham/src/gameplay/scene.cpp index 8957a9f..47c3c33 100644 --- a/YuppleMayham/src/gameplay/scene.cpp +++ b/YuppleMayham/src/gameplay/scene.cpp @@ -2,6 +2,7 @@ #include "gameplay/camera.h" #include "gameplay/gameactor.h" #include "gameplay/weapons/weapons.h" +#include "gameplay/weapons/bulletmanager.h" #include "gameplay/map.h" #include "gameplay/physics.h" #include "gameplay/ai.h" @@ -135,14 +136,28 @@ void Scene::update(double deltaTime) camera->update(deltaTime); } -void Scene::render() +void Scene::render(std::shared_ptr renderer) { - map->render(camera); + renderer->clear(); + + renderer->setProjAndViewMatrix(camera->getProjectionMatrix(), camera->getViewMatrix()); + renderer->addDrawable(RenderLayer::Map, map); + //map->draw(); for (auto& [id, e] : entities) { - e->render(camera); + //e->draw(); + renderer->addDrawable(RenderLayer::GameObjects, e); + if (e->getHeldWeapon()) { + renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon()); + for (const auto& bullet : e->getHeldWeapon()->getBulletManager()->getBullets()) { + renderer->addDrawable(RenderLayer::GameObjects, bullet); + } + } } + DebugDrawer::getInstance().draw(camera->getProjectionMatrix() * camera->getViewMatrix()); + + renderer->render(); } void Scene::unloadScene() @@ -158,7 +173,7 @@ void Scene::hookSceneEvents() std::shared_ptr target = getGameActorByID(collideEvent->victimID); if (shooter && target) if (auto& weapon = shooter->getHeldWeapon()) - weapon.value()->onHitCallback(target, collideEvent->bullet, collideEvent->normal); + weapon->onHitCallback(target, collideEvent->bullet, collideEvent->normal); }); } diff --git a/YuppleMayham/src/gameplay/weapons/bullet.cpp b/YuppleMayham/src/gameplay/weapons/bullet.cpp index e976f24..f077f93 100644 --- a/YuppleMayham/src/gameplay/weapons/bullet.cpp +++ b/YuppleMayham/src/gameplay/weapons/bullet.cpp @@ -21,9 +21,9 @@ void Bullet::update(double deltaTime) component->update(); } -void Bullet::render(const std::shared_ptr& camera) +void Bullet::draw() { - Entity::render(camera); + Entity::draw(); for (auto& component : components) { diff --git a/YuppleMayham/src/gameplay/weapons/bulletmanager.cpp b/YuppleMayham/src/gameplay/weapons/bulletmanager.cpp index 87dc789..3b75ad7 100644 --- a/YuppleMayham/src/gameplay/weapons/bulletmanager.cpp +++ b/YuppleMayham/src/gameplay/weapons/bulletmanager.cpp @@ -30,10 +30,10 @@ void BulletManager::addBullet(const unsigned int owner, const glm::vec3& fireFro float bulletSpeed, float bulletDrop, glm::vec2 bulletSize, - const std::shared_ptr& shader, + const unsigned& shaderID, const std::shared_ptr& sprite) { - auto bullet = std::make_shared(owner, shader, fireFrom, direction, bulletSpeed, bulletDrop, bulletSize); + auto bullet = std::make_shared(owner, shaderID, fireFrom, direction, bulletSpeed, bulletDrop, bulletSize); bullet->addComponent(sprite); //bullet->addPhysicsComponent(phy) bullets.emplace_back(bullet); @@ -55,11 +55,11 @@ void BulletManager::update(double deltaTime) } } -void BulletManager::render(const std::shared_ptr& camera) +void BulletManager::draw() { for (auto& bullet : bullets) { if (!bullet) continue; - bullet->render(camera); + bullet->draw(); } } \ No newline at end of file diff --git a/YuppleMayham/src/gameplay/weapons/weapon.cpp b/YuppleMayham/src/gameplay/weapons/weapon.cpp index 0c00df6..5511fa0 100644 --- a/YuppleMayham/src/gameplay/weapons/weapon.cpp +++ b/YuppleMayham/src/gameplay/weapons/weapon.cpp @@ -14,10 +14,10 @@ // TODO: Regular clean up, make this mess readable! -Weapon::Weapon(std::shared_ptr data, const std::shared_ptr& weaponShader, const std::shared_ptr& bulletShader, ResourceManager* resourceManager) +Weapon::Weapon(std::shared_ptr data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager) : - Entity (weaponShader), - bulletShader (bulletShader), + Entity (weaponShaderID), + bulletShaderID (bulletShaderID), weaponSize (glm::vec2(data->sizeX, data->sizeY)), weaponOffset (glm::vec2(data->offsetX, data->offsetY)), weaponMagSize (data->clipSize), @@ -169,9 +169,9 @@ void Weapon::update(double deltaTime) bulletManager->update(deltaTime); } -void Weapon::render(const std::shared_ptr& camera) +void Weapon::draw() { - Entity::render(camera); + Entity::draw(); if (wielded) { for (auto& component : components) @@ -181,7 +181,7 @@ void Weapon::render(const std::shared_ptr& camera) component->render(); } } - bulletManager->render(camera); + //bulletManager->draw(); } void Weapon::adjustWeapon() @@ -241,7 +241,7 @@ Weapon::BulletData Weapon::genBulletData() void Weapon::createBullet(const Weapon::BulletData& data) { - auto bullet = std::make_shared(wielder->getEntityID(), bulletShader, data.origin, data.direction, bulletSpeed, bulletDrop, bulletSize); + auto bullet = std::make_shared(wielder->getEntityID(), bulletShaderID, data.origin, data.direction, bulletSpeed, bulletDrop, bulletSize); bullet->addComponent(bulletSprite); bullet->addPhysicsComponent(std::make_shared(PhysicsComponentFactory::makeBullet(wielder->getEntityID(), data.origin, data.mass, bulletSize.x / 2))); bullet->getPhysicsComponent()->rigidBody.velocity += bulletSpeed * glm::vec3(data.direction.x, data.direction.y, 0.f) / data.mass; diff --git a/YuppleMayham/src/graphics/renderer.cpp b/YuppleMayham/src/graphics/renderer.cpp new file mode 100644 index 0000000..5f51565 --- /dev/null +++ b/YuppleMayham/src/graphics/renderer.cpp @@ -0,0 +1,102 @@ +#include "graphics/renderer.h" +#include "graphics/shader.h" +#include "utility/resourcemanager.h" +#include "utility/logger.h" + +#include + +Renderer::Renderer(const std::shared_ptr& r) + : resourceManager(r) +{ + projMat = glm::mat4(0.f); + viewMat = glm::mat4(0.f); +} + +void Renderer::setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view) +{ + projMat = proj; + viewMat = view; +} + +void Renderer::addDrawable(RenderLayer renderLayer, std::shared_ptr drawable) +{ + layerPool[renderLayer].push_back(drawable); +} + +void Renderer::removeDrawable(RenderLayer renderLayer, std::shared_ptr drawable) +{ + auto& pool = layerPool[renderLayer]; + pool.erase(std::remove(pool.begin(), pool.end(), drawable)); +} + +void Renderer::render() +{ + // Sort by shader id, this works to batch shaders together to avoid shader switching too much + for (auto& [_,pool] : layerPool) { + std::sort(pool.begin(), pool.end(), + [](const std::shared_ptr& a, const std::shared_ptr& b) { + return a->getShaderID() < b->getShaderID(); + }); + } + Shader* curShader = nullptr; + for (const auto& layer : renderingOrder) { + unsigned curShaderID = static_cast(-1); + for (const auto& item : layerPool[layer]) { + if (item->getShaderID() != curShaderID) { + curShaderID = item->getShaderID(); + curShader = resourceManager->getShaderByID(curShaderID); + + if (curShader) { + curShader->use(); + curShader->setMatrix4f("projection", glm::value_ptr(projMat)); + curShader->setMatrix4f("view", glm::value_ptr(viewMat)); + } else { + LOG(ERROR, "Shader with ID {} not found!", curShaderID); + continue; + } + } + if (!item->getOneShotUniforms().empty()) { + uploadUniforms(curShaderID, item->getOneShotUniforms()); + item->clearOneShot(); + } + uploadUniforms(curShaderID, item->getUniforms()); + item->clearUniforms(); + + item->draw(); + } + } +} + +void Renderer::clear() +{ + layerPool.clear(); +} + +void Renderer::uploadUniforms(const unsigned shaderID, const std::vector& uniforms) +{ + Shader *shader = resourceManager->getShaderByID(shaderID); + if (shader == nullptr) { + LOG(ERROR, "No shader found with id {} !", shaderID); + return; + } + for (const auto& uniform : uniforms) { + std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + shader->setBool(uniform.name, arg); + } + else if constexpr (std::is_same_v) { + shader->setInt(uniform.name, arg); + } + else if constexpr (std::is_same_v) { + shader->setFloat(uniform.name, arg); + } + else if constexpr (std::is_same_v) { + shader->setVec2(uniform.name, glm::value_ptr(arg)); + } + else if constexpr (std::is_same_v) { + shader->setMatrix4f(uniform.name, glm::value_ptr(arg)); + } + }, uniform.value); + } +} \ No newline at end of file diff --git a/YuppleMayham/src/graphics/sprite.cpp b/YuppleMayham/src/graphics/sprite.cpp index 1708e76..8fb17e6 100644 --- a/YuppleMayham/src/graphics/sprite.cpp +++ b/YuppleMayham/src/graphics/sprite.cpp @@ -3,6 +3,8 @@ #include "util.h" #include "utility/events.h" +bool Sprite::loaded() const { return (texture != nullptr); } + SpriteStatic::SpriteStatic(const char* texturePath) { EBO = 0, VBO = 0, VAO = 0; @@ -10,6 +12,8 @@ SpriteStatic::SpriteStatic(const char* texturePath) texture->loadTexture(texturePath); if (texture) setupSprite(); + else + delete texture; } void SpriteStatic::setupSprite() @@ -71,6 +75,8 @@ SpriteAtlas::SpriteAtlas(const char* textureAtlasPath, float frameSize, bool isD else SetupDirectional(frameSize); } + else + delete texture; } void SpriteAtlas::Setup(float frameSize) diff --git a/YuppleMayham/src/main.cpp b/YuppleMayham/src/main.cpp index 01b352b..6feb5ad 100644 --- a/YuppleMayham/src/main.cpp +++ b/YuppleMayham/src/main.cpp @@ -1,7 +1,6 @@ #include #include - #include // TODO: Fix circular dependency issues, mostly with input.h needing gameactor.h and command.h diff --git a/YuppleMayham/src/utility/resourcemanager.cpp b/YuppleMayham/src/utility/resourcemanager.cpp index 79c6865..9476784 100644 --- a/YuppleMayham/src/utility/resourcemanager.cpp +++ b/YuppleMayham/src/utility/resourcemanager.cpp @@ -22,6 +22,8 @@ std::shared_ptr ResourceManager::loadSpriteStatic(const std::string& pat if (iterator != sprites.end()) return iterator->second; auto sprite = std::make_shared(path.c_str()); + if (!sprite->loaded()) + return nullptr; sprites[path] = sprite; return sprite; } @@ -41,22 +43,30 @@ std::shared_ptr ResourceManager::loadTileSet(const std::string& nam return xmlLoader->getTileSetData(name); } -std::shared_ptr ResourceManager::loadShader(const std::string& name, const std::string& vertexPath, const std::string& fragPath) +const unsigned ResourceManager::loadShader(const std::string& name, const std::string& vertexPath, const std::string& fragPath) { auto iterator = shaders.find(name); if (iterator != shaders.end()) - return iterator->second; - auto shader = std::make_shared(vertexPath.c_str(), fragPath.c_str()); - shaders[name] = shader; - return shader; + return iterator->second->ID; + auto shader = std::make_unique(vertexPath.c_str(), fragPath.c_str()); + unsigned id = shader->ID; + shaderIDs[shader->ID] = shader.get(); + shaders[name] = std::move(shader); + return id; +} + +Shader* ResourceManager::getShaderByID(unsigned int ID) +{ + auto iterator = shaderIDs.find(ID); + return (iterator != shaderIDs.end() ? iterator->second : nullptr); } // We attach our script after we create our weapon because we are passing a reference to the weapon into the script and we don't want to pass an // incomplete reference to our script. -std::shared_ptr ResourceManager::loadWeapon(const std::string& name, std::shared_ptr weaponShader, std::shared_ptr shader) +std::shared_ptr ResourceManager::loadWeapon(const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID) { std::shared_ptr data = xmlLoader->getWeaponData(name); - auto weapon = std::make_shared(data, weaponShader, shader, this); + auto weapon = std::make_shared(data, weaponShaderID, bulletShaderID, this); if (!data->script.empty()) weapon->attachScript(loadWeaponScript(data->script)); return weapon; @@ -92,6 +102,7 @@ void ResourceManager::clearResources() { sprites.clear(); shaders.clear(); + shaderIDs.clear(); weapons.clear(); tileSets.clear(); } diff --git a/YuppleMayham/src/utility/xmlloader.cpp b/YuppleMayham/src/utility/xmlloader.cpp index 38c45ca..adc8de2 100644 --- a/YuppleMayham/src/utility/xmlloader.cpp +++ b/YuppleMayham/src/utility/xmlloader.cpp @@ -33,13 +33,17 @@ bool XMLLoader::loadXmlScene(const char* xmlFile, SceneData* out) ERROR_LOG("Failed to load file: {}", xmlFile); tinyxml2::XMLElement* scene = doc.FirstChildElement("scene"); - const char* type, * id, * mapName; + const char* type, * id, * mapName, * bgFile; if (scene->QueryStringAttribute("type", &type) != tinyxml2::XML_SUCCESS || scene->QueryStringAttribute("id", &id) != tinyxml2::XML_SUCCESS) ERROR_LOG("Could not read type or id tag in file: {}", xmlFile); out->type = type; out->id = id; + if (scene->QueryStringAttribute("bg", &bgFile) != tinyxml2::XML_SUCCESS) + LOG(WARN, "No background set! attribute 'bg' is empty"); + else + out->bgFile = bgFile; tinyxml2::XMLElement* map = scene->FirstChildElement("map"); if (map == NULL)