diff --git a/ToyEngine/Shaders/model_shadow.vert b/ToyEngine/Shaders/model_shadow.vert index 872c519..f48641d 100644 --- a/ToyEngine/Shaders/model_shadow.vert +++ b/ToyEngine/Shaders/model_shadow.vert @@ -2,13 +2,47 @@ layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in ivec4 boneIds; +layout (location = 4) in vec4 weights; out vec2 vTexCoords; uniform mat4 model; +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +layout (std140, binding = 1) uniform FinalBonesMatrices +{ + mat4 finalBonesMatrices[MAX_BONES]; +}; + void main() { + vec4 totalPosition = vec4(0.0f); + vec3 totalNormal = vec3(0); + int boneCount = 0; + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + if(boneIds[i] == -1) + continue; + if(boneIds[i] >= MAX_BONES) + { + totalPosition = vec4(aPos,1.0f); + break; + } + boneCount++; + vec4 localPosition = finalBonesMatrices[boneIds[i]] * vec4(aPos,1.0f); + totalPosition += localPosition * weights[i]; + vec3 localNormal = mat3(finalBonesMatrices[boneIds[i]]) * aNormal; + totalNormal += localNormal * weights[i]; + } + + if(boneCount == 0) + { + totalPosition = vec4(aPos, 1); + totalNormal = vec3(aNormal); + } + vTexCoords = aTexCoords; - gl_Position = model * vec4(aPos, 1.0); + gl_Position = model * totalPosition; } \ No newline at end of file diff --git a/ToyEngine/ToyEngine.vcxproj b/ToyEngine/ToyEngine.vcxproj index fd95a7c..9d085e7 100644 --- a/ToyEngine/ToyEngine.vcxproj +++ b/ToyEngine/ToyEngine.vcxproj @@ -31,6 +31,7 @@ + @@ -46,6 +47,7 @@ + @@ -160,6 +162,7 @@ true stdcpp20 stdc17 + true Console @@ -176,6 +179,7 @@ true stdcpp20 stdc17 + true Console diff --git a/ToyEngine/ToyEngine.vcxproj.filters b/ToyEngine/ToyEngine.vcxproj.filters index 1eef953..51abfa2 100644 --- a/ToyEngine/ToyEngine.vcxproj.filters +++ b/ToyEngine/ToyEngine.vcxproj.filters @@ -54,6 +54,9 @@ 头文件 + + 头文件 + @@ -95,6 +98,9 @@ 源文件 + + 源文件 + diff --git a/ToyEngine/src/Actor.cpp b/ToyEngine/src/Actor.cpp index e96e3f2..31a3f5c 100644 --- a/ToyEngine/src/Actor.cpp +++ b/ToyEngine/src/Actor.cpp @@ -1 +1,50 @@ #include "Actor.h" +#include "MainWindow.h" + +Actor::Actor(const std::string& path) + : gl(MainWindow::getGLContext()) + , model(gl, path) + , danceAnimation(path, &model) + , animator(gl, &danceAnimation) +{ +} + +void Actor::tick(float deltaTime) +{ + animator.UpdateAnimation(deltaTime); +} + +void Actor::draw(Shader& shader) +{ + gl->BindBufferBase(GL_UNIFORM_BUFFER, 1, animator.getFinalBonesMatricesUBO()); + model.draw(shader); + gl->BindBufferBase(GL_UNIFORM_BUFFER, 1, 0); +} + +void Actor::setPosition(const glm::vec3& position) +{ + this->position = position; + updateTransform(); +} + +void Actor::setScale(const glm::vec3& scale) +{ + this->scale = scale; + updateTransform(); +} + +void Actor::setRotaion(const glm::quat& rotation) +{ + this->rotation = rotation; + updateTransform(); +} + +std::pair Actor::getAABB() +{ + return model.getAABB(); +} + +void Actor::updateTransform() +{ + model.setTransform(glm::translate(glm::mat4(1), position) * glm::scale(glm::mat4(1), scale) * glm::mat4_cast(rotation)); +} diff --git a/ToyEngine/src/Actor.h b/ToyEngine/src/Actor.h index 9647a6d..e89fd04 100644 --- a/ToyEngine/src/Actor.h +++ b/ToyEngine/src/Actor.h @@ -1,10 +1,29 @@ #pragma once #include "Model.h" +#include +#include "Animation.h" +#include "Animator.h" + class Actor { public: + Actor(const std::string& path); + void tick(float deltaTime); + void draw(Shader& shader); + void setPosition(const glm::vec3& position); + void setScale(const glm::vec3& scale); + void setRotaion(const glm::quat& rotation); + std::pair getAABB(); private: - + void updateTransform(); + + GladGLContext* gl; + Model model; + Animation danceAnimation; + Animator animator; + glm::vec3 position = glm::vec3(0); + glm::vec3 scale = glm::vec3(1); + glm::quat rotation = glm::quat(1, 0, 0, 0); }; diff --git a/ToyEngine/src/Animator.h b/ToyEngine/src/Animator.h index 47ef5d3..9fb595d 100644 --- a/ToyEngine/src/Animator.h +++ b/ToyEngine/src/Animator.h @@ -11,32 +11,34 @@ class Animator public: static constexpr GLint kMaxBone = 100; - Animator(Animation* animation) + Animator(GladGLContext* gl, Animation* animation) : gl(gl) { - m_CurrentTime = 0.0; - m_CurrentAnimation = animation; + currentTime = 0.0; + currentAnimation = animation; - m_FinalBoneMatrices.reserve(100); + finalBoneMatrices.reserve(100); for (int i = 0; i < 100; i++) - m_FinalBoneMatrices.push_back(glm::mat4(1.0f)); + finalBoneMatrices.push_back(glm::mat4(1.0f)); + + gl->CreateBuffers(1, &finalBonesMatricesUBO); + gl->NamedBufferData(finalBonesMatricesUBO, sizeof(glm::mat4) * Animator::kMaxBone, nullptr, GL_DYNAMIC_DRAW); } - void UpdateAnimation(float dt) + void UpdateAnimation(float deltaTime) { - m_DeltaTime = dt; - if (m_CurrentAnimation) + if (currentAnimation) { - m_CurrentTime += m_CurrentAnimation->GetTicksPerSecond() * dt; - m_CurrentTime = fmod(m_CurrentTime, m_CurrentAnimation->GetDuration()); - CalculateBoneTransform(&m_CurrentAnimation->GetRootNode(), glm::mat4(1.0f)); + currentTime += currentAnimation->GetTicksPerSecond() * deltaTime; + currentTime = fmod(currentTime, currentAnimation->GetDuration()); + CalculateBoneTransform(¤tAnimation->GetRootNode(), glm::mat4(1.0f)); } } void PlayAnimation(Animation* pAnimation) { - m_CurrentAnimation = pAnimation; - m_CurrentTime = 0.0f; + currentAnimation = pAnimation; + currentTime = 0.0f; } void CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform) @@ -44,22 +46,22 @@ public: std::string nodeName = node->name; glm::mat4 nodeTransform = node->transformation; - Bone* Bone = m_CurrentAnimation->FindBone(nodeName); + Bone* Bone = currentAnimation->FindBone(nodeName); if (Bone) { - Bone->Update(m_CurrentTime); + Bone->Update(currentTime); nodeTransform = Bone->GetLocalTransform(); } glm::mat4 globalTransformation = parentTransform * nodeTransform; - auto boneInfoMap = m_CurrentAnimation->GetBoneIDMap(); + auto boneInfoMap = currentAnimation->GetBoneIDMap(); if (boneInfoMap.find(nodeName) != boneInfoMap.end()) { int index = boneInfoMap[nodeName].id; glm::mat4 offset = boneInfoMap[nodeName].offset; - m_FinalBoneMatrices[index] = globalTransformation * offset; + finalBoneMatrices[index] = globalTransformation * offset; } for (int i = 0; i < node->childrenCount; i++) @@ -68,13 +70,19 @@ public: std::vector GetFinalBoneMatrices() { - return m_FinalBoneMatrices; + return finalBoneMatrices; + } + + GLuint getFinalBonesMatricesUBO() + { + gl->NamedBufferSubData(finalBonesMatricesUBO, 0, finalBoneMatrices.size() * sizeof(finalBoneMatrices[0]), finalBoneMatrices.data()); + return finalBonesMatricesUBO; } private: - std::vector m_FinalBoneMatrices; - Animation* m_CurrentAnimation; - float m_CurrentTime; - float m_DeltaTime; - + GladGLContext* gl; + std::vector finalBoneMatrices; + GLuint finalBonesMatricesUBO; + Animation* currentAnimation; + float currentTime; }; diff --git a/ToyEngine/src/Camera.h b/ToyEngine/src/Camera.h index ba618c7..fd6ce51 100644 --- a/ToyEngine/src/Camera.h +++ b/ToyEngine/src/Camera.h @@ -20,7 +20,7 @@ public: // Default camera values static constexpr float YAW = -90.0f; static constexpr float PITCH = 0.0f; - static constexpr float SPEED = 20.f; + static constexpr float SPEED = 5.f; static constexpr float SENSITIVITY = 0.1f; static constexpr float ZOOM = 45.0f; // camera Attributes @@ -40,7 +40,7 @@ public: float Zoom; float Ratio; float NearPlane = 0.1f; - float FarPlane = 1000.f; + float FarPlane = 100.f; // constructor with vectors Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH); diff --git a/ToyEngine/src/Light.cpp b/ToyEngine/src/Light.cpp index 90653c2..cf58e02 100644 --- a/ToyEngine/src/Light.cpp +++ b/ToyEngine/src/Light.cpp @@ -78,39 +78,27 @@ glm::mat4 Light::getLightSpaceMatrix(const float nearPlane, const float farPlane minZ = std::min(minZ, -trf.z); maxZ = std::max(maxZ, -trf.z); } - if (model != nullptr) - for (const glm::vec3& v : model->AABB) - { - const glm::vec4 trf = lightView * glm::vec4(v, 1); - //qDebug() << v; - //qDebug() << trf; - //minX = std::min(minX, trf.x()); - //maxX = std::max(maxX, trf.x()); - //minY = std::min(minY, trf.y()); - //maxY = std::max(maxY, trf.y()); - minZ = std::min(minZ, -trf.z); - //maxZ = std::max(maxZ, trf.z()); - } - //qDebug() << minZ; - // Tune this parameter according to the scene - /* constexpr float zMult = 10.0f; - if (minZ < 0) + std::vector aabbVertexs; + auto& [minPos, maxPos] = sceneAABB; + aabbVertexs.emplace_back(minPos.x, minPos.y, minPos.z); + aabbVertexs.emplace_back(minPos.x, minPos.y, maxPos.z); + aabbVertexs.emplace_back(minPos.x, maxPos.y, minPos.z); + aabbVertexs.emplace_back(minPos.x, maxPos.y, maxPos.z); + aabbVertexs.emplace_back(maxPos.x, minPos.y, minPos.z); + aabbVertexs.emplace_back(maxPos.x, minPos.y, maxPos.z); + aabbVertexs.emplace_back(maxPos.x, maxPos.y, minPos.z); + aabbVertexs.emplace_back(maxPos.x, maxPos.y, maxPos.z); + for (const glm::vec3& v : aabbVertexs) { - minZ *= zMult; + const glm::vec4 trf = lightView * glm::vec4(v, 1); + //minX = std::min(minX, trf.x()); + //maxX = std::max(maxX, trf.x()); + //minY = std::min(minY, trf.y()); + //maxY = std::max(maxY, trf.y()); + minZ = std::min(minZ, -trf.z); + //maxZ = std::max(maxZ, trf.z()); } - else - { - minZ /= zMult; - } - if (maxZ < 0) - { - maxZ /= zMult; - } - else - { - maxZ *= zMult; - }*/ glm::mat4 lightProjection = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ); frustumSizes.push_back(std::max(maxX - minX, maxY - minY)); diff --git a/ToyEngine/src/Light.h b/ToyEngine/src/Light.h index 1493869..2abf503 100644 --- a/ToyEngine/src/Light.h +++ b/ToyEngine/src/Light.h @@ -11,11 +11,12 @@ class Light { public: - glm::vec3 lightDirection = glm::normalize(glm::vec3(0.2, 4, 1)); + glm::vec3 lightDirection = glm::normalize(glm::vec3(0.2, 4, 0.4)); std::vector shadowCascadeLevels; float blendRatio = 0.3; std::vector frustumSizes; - Model* model = nullptr; + std::pair sceneAABB; + Light(Camera* camera); std::vector getFrustumCornersWorldSpace(const glm::mat4& projview); std::vector getFrustumCornersWorldSpace(const glm::mat4& proj, const glm::mat4& view); diff --git a/ToyEngine/src/MainWindow.cpp b/ToyEngine/src/MainWindow.cpp index 31a9f38..b9babcb 100644 --- a/ToyEngine/src/MainWindow.cpp +++ b/ToyEngine/src/MainWindow.cpp @@ -1,6 +1,7 @@ #include "MainWindow.h" #include "IblUtils.h" #include "RenderPass.h" +#include "World.h" MainWindow::MainWindow() : camera(glm::vec3(0.0f, 0.0f, 3.0f)) @@ -8,6 +9,105 @@ MainWindow::MainWindow() { } +int MainWindow::exec() +{ + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + float xscale, yscale; + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + GLFWwindow* window = glfwCreateWindow(kWindowWidth * xscale, kWindowHeight * yscale, "ToyEngine", NULL, NULL); + glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) { + MainWindow::instance().framebufferSizeCallback(window, width, height); + }); + glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos) { + MainWindow::instance().mouseCallback(window, xpos, ypos); + }); + glfwSetScrollCallback(window, [](GLFWwindow* window, double xoffset, double yoffset) { + MainWindow::instance().scrollCallback(window, xoffset, yoffset); + }); + int xpos, ypos, width, height; + glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height); + glfwSetWindowPos(window, xpos + (width - (kWindowWidth * xscale)) / 2, ypos + (height - kWindowHeight * yscale) / 2); + glfwMakeContextCurrent(window); + gl = std::make_unique(); + if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)glfwGetProcAddress(name); })) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } + gl->Enable(GL_DEBUG_OUTPUT); + //gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + gl->DebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { + if (type == GL_DEBUG_TYPE_ERROR) + std::cerr << std::format("GL_ERROR: type = {:#x}, severity = {:#x}, message = {}", type, severity, message); + }, 0); + gl->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->Enable(GL_DEPTH_TEST); + gl->DepthFunc(GL_LEQUAL); + gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + std::string modelFilePath; + //modelFilePath = "E:\\3D Objects\\plane\\obj\\plane.obj"; + //modelFilePath = "E:\\3D Objects\\plane\\plane.gltf"; + modelFilePath = "E:\\3D Objects\\vampire/gltf/vampire.gltf"; + //modelFilePath = "E:\\3D Objects\\cup\\cup.gltf"; + //modelFilePath = "E:\\3D Objects\\Sponza\\Sponza.gltf"; + + auto actor = std::make_shared(modelFilePath); + actor->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0))); + auto sponza = std::make_shared("E:\\3D Objects\\Sponza\\Sponza.gltf"); + sponza->setScale(glm::vec3(2)); + World world; + world.addActor(actor); + world.addActor(sponza); + + auto [minPos, maxPos] = world.getAABB(); + std::cout << std::format("{},{},{} {},{},{}\n", minPos.x, minPos.y, minPos.z, maxPos.x, maxPos.y, maxPos.z); + + light.sceneAABB = world.getAABB(); + + glm::mat4 projection, view; + auto [skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture] = IblUtils::precomputeCubemaps(gl.get()); + + ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, world, light); + GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, world, projection, view); + LightingPass lightingPass(gl.get(), frameWidth, frameHeight, view, camera, light, mainLightRadiance, + gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture); + FinalPass finalPass(gl.get(), frameWidth, frameHeight, gbuffers, exposure); + SkyboxPass skyboxPass(gl.get(), projection, view, exposure, skyCubemap); + + int w, h; + glfwGetFramebufferSize(window, &w, &h); + framebufferSizeCallback(window, w, h); + + while (!glfwWindowShouldClose(window)) + { + float currentFrame = glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + processInput(window); + + world.tick(deltaTime); + + projection = camera.getProjectionMatrix(); + view = camera.getViewMatrix(); + + shadowMapPass.dispatch(); + geometryPass.dispatch(); + lightingPass.dispatch(); + finalPass.dispatch(); + skyboxPass.dispatch(); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + glfwTerminate(); +} void MainWindow::processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) @@ -26,16 +126,17 @@ void MainWindow::processInput(GLFWwindow* window) if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) camera.processKeyboard(DOWN, deltaTime); - glm::mat4 transform(1); + static glm::mat4 transform(1); float speed = 1; if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) - modelPtr->setTransform(glm::translate(transform, glm::vec3(0, 0, speed))); + transform = glm::translate(transform, glm::vec3(0, 0, speed)); if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) - modelPtr->setTransform(glm::translate(transform, glm::vec3(0, 0, -speed))); + transform = glm::translate(transform, glm::vec3(0, 0, -speed)); if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) - modelPtr->setTransform(glm::translate(transform, glm::vec3(-speed, 0, 0))); + transform = glm::translate(transform, glm::vec3(-speed, 0, 0)); if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) - modelPtr->setTransform(glm::translate(transform, glm::vec3(speed, 0, 0))); + transform = glm::translate(transform, glm::vec3(speed, 0, 0)); + //modelPtr->setTransform(transform); } void MainWindow::framebufferSizeCallback(GLFWwindow* window, int width, int height) @@ -145,9 +246,9 @@ void MainWindow::mouseCallback(GLFWwindow* window, double xpos, double ypos) if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) { float speed = 0.2f; - glm::mat4 rotate(1); + static glm::mat4 rotate(1); rotate = glm::rotate(rotate, glm::radians(glm::length(glm::vec2(xoffset, yoffset)) * speed), glm::vec3(glm::vec2(-yoffset, xoffset), 0.0)); - modelPtr->setTransform(rotate); + //modelPtr->setTransform(rotate); } if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) camera.processMouseMovement(xoffset, yoffset); @@ -164,97 +265,7 @@ MainWindow& MainWindow::instance() return window; } -int MainWindow::exec() +GladGLContext* MainWindow::getGLContext() { - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - float xscale, yscale; - glfwGetMonitorContentScale(monitor, &xscale, &yscale); - GLFWwindow* window = glfwCreateWindow(kWindowWidth * xscale, kWindowHeight * yscale, "RenderModel", NULL, NULL); - MainWindow& m = *this; - glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) { - MainWindow::instance().framebufferSizeCallback(window, width, height); - }); - glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos) { - MainWindow::instance().mouseCallback(window, xpos, ypos); - }); - glfwSetScrollCallback(window, [](GLFWwindow* window, double xoffset, double yoffset) { - MainWindow::instance().scrollCallback(window, xoffset, yoffset); - }); - int xpos, ypos, width, height; - glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height); - glfwSetWindowPos(window, xpos + (width - (kWindowWidth * xscale)) / 2, ypos + (height - kWindowHeight * yscale) / 2); - glfwMakeContextCurrent(window); - gl = std::make_unique(); - if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)glfwGetProcAddress(name); })) - { - std::cout << "Failed to initialize GLAD" << std::endl; - return -1; - } - gl->Enable(GL_DEBUG_OUTPUT); - //gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - gl->DebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { - if (type == GL_DEBUG_TYPE_ERROR) - std::cerr << std::format("GL_ERROR: type = {:#x}, severity = {:#x}, message = {}", type, severity, message); - }, 0); - gl->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); - gl->Enable(GL_DEPTH_TEST); - gl->DepthFunc(GL_LEQUAL); - gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - std::string modelFilePath; - //modelFilePath = "E:\\3D Objects\\plane\\obj\\plane.obj"; - //modelFilePath = "E:\\3D Objects\\plane\\plane.gltf"; - modelFilePath = "E:\\3D Objects\\vampire/gltf/vampire.gltf"; - //modelFilePath = "E:\\3D Objects\\cup\\cup.gltf"; - //modelFilePath = "E:\\3D Objects\\Sponza\\Sponza.gltf"; - - Model model(gl.get(), modelFilePath); - modelPtr = &model; - light.model = &model; - - Animation danceAnimation(modelFilePath, &model); - Animator animator(&danceAnimation); - - glm::mat4 projection, view; - auto [skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture] = IblUtils::precomputeCubemaps(gl.get()); - - ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, model, light); - GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, model, projection, view, animator); - LightingPass lightingPass(gl.get(), frameWidth, frameHeight, view, camera, light, mainLightRadiance, - gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture); - FinalPass finalPass(gl.get(), frameWidth, frameHeight, gbuffers, exposure); - SkyboxPass skyboxPass(gl.get(), projection, view, exposure, skyCubemap); - - int w, h; - glfwGetFramebufferSize(window, &w, &h); - framebufferSizeCallback(window, w, h); - - while (!glfwWindowShouldClose(window)) - { - float currentFrame = glfwGetTime(); - deltaTime = currentFrame - lastFrame; - lastFrame = currentFrame; - processInput(window); - - animator.UpdateAnimation(deltaTime); - - projection = camera.getProjectionMatrix(); - view = camera.getViewMatrix(); - - shadowMapPass.dispatch(); - geometryPass.dispatch(); - lightingPass.dispatch(); - finalPass.dispatch(); - skyboxPass.dispatch(); - - glfwSwapBuffers(window); - glfwPollEvents(); - } - - glfwTerminate(); -} + return instance().gl.get(); +} \ No newline at end of file diff --git a/ToyEngine/src/MainWindow.h b/ToyEngine/src/MainWindow.h index 1bf9b2d..7f52f9e 100644 --- a/ToyEngine/src/MainWindow.h +++ b/ToyEngine/src/MainWindow.h @@ -10,6 +10,7 @@ class MainWindow { public: static MainWindow& instance(); + static GladGLContext* getGLContext(); int exec(); private: @@ -24,7 +25,6 @@ private: unsigned int frameWidth; unsigned int frameHeight; - Model* modelPtr = nullptr; Camera camera; Light light; glm::vec3 mainLightRadiance = 40.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784)); diff --git a/ToyEngine/src/Model.cpp b/ToyEngine/src/Model.cpp index f8c10ab..d420e73 100644 --- a/ToyEngine/src/Model.cpp +++ b/ToyEngine/src/Model.cpp @@ -20,8 +20,17 @@ void Model::draw(Shader& shader) void Model::setTransform(const glm::mat4& trans) { + auto inverse = glm::inverse(transform); + transform = trans; for (auto& mesh : meshes) - mesh->model = trans * mesh->model; + mesh->model = transform * inverse * mesh->model; + minPos = transform * inverse * glm::vec4(minPos, 1); + maxPos = transform * inverse * glm::vec4(maxPos, 1); +} + +std::pair Model::getAABB() +{ + return { minPos, maxPos }; } void Model::loadModel(std::string const& path) @@ -38,17 +47,9 @@ void Model::loadModel(std::string const& path) } aiMatrix4x4 transform; - aiMatrix4x4::Scaling(aiVector3D(10), transform); + //aiMatrix4x4::Scaling(aiVector3D(10), transform); //aiMatrix4x4::Rotation(glm::radians(-90.f), { 1,0,0 }, transform); processNode(scene->mRootNode, scene, transform * scene->mRootNode->mTransformation); - AABB.emplace_back(minPos.x, minPos.y, minPos.z); - AABB.emplace_back(minPos.x, minPos.y, maxPos.z); - AABB.emplace_back(minPos.x, maxPos.y, minPos.z); - AABB.emplace_back(minPos.x, maxPos.y, maxPos.z); - AABB.emplace_back(maxPos.x, minPos.y, minPos.z); - AABB.emplace_back(maxPos.x, minPos.y, maxPos.z); - AABB.emplace_back(maxPos.x, maxPos.y, minPos.z); - AABB.emplace_back(maxPos.x, maxPos.y, maxPos.z); } void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4) @@ -56,7 +57,7 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4) for (unsigned int i = 0; i < node->mNumMeshes; i++) if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4)) meshes.emplace_back(std::move(mesh)); - + for (unsigned int i = 0; i < node->mNumChildren; i++) processNode(node->mChildren[i], scene, mat4 * node->mChildren[i]->mTransformation); } diff --git a/ToyEngine/src/Model.h b/ToyEngine/src/Model.h index a9186d8..8dc91a8 100644 --- a/ToyEngine/src/Model.h +++ b/ToyEngine/src/Model.h @@ -21,7 +21,7 @@ struct BoneInfo class Model { public: - std::vector AABB; + glm::mat4 transform = glm::mat4(1); std::vector> meshes; std::map boneInfoMap; int boneCount = 0; @@ -29,6 +29,7 @@ public: Model(GladGLContext* gl, std::string const& path); void draw(Shader& shader); void setTransform(const glm::mat4& trans); + std::pair getAABB(); private: GladGLContext* gl; std::filesystem::path directory; /// ģ· diff --git a/ToyEngine/src/RenderPass.cpp b/ToyEngine/src/RenderPass.cpp index 462422d..4d17a73 100644 --- a/ToyEngine/src/RenderPass.cpp +++ b/ToyEngine/src/RenderPass.cpp @@ -2,12 +2,12 @@ #include "IblUtils.h" #include "Mesh.h" -ShadowMapPass::ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, Model& model, Light& light) +ShadowMapPass::ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, World& world, Light& light) : RenderPass(gl) , modelShadowShader(gl, "Shaders/model_shadow.vert", "Shaders/model_shadow.frag", "Shaders/model_shadow.geom") , shadowFboHandle(shadowFboHandle) , shadowMapResolution(shadowMapResolution) - , model(model) + , world(world) , light(light) { gl->CreateBuffers(1, &lightSpaceMatricesUBO); @@ -24,26 +24,22 @@ void ShadowMapPass::dispatch() gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution); gl->Clear(GL_DEPTH_BUFFER_BIT); modelShadowShader.use(); - model.draw(modelShadowShader); + world.draw(modelShadowShader); modelShadowShader.release(); gl->BindFramebuffer(GL_FRAMEBUFFER, 0); } -GeometryPass::GeometryPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, GLuint& fbo, Model& model, glm::mat4& projection, glm::mat4& view, Animator& animator) +GeometryPass::GeometryPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, GLuint& fbo, World& world, glm::mat4& projection, glm::mat4& view) : RenderPass(gl) , modelShader(gl, "Shaders/model.vert", "Shaders/model.frag") , plainShader(gl, "Shaders/plain.vert", "Shaders/plain.frag") , frameWidth(frameWidth) , frameHeight(frameHeight) , fbo(fbo) - , model(model) + , world(world) , projection(projection) , view(view) - , animator(animator) { - gl->CreateBuffers(1, &finalBonesMatricesUBO); - gl->NamedBufferData(finalBonesMatricesUBO, sizeof(glm::mat4) * Animator::kMaxBone, nullptr, GL_DYNAMIC_DRAW); - gl->BindBufferBase(GL_UNIFORM_BUFFER, 1, finalBonesMatricesUBO); } void GeometryPass::dispatch() @@ -55,9 +51,7 @@ void GeometryPass::dispatch() modelShader.use(); modelShader.setUniformValue("projection", projection); modelShader.setUniformValue("view", view); - auto boneMatrices = animator.GetFinalBoneMatrices(); - gl->NamedBufferSubData(finalBonesMatricesUBO, 0, boneMatrices.size() * sizeof(boneMatrices[0]), boneMatrices.data()); - model.draw(modelShader); + world.draw(modelShader); modelShader.release(); /// Debug Lighting diff --git a/ToyEngine/src/RenderPass.h b/ToyEngine/src/RenderPass.h index d338acc..6ca97c2 100644 --- a/ToyEngine/src/RenderPass.h +++ b/ToyEngine/src/RenderPass.h @@ -1,7 +1,7 @@ #pragma once #include #include "Shader.h" -#include "Model.h" +#include "World.h" #include "Light.h" #include #include "Animator.h" @@ -18,13 +18,13 @@ protected: class ShadowMapPass : public RenderPass { public: - ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, Model& model, Light& light); + ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, World& world, Light& light); void dispatch(); private: Shader modelShadowShader; GLuint& shadowFboHandle; int& shadowMapResolution; - Model& model; + World& world; Light& light; GLuint lightSpaceMatricesUBO; }; @@ -33,7 +33,7 @@ class GeometryPass : public RenderPass { public: GeometryPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, - GLuint& fbo, Model& model, glm::mat4& projection, glm::mat4& view, Animator& animator); + GLuint& fbo, World& world, glm::mat4& projection, glm::mat4& view); void dispatch(); private: Shader modelShader; @@ -42,10 +42,9 @@ private: unsigned int& frameWidth; unsigned int& frameHeight; GLuint& fbo; - Model& model; + World& world; glm::mat4& projection; glm::mat4& view; - Animator& animator; }; class LightingPass : public RenderPass diff --git a/ToyEngine/src/World.cpp b/ToyEngine/src/World.cpp new file mode 100644 index 0000000..72284f3 --- /dev/null +++ b/ToyEngine/src/World.cpp @@ -0,0 +1,31 @@ +#include "World.h" + +void World::tick(float deltaTime) +{ + for (auto& actor : actors) + actor->tick(deltaTime); +} + +void World::draw(Shader& shader) +{ + for (auto& actor : actors) + actor->draw(shader); +} + +void World::addActor(std::shared_ptr actor) +{ + actors.push_back(actor); +} + +std::pair World::getAABB() +{ + glm::vec3 minPos = glm::vec3(std::numeric_limits::max()); + glm::vec3 maxPos = glm::vec3(std::numeric_limits::min()); + for (auto& actor : actors) + { + auto [min, max] = actor->getAABB(); + minPos = glm::min(minPos, min); + maxPos = glm::max(maxPos, max); + } + return { minPos, maxPos }; +} diff --git a/ToyEngine/src/World.h b/ToyEngine/src/World.h new file mode 100644 index 0000000..4dd841e --- /dev/null +++ b/ToyEngine/src/World.h @@ -0,0 +1,13 @@ +#pragma once +#include "Actor.h" + +class World +{ +public: + std::vector> actors; + void tick(float deltaTime); + void draw(Shader& shader); + void addActor(std::shared_ptr actor); + std::pair getAABB(); +}; +