From 5501a1348820e88e598c962d5501b46eb652680f Mon Sep 17 00:00:00 2001 From: Ethan Adams Date: Mon, 24 Feb 2025 21:30:48 -0500 Subject: [PATCH] Added framebuffers for world and hud for postprocessing. Also fixed a nagging NDC issue --- .vscode/settings.json | 13 +- Resources/maps/yupple.tiled-session | 6 +- Resources/shaders/GL_bubble.frag | 2 +- Resources/shaders/GL_pp_hud.frag | 16 +++ Resources/shaders/GL_pp_hud.vert | 11 ++ Resources/shaders/GL_pp_world.frag | 12 ++ Resources/shaders/GL_pp_world.vert | 11 ++ YuppleMayham/CMakeLists.txt | 1 + YuppleMayham/include/gameplay/camera.h | 6 +- YuppleMayham/include/gameplay/entity.h | 4 +- YuppleMayham/include/gameplay/physics.h | 2 +- YuppleMayham/include/graphics/animation.h | 2 +- YuppleMayham/include/graphics/instancedraw.h | 8 +- YuppleMayham/include/graphics/quad.h | 55 ++++++++ YuppleMayham/include/graphics/renderer.h | 23 +++- YuppleMayham/include/graphics/sprite.h | 18 +-- YuppleMayham/include/utility/component.h | 6 +- .../include/utility/resourcemanager.h | 9 +- YuppleMayham/src/gameplay/camera.cpp | 9 +- YuppleMayham/src/gameplay/entity.cpp | 4 +- YuppleMayham/src/gameplay/map.cpp | 6 +- YuppleMayham/src/gameplay/physics.cpp | 22 ++- YuppleMayham/src/gameplay/scene.cpp | 6 +- YuppleMayham/src/gameplay/weapons/weapon.cpp | 4 +- YuppleMayham/src/graphics/quad.cpp | 46 +++++++ YuppleMayham/src/graphics/renderer.cpp | 129 ++++++++++++++++-- YuppleMayham/src/graphics/shader.cpp | 13 +- YuppleMayham/src/graphics/sprite.cpp | 58 +++----- YuppleMayham/src/utility/resourcemanager.cpp | 21 +-- 29 files changed, 388 insertions(+), 135 deletions(-) create mode 100644 Resources/shaders/GL_pp_hud.frag create mode 100644 Resources/shaders/GL_pp_hud.vert create mode 100644 Resources/shaders/GL_pp_world.frag create mode 100644 Resources/shaders/GL_pp_world.vert create mode 100644 YuppleMayham/include/graphics/quad.h create mode 100644 YuppleMayham/src/graphics/quad.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json index 9903512..b43ba82 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,16 @@ { "files.associations": { - "memory": "cpp" + "memory": "cpp", + "execution": "cpp", + "algorithm": "cpp", + "iostream": "cpp", + "charconv": "cpp", + "format": "cpp", + "random": "cpp", + "sstream": "cpp", + "xhash": "cpp", + "xlocnum": "cpp", + "xmemory": "cpp", + "cassert": "cpp" } } \ No newline at end of file diff --git a/Resources/maps/yupple.tiled-session b/Resources/maps/yupple.tiled-session index 85a7072..08a564c 100644 --- a/Resources/maps/yupple.tiled-session +++ b/Resources/maps/yupple.tiled-session @@ -32,8 +32,8 @@ "scale": 0.75, "selectedLayer": 2, "viewCenter": { - "x": 989.3333333333334, - "y": 665.3333333333334 + "x": 1440, + "y": 872 } }, "newmap.tmx": { @@ -41,7 +41,7 @@ "selectedLayer": 1, "viewCenter": { "x": 930, - "y": 621 + "y": 620 } }, "shooterWorldOneAtlas.tsx": { diff --git a/Resources/shaders/GL_bubble.frag b/Resources/shaders/GL_bubble.frag index eb901fe..20aa84c 100644 --- a/Resources/shaders/GL_bubble.frag +++ b/Resources/shaders/GL_bubble.frag @@ -7,5 +7,5 @@ uniform sampler2D sprite; void main() { - FragColor = texture(sprite, texCoord) * vec4(1.0, 0.8, 1.0, 1.0); + FragColor = texture(sprite, texCoord); } \ No newline at end of file diff --git a/Resources/shaders/GL_pp_hud.frag b/Resources/shaders/GL_pp_hud.frag new file mode 100644 index 0000000..9df999e --- /dev/null +++ b/Resources/shaders/GL_pp_hud.frag @@ -0,0 +1,16 @@ +#version 330 core +out vec4 FragColor; + +in vec2 texCoord; + +uniform sampler2D screenTexture; + +void main() +{ + //FragColor = texture(screenTexture, texCoord); + vec4 color = texture(screenTexture, texCoord); + if (color.rgb == vec3(0.0, 0.0, 0.0)) + FragColor = vec4(0.0, 0.0, 1.0, 1.0); + else + FragColor = color; +} \ No newline at end of file diff --git a/Resources/shaders/GL_pp_hud.vert b/Resources/shaders/GL_pp_hud.vert new file mode 100644 index 0000000..b00c680 --- /dev/null +++ b/Resources/shaders/GL_pp_hud.vert @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoord; + +out vec2 texCoord; + +void main() +{ + texCoord = aTexCoord; + gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); +} \ No newline at end of file diff --git a/Resources/shaders/GL_pp_world.frag b/Resources/shaders/GL_pp_world.frag new file mode 100644 index 0000000..0023cfe --- /dev/null +++ b/Resources/shaders/GL_pp_world.frag @@ -0,0 +1,12 @@ +#version 330 core +out vec4 FragColor; + +in vec2 texCoord; + +uniform sampler2D world_color; + +void main() +{ + //FragColor = vec4(0.0, 1.0, 1.0, 1.0); + FragColor = mix(texture(world_color, texCoord), vec4(0.4, 0.2, 0.2, 1.0), 0.2); +} \ No newline at end of file diff --git a/Resources/shaders/GL_pp_world.vert b/Resources/shaders/GL_pp_world.vert new file mode 100644 index 0000000..b00c680 --- /dev/null +++ b/Resources/shaders/GL_pp_world.vert @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoord; + +out vec2 texCoord; + +void main() +{ + texCoord = aTexCoord; + gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); +} \ No newline at end of file diff --git a/YuppleMayham/CMakeLists.txt b/YuppleMayham/CMakeLists.txt index 35eba0d..db401ad 100644 --- a/YuppleMayham/CMakeLists.txt +++ b/YuppleMayham/CMakeLists.txt @@ -58,6 +58,7 @@ add_executable (YuppleMayham "include/gameplay/scene.h" "include/graphics/texture.h" + "src/graphics/quad.cpp" "include/utility/resourcemanager.h" "include/utility/xmlloader.h" diff --git a/YuppleMayham/include/gameplay/camera.h b/YuppleMayham/include/gameplay/camera.h index 6491698..055e3da 100644 --- a/YuppleMayham/include/gameplay/camera.h +++ b/YuppleMayham/include/gameplay/camera.h @@ -7,7 +7,7 @@ class Camera { public: Camera(float viewPortW, float viewPortH) : - position(glm::vec3(0.0f, 0.0f, 1.0f)), + position(glm::vec3(0.0f, 0.0f, 0.0f)), front(glm::vec3(0.0f, 0.0f, -1.0f)), up(glm::vec3(0.0f, 1.0f, 0.0f)), viewPortW(viewPortW), @@ -22,9 +22,9 @@ public: void unsetTarget() { target = nullptr; } bool isTargeting() { return (target != nullptr); } - void update(float deltaTime); + void update(double deltaTime); - const glm::vec3 worldToLocal(const glm::vec3& worldCoordinates) const; + const glm::vec3 worldToLocal(const glm::vec3& worldCoordinates); glm::mat4 getViewMatrix(); glm::mat4 getProjectionMatrix(); diff --git a/YuppleMayham/include/gameplay/entity.h b/YuppleMayham/include/gameplay/entity.h index 0a91ffd..78feaf9 100644 --- a/YuppleMayham/include/gameplay/entity.h +++ b/YuppleMayham/include/gameplay/entity.h @@ -39,7 +39,8 @@ public: const float getRotation() const { return this->rotation; } const bool isFlipped() const { return flipped; } const glm::vec2 getFacingDir() const { return glm::vec2(cos(glm::radians(rotation)), sin(glm::radians(rotation))); } - const glm::vec3 getCenter() const { return glm::vec3(position.x + (0.5f * scale.x), position.y + (0.5f * scale.y), 0.0f); } + const glm::vec3 getCenter() const { return glm::vec3(position.x, position.y, 0.0f); } + //const glm::vec3 getCenter() const { return glm::vec3(position.x + (0.5f * scale.x), position.y + (0.5f * scale.y), 0.0f); } const bool getIsMoving() const { return isMoving; } const int getEntityID() const { return entityid; } const std::shared_ptr getPhysicsComponent() const { return physics; } @@ -59,6 +60,7 @@ protected: int entityid; + // Should consider move to using unique pointers for this. std::shared_ptr physics; bool isMoving = false; diff --git a/YuppleMayham/include/gameplay/physics.h b/YuppleMayham/include/gameplay/physics.h index c9d2af0..f290d9d 100644 --- a/YuppleMayham/include/gameplay/physics.h +++ b/YuppleMayham/include/gameplay/physics.h @@ -54,7 +54,7 @@ public: void loadCollisionMap(const std::vector>&, float tileSize); void addObject(const std::shared_ptr&); void removeObject(const std::shared_ptr&); - void update(float deltaTime); + void update(double deltaTime); private: void resolveWorldCollision(const std::shared_ptr&); void resolvePossibleCollisions(); diff --git a/YuppleMayham/include/graphics/animation.h b/YuppleMayham/include/graphics/animation.h index 841df35..295c4f9 100644 --- a/YuppleMayham/include/graphics/animation.h +++ b/YuppleMayham/include/graphics/animation.h @@ -45,7 +45,7 @@ private: std::string animName; std::string animType; - std::shared_ptr spriteAtlas; + SpriteAtlas* spriteAtlas; Uint32 elapsedTime = 0; Uint32 lastFrameTick = 0; diff --git a/YuppleMayham/include/graphics/instancedraw.h b/YuppleMayham/include/graphics/instancedraw.h index 2b4b8d8..c1df86a 100644 --- a/YuppleMayham/include/graphics/instancedraw.h +++ b/YuppleMayham/include/graphics/instancedraw.h @@ -55,10 +55,10 @@ private: TextureArray* textures = nullptr; float vertices[20] = { // vertex - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left - 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // bottom right - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right - 0.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left + 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right + 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right + -0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left }; }; diff --git a/YuppleMayham/include/graphics/quad.h b/YuppleMayham/include/graphics/quad.h new file mode 100644 index 0000000..4d49a85 --- /dev/null +++ b/YuppleMayham/include/graphics/quad.h @@ -0,0 +1,55 @@ +#ifndef _H_QUAD_H +#define _H_QUAD_H + +#include + +class Quad +{ +public: + void draw(); + ~Quad(); +protected: + Quad(const float* vertexData); +private: + unsigned indices[6] = { + 0, 1, 2, + 3, 2, 0 + }; + + // Vertex Array, Vertex Buffer, Element Buffer + unsigned VAO, VBO, EBO; + + float vertices[20]; +}; + +class UnitQuad : public Quad +{ +public: + UnitQuad() : Quad(vertices) {} +private: + // simple rectangle. Most scales will be done based on this generic vertex data. + static constexpr float vertices[20] = { + // vertex texturecoords + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left + 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right + 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right + -0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left + }; +}; + +class ScreenQuad : public Quad +{ +public: + ScreenQuad() : Quad(vertices) {} +private: + // simple rectangle. Most scales will be done based on this generic vertex data. + static constexpr float vertices[20] = { + // vertex texturecoords + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left + }; +}; + +#endif // _H_QUAD_H \ No newline at end of file diff --git a/YuppleMayham/include/graphics/renderer.h b/YuppleMayham/include/graphics/renderer.h index 2499fb4..5c2064e 100644 --- a/YuppleMayham/include/graphics/renderer.h +++ b/YuppleMayham/include/graphics/renderer.h @@ -8,7 +8,10 @@ #include #include +#include "graphics/quad.h" + class ResourceManager; +class Shader; enum class RenderLayer { Background, @@ -64,6 +67,7 @@ class Renderer { public: Renderer(const std::shared_ptr&); + void clear(); void setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view); @@ -73,7 +77,8 @@ public: void render(); private: - std::unordered_map>> layerPool; + std::unordered_map>> worldLayerPool; + std::unordered_map>> HUDLayerPool; std::vector renderingOrder = { RenderLayer::Background, RenderLayer::Map, @@ -88,7 +93,23 @@ private: glm::mat4 projMat; glm::mat4 viewMat; + union FrameBuffer { + unsigned int frame; + unsigned int texture; + }worldBuffer, hudBuffer; + + std::unique_ptr screenQuad; + std::shared_ptr resourceManager; + + void initFrameBuffers(); + void loadPostProcessShaders(); + + Shader* postProcess_World; + Shader* postProcess_HUD; + + void sortLayerPool(auto& layerPool); + void renderPool(auto& layerPool); }; #endif \ No newline at end of file diff --git a/YuppleMayham/include/graphics/sprite.h b/YuppleMayham/include/graphics/sprite.h index 730b5c3..1cc7985 100644 --- a/YuppleMayham/include/graphics/sprite.h +++ b/YuppleMayham/include/graphics/sprite.h @@ -15,6 +15,7 @@ enum class TileType; class Texture; class EventManager; +class UnitQuad; class Sprite { @@ -49,19 +50,7 @@ public: private: void setupSprite(); - - // Vertex Array, Vertex Buffer, Element Buffer - unsigned VAO, VBO, EBO; - - // simple rectangle. Most scales will be done based on this generic vertex data. - float vertices[20] = { - // vertex texturecoords - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left - 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // bottom right - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right - 0.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left - }; - + UnitQuad* quad; }; class SpriteAtlas : public Sprite @@ -74,6 +63,7 @@ public: SpriteAtlas(const char* textureAtlasPath, float frameSize, bool isDirectional = false); ~SpriteAtlas(); + // bind the frame VAO before drawing void bindFrame(VertexIDs* f); // draw current frame void draw() override; @@ -96,8 +86,6 @@ private: unsigned EBO; bool isDirectional; - VertexIDs* curFrame; - VertexIDs singleFrame(int index) const { return (index < 0 || index >= singleIDs.size()) ? singleIDs[0] : singleIDs[index]; } diff --git a/YuppleMayham/include/utility/component.h b/YuppleMayham/include/utility/component.h index 2f4537f..cb04cd9 100644 --- a/YuppleMayham/include/utility/component.h +++ b/YuppleMayham/include/utility/component.h @@ -50,7 +50,7 @@ private: class SpriteComponent : public Component { public: - SpriteComponent(std::shared_ptr sprite) : sprite(sprite), Component(nullptr) {} + SpriteComponent(Sprite* sprite) : sprite(sprite), Component(nullptr) {} void bind() override { if (sprite) sprite->bind(); @@ -62,12 +62,12 @@ public: void play() override { /*unused*/ } void idle() override { /*unused*/ } - std::shared_ptr& getSprite() { return sprite; } + Sprite* getSprite() { return sprite; } ~SpriteComponent() { /*sprite->~Sprite();*/ } private: - std::shared_ptr sprite; + Sprite* sprite; }; class AnimationComponent : public Component diff --git a/YuppleMayham/include/utility/resourcemanager.h b/YuppleMayham/include/utility/resourcemanager.h index 8e4e704..54b4cee 100644 --- a/YuppleMayham/include/utility/resourcemanager.h +++ b/YuppleMayham/include/utility/resourcemanager.h @@ -7,10 +7,9 @@ #include "utility/xmlloader.h" #include "graphics/shader.h" +#include "graphics/sprite.h" #include -class Sprite; -class SpriteAtlas; class Weapon; class Script; class AnimationSet; @@ -32,8 +31,8 @@ public: xmlLoader->loadScenes("scenes"); }; - std::shared_ptr loadSpriteAtlas (const std::string& path, float frameSize, bool isDirectional = false); - std::shared_ptr loadSpriteStatic (const std::string& path); + SpriteAtlas* loadSpriteAtlas (const std::string& path, float frameSize, bool isDirectional = false); + Sprite* loadSpriteStatic (const std::string& path); std::shared_ptr loadAIScript (const std::string& path); std::shared_ptr loadWeaponScript (const std::string& path); @@ -52,7 +51,7 @@ public: private: std::unordered_map> shaders; std::unordered_map shaderIDs; - std::unordered_map> sprites; + std::unordered_map> sprites; std::unordered_map> weapons; std::unordered_map> scripts; std::unordered_map>tileSets; diff --git a/YuppleMayham/src/gameplay/camera.cpp b/YuppleMayham/src/gameplay/camera.cpp index a22f140..bc560b4 100644 --- a/YuppleMayham/src/gameplay/camera.cpp +++ b/YuppleMayham/src/gameplay/camera.cpp @@ -1,12 +1,12 @@ #include "gameplay/camera.h" -void Camera::update(float deltaTime) +void Camera::update(double deltaTime) { if (target == nullptr) return; float smoothingFactor = 5.0f; //if (glm::distance(target->getCenter(), getCenterPos()) > 20.f) - position += (target->getCenter() - getCenterPos()) * smoothingFactor * deltaTime; + position += (target->getCenter() - getCenterPos()) * smoothingFactor * static_cast(deltaTime); } glm::mat4 Camera::getViewMatrix() @@ -19,7 +19,8 @@ glm::mat4 Camera::getProjectionMatrix() return glm::ortho(0.f, viewPortW, viewPortH, 0.f); } -const glm::vec3 Camera::worldToLocal(const glm::vec3& worldCoordinates) const +const glm::vec3 Camera::worldToLocal(const glm::vec3& worldCoordinates) { - return worldCoordinates - position; + //return worldCoordinates - position; + return glm::vec3(getViewMatrix() * glm::vec4(worldCoordinates, 1.0f)); } diff --git a/YuppleMayham/src/gameplay/entity.cpp b/YuppleMayham/src/gameplay/entity.cpp index 94faaeb..5df2d6e 100644 --- a/YuppleMayham/src/gameplay/entity.cpp +++ b/YuppleMayham/src/gameplay/entity.cpp @@ -63,12 +63,10 @@ void Entity::draw() void Entity::updateModelMatrix() { - glm::mat4 origin = glm::translate(glm::mat4(1.f), -0.5f * scale); glm::mat4 rotationMat = (isRotatable) ? glm::rotate(glm::mat4(1.f), glm::radians(rotation), glm::vec3(0.0f, 0.0f, 1.0f)) : glm::mat4(1.0f); - glm::mat4 translation = glm::translate(glm::mat4(1.f), position + 0.5f * scale); + glm::mat4 translation = glm::translate(glm::mat4(1.f), position); modelMatrix = translation * rotationMat * - origin * glm::scale(glm::mat4(1.0f), scale); } diff --git a/YuppleMayham/src/gameplay/map.cpp b/YuppleMayham/src/gameplay/map.cpp index b5129ea..fc3e3ef 100644 --- a/YuppleMayham/src/gameplay/map.cpp +++ b/YuppleMayham/src/gameplay/map.cpp @@ -4,6 +4,7 @@ #include "graphics/texture.h" #include "utility/xmlloader.h" #include "utility/resourcemanager.h" +#include "utility/logger.h" #include @@ -33,7 +34,7 @@ Map::Map(std::shared_ptr mapData, const unsigned shaderID, std::shared_ } } - +#include void Map::loadMap() { tileData.resize(tileIds.size()); @@ -47,7 +48,6 @@ void Map::loadMap() glm::translate(glm::mat4(1.f), glm::vec3(x * mapData->tileSize, y * mapData->tileSize, 0.0f)) * glm::scale(glm::mat4(1.f), glm::vec3(mapData->tileSize, mapData->tileSize, 1.0f)); - int textureIndex = getTileSetIndex(tileIds[layer][y][x]); glm::vec2 originalSize = (textureIndex != -1) ? glm::vec2(tileSetData[textureIndex]->width, tileSetData[textureIndex]->height) : @@ -115,7 +115,7 @@ int Map::getTileSetIndex(int id) const { // work from the bottom, break if ID > startID // If we get a textureIndex of -1 then we are on an empty tile - int tileSetIndex = mapData->tileSets.size() - 1; + size_t tileSetIndex = mapData->tileSets.size() - 1; for (; tileSetIndex != -1; --tileSetIndex) { if (id >= mapData->tileSets[tileSetIndex].startID) diff --git a/YuppleMayham/src/gameplay/physics.cpp b/YuppleMayham/src/gameplay/physics.cpp index 5b13afa..0cfe74d 100644 --- a/YuppleMayham/src/gameplay/physics.cpp +++ b/YuppleMayham/src/gameplay/physics.cpp @@ -58,8 +58,8 @@ void PhysicsEngine::removeObject(const std::shared_ptr& compon int PhysicsEngine::getTileCollider(const glm::vec3& position) { - int x = static_cast(position.x / tileSize); - int y = static_cast(position.y / tileSize); + int x = static_cast((position.x + 0.5f * tileSize) / tileSize); + int y = static_cast((position.y + 0.5f * tileSize) / tileSize); if (y >= 0 && y < collisionMap.size()) { if (x >= 0 && x < collisionMap[y].size()) @@ -150,34 +150,32 @@ void PhysicsEngine::resolveWorldCollision(const std::shared_ptr((position.y) / tileSize); + int tileX = static_cast((position.x) / tileSize); if (topTile) { //obj->rigidBody.velocity.y = -obj->rigidBody.velocity.y; - int tileY = static_cast((position.y - radius) / tileSize); - obj->rigidBody.position.y = (tileY) * tileSize + radius + obj->collider.offset.y; + obj->rigidBody.position.y = (tileY+1) * tileSize + obj->collider.offset.y; } if (bottomTile) { //obj->rigidBody.velocity.y = -obj->rigidBody.velocity.y; - int tileY = static_cast((position.y + radius) / tileSize); - obj->rigidBody.position.y = tileY * tileSize - radius - obj->collider.offset.y; + obj->rigidBody.position.y = (tileY) * tileSize - obj->collider.offset.y; } if (leftTile) { //obj->rigidBody.velocity.x = -obj->rigidBody.velocity.x; - int tileX = static_cast((position.x - radius) / tileSize); - obj->rigidBody.position.x = (tileX) * tileSize + radius + obj->collider.offset.x; + obj->rigidBody.position.x = (tileX + 1) * tileSize + obj->collider.offset.x; } if (rightTile) { //obj->rigidBody.velocity.x = -obj->rigidBody.velocity.x; - int tileX = static_cast((position.x + radius) / tileSize); - obj->rigidBody.position.x = tileX * tileSize - radius - obj->collider.offset.x; + obj->rigidBody.position.x = (tileX) * tileSize - obj->collider.offset.x; } } } -void PhysicsEngine::update(float deltaTime) +void PhysicsEngine::update(double deltaTime) { for (auto& obj : objects) { @@ -205,7 +203,7 @@ void PhysicsEngine::update(float deltaTime) // check map collisions resolveWorldCollision(obj); } - obj->rigidBody.position += obj->rigidBody.velocity * deltaTime; + obj->rigidBody.position += obj->rigidBody.velocity * static_cast(deltaTime); } getPossibleCollisions(); if (!objCollisions.empty()) diff --git a/YuppleMayham/src/gameplay/scene.cpp b/YuppleMayham/src/gameplay/scene.cpp index 5ab57fe..2a11c7a 100644 --- a/YuppleMayham/src/gameplay/scene.cpp +++ b/YuppleMayham/src/gameplay/scene.cpp @@ -90,8 +90,7 @@ void Scene::loadDebugShooterScene() entity->getPosition(), 49.0, PhysicsComponent::Collider::Shape::Circle, - glm::vec3(mapData->tileSize / 2), - glm::abs(entity->getCenter() - entity->getPosition())) + glm::vec3(mapData->tileSize / 2)) ); if (entityData.isPlayer) @@ -159,9 +158,8 @@ void Scene::render(std::shared_ptr renderer) } } - DebugDrawer::getInstance().draw(camera->getProjectionMatrix() * camera->getViewMatrix()); - renderer->render(); + DebugDrawer::getInstance().draw(camera->getProjectionMatrix() * camera->getViewMatrix()); } void Scene::unloadScene() diff --git a/YuppleMayham/src/gameplay/weapons/weapon.cpp b/YuppleMayham/src/gameplay/weapons/weapon.cpp index 5511fa0..b022d9b 100644 --- a/YuppleMayham/src/gameplay/weapons/weapon.cpp +++ b/YuppleMayham/src/gameplay/weapons/weapon.cpp @@ -194,8 +194,8 @@ void Weapon::adjustWeapon() 0.0f ); glm::vec3 origin = wielder->getCenter() + offset; - origin.x -= (weaponSize.x) * 0.5f; - origin.y -= (weaponSize.y) * 0.5f; + //origin.x += (weaponSize.x) * 0.25f; + //origin.y += (weaponSize.y) * 0.25f; // Flip the texture if the weapon is facing upwards or downwards Direction d = getDirectionFromRotation(glm::degrees(rotation)); diff --git a/YuppleMayham/src/graphics/quad.cpp b/YuppleMayham/src/graphics/quad.cpp new file mode 100644 index 0000000..cc019cd --- /dev/null +++ b/YuppleMayham/src/graphics/quad.cpp @@ -0,0 +1,46 @@ +#include "graphics/quad.h" + +#include + +Quad::Quad(const float* vertexData) +{ + std::memcpy(vertices, vertexData, sizeof(vertices)); + VAO = 0, VBO = 0, EBO = 0; + + // Assigning vertex data + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glGenBuffers(1, &EBO); + + glBindVertexArray(VAO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + // Position + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); + // Texture Coordinates + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +void Quad::draw() +{ + glBindVertexArray(VAO); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); +} + +Quad::~Quad() +{ + glDeleteBuffers(1, &VBO); + glDeleteBuffers(1, &EBO); + glDeleteVertexArrays(1, &VAO); +} \ No newline at end of file diff --git a/YuppleMayham/src/graphics/renderer.cpp b/YuppleMayham/src/graphics/renderer.cpp index 5f51565..0131162 100644 --- a/YuppleMayham/src/graphics/renderer.cpp +++ b/YuppleMayham/src/graphics/renderer.cpp @@ -10,6 +10,74 @@ Renderer::Renderer(const std::shared_ptr& r) { projMat = glm::mat4(0.f); viewMat = glm::mat4(0.f); + + initFrameBuffers(); + loadPostProcessShaders(); + screenQuad = std::make_unique(); +} + +// Initialize the framebuffers used by the renderer to allow for post-processing effects +void Renderer::initFrameBuffers() +{ + glGenFramebuffers(1, &worldBuffer.frame); + glGenFramebuffers(1, &hudBuffer.frame); + glBindFramebuffer(GL_FRAMEBUFFER, worldBuffer.frame); + + // World buffer creation + glGenTextures(1, &worldBuffer.texture); + glBindTexture(GL_TEXTURE_2D, worldBuffer.texture); + // !!! NEED TO CREATE STATIC WINDOW SIZING !!! + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + //Attaching empty texture as color buffer for framebuffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, worldBuffer.texture, 0); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + LOG(ERROR, "Failed to complete world framebuffer: {}", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + assert(1 == 0); // force crash + } + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // same thing is done for the hud texture + glBindFramebuffer(GL_FRAMEBUFFER, hudBuffer.frame); + + glGenTextures(1, &hudBuffer.texture); + glBindTexture(GL_TEXTURE_2D, hudBuffer.texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hudBuffer.texture, 0); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + LOG(ERROR, "Failed to complete hud framebuffer: {}", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + assert(1 == 0); // force crash + } + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void Renderer::loadPostProcessShaders() +{ + postProcess_World = resourceManager->getShaderByID(resourceManager->loadShader("GL_pp_world-DEFAULT", "shaders/GL_pp_world.vert", "shaders/GL_pp_world.frag")); + if (postProcess_World == nullptr) { + LOG(ERROR, "Failed to load world shader: GL_pp_world!"); + assert(1 == 0); // force crash + } + postProcess_HUD = resourceManager->getShaderByID(resourceManager->loadShader("GL_pp_hud-DEFAULT", "shaders/GL_pp_hud.vert", "shaders/GL_pp_hud.frag")); + if (postProcess_HUD == nullptr) { + LOG(ERROR, "Failed to load hud shader: GL_pp_hud!"); + assert(1 == 0); // force crash + } } void Renderer::setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view) @@ -20,24 +88,52 @@ void Renderer::setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view void Renderer::addDrawable(RenderLayer renderLayer, std::shared_ptr drawable) { - layerPool[renderLayer].push_back(drawable); + if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu) + HUDLayerPool[renderLayer].push_back(drawable); + else + worldLayerPool[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)); + auto erase = [&](auto& pool) { + pool.erase(std::remove(pool.begin(), pool.end(), drawable), pool.end()); + }; + if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu) { + erase(HUDLayerPool[renderLayer]); + } + else + erase(worldLayerPool[renderLayer]); } 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(); - }); - } + // Bind the world frame buffer + glBindFramebuffer(GL_FRAMEBUFFER, worldBuffer.frame); + // clear color and depth buffer + glClearColor(1.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + renderPool(worldLayerPool); + + glBindFramebuffer(GL_FRAMEBUFFER, hudBuffer.frame); + glClearColor(0.0f, 1.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + renderPool(HUDLayerPool); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, worldBuffer.texture); + postProcess_World->use(); + screenQuad->draw(); + + glBindTexture(GL_TEXTURE_2D, hudBuffer.texture); + postProcess_HUD->use(); + screenQuad->draw(); +} + +void Renderer::renderPool(auto& layerPool) +{ + sortLayerPool(layerPool); Shader* curShader = nullptr; for (const auto& layer : renderingOrder) { unsigned curShaderID = static_cast(-1); @@ -69,7 +165,8 @@ void Renderer::render() void Renderer::clear() { - layerPool.clear(); + worldLayerPool.clear(); + HUDLayerPool.clear(); } void Renderer::uploadUniforms(const unsigned shaderID, const std::vector& uniforms) @@ -99,4 +196,14 @@ void Renderer::uploadUniforms(const unsigned shaderID, const std::vector& a, const std::shared_ptr& b) { + return a->getShaderID() < b->getShaderID(); + }); + } } \ No newline at end of file diff --git a/YuppleMayham/src/graphics/shader.cpp b/YuppleMayham/src/graphics/shader.cpp index 4ee0a80..b999c07 100644 --- a/YuppleMayham/src/graphics/shader.cpp +++ b/YuppleMayham/src/graphics/shader.cpp @@ -1,5 +1,8 @@ #include "graphics/shader.h" +#include "utility/logger.h" +#include + Shader::Shader(const char* vertexPath, const char* fragmentPath) { std::string vertexSource; @@ -27,8 +30,8 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath) } catch(std::exception e) { - std::cout << "failed to open shader files " << e.what() << std::endl; - return; + LOG(ERROR, "failed to open shader files '{}', '{}' error: {}", vertexPath, fragmentPath, e.what()); + assert(1 == 0); // force crash } const char* vSource = vertexSource.c_str(); const char* fSource = fragmentSource.c_str(); @@ -46,7 +49,7 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath) if (!success) { glGetShaderInfoLog(vertexid, 512, NULL, infoLog); - std::cout << "VERTEX SHADER COMPILE ERROR\n" << infoLog << std::endl; + LOG(ERROR, "VERTEX SHADER '{}' COMPILE ERROR\n{}", vertexPath, infoLog); } //compile fragment shader @@ -58,7 +61,7 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath) if (!success) { glGetShaderInfoLog(fragmentid, 512, NULL, infoLog); - std::cout << "FRAGMENT SHADER COMPILE ERROR\n" << infoLog << std::endl; + LOG(ERROR, "FRAGMENT SHADER '{}' COMPILE ERROR\n{}", fragmentPath, infoLog); } //create and link program with compiled shaders @@ -71,7 +74,7 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath) if (!success) { glGetProgramInfoLog(ID, 512, NULL, infoLog); - std::cout << "PROGRAM LINKER ERROR\n" << infoLog << std::endl; + LOG(ERROR, "PROGRAM LINKER ERROR\n{}", infoLog); } glDeleteShader(vertexid); diff --git a/YuppleMayham/src/graphics/sprite.cpp b/YuppleMayham/src/graphics/sprite.cpp index 8fb17e6..89a8b49 100644 --- a/YuppleMayham/src/graphics/sprite.cpp +++ b/YuppleMayham/src/graphics/sprite.cpp @@ -1,5 +1,6 @@ #include "graphics/sprite.h" #include "graphics/texture.h" +#include "graphics/quad.h" #include "util.h" #include "utility/events.h" @@ -7,7 +8,6 @@ bool Sprite::loaded() const { return (texture != nullptr); } SpriteStatic::SpriteStatic(const char* texturePath) { - EBO = 0, VBO = 0, VAO = 0; texture = new Texture(); texture->loadTexture(texturePath); if (texture) @@ -18,28 +18,7 @@ SpriteStatic::SpriteStatic(const char* texturePath) void SpriteStatic::setupSprite() { - // Assigning vertex data - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - glGenBuffers(1, &EBO); - - glBindVertexArray(VAO); - - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - - // Position - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); - // Texture Coordinates - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + quad = new UnitQuad(); } void Sprite::bind() @@ -50,20 +29,16 @@ void Sprite::bind() void SpriteStatic::draw() { - glBindVertexArray(VAO); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - glBindVertexArray(0); + quad->draw(); } SpriteStatic::~SpriteStatic() { delete texture; - glDeleteBuffers(1, &VBO); - glDeleteBuffers(1, &EBO); - glDeleteVertexArrays(1, &VAO); + delete quad; } -SpriteAtlas::SpriteAtlas(const char* textureAtlasPath, float frameSize, bool isDirectional) : isDirectional(isDirectional), curFrame(nullptr) +SpriteAtlas::SpriteAtlas(const char* textureAtlasPath, float frameSize, bool isDirectional) : isDirectional(isDirectional) { EBO = 0; texture = new Texture(); @@ -97,10 +72,10 @@ void SpriteAtlas::Setup(float frameSize) float bottom = (row) * (frameSize / height); float top = (row + 1) * (frameSize / height); float vertices[] = { - 0.0f, 0.0f, 0.0f, left, bottom, // bottom left - 1.0f, 0.0f, 0.0f, right, bottom, // bottom right - 1.0f, 1.0f, 0.0f, right, top, // top right - 0.0f, 1.0f, 0.0f, left, top // top left + -0.5f, -0.5f, 0.0f, left, bottom, // bottom left + 0.5f, -0.5f, 0.0f, right, bottom, // bottom right + 0.5f, 0.5f, 0.0f, right, top, // top right + -0.5f, 0.5f, 0.0f, left, top // top left }; unsigned VAO, VBO; @@ -128,12 +103,11 @@ void SpriteAtlas::Setup(float frameSize) void SpriteAtlas::bindFrame(VertexIDs* f) { - curFrame = f; + glBindVertexArray(f->VAO); } void SpriteAtlas::draw() { - glBindVertexArray(curFrame->VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); } @@ -162,8 +136,8 @@ void SpriteAtlas::SetupDirectional(float frameSize) { int width = texture->getWidth(); int height = texture->getHeight(); - int frameRows = height / frameSize; - int frameCols = width / frameSize; + int frameRows = static_cast(height / frameSize); + int frameCols = static_cast(width / frameSize); glGenBuffers(1, &EBO); @@ -182,10 +156,10 @@ void SpriteAtlas::SetupDirectional(float frameSize) float bottom = (row) * (frameSize / height); float top = (row + 1) * (frameSize / height); float vertices[] = { - 0.0f, 0.0f, 0.0f, left, bottom, // bottom left - 1.0f, 0.0f, 0.0f, right, bottom, // bottom right - 1.0f, 1.0f, 0.0f, right, top, // top right - 0.0f, 1.0f, 0.0f, left, top // top left + -0.5f, -0.5f, 0.0f, left, bottom, // bottom left + 0.5f, -0.5f, 0.0f, right, bottom, // bottom right + 0.5f, 0.5f, 0.0f, right, top, // top right + -0.5f, 0.5f, 0.0f, left, top // top left }; unsigned VAO, VBO; diff --git a/YuppleMayham/src/utility/resourcemanager.cpp b/YuppleMayham/src/utility/resourcemanager.cpp index 9476784..428f479 100644 --- a/YuppleMayham/src/utility/resourcemanager.cpp +++ b/YuppleMayham/src/utility/resourcemanager.cpp @@ -6,26 +6,27 @@ #include "graphics/animation.h" #include "gameplay/weapons/weapons.h" -std::shared_ptr ResourceManager::loadSpriteAtlas(const std::string& path, float frameSize, bool isDirectional) +SpriteAtlas* ResourceManager::loadSpriteAtlas(const std::string& path, float frameSize, bool isDirectional) { auto iterator = sprites.find(path); if (iterator != sprites.end()) - return std::dynamic_pointer_cast(iterator->second); - auto sprite = std::make_shared(path.c_str(), frameSize, isDirectional); - sprites[path] = sprite; - return sprite; + return static_cast(iterator->second.get()); + auto sprite = std::make_unique(path.c_str(), frameSize, isDirectional); + sprites[path] = std::move(sprite); + SpriteAtlas& l = static_cast(*sprites[path].get()); + return static_cast(sprites[path].get()); } -std::shared_ptr ResourceManager::loadSpriteStatic(const std::string& path) +Sprite* ResourceManager::loadSpriteStatic(const std::string& path) { auto iterator = sprites.find(path); if (iterator != sprites.end()) - return iterator->second; - auto sprite = std::make_shared(path.c_str()); + return iterator->second.get(); + auto sprite = std::make_unique(path.c_str()); if (!sprite->loaded()) return nullptr; - sprites[path] = sprite; - return sprite; + sprites[path] = std::move(sprite); + return sprites[path].get(); } std::shared_ptr ResourceManager::loadAIScript(const std::string& path)