Compare commits

...

5 Commits

Author SHA1 Message Date
wuyize 7ca74a245d 分离出RenderingSystem 2023-06-01 14:13:08 +08:00
wuyize e0a4c25242 Merge branch 'main' of http://101.34.228.45:3000/wuyize/ToyEngine 2023-04-20 13:46:15 +08:00
wuyize 942db18774 完成丢手雷 2023-04-20 13:46:01 +08:00
wuyize 62369c0bf0 完成丢手雷 2023-04-20 13:45:46 +08:00
wuyize dbae5cb272 添加手雷对吊桥扰动 2023-04-20 13:40:05 +08:00
22 changed files with 519 additions and 223 deletions

158
ToyEngine/ClassDiagram.cd Normal file
View File

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="NameAndType">
<Class Name="Animation">
<Position X="5" Y="0.5" Width="5" />
<TypeIdentifier>
<HashCode>AAABAAGwAAAAAAAQgEAAAAQAAAAAAAQAAAAACAABMAE=</HashCode>
<FileName>src\Animation.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="Animator">
<Position X="6.5" Y="2" Width="6" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAIAAAAAEQAABAEAAgAAAACgIAQAIAQAAgA=</HashCode>
<FileName>src\Animator.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="Particle">
<Position X="18.75" Y="1" Width="4.75" />
<TypeIdentifier>
<HashCode>AMxAgQgABAAACAAAAAKAAAAABAAQAQQhCAAAAAAAAAA=</HashCode>
<FileName>src\Particle.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="Actor">
<Position X="13.25" Y="1" Width="4.75" />
<TypeIdentifier>
<HashCode>BAEAIIAAAAAIgAAEAAKAIIACAAAgAAAiQAAAAAAIAgA=</HashCode>
<FileName>src\Actor.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="MainWindow">
<Position X="1" Y="7.25" Width="5.75" />
<TypeIdentifier>
<HashCode>AIAAkAAAAAAAhAAQAAAEACAAAAJAAAAIAAAQIAAAAgA=</HashCode>
<FileName>src\MainWindow.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="World">
<Position X="13.25" Y="7" Width="3.5" />
<TypeIdentifier>
<HashCode>AAAAgAAAAhQIBAAAAYIAACAAAAIAAAAgQAAAIAAAAAA=</HashCode>
<FileName>src\World.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="RenderPass">
<Position X="9" Y="15.5" Width="1.75" />
<TypeIdentifier>
<HashCode>EAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAgA=</HashCode>
<FileName>src\RenderPass.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="ShadowMapPass">
<Position X="5" Y="18.25" Width="2" />
<TypeIdentifier>
<HashCode>AAAAEAAAAAAAAAAAoABAAIAAAAQAAAAAAAAAAAAIAAA=</HashCode>
<FileName>src\RenderPass.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="GeometryPass">
<Position X="7.25" Y="18.25" Width="1.5" />
<TypeIdentifier>
<HashCode>ABAgEAAAAADAAAAAAAAAAAAAAAAAQAAgAQCAAAAIAAA=</HashCode>
<FileName>src\RenderPass.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="LightingPass">
<Position X="9" Y="18.25" Width="1.75" />
<TypeIdentifier>
<HashCode>AAAAAAAAEwAAAEAAAACQAAAAAAIAQAAgAwAAAAAIAAA=</HashCode>
<FileName>src\RenderPass.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="FinalPass">
<Position X="11" Y="18.25" Width="1.75" />
<TypeIdentifier>
<HashCode>ACAAAAAABEAAAAAAAAAgAAIQAAAAQAAgAAAAAAAIAgA=</HashCode>
<FileName>src\RenderPass.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="SkyboxPass">
<Position X="13" Y="18.25" Width="1.5" />
<TypeIdentifier>
<HashCode>ABAAAAACAAAAAAAAAgAAAAAQAAAAQAAAAQAAAAAIAAA=</HashCode>
<FileName>src\RenderPass.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="Bone">
<Position X="0.5" Y="0.5" Width="2" />
<TypeIdentifier>
<HashCode>EAQAAAgAAIAAAFAEEAAAIAAAAAgQAwAAAAikEIQACAA=</HashCode>
<FileName>src\Bone.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="RenderingSystem">
<Position X="8.25" Y="7.75" Width="3.75" />
<TypeIdentifier>
<HashCode>ADBAFBBAQQRAAgBAggGQAIIQAABAQAAgAwABAABAAgI=</HashCode>
<FileName>src\RenderingSystem.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="PhysicsManager">
<Position X="0.5" Y="11.25" Width="6.5" />
<TypeIdentifier>
<HashCode>AABAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAQAAAAAAA=</HashCode>
<FileName>src\PhysicsManager.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="DemoWorld">
<Position X="13.25" Y="11.5" Width="3.5" />
<TypeIdentifier>
<HashCode>AAAAgAAAAAAIAAAAEEgAACAAAAAAAAAgAAAAIAEIBCA=</HashCode>
<FileName>src\DemoWorld.h</FileName>
</TypeIdentifier>
</Class>
<Struct Name="AssimpNodeData">
<Position X="5" Y="4.75" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAAAABAAAAEAAAAAAAABAAAAAA=</HashCode>
<FileName>src\Animation.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Force">
<Position X="24" Y="4.5" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAIAAA=</HashCode>
<FileName>src\Particle.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="KeyPosition">
<Position X="3" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AIAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>src\Bone.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="KeyRotation">
<Position X="3" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>src\Bone.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="KeyScale">
<Position X="3" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AIAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>src\Bone.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="BinaryConstraint">
<Position X="0.5" Y="13.25" Width="6.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAEADAAAgAAAAgAAAAA=</HashCode>
<FileName>src\PhysicsManager.h</FileName>
</TypeIdentifier>
</Struct>
<Font Name="Microsoft YaHei UI" Size="9" />
</ClassDiagram>

View File

@ -32,6 +32,7 @@
<ClInclude Include="src\Model.h" />
<ClInclude Include="src\Particle.h" />
<ClInclude Include="src\PhysicsManager.h" />
<ClInclude Include="src\RenderingSystem.h" />
<ClInclude Include="src\RenderPass.h" />
<ClInclude Include="src\RenderPassContext.h" />
<ClInclude Include="src\Shader.h" />
@ -53,11 +54,13 @@
<ClCompile Include="src\Model.cpp" />
<ClCompile Include="src\Particle.cpp" />
<ClCompile Include="src\PhysicsManager.cpp" />
<ClCompile Include="src\RenderingSystem.cpp" />
<ClCompile Include="src\RenderPass.cpp" />
<ClCompile Include="src\Shader.cpp" />
<ClCompile Include="src\World.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="ClassDiagram.cd" />
<None Include="Shaders\brdf_lut.comp" />
<None Include="Shaders\cubemap.frag" />
<None Include="Shaders\cubemap.vert" />

View File

@ -63,6 +63,15 @@
<ClInclude Include="src\DemoWorld.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\PhysicsManager.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\RenderPassContext.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\RenderingSystem.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\gl.c">
@ -113,6 +122,15 @@
<ClCompile Include="src\DemoWorld.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\PhysicsManager.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Shader.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\RenderingSystem.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Shaders\brdf_lut.comp">
@ -166,5 +184,12 @@
<None Include="Shaders\skybox.vert">
<Filter>Shaders</Filter>
</None>
<None Include="ClassDiagram.cd" />
<None Include="Shaders\debug.frag">
<Filter>Shaders</Filter>
</None>
<None Include="Shaders\debug.vert">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -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<Actor>(modelFilePath);
actor->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
@ -95,12 +95,74 @@ void DemoWorld::logicalTick(float deltaTime)
{
mk2->setPosition(throwPerson->getPosition() + glm::vec3(-0.5, 2.2, 0));
mk2->setSpeed(glm::mat3_cast(throwPerson->getRotation() * glm::rotation(glm::vec3(1, 0, 0), glm::normalize(glm::vec3(0, 0.8, 1)/*方向*/))) * glm::vec3(8.3/*速度*/, 0, 0));
//mk2->setSpeed(glm::mat3_cast(throwPerson->getRotation() * glm::rotation(glm::vec3(1, 0, 0), glm::normalize(glm::vec3(0, 2, 1)/*方向*/))) * glm::vec3(10/*速度*/, 0, 0));
mk2->setEnableGravity(true);
}
if (mk2->getPosition().y < 7.5f && mk2->getSpeed().y < 0)
{
particles[3]->setSpeed(particles[3]->getSpeed() + mk2->getSpeed() / 2.f);
mk2->setEnableGravity(false);
mk2->setSpeed(glm::vec3(0));
mk2->setPosition({ 0,-100,0 });
}
}
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<double>());
else if (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS)
lightYaw = glm::mod(lightYaw + yoffset / 100., 2 * glm::pi<double>());
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);
}

View File

@ -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<std::shared_ptr<Particle>> particles;
std::shared_ptr<Actor> throwPerson;
std::shared_ptr<Particle> 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);
};

View File

@ -1,3 +1,4 @@
#include <glad/gl.h>
#include "IblUtils.h"
#include <array>
#include <glm/glm.hpp>

View File

@ -1,8 +1,8 @@
#pragma once
#include <glad/gl.h>
#include <tuple>
#include <glm/ext/matrix_float4x4.hpp>
struct GladGLContext;
class IblUtils
{

View File

@ -4,14 +4,14 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glad/gl.h>
#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<float> shadowCascadeLevels;
float blendRatio = 0.3;
std::vector<float> frustumSizes;

View File

@ -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> world = std::make_unique<DemoWorld>();
world = std::make_unique<DemoWorld>();
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<GLenum> 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();
}
}
GLFWwindow* MainWindow::getWindow()
{
return window;
}

View File

@ -1,21 +1,20 @@
#pragma once
#include "Model.h"
#include "Camera.h"
#include "Light.h"
#include <array>
#include <glad/gl.h>
#include <array>
#include <GLFW/glfw3.h>
#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<GladGLContext> gl;
GLuint fbo = 0;
std::array<GLuint, 5> 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> world;
};

View File

@ -1,3 +1,4 @@
#include <glad/gl.h>
#include "Model.h"
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>

View File

@ -1,5 +1,4 @@
#pragma once
#include <glad/gl.h>
#include <glm/glm.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>

View File

@ -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<std::mutex> 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<std::mutex> 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> force)
{
std::lock_guard<std::mutex> lk(forcesMutex);
forces.insert(force);
}
void Particle::removeForce(std::shared_ptr<Force> force)
{
std::lock_guard<std::mutex> lk(forcesMutex);
forces.erase(force);
}
@ -120,8 +117,8 @@ void Particle::setEnableGravity(bool enable)
if (!gravity)
{
gravity = std::make_shared<Force>(glm::vec3(0.f, -getMass() * 9.80665f, 0.f));
addForce(gravity);
}
addForce(gravity);
}
else
{

View File

@ -18,6 +18,7 @@ public:
virtual void draw(const RenderPassContext& context, Shader& shader);
void addForce(std::shared_ptr<Force> force);
void removeForce(std::shared_ptr<Force> force);
std::mutex forcesMutex;
float getMass();
glm::vec3 getSpeed();
void setSpeed(const glm::vec3& speed);

View File

@ -1,14 +1,14 @@
#include <glad/gl.h>
#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<GLuint, 5>& 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<GLuint, 5>& 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]);

View File

@ -1,5 +1,4 @@
#pragma once
#include <glad/gl.h>
#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<GLuint, 5>& 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<GLuint, 5>& gbuffers;
GLuint& shadowGbuffer;
GLuint& irradianceMap;

View File

@ -0,0 +1,136 @@
#include <glad/gl.h>
#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<ShadowMapPass>(gl, shadowFboHandle, shadowMapResolution, *world);
geometryPass = std::make_unique<GeometryPass>(gl, frameWidth, frameHeight, fbo, *world, projection, view);
lightingPass = std::make_unique<LightingPass>(gl, frameWidth, frameHeight, view, world->camera, world->light,
gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
finalPass = std::make_unique<FinalPass>(gl, frameWidth, frameHeight, gBaseColor, gDebug, exposure);
skyboxPass = std::make_unique<SkyboxPass>(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<GLenum> 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);
}
}

View File

@ -0,0 +1,55 @@
#pragma once
#include <array>
#include <GLFW/glfw3.h>
#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<GLuint, 5> 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> shadowMapPass;
std::unique_ptr<GeometryPass> geometryPass;
std::unique_ptr<LightingPass> lightingPass;
std::unique_ptr<FinalPass> finalPass;
std::unique_ptr<SkyboxPass> skyboxPass;
};

View File

@ -1,3 +1,4 @@
#include <glad/gl.h>
#include "Shader.h"
Shader::Shader(GladGLContext* gl, const char* vertexPath, const char* fragmentPath, const char* geometryPath)

View File

@ -1,7 +1,6 @@
#ifndef SHADER_H
#define SHADER_H
#include <glad/gl.h>
#include <glm/glm.hpp>
#include <string>

View File

@ -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);

View File

@ -2,17 +2,29 @@
#include "Actor.h"
#include "RenderPassContext.h"
#include "PhysicsManager.h"
#include "Camera.h"
#include "Light.h"
#include <GLFW/glfw3.h>
class World
{
public:
Camera camera;
Light light;
std::vector<std::shared_ptr<Actor>> 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> actor);
std::pair<glm::vec3, glm::vec3> 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;
};