diff --git a/CMakeLists.txt b/CMakeLists.txt index 964f8ab..d89358b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ set(INCLUDE_FILES "include/scene.hpp" "include/ecs/ecs_system.hpp" + "include/ecs/transform.hpp" "include/ecs/mesh_renderer.hpp" "include/util/files.hpp" diff --git a/include/ecs/ecs_system.hpp b/include/ecs/ecs_system.hpp index aafa4d6..ba1a9d2 100644 --- a/include/ecs/ecs_system.hpp +++ b/include/ecs/ecs_system.hpp @@ -24,8 +24,6 @@ namespace engine { std::map m_components{}; - virtual void onUpdate(float ts) = 0; - }; } diff --git a/include/ecs/mesh_renderer.hpp b/include/ecs/mesh_renderer.hpp index b2c14e1..dc6edcd 100644 --- a/include/ecs/mesh_renderer.hpp +++ b/include/ecs/mesh_renderer.hpp @@ -4,14 +4,19 @@ #include "resources/material.hpp" #include "resources/shader.hpp" +#include "resources/texture.hpp" #include "resources/mesh.hpp" #include "log.hpp" #include "scene.hpp" #include "application.hpp" +#include "window.hpp" #include "gfx_device.hpp" #include +#include + +#include namespace engine::ecs { @@ -26,13 +31,32 @@ namespace engine::ecs { RendererSystem(Scene* scene) : EcsSystem(scene) { - + updateProjectionMatrix(); } - void onUpdate(float ts) override + void drawMeshes(const std::map& worldTransforms) { + + glm::mat4 cameraTransform{1.0f}; +// cameraTransform = glm::mat4_cast(m_cameraRot); +// reinterpret_cast(cameraTransform[3]) = m_cameraPos; + glm::mat4 viewMatrix = glm::inverse(cameraTransform); + + if (m_scene->app()->window()->getWindowResized()) { + updateProjectionMatrix(); + } + + std::set uniqueShaders{}; for (const auto& [id, data] : m_components) { - DEBUG("rendering entity {}\tts={}", id, ts); + uniqueShaders.insert(data.material->getShader()); + } + for (resources::Shader* shader : uniqueShaders) { + DEBUG("TEST {}", (void*)shader); + m_scene->app()->gfx()->updateUniformBuffer(shader->getPipeline(), &m_projMatrix, sizeof(m_projMatrix), 0); + } + + for (const auto& [id, data] : m_components) { + DEBUG("drawing entity {}", id); DEBUG("material shader addr: {}", (void*)data.material->getShader()); assert(data.material != nullptr); @@ -42,7 +66,7 @@ namespace engine::ecs { glm::mat4 model; glm::mat4 view; } pushConsts{}; - pushConsts.model = glm::mat4{1.0f}; + pushConsts.model = worldTransforms.at(id); pushConsts.view = glm::mat4{1.0f}; m_scene->app()->gfx()->draw( @@ -50,9 +74,30 @@ namespace engine::ecs { data.mesh->getVB(), data.mesh->getIB(), data.mesh->getCount(), - &pushConsts, sizeof(pushConsts), nullptr); + &pushConsts, sizeof(pushConsts), + data.material->m_texture->getHandle()); } } + + glm::vec3 m_cameraPos; + glm::quat m_cameraRot; + + glm::mat4 m_projMatrix; + + private: + + void updateProjectionMatrix() + { + constexpr float NEAR = 0.1f; + constexpr float FAR = 1000.0f; + float fovRad = glm::radians(75.0f); + uint32_t viewportWidth, viewportHeight; + m_scene->app()->gfx()->getViewportSize(&viewportWidth, &viewportHeight); + float aspect = (float)viewportWidth / (float)viewportHeight; + float fovY = fovRad / aspect; + m_projMatrix = glm::perspectiveZO(fovY, aspect, NEAR, FAR); + } + }; diff --git a/include/ecs/transform.hpp b/include/ecs/transform.hpp new file mode 100644 index 0000000..3c184b7 --- /dev/null +++ b/include/ecs/transform.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "ecs_system.hpp" + +#include +#include +#include + +namespace engine::ecs { + + struct TransformComponent { + uint32_t parent; + glm::vec3 scale; + glm::vec3 position; + glm::quat rotation; + }; + + class TransformSystem : public EcsSystem { + + public: + TransformSystem(Scene* scene) + : EcsSystem(scene) + { + + } + + std::unique_ptr> getMatrices() + { + auto transforms = std::make_unique>(); + for (const auto& [id, data] : m_components) { + glm::mat4 transform; + + // rotation + transform = glm::mat4_cast(data.rotation); + // position + reinterpret_cast(transform[3]) = data.position; + // scale (effectively applied first) + transform = glm::scale(transform, data.scale); + + if (data.parent != 0) { + transform = transforms->at(data.parent) * transform; + } + + transforms->emplace(id, transform); + } + return transforms; + } + }; + +} diff --git a/include/resources/material.hpp b/include/resources/material.hpp index 4c9f310..599d63a 100644 --- a/include/resources/material.hpp +++ b/include/resources/material.hpp @@ -5,6 +5,7 @@ namespace engine::resources { class Shader; + class Texture; class Material { @@ -14,7 +15,9 @@ namespace engine::resources { Material(const Material&) = delete; Material& operator=(const Material&) = delete; - Shader* getShader() { return m_shader.get(); } + auto getShader() { return m_shader.get(); } + + std::shared_ptr m_texture; private: const std::shared_ptr m_shader; diff --git a/include/scene.hpp b/include/scene.hpp index 8fcbf72..252e573 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -9,6 +9,7 @@ namespace engine { class Application; namespace ecs { + class TransformSystem; class RendererSystem; } @@ -27,6 +28,7 @@ namespace engine { return m_nextEntityID++; } + std::unique_ptr m_transformSystem; std::unique_ptr m_renderSystem; Application* app() { return m_app; } diff --git a/src/scene.cpp b/src/scene.cpp index 9f53be4..b3f01ea 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -1,5 +1,6 @@ #include "scene.hpp" +#include "ecs/transform.hpp" #include "ecs/mesh_renderer.hpp" namespace engine { @@ -8,13 +9,16 @@ namespace engine { : m_app(app) { m_renderSystem = std::make_unique(this); + m_transformSystem = std::make_unique(this); } Scene::~Scene() {} void Scene::update(float ts) { - m_renderSystem->onUpdate(ts); + auto transforms = m_transformSystem->getMatrices(); + + m_renderSystem->drawMeshes(*transforms); } } diff --git a/test/src/game.cpp b/test/src/game.cpp index d0da0c4..2cf6156 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -8,6 +8,7 @@ #include "resources/shader.hpp" #include "resources/texture.hpp" #include "resources/mesh.hpp" +#include "ecs/transform.hpp" #include "ecs/mesh_renderer.hpp" void playGame() @@ -19,6 +20,9 @@ void playGame() auto myScene = app.sceneManager()->createScene(); + myScene->m_renderSystem->m_cameraPos = { 0.0f, 2.0f, 0.0f }; + myScene->m_renderSystem->m_cameraRot = glm::angleAxis(0.0f, glm::vec3{ 0.0f, 0.0f, -1.0f }); + { auto entity1 = myScene->createEntity(); engine::gfx::VertexFormat vertFormat{}; @@ -28,20 +32,19 @@ void playGame() vertFormat.attributeDescriptions.emplace_back(2, engine::gfx::VertexAttribFormat::VEC2, sizeof(float) * 6); auto myShader = std::make_unique( app.gfx(), - app.getResourcePath("engine/shaders/basic.vert").c_str(), - app.getResourcePath("engine/shaders/basic.frag").c_str(), + app.getResourcePath("engine/shaders/texture.vert").c_str(), + app.getResourcePath("engine/shaders/texture.frag").c_str(), vertFormat, false, false ); - glm::mat4 uniformBuffer{1.0f}; - app.gfx()->updateUniformBuffer(myShader->getPipeline(), &uniformBuffer, sizeof(glm::mat4), 0); auto myMaterial = std::make_unique(std::move(myShader)); std::vector triVertices{ - { { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f } }, - { { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } }, - { { 0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f } }, + { { 0.5f, 0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f } }, + { { -0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } }, + { { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f } }, }; + myMaterial->m_texture = std::make_unique(app.gfx(), app.getResourcePath("textures/grass.jpg")); auto myMesh = std::make_unique(app.gfx(), triVertices); myScene->m_renderSystem->m_components.emplace( entity1, @@ -50,6 +53,15 @@ void playGame() std::move(myMesh), } ); + myScene->m_transformSystem->m_components.emplace( + entity1, + engine::ecs::TransformComponent{ + .parent = 0, + .scale = {1.0f, 1.0f, 1.0f}, + .position = {0.0f, 0.0f, -10.0f}, + .rotation = glm::angleAxis(glm::radians(24.0f), glm::vec3{ 0.0f, 1.0f, 0.0f }) + } + ); } app.gameLoop();