diff --git a/ToyEngine/ClassDiagram.cd b/ToyEngine/ClassDiagram.cd
new file mode 100644
index 0000000..e937fce
--- /dev/null
+++ b/ToyEngine/ClassDiagram.cd
@@ -0,0 +1,158 @@
+
+
+
+
+
+ AAABAAGwAAAAAAAQgEAAAAQAAAAAAAQAAAAACAABMAE=
+ src\Animation.h
+
+
+
+
+
+ AAAAAAAAAAIAAAAAEQAABAEAAgAAAACgIAQAIAQAAgA=
+ src\Animator.h
+
+
+
+
+
+ AMxAgQgABAAACAAAAAKAAAAABAAQAQQhCAAAAAAAAAA=
+ src\Particle.h
+
+
+
+
+
+ BAEAIIAAAAAIgAAEAAKAIIACAAAgAAAiQAAAAAAIAgA=
+ src\Actor.h
+
+
+
+
+
+ AIAAkAAAAAAAhAAQAAAEACAAAAJAAAAIAAAQIAAAAgA=
+ src\MainWindow.h
+
+
+
+
+
+ AAAAgAAAAhQIBAAAAYIAACAAAAIAAAAgQAAAIAAAAAA=
+ src\World.h
+
+
+
+
+
+ EAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAgA=
+ src\RenderPass.h
+
+
+
+
+
+ AAAAEAAAAAAAAAAAoABAAIAAAAQAAAAAAAAAAAAIAAA=
+ src\RenderPass.h
+
+
+
+
+
+ ABAgEAAAAADAAAAAAAAAAAAAAAAAQAAgAQCAAAAIAAA=
+ src\RenderPass.h
+
+
+
+
+
+ AAAAAAAAEwAAAEAAAACQAAAAAAIAQAAgAwAAAAAIAAA=
+ src\RenderPass.h
+
+
+
+
+
+ ACAAAAAABEAAAAAAAAAgAAIQAAAAQAAgAAAAAAAIAgA=
+ src\RenderPass.h
+
+
+
+
+
+ ABAAAAACAAAAAAAAAgAAAAAQAAAAQAAAAQAAAAAIAAA=
+ src\RenderPass.h
+
+
+
+
+
+ EAQAAAgAAIAAAFAEEAAAIAAAAAgQAwAAAAikEIQACAA=
+ src\Bone.h
+
+
+
+
+
+ ADBAFBBAQQRAAgBAggGQAIIQAABAQAAgAwABAABAAgI=
+ src\RenderingSystem.h
+
+
+
+
+
+ AABAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAQAAAAAAA=
+ src\PhysicsManager.h
+
+
+
+
+
+ AAAAgAAAAAAIAAAAEEgAACAAAAAAAAAgAAAAIAEIBCA=
+ src\DemoWorld.h
+
+
+
+
+
+ AAAAAAAAAAAAAAQAAAAAAABAAAAEAAAAAAAABAAAAAA=
+ src\Animation.h
+
+
+
+
+
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAIAAA=
+ src\Particle.h
+
+
+
+
+
+ AIAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAA=
+ src\Bone.h
+
+
+
+
+
+ AIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+ src\Bone.h
+
+
+
+
+
+ AIAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAA=
+ src\Bone.h
+
+
+
+
+
+ AAAAAAAAAAAAAAAAAAAAAAAAAAEADAAAgAAAAgAAAAA=
+ src\PhysicsManager.h
+
+
+
+
\ No newline at end of file
diff --git a/ToyEngine/ToyEngine.vcxproj b/ToyEngine/ToyEngine.vcxproj
index df6cbda..dced617 100644
--- a/ToyEngine/ToyEngine.vcxproj
+++ b/ToyEngine/ToyEngine.vcxproj
@@ -32,6 +32,7 @@
+
@@ -53,11 +54,13 @@
+
+
diff --git a/ToyEngine/ToyEngine.vcxproj.filters b/ToyEngine/ToyEngine.vcxproj.filters
index 467f3cd..161e55d 100644
--- a/ToyEngine/ToyEngine.vcxproj.filters
+++ b/ToyEngine/ToyEngine.vcxproj.filters
@@ -63,6 +63,15 @@
头文件
+
+ 头文件
+
+
+ 头文件
+
+
+ 头文件
+
@@ -113,6 +122,15 @@
源文件
+
+ 源文件
+
+
+ 源文件
+
+
+ 源文件
+
@@ -166,5 +184,12 @@
Shaders
+
+
+ Shaders
+
+
+ Shaders
+
\ No newline at end of file
diff --git a/ToyEngine/src/DemoWorld.cpp b/ToyEngine/src/DemoWorld.cpp
index 0c8ae72..c469d66 100644
--- a/ToyEngine/src/DemoWorld.cpp
+++ b/ToyEngine/src/DemoWorld.cpp
@@ -1,14 +1,14 @@
#include "DemoWorld.h"
#include "Particle.h"
+#include "RenderingSystem.h"
DemoWorld::DemoWorld()
{
+ light.lightDirection = glm::normalize(glm::vec3((cos(lightPitch) * cos(lightYaw)), (sin(lightPitch)), (cos(lightPitch) * sin(lightYaw))));
+ light.radiance = 15.f * lightColor;
+
std::string modelFilePath;
- //modelFilePath = "E:\\3D Objects\\plane\\obj\\plane.obj";
- //modelFilePath = "E:\\3D Objects\\plane\\plane.gltf";
modelFilePath = "Models/vampire/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)));
@@ -99,9 +99,9 @@ void DemoWorld::logicalTick(float deltaTime)
mk2->setEnableGravity(true);
}
- if (mk2->getPosition().y < 7.5f && mk2->getSpeed().y<0)
+ if (mk2->getPosition().y < 7.5f && mk2->getSpeed().y < 0)
{
- particles[3]->setSpeed(particles[3]->getSpeed() + mk2->getSpeed()/2.f);
+ particles[3]->setSpeed(particles[3]->getSpeed() + mk2->getSpeed() / 2.f);
mk2->setEnableGravity(false);
mk2->setSpeed(glm::vec3(0));
mk2->setPosition({ 0,-100,0 });
@@ -111,6 +111,58 @@ void DemoWorld::logicalTick(float deltaTime)
void DemoWorld::rendererTick(float deltaTime)
{
-
World::rendererTick(deltaTime);
}
+
+void DemoWorld::mouseCallback(GLFWwindow* window, double xpos, double ypos)
+{
+ static bool firstMouse = true;
+ static float lastX;
+ static float lastY;
+
+ float xoffset = xpos - lastX;
+ float yoffset = lastY - ypos;
+
+ lastX = xpos;
+ lastY = ypos;
+
+ if (firstMouse)
+ {
+ firstMouse = false;
+ return;
+ }
+
+ if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
+ camera.processMouseMovement(xoffset, yoffset);
+}
+
+void DemoWorld::scrollCallback(GLFWwindow* window, double xoffset, double yoffset)
+{
+ if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)
+ lightPitch = glm::mod(lightPitch + yoffset / 100., glm::pi());
+ else if (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS)
+ lightYaw = glm::mod(lightYaw + yoffset / 100., 2 * glm::pi());
+ else if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS)
+ light.radiance = glm::clamp((light.radiance / lightColor).x + (float)yoffset, 0.f, 100.f) * lightColor;
+ else if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
+ RenderingSystem::instance().exposure = glm::clamp(RenderingSystem::instance().exposure + (float)yoffset*0.1f, 0.f, 2.f);
+ else camera.processMouseScroll(yoffset);
+
+ light.lightDirection = glm::normalize(glm::vec3((cos(lightPitch) * cos(lightYaw)), (sin(lightPitch)), (cos(lightPitch) * sin(lightYaw))));
+}
+
+void DemoWorld::processInput(GLFWwindow* window, float deltaTime)
+{
+ if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
+ camera.processKeyboard(FORWARD, deltaTime);
+ if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
+ camera.processKeyboard(BACKWARD, deltaTime);
+ if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
+ camera.processKeyboard(LEFT, deltaTime);
+ if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
+ camera.processKeyboard(RIGHT, deltaTime);
+ if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
+ camera.processKeyboard(UP, deltaTime);
+ if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
+ camera.processKeyboard(DOWN, deltaTime);
+}
diff --git a/ToyEngine/src/DemoWorld.h b/ToyEngine/src/DemoWorld.h
index 66fb3cc..a9d0128 100644
--- a/ToyEngine/src/DemoWorld.h
+++ b/ToyEngine/src/DemoWorld.h
@@ -5,11 +5,19 @@ class DemoWorld : public World
{
public:
DemoWorld();
- virtual void logicalTick(float deltaTime) override;
- virtual void rendererTick(float deltaTime) override;
+ void logicalTick(float deltaTime) override;
+ void rendererTick(float deltaTime) override;
+ virtual void mouseCallback(GLFWwindow* window, double xpos, double ypos) override;
+ virtual void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) override;
+ virtual void processInput(GLFWwindow* window, float deltaTime) override;
+
private:
std::vector> particles;
std::shared_ptr throwPerson;
std::shared_ptr mk2;
+
+ glm::vec3 lightColor = glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784));
+ float lightYaw = glm::radians(80.f);
+ float lightPitch = glm::radians(105.f);
};
diff --git a/ToyEngine/src/IblUtils.cpp b/ToyEngine/src/IblUtils.cpp
index 09ba63d..5d5695c 100644
--- a/ToyEngine/src/IblUtils.cpp
+++ b/ToyEngine/src/IblUtils.cpp
@@ -1,3 +1,4 @@
+#include
#include "IblUtils.h"
#include
#include
diff --git a/ToyEngine/src/IblUtils.h b/ToyEngine/src/IblUtils.h
index 106371c..c91a6ad 100644
--- a/ToyEngine/src/IblUtils.h
+++ b/ToyEngine/src/IblUtils.h
@@ -1,8 +1,8 @@
#pragma once
-#include
#include
#include
+struct GladGLContext;
class IblUtils
{
diff --git a/ToyEngine/src/Light.h b/ToyEngine/src/Light.h
index 2abf503..1d458a1 100644
--- a/ToyEngine/src/Light.h
+++ b/ToyEngine/src/Light.h
@@ -4,14 +4,14 @@
#include
#include
#include
-#include
#include "Camera.h"
-#include "Model.h"
class Light
{
public:
glm::vec3 lightDirection = glm::normalize(glm::vec3(0.2, 4, 0.4));
+ glm::vec3 radiance = glm::vec3(0);
+
std::vector shadowCascadeLevels;
float blendRatio = 0.3;
std::vector frustumSizes;
diff --git a/ToyEngine/src/MainWindow.cpp b/ToyEngine/src/MainWindow.cpp
index 4f710f7..b3110d7 100644
--- a/ToyEngine/src/MainWindow.cpp
+++ b/ToyEngine/src/MainWindow.cpp
@@ -1,13 +1,10 @@
#include "MainWindow.h"
-#include "IblUtils.h"
-#include "RenderPass.h"
-#include "World.h"
#include "Particle.h"
#include "DemoWorld.h"
+#include "RenderingSystem.h"
+
MainWindow::MainWindow()
- : camera(glm::vec3(0.0f, 0.0f, 3.0f))
- , light(&camera)
{
}
@@ -21,9 +18,9 @@ int MainWindow::exec()
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
float xscale, yscale;
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
- GLFWwindow* window = glfwCreateWindow(kWindowWidth * xscale, kWindowHeight * yscale, "ToyEngine", NULL, NULL);
+ window = glfwCreateWindow(kWindowWidth * xscale, kWindowHeight * yscale, "ToyEngine", NULL, NULL);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) {
- MainWindow::instance().framebufferSizeCallback(window, width, height);
+ RenderingSystem::instance().framebufferSizeCallback(window, width, height);
});
glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos) {
MainWindow::instance().mouseCallback(window, xpos, ypos);
@@ -44,38 +41,18 @@ int MainWindow::exec()
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, 0.0f);
- gl->Enable(GL_DEPTH_TEST);
- gl->DepthFunc(GL_LEQUAL);
- gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
- gl->LineWidth(5 * xscale);
+
- std::unique_ptr world = std::make_unique();
+ world = std::make_unique();
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, gBaseColor, gDebug, exposure);
- SkyboxPass skyboxPass(gl.get(), projection, view, exposure, skyCubemap);
+ RenderingSystem::instance().initialize(gl.get(), xscale, world.get());
int w, h;
glfwGetFramebufferSize(window, &w, &h);
- framebufferSizeCallback(window, w, h);
+ RenderingSystem::instance().framebufferSizeCallback(window, w, h);
int logicalTickCount = 0;
auto logicalThread = std::jthread([&](std::stop_token stop) {
@@ -107,15 +84,7 @@ int MainWindow::exec()
world->rendererTick(deltaTime);
- projection = camera.getProjectionMatrix();
- view = camera.getViewMatrix();
-
- shadowMapPass.dispatch();
- geometryPass.dispatch();
- lightingPass.dispatch();
- finalPass.setShowDebug(showDebug);
- finalPass.dispatch();
- skyboxPass.dispatch();
+ RenderingSystem::instance().tick(deltaTime);
glfwSwapBuffers(window);
glfwPollEvents();
@@ -126,7 +95,7 @@ int MainWindow::exec()
if (accTime > 1.)
{
std::cout << std::format("{:20}\r", "");
- std::cout << std::format("FPS: {:.2f} TPS: {:.2f} {} {} {}\r", frameCnt / accTime, logicalTickCount / accTime, camera.Position.x, camera.Position.y, camera.Position.z);
+ std::cout << std::format("FPS: {:.2f} TPS: {:.2f}\r", frameCnt / accTime, logicalTickCount / accTime);
accTime = 0;
frameCnt = 0;
logicalTickCount = 0;
@@ -141,141 +110,24 @@ void MainWindow::processInput(GLFWwindow* window, float deltaTime)
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
- if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
- camera.processKeyboard(FORWARD, deltaTime);
- if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
- camera.processKeyboard(BACKWARD, deltaTime);
- if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
- camera.processKeyboard(LEFT, deltaTime);
- if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
- camera.processKeyboard(RIGHT, deltaTime);
- if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
- camera.processKeyboard(UP, deltaTime);
- if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
- camera.processKeyboard(DOWN, deltaTime);
-
- static glm::mat4 transform(1);
- float speed = 1;
- if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
- transform = glm::translate(transform, glm::vec3(0, 0, speed));
- if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
- transform = glm::translate(transform, glm::vec3(0, 0, -speed));
- if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
- transform = glm::translate(transform, glm::vec3(-speed, 0, 0));
- if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
- transform = glm::translate(transform, glm::vec3(speed, 0, 0));
- //modelPtr->setTransform(transform);
-}
-
-void MainWindow::framebufferSizeCallback(GLFWwindow* window, int width, int height)
-{
- frameWidth = width;
- frameHeight = height;
- camera.Ratio = (float)frameWidth / (float)frameHeight;
- if (fbo)
- {
- gl->DeleteRenderbuffers(1, &rboDepth);
- gl->DeleteTextures(gbuffers.size(), gbuffers.data());
- gl->DeleteFramebuffers(1, &fbo);
- }
-
- {
- gl->CreateFramebuffers(1, &fbo);
- gl->CreateTextures(GL_TEXTURE_2D, gbuffers.size(), gbuffers.data());
- gl->TextureStorage2D(gBaseColor, 1, GL_RGBA8, frameWidth, frameHeight);
- gl->TextureStorage2D(gNormal, 1, GL_RGB16F, frameWidth, frameHeight);
- gl->TextureStorage2D(gPosition, 1, GL_RGB32F, frameWidth, frameHeight);
- gl->TextureStorage2D(gMetallicRoughness, 1, GL_RG8, frameWidth, frameHeight);
- gl->TextureStorage2D(gDebug, 1, GL_RGBA8, frameWidth, frameHeight);
-
- std::vector attachments;
- for (auto i = 0U; i < gbuffers.size(); i++)
- {
- gl->TextureParameteri(gbuffers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- gl->TextureParameteri(gbuffers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- gl->NamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0 + i, gbuffers[i], 0);
- attachments.push_back(GL_COLOR_ATTACHMENT0 + i);
- }
- gl->NamedFramebufferDrawBuffers(fbo, attachments.size(), attachments.data());
- gl->CreateRenderbuffers(1, &rboDepth);
- gl->NamedRenderbufferStorage(rboDepth, GL_DEPTH_COMPONENT, frameWidth, frameHeight);
- gl->NamedFramebufferRenderbuffer(fbo, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
-
- if (gl->CheckNamedFramebufferStatus(fbo, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- std::cerr << "Framebuffer not complete!\n";
- }
-
- if (shadowFboHandle != 0)
- {
- gl->DeleteTextures(1, &shadowGbuffer);
- gl->DeleteFramebuffers(1, &shadowFboHandle);
- }
-
- shadowMapResolution = 2048;
- gl->GenFramebuffers(1, &shadowFboHandle);
- {
- gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
- gl->GenTextures(1, &shadowGbuffer);
- //Depth
- gl->BindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
- gl->TexImage3D(
- GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, shadowMapResolution, shadowMapResolution, (int)light.shadowCascadeLevels.size(),
- 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
-
- gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- gl->TexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
- gl->FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowGbuffer, 0);
- gl->DrawBuffer(GL_NONE);
- gl->ReadBuffer(GL_NONE);
-
- if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- std::cerr << "ShadowFramebuffer not complete!\n";
- gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
- }
-
+ world->processInput(window, deltaTime);
}
void MainWindow::mouseCallback(GLFWwindow* window, double xpos, double ypos)
{
- static bool firstMouse = true;
- static float lastX;
- static float lastY;
-
- float xoffset = xpos - lastX;
- float yoffset = lastY - ypos;
-
- lastX = xpos;
- lastY = ypos;
-
- if (firstMouse)
- {
- firstMouse = false;
- return;
- }
-
- if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
- {
- float speed = 0.2f;
- 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);
- }
- if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
- camera.processMouseMovement(xoffset, yoffset);
+ world->mouseCallback(window, xpos, ypos);
}
void MainWindow::scrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
- camera.processMouseScroll(yoffset);
+ world->scrollCallback(window, xoffset, yoffset);
}
void MainWindow::keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_TAB && action == GLFW_PRESS)
- showDebug = !showDebug;
+ RenderingSystem::instance().setShowDebug(!RenderingSystem::instance().getShowDebug());
+ world->keyCallback(window, key, scancode, action, mods);
}
MainWindow& MainWindow::instance()
@@ -287,4 +139,9 @@ MainWindow& MainWindow::instance()
GladGLContext* MainWindow::getGLContext()
{
return instance().gl.get();
-}
\ No newline at end of file
+}
+
+GLFWwindow* MainWindow::getWindow()
+{
+ return window;
+}
diff --git a/ToyEngine/src/MainWindow.h b/ToyEngine/src/MainWindow.h
index 2b90c08..4bd891e 100644
--- a/ToyEngine/src/MainWindow.h
+++ b/ToyEngine/src/MainWindow.h
@@ -1,21 +1,20 @@
#pragma once
-#include "Model.h"
-#include "Camera.h"
-#include "Light.h"
-#include
#include
+#include
#include
+#include "World.h"
+
class MainWindow
{
public:
static MainWindow& instance();
static GladGLContext* getGLContext();
+ GLFWwindow* getWindow();
int exec();
private:
MainWindow();
- void framebufferSizeCallback(GLFWwindow* window, int width, int height);
void mouseCallback(GLFWwindow* window, double xpos, double ypos);
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
@@ -23,29 +22,9 @@ private:
static constexpr int kWindowWidth = 1200;
static constexpr int kWindowHeight = 675;
- unsigned int frameWidth;
- unsigned int frameHeight;
-
- Camera camera;
- Light light;
- glm::vec3 mainLightRadiance = 30.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784));
- float exposure = 0.6f;
-
+
+ GLFWwindow* window = nullptr;
std::unique_ptr gl;
-
- GLuint fbo = 0;
- std::array gbuffers;
- GLuint& gBaseColor = gbuffers[0];
- GLuint& gNormal = gbuffers[1];
- GLuint& gPosition = gbuffers[2];
- GLuint& gMetallicRoughness = gbuffers[3];
- GLuint& gDebug = gbuffers[4];
- GLuint rboDepth = 0;
-
- GLuint shadowFboHandle = 0;
- GLuint shadowGbuffer;
- int shadowMapResolution;
-
- bool showDebug = false;
+ std::unique_ptr world;
};
diff --git a/ToyEngine/src/Model.cpp b/ToyEngine/src/Model.cpp
index 2e4b475..75d7642 100644
--- a/ToyEngine/src/Model.cpp
+++ b/ToyEngine/src/Model.cpp
@@ -1,3 +1,4 @@
+#include
#include "Model.h"
#include
#include
diff --git a/ToyEngine/src/Model.h b/ToyEngine/src/Model.h
index 4f8c07f..65d99be 100644
--- a/ToyEngine/src/Model.h
+++ b/ToyEngine/src/Model.h
@@ -1,5 +1,4 @@
#pragma once
-#include
#include
#include
#include
diff --git a/ToyEngine/src/Particle.cpp b/ToyEngine/src/Particle.cpp
index a083b3a..695f5c6 100644
--- a/ToyEngine/src/Particle.cpp
+++ b/ToyEngine/src/Particle.cpp
@@ -20,7 +20,7 @@ Particle::Particle(float mass, const std::string& path)
void Particle::logicalTick(float deltaTime)
{
resultantForce = glm::vec3(0);
- for (auto& force : forces)
+ for (std::lock_guard lk(forcesMutex); auto & force : forces)
resultantForce += force->value;
if (fixed)
@@ -32,13 +32,8 @@ void Particle::logicalTick(float deltaTime)
//auto pos = getPosition() + speed * deltaTime + 0.5f * resultantForce / mass * deltaTime * deltaTime;
speed += resultantForce / mass * deltaTime;
auto pos = getPosition() + speed * deltaTime;
- //if (speed.y < 0 && pos.y < 0.4)
- //{
- // speed.y = -speed.y;
- //}
setPosition(pos);
}
-
}
void Particle::draw(const RenderPassContext& context, Shader& shader)
@@ -71,7 +66,7 @@ void Particle::draw(const RenderPassContext& context, Shader& shader)
debugShader.setUniformValue("view", *context.view);
glm::mat4 modelMatrix = glm::translate(glm::mat4(1), getPosition());// *glm::scale(glm::mat4(1), glm::vec3(glm::abs(resultantForce / mass)));
gl->BindVertexArray(vao);
- for (auto& force : forces)
+ for (std::lock_guard lk(forcesMutex); auto & force : forces)
{
debugShader.setUniformValue("model", modelMatrix * glm::scale(glm::mat4(1), glm::vec3(1)) * glm::mat4_cast(glm::rotation(glm::vec3(1, 0, 0), glm::normalize(force->value))));
debugShader.setUniformValue("color", glm::vec3(0, 1, 0));
@@ -85,11 +80,13 @@ void Particle::draw(const RenderPassContext& context, Shader& shader)
void Particle::addForce(std::shared_ptr force)
{
+ std::lock_guard lk(forcesMutex);
forces.insert(force);
}
void Particle::removeForce(std::shared_ptr force)
{
+ std::lock_guard lk(forcesMutex);
forces.erase(force);
}
diff --git a/ToyEngine/src/Particle.h b/ToyEngine/src/Particle.h
index a0a2e73..0496b58 100644
--- a/ToyEngine/src/Particle.h
+++ b/ToyEngine/src/Particle.h
@@ -18,6 +18,7 @@ public:
virtual void draw(const RenderPassContext& context, Shader& shader);
void addForce(std::shared_ptr force);
void removeForce(std::shared_ptr force);
+ std::mutex forcesMutex;
float getMass();
glm::vec3 getSpeed();
void setSpeed(const glm::vec3& speed);
diff --git a/ToyEngine/src/RenderPass.cpp b/ToyEngine/src/RenderPass.cpp
index d168cd6..7964536 100644
--- a/ToyEngine/src/RenderPass.cpp
+++ b/ToyEngine/src/RenderPass.cpp
@@ -1,14 +1,14 @@
+#include
#include "RenderPass.h"
#include "IblUtils.h"
#include "Mesh.h"
-ShadowMapPass::ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, World& world, Light& light)
+ShadowMapPass::ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, World& world)
: RenderPass(gl, { typeid(ShadowMapPass) })
, modelShadowShader(gl, "Shaders/model_shadow.vert", "Shaders/model_shadow.frag", "Shaders/model_shadow.geom")
, shadowFboHandle(shadowFboHandle)
, shadowMapResolution(shadowMapResolution)
, world(world)
- , light(light)
{
gl->CreateBuffers(1, &lightSpaceMatricesUBO);
gl->NamedBufferData(lightSpaceMatricesUBO, sizeof(glm::mat4) * 16, nullptr, GL_STATIC_DRAW);
@@ -17,7 +17,7 @@ ShadowMapPass::ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& sh
void ShadowMapPass::dispatch()
{
- const auto lightMatrices = light.getLightSpaceMatrices();
+ const auto lightMatrices = world.light.getLightSpaceMatrices();
gl->NamedBufferSubData(lightSpaceMatricesUBO, 0, lightMatrices.size() * sizeof(lightMatrices[0]), lightMatrices.data());
gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
@@ -89,7 +89,7 @@ void GeometryPass::dispatch()
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
}
-LightingPass::LightingPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, glm::mat4& view, Camera& camera, Light& light, glm::vec3& mainLightRadiance, std::array& gbuffers, GLuint& shadowGbuffer, GLuint& irradianceMap, GLuint& prefilterMap, GLuint& brdfLUTTexture)
+LightingPass::LightingPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, glm::mat4& view, Camera& camera, Light& light, std::array& gbuffers, GLuint& shadowGbuffer, GLuint& irradianceMap, GLuint& prefilterMap, GLuint& brdfLUTTexture)
: RenderPass(gl, { typeid(LightingPass) })
, pbrShader(gl, "Shaders/pbr.comp")
, frameWidth(frameWidth)
@@ -97,7 +97,6 @@ LightingPass::LightingPass(GladGLContext* gl, unsigned int& frameWidth, unsigned
, view(view)
, camera(camera)
, light(light)
- , mainLightRadiance(mainLightRadiance)
, gbuffers(gbuffers)
, shadowGbuffer(shadowGbuffer)
, irradianceMap(irradianceMap)
@@ -126,7 +125,7 @@ void LightingPass::dispatch()
pbrShader.setUniformValue("shadowBlendRatio", light.blendRatio);
pbrShader.setUniformValue("camPos", camera.Position);
pbrShader.setUniformValue("mainLightDirection", light.lightDirection);
- pbrShader.setUniformValue("mainLightRadiance", mainLightRadiance);
+ pbrShader.setUniformValue("mainLightRadiance", light.radiance);
gl->BindTextureUnit(1, gbuffers[1]);
gl->BindTextureUnit(2, gbuffers[2]);
diff --git a/ToyEngine/src/RenderPass.h b/ToyEngine/src/RenderPass.h
index 3f9b980..05e141e 100644
--- a/ToyEngine/src/RenderPass.h
+++ b/ToyEngine/src/RenderPass.h
@@ -1,5 +1,4 @@
#pragma once
-#include
#include "Shader.h"
#include "World.h"
#include "Light.h"
@@ -20,14 +19,13 @@ protected:
class ShadowMapPass : public RenderPass
{
public:
- ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, World& world, Light& light);
+ ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, World& world);
void dispatch();
private:
Shader modelShadowShader;
GLuint& shadowFboHandle;
int& shadowMapResolution;
World& world;
- Light& light;
GLuint lightSpaceMatricesUBO;
};
@@ -52,7 +50,7 @@ class LightingPass : public RenderPass
{
public:
LightingPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight,
- glm::mat4& view, Camera& camera, Light& light, glm::vec3& mainLightRadiance,
+ glm::mat4& view, Camera& camera, Light& light,
std::array& gbuffers, GLuint& shadowGbuffer, GLuint& irradianceMap,
GLuint& prefilterMap, GLuint& brdfLUTTexture);
void dispatch();
@@ -63,7 +61,6 @@ private:
glm::mat4& view;
Camera& camera;
Light& light;
- glm::vec3& mainLightRadiance;
std::array& gbuffers;
GLuint& shadowGbuffer;
GLuint& irradianceMap;
diff --git a/ToyEngine/src/RenderingSystem.cpp b/ToyEngine/src/RenderingSystem.cpp
new file mode 100644
index 0000000..55029b6
--- /dev/null
+++ b/ToyEngine/src/RenderingSystem.cpp
@@ -0,0 +1,136 @@
+#include
+#include "RenderingSystem.h"
+#include "IblUtils.h"
+
+RenderingSystem::RenderingSystem()
+{
+}
+
+void RenderingSystem::initialize(GladGLContext* gl, float pixelRatio, World* world)
+{
+ world->light.sceneAABB = world->getAABB();
+
+ this->gl = gl;
+ this->world = world;
+
+ 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, 0.0f);
+ gl->Enable(GL_DEPTH_TEST);
+ gl->DepthFunc(GL_LEQUAL);
+ gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ gl->LineWidth(5 * pixelRatio);
+
+ std::tie(skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture) = IblUtils::precomputeCubemaps(gl);
+
+ shadowMapPass = std::make_unique(gl, shadowFboHandle, shadowMapResolution, *world);
+ geometryPass = std::make_unique(gl, frameWidth, frameHeight, fbo, *world, projection, view);
+ lightingPass = std::make_unique(gl, frameWidth, frameHeight, view, world->camera, world->light,
+ gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
+ finalPass = std::make_unique(gl, frameWidth, frameHeight, gBaseColor, gDebug, exposure);
+ skyboxPass = std::make_unique(gl, projection, view, exposure, skyCubemap);
+}
+
+void RenderingSystem::tick(float deltaTime)
+{
+ projection = world->camera.getProjectionMatrix();
+ view = world->camera.getViewMatrix();
+
+ shadowMapPass->dispatch();
+ geometryPass->dispatch();
+ lightingPass->dispatch();
+
+ finalPass->dispatch();
+ skyboxPass->dispatch();
+}
+
+RenderingSystem& RenderingSystem::instance()
+{
+ static RenderingSystem renderingSystem;
+ return renderingSystem;
+}
+
+bool RenderingSystem::getShowDebug()
+{
+ return finalPass->getShowDebug();
+}
+
+void RenderingSystem::setShowDebug(bool showDebug)
+{
+ finalPass->setShowDebug(showDebug);
+}
+
+void RenderingSystem::framebufferSizeCallback(GLFWwindow* window, int width, int height)
+{
+ frameWidth = width;
+ frameHeight = height;
+ world->camera.Ratio = (float)frameWidth / (float)frameHeight;
+ if (fbo)
+ {
+ gl->DeleteRenderbuffers(1, &rboDepth);
+ gl->DeleteTextures(gbuffers.size(), gbuffers.data());
+ gl->DeleteFramebuffers(1, &fbo);
+ }
+
+ {
+ gl->CreateFramebuffers(1, &fbo);
+ gl->CreateTextures(GL_TEXTURE_2D, gbuffers.size(), gbuffers.data());
+ gl->TextureStorage2D(gBaseColor, 1, GL_RGBA8, frameWidth, frameHeight);
+ gl->TextureStorage2D(gNormal, 1, GL_RGB16F, frameWidth, frameHeight);
+ gl->TextureStorage2D(gPosition, 1, GL_RGB32F, frameWidth, frameHeight);
+ gl->TextureStorage2D(gMetallicRoughness, 1, GL_RG8, frameWidth, frameHeight);
+ gl->TextureStorage2D(gDebug, 1, GL_RGBA8, frameWidth, frameHeight);
+
+ std::vector attachments;
+ for (auto i = 0U; i < gbuffers.size(); i++)
+ {
+ gl->TextureParameteri(gbuffers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->TextureParameteri(gbuffers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->NamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0 + i, gbuffers[i], 0);
+ attachments.push_back(GL_COLOR_ATTACHMENT0 + i);
+ }
+ gl->NamedFramebufferDrawBuffers(fbo, attachments.size(), attachments.data());
+ gl->CreateRenderbuffers(1, &rboDepth);
+ gl->NamedRenderbufferStorage(rboDepth, GL_DEPTH_COMPONENT, frameWidth, frameHeight);
+ gl->NamedFramebufferRenderbuffer(fbo, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
+
+ if (gl->CheckNamedFramebufferStatus(fbo, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ std::cerr << "Framebuffer not complete!\n";
+ }
+
+ if (shadowFboHandle != 0)
+ {
+ gl->DeleteTextures(1, &shadowGbuffer);
+ gl->DeleteFramebuffers(1, &shadowFboHandle);
+ }
+
+ shadowMapResolution = 2048;
+ gl->GenFramebuffers(1, &shadowFboHandle);
+ {
+ gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
+ gl->GenTextures(1, &shadowGbuffer);
+ //Depth
+ gl->BindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
+ gl->TexImage3D(
+ GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, shadowMapResolution, shadowMapResolution, (int)world->light.shadowCascadeLevels.size(),
+ 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
+
+ gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ gl->TexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
+ gl->FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowGbuffer, 0);
+ gl->DrawBuffer(GL_NONE);
+ gl->ReadBuffer(GL_NONE);
+
+ if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ std::cerr << "ShadowFramebuffer not complete!\n";
+ gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+}
\ No newline at end of file
diff --git a/ToyEngine/src/RenderingSystem.h b/ToyEngine/src/RenderingSystem.h
new file mode 100644
index 0000000..e1651cd
--- /dev/null
+++ b/ToyEngine/src/RenderingSystem.h
@@ -0,0 +1,55 @@
+#pragma once
+#include
+#include
+#include "Model.h"
+#include "Camera.h"
+#include "Light.h"
+#include "World.h"
+#include "RenderPass.h"
+#include "MainWindow.h"
+
+class RenderingSystem
+{
+public:
+ static RenderingSystem& instance();
+ void initialize(GladGLContext* gl, float pixelRatio, World* world);
+ void tick(float deltaTime);
+ void framebufferSizeCallback(GLFWwindow* window, int width, int height);
+ bool getShowDebug();
+ void setShowDebug(bool showDebug);
+
+ float exposure = 0.6f;
+
+private:
+ RenderingSystem();
+
+ unsigned int frameWidth;
+ unsigned int frameHeight;
+
+ glm::mat4 projection, view;
+ World* world;
+
+ GladGLContext* gl;
+
+ GLuint skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture;
+
+ GLuint fbo = 0;
+ std::array gbuffers;
+ GLuint& gBaseColor = gbuffers[0];
+ GLuint& gNormal = gbuffers[1];
+ GLuint& gPosition = gbuffers[2];
+ GLuint& gMetallicRoughness = gbuffers[3];
+ GLuint& gDebug = gbuffers[4];
+ GLuint rboDepth = 0;
+
+ GLuint shadowFboHandle = 0;
+ GLuint shadowGbuffer;
+ int shadowMapResolution;
+
+ std::unique_ptr shadowMapPass;
+ std::unique_ptr geometryPass;
+ std::unique_ptr lightingPass;
+ std::unique_ptr finalPass;
+ std::unique_ptr skyboxPass;
+};
+
diff --git a/ToyEngine/src/Shader.cpp b/ToyEngine/src/Shader.cpp
index 4e18fe7..acecd6f 100644
--- a/ToyEngine/src/Shader.cpp
+++ b/ToyEngine/src/Shader.cpp
@@ -1,3 +1,4 @@
+#include
#include "Shader.h"
Shader::Shader(GladGLContext* gl, const char* vertexPath, const char* fragmentPath, const char* geometryPath)
diff --git a/ToyEngine/src/Shader.h b/ToyEngine/src/Shader.h
index 752e6cb..9a1db7d 100644
--- a/ToyEngine/src/Shader.h
+++ b/ToyEngine/src/Shader.h
@@ -1,7 +1,6 @@
#ifndef SHADER_H
#define SHADER_H
-#include
#include
#include
diff --git a/ToyEngine/src/World.cpp b/ToyEngine/src/World.cpp
index 7d73ed7..87b5959 100644
--- a/ToyEngine/src/World.cpp
+++ b/ToyEngine/src/World.cpp
@@ -1,5 +1,11 @@
#include "World.h"
+World::World()
+ : camera(glm::vec3(0.0f, 0.0f, 3.0f))
+ , light(&camera)
+{
+}
+
void World::logicalTick(float deltaTime)
{
physicsManager.tick(deltaTime);
diff --git a/ToyEngine/src/World.h b/ToyEngine/src/World.h
index 03bbc92..f2bec0c 100644
--- a/ToyEngine/src/World.h
+++ b/ToyEngine/src/World.h
@@ -2,17 +2,29 @@
#include "Actor.h"
#include "RenderPassContext.h"
#include "PhysicsManager.h"
+#include "Camera.h"
+#include "Light.h"
+#include
class World
{
public:
+ Camera camera;
+ Light light;
std::vector> actors;
+
+ World();
virtual void logicalTick(float deltaTime);
virtual void rendererTick(float deltaTime);
void draw(const RenderPassContext& context, Shader& shader);
void addActor(std::shared_ptr actor);
std::pair getAABB();
+ virtual void mouseCallback(GLFWwindow* window, double xpos, double ypos) {};
+ virtual void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {};
+ virtual void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {};
+ virtual void processInput(GLFWwindow* window, float deltaTime) {};
protected:
PhysicsManager physicsManager;
+
};