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();
+};
+