优化calculateBoneTransform性能

逻辑与渲染分离
main
wuyize 2023-04-18 14:06:28 +08:00
parent c5f8ce41c7
commit c5b8729ed6
21 changed files with 347 additions and 113 deletions

View File

@ -101,6 +101,7 @@ const int pcfRadius = 3;
float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer) float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer)
{ {
float normalBias = 1.2*4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x; float normalBias = 1.2*4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x;
normalBias = max(normalBias, 0.05);
vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0); vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0);
// perform perspective divide // perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;

View File

@ -24,11 +24,13 @@
<ClInclude Include="src\Animator.h" /> <ClInclude Include="src\Animator.h" />
<ClInclude Include="src\Bone.h" /> <ClInclude Include="src\Bone.h" />
<ClInclude Include="src\Camera.h" /> <ClInclude Include="src\Camera.h" />
<ClInclude Include="src\DemoWorld.h" />
<ClInclude Include="src\IblUtils.h" /> <ClInclude Include="src\IblUtils.h" />
<ClInclude Include="src\Light.h" /> <ClInclude Include="src\Light.h" />
<ClInclude Include="src\MainWindow.h" /> <ClInclude Include="src\MainWindow.h" />
<ClInclude Include="src\Mesh.h" /> <ClInclude Include="src\Mesh.h" />
<ClInclude Include="src\Model.h" /> <ClInclude Include="src\Model.h" />
<ClInclude Include="src\Particle.h" />
<ClInclude Include="src\RenderPass.h" /> <ClInclude Include="src\RenderPass.h" />
<ClInclude Include="src\Shader.h" /> <ClInclude Include="src\Shader.h" />
<ClInclude Include="src\World.h" /> <ClInclude Include="src\World.h" />
@ -39,6 +41,7 @@
<ClCompile Include="src\Animator.cpp" /> <ClCompile Include="src\Animator.cpp" />
<ClCompile Include="src\Bone.cpp" /> <ClCompile Include="src\Bone.cpp" />
<ClCompile Include="src\Camera.cpp" /> <ClCompile Include="src\Camera.cpp" />
<ClCompile Include="src\DemoWorld.cpp" />
<ClCompile Include="src\gl.c" /> <ClCompile Include="src\gl.c" />
<ClCompile Include="src\IblUtils.cpp" /> <ClCompile Include="src\IblUtils.cpp" />
<ClCompile Include="src\Light.cpp" /> <ClCompile Include="src\Light.cpp" />
@ -46,6 +49,7 @@
<ClCompile Include="src\MainWindow.cpp" /> <ClCompile Include="src\MainWindow.cpp" />
<ClCompile Include="src\Mesh.cpp" /> <ClCompile Include="src\Mesh.cpp" />
<ClCompile Include="src\Model.cpp" /> <ClCompile Include="src\Model.cpp" />
<ClCompile Include="src\Particle.cpp" />
<ClCompile Include="src\RenderPass.cpp" /> <ClCompile Include="src\RenderPass.cpp" />
<ClCompile Include="src\World.cpp" /> <ClCompile Include="src\World.cpp" />
</ItemGroup> </ItemGroup>
@ -163,6 +167,9 @@
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C> <LanguageStandard_C>stdc17</LanguageStandard_C>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
<Optimization>MaxSpeed</Optimization>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

View File

@ -57,6 +57,12 @@
<ClInclude Include="src\World.h"> <ClInclude Include="src\World.h">
<Filter>头文件</Filter> <Filter>头文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\Particle.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\DemoWorld.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\gl.c"> <ClCompile Include="src\gl.c">
@ -101,6 +107,12 @@
<ClCompile Include="src\World.cpp"> <ClCompile Include="src\World.cpp">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Particle.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\DemoWorld.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Shaders\brdf_lut.comp"> <None Include="Shaders\brdf_lut.comp">

View File

@ -1,17 +1,29 @@
#include "Actor.h" #include "Actor.h"
#include "MainWindow.h" #include "MainWindow.h"
Actor::Actor()
: gl(MainWindow::getGLContext())
, model(gl)
, animator(gl, animation.get())
{
}
Actor::Actor(const std::string& path) Actor::Actor(const std::string& path)
: gl(MainWindow::getGLContext()) : gl(MainWindow::getGLContext())
, model(gl, path) , model(gl, path)
, danceAnimation(path, &model) , animation(std::make_unique<Animation>(path, &model))
, animator(gl, &danceAnimation) , animator(gl, animation->available() ? animation.get() : nullptr)
{ {
} }
void Actor::tick(float deltaTime) void Actor::logicalTick(float deltaTime)
{ {
animator.UpdateAnimation(deltaTime); animator.updateAnimation(deltaTime);
}
void Actor::rendererTick(float deltaTime)
{
} }
void Actor::draw(Shader& shader) void Actor::draw(Shader& shader)
@ -39,6 +51,21 @@ void Actor::setRotaion(const glm::quat& rotation)
updateTransform(); updateTransform();
} }
glm::vec3 Actor::getPosition()
{
return position;
}
glm::vec3 Actor::getScale()
{
return scale;
}
glm::quat Actor::getRotation()
{
return rotation;
}
std::pair<glm::vec3, glm::vec3> Actor::getAABB() std::pair<glm::vec3, glm::vec3> Actor::getAABB()
{ {
return model.getAABB(); return model.getAABB();

View File

@ -7,21 +7,32 @@
class Actor class Actor
{ {
public: public:
Actor();
Actor(const std::string& path); Actor(const std::string& path);
void tick(float deltaTime); virtual ~Actor() = default;
void draw(Shader& shader); virtual void logicalTick(float deltaTime);
virtual void rendererTick(float deltaTime);
virtual void draw(Shader& shader);
void setPosition(const glm::vec3& position); void setPosition(const glm::vec3& position);
void setScale(const glm::vec3& scale); void setScale(const glm::vec3& scale);
void setRotaion(const glm::quat& rotation); void setRotaion(const glm::quat& rotation);
glm::vec3 getPosition();
glm::vec3 getScale();
glm::quat getRotation();
std::pair<glm::vec3, glm::vec3> getAABB(); std::pair<glm::vec3, glm::vec3> getAABB();
protected:
GladGLContext* gl;
Model model;
std::unique_ptr<Animation> animation;
Animator animator;
private: private:
void updateTransform(); void updateTransform();
GladGLContext* gl;
Model model;
Animation danceAnimation;
Animator animator;
glm::vec3 position = glm::vec3(0); glm::vec3 position = glm::vec3(0);
glm::vec3 scale = glm::vec3(1); glm::vec3 scale = glm::vec3(1);
glm::quat rotation = glm::quat(1, 0, 0, 0); glm::quat rotation = glm::quat(1, 0, 0, 0);

View File

@ -7,6 +7,7 @@
#include "Bone.h" #include "Bone.h"
#include "Model.h" #include "Model.h"
#include <functional> #include <functional>
#include <set>
struct AssimpNodeData struct AssimpNodeData
{ {
@ -41,16 +42,16 @@ public:
{ {
} }
bool available()
{
return m_TicksPerSecond;
}
Bone* FindBone(const std::string& name) Bone* FindBone(const std::string& name)
{ {
auto iter = std::find_if(m_Bones.begin(), m_Bones.end(), auto iter = m_Bones.find(name);
[&](const Bone& Bone)
{
return Bone.GetBoneName() == name;
}
);
if (iter == m_Bones.end()) return nullptr; if (iter == m_Bones.end()) return nullptr;
else return &(*iter); else return &iter->second;
} }
@ -81,7 +82,8 @@ private:
boneInfoMap[boneName].id = boneCount; boneInfoMap[boneName].id = boneCount;
boneCount++; boneCount++;
} }
m_Bones.push_back(Bone(channel->mNodeName.data,
m_Bones.emplace(std::piecewise_construct, std::forward_as_tuple(channel->mNodeName.data), std::forward_as_tuple(channel->mNodeName.data,
boneInfoMap[channel->mNodeName.data].id, channel)); boneInfoMap[channel->mNodeName.data].id, channel));
} }
@ -103,9 +105,11 @@ private:
dest.children.push_back(newData); dest.children.push_back(newData);
} }
} }
float m_Duration; float m_Duration = 0.f;
int m_TicksPerSecond; int m_TicksPerSecond = 0;
std::vector<Bone> m_Bones; std::unordered_map<std::string, Bone> m_Bones;
//std::set<Bone> m_Bones;
AssimpNodeData m_RootNode; AssimpNodeData m_RootNode;
std::map<std::string, BoneInfo> m_BoneInfoMap; std::map<std::string, BoneInfo> m_BoneInfoMap;
}; };

View File

@ -11,37 +11,43 @@ class Animator
public: public:
static constexpr GLint kMaxBone = 100; static constexpr GLint kMaxBone = 100;
Animator(GladGLContext* gl, Animation* animation) : gl(gl) Animator(GladGLContext* gl, Animation* animation)
: gl(gl)
{ {
currentTime = 0.0; playAnimation(animation);
currentAnimation = animation;
finalBoneMatrices.reserve(100);
for (int i = 0; i < 100; i++)
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 deltaTime) void updateAnimation(float deltaTime)
{ {
if (currentAnimation) if (currentAnimation)
{ {
currentTime += currentAnimation->GetTicksPerSecond() * deltaTime; currentTime += currentAnimation->GetTicksPerSecond() * deltaTime;
currentTime = fmod(currentTime, currentAnimation->GetDuration()); currentTime = fmod(currentTime, currentAnimation->GetDuration());
CalculateBoneTransform(&currentAnimation->GetRootNode(), glm::mat4(1.0f)); calculateBoneTransform(&currentAnimation->GetRootNode(), glm::mat4(1.0f));
} }
} }
void PlayAnimation(Animation* pAnimation) void playAnimation(Animation* pAnimation)
{ {
currentAnimation = pAnimation; currentAnimation = pAnimation;
currentTime = 0.0f; currentTime = 0.0f;
if (currentAnimation)
{
finalBoneMatrices.clear();
finalBoneMatrices.reserve(kMaxBone);
for (int i = 0; i < kMaxBone; i++)
finalBoneMatrices.push_back(glm::mat4(1.0f));
if (!finalBonesMatricesUBO)
{
gl->CreateBuffers(1, &finalBonesMatricesUBO);
gl->NamedBufferData(finalBonesMatricesUBO, sizeof(glm::mat4) * Animator::kMaxBone, nullptr, GL_DYNAMIC_DRAW);
}
}
} }
void CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform) void calculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform)
{ {
std::string nodeName = node->name; std::string nodeName = node->name;
glm::mat4 nodeTransform = node->transformation; glm::mat4 nodeTransform = node->transformation;
@ -56,33 +62,33 @@ public:
glm::mat4 globalTransformation = parentTransform * nodeTransform; glm::mat4 globalTransformation = parentTransform * nodeTransform;
auto boneInfoMap = currentAnimation->GetBoneIDMap(); auto& boneInfoMap = currentAnimation->GetBoneIDMap();
if (boneInfoMap.find(nodeName) != boneInfoMap.end()) if (auto iter = boneInfoMap.find(nodeName); iter != boneInfoMap.end())
{ {
int index = boneInfoMap[nodeName].id; auto& [index, offset] = iter->second;
glm::mat4 offset = boneInfoMap[nodeName].offset;
finalBoneMatrices[index] = globalTransformation * offset; finalBoneMatrices[index] = globalTransformation * offset;
} }
for (int i = 0; i < node->childrenCount; i++) for (int i = 0; i < node->childrenCount; i++)
CalculateBoneTransform(&node->children[i], globalTransformation); calculateBoneTransform(&node->children[i], globalTransformation);
} }
std::vector<glm::mat4> GetFinalBoneMatrices() std::vector<glm::mat4> getFinalBoneMatrices()
{ {
return finalBoneMatrices; return finalBoneMatrices;
} }
GLuint getFinalBonesMatricesUBO() GLuint getFinalBonesMatricesUBO()
{ {
gl->NamedBufferSubData(finalBonesMatricesUBO, 0, finalBoneMatrices.size() * sizeof(finalBoneMatrices[0]), finalBoneMatrices.data()); if (finalBonesMatricesUBO)
gl->NamedBufferSubData(finalBonesMatricesUBO, 0, finalBoneMatrices.size() * sizeof(finalBoneMatrices[0]), finalBoneMatrices.data());
return finalBonesMatricesUBO; return finalBonesMatricesUBO;
} }
private: private:
GladGLContext* gl; GladGLContext* gl;
std::vector<glm::mat4> finalBoneMatrices; std::vector<glm::mat4> finalBoneMatrices;
GLuint finalBonesMatricesUBO; GLuint finalBonesMatricesUBO = 0;
Animation* currentAnimation; Animation* currentAnimation = nullptr;
float currentTime; float currentTime;
}; };

View File

@ -114,6 +114,10 @@ public:
assert(0); assert(0);
} }
bool operator<(const Bone& e) const
{
return m_ID < e.m_ID;
}
private: private:

View File

@ -0,0 +1,33 @@
#include "DemoWorld.h"
#include "Particle.h"
DemoWorld::DemoWorld()
{
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)));
auto actor2 = std::make_shared<Actor>(modelFilePath);
actor2->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor2->setPosition({ 1,0,-1 });
auto actor3 = std::make_shared<Actor>(modelFilePath);
actor3->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor3->setPosition({ -1,0,-1 });
auto sponza = std::make_shared<Actor>("Models\\Sponza\\Sponza.gltf");
sponza->setScale(glm::vec3(2));
auto particle = std::make_shared<Particle>(10);
particle->setPosition({ 4, 5, 0 });
particle->addForce(glm::vec3(0, -particle->getMass() * 9.8f, 0));
addActor(actor);
addActor(actor2);
addActor(actor3);
addActor(sponza);
addActor(particle);
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "World.h"
class DemoWorld : public World
{
public:
DemoWorld();
};

View File

@ -2,6 +2,8 @@
#include "IblUtils.h" #include "IblUtils.h"
#include "RenderPass.h" #include "RenderPass.h"
#include "World.h" #include "World.h"
#include "Particle.h"
#include "DemoWorld.h"
MainWindow::MainWindow() MainWindow::MainWindow()
: camera(glm::vec3(0.0f, 0.0f, 3.0f)) : camera(glm::vec3(0.0f, 0.0f, 3.0f))
@ -50,39 +52,18 @@ int MainWindow::exec()
gl->DepthFunc(GL_LEQUAL); gl->DepthFunc(GL_LEQUAL);
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
std::string modelFilePath; std::unique_ptr<World> world = std::make_unique<DemoWorld>();
//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); auto [minPos, maxPos] = world->getAABB();
actor->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
auto actor2 = std::make_shared<Actor>(modelFilePath);
actor2->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor2->setPosition({ 1,0,-1 });
auto actor3 = std::make_shared<Actor>(modelFilePath);
actor3->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor3->setPosition({ -1,0,-1 });
auto sponza = std::make_shared<Actor>("Models\\Sponza\\Sponza.gltf");
sponza->setScale(glm::vec3(2));
World world;
world.addActor(actor);
world.addActor(actor2);
world.addActor(actor3);
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); std::cout << std::format("{},{},{} {},{},{}\n", minPos.x, minPos.y, minPos.z, maxPos.x, maxPos.y, maxPos.z);
light.sceneAABB = world.getAABB(); light.sceneAABB = world->getAABB();
glm::mat4 projection, view; glm::mat4 projection, view;
auto [skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture] = IblUtils::precomputeCubemaps(gl.get()); auto [skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture] = IblUtils::precomputeCubemaps(gl.get());
ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, world, light); ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, *world, light);
GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, world, projection, view); GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, *world, projection, view);
LightingPass lightingPass(gl.get(), frameWidth, frameHeight, view, camera, light, mainLightRadiance, LightingPass lightingPass(gl.get(), frameWidth, frameHeight, view, camera, light, mainLightRadiance,
gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture); gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
FinalPass finalPass(gl.get(), frameWidth, frameHeight, gbuffers, exposure); FinalPass finalPass(gl.get(), frameWidth, frameHeight, gbuffers, exposure);
@ -92,14 +73,35 @@ int MainWindow::exec()
glfwGetFramebufferSize(window, &w, &h); glfwGetFramebufferSize(window, &w, &h);
framebufferSizeCallback(window, w, h); framebufferSizeCallback(window, w, h);
int logicalTickCount = 0;
auto logicalThread = std::jthread([&](std::stop_token stop) {
using namespace std::chrono_literals;
constexpr auto targetDuration = 1666us;
auto sleepTime = 0ns;
auto lastTick = std::chrono::high_resolution_clock::now();
while (!stop.stop_requested())
{
auto currentTick = std::chrono::high_resolution_clock::now();
auto deltaTime = currentTick - lastTick;
double deltaTime_s = std::chrono::duration<double>(deltaTime).count();
lastTick = currentTick;
processInput(window, deltaTime_s);
world->logicalTick(deltaTime_s);
logicalTickCount++;
sleepTime = targetDuration - (deltaTime - sleepTime);
std::this_thread::sleep_for(sleepTime);
}
});
float lastFrame = glfwGetTime();
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
float currentFrame = glfwGetTime(); float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame; float deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame; lastFrame = currentFrame;
processInput(window);
world.tick(deltaTime); world->rendererTick(deltaTime);
projection = camera.getProjectionMatrix(); projection = camera.getProjectionMatrix();
view = camera.getViewMatrix(); view = camera.getViewMatrix();
@ -112,11 +114,24 @@ int MainWindow::exec()
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();
static float accTime = 0, frameCnt = 0;
accTime += deltaTime;
frameCnt++;
if (accTime > 1.)
{
std::cout << std::format("{:20}\r", "");
std::cout << std::format("FPS: {:.2f} TPS: {:.2f}\r", frameCnt / accTime, logicalTickCount / accTime);
accTime = 0;
frameCnt = 0;
logicalTickCount = 0;
}
} }
glfwTerminate(); glfwTerminate();
} }
void MainWindow::processInput(GLFWwindow* window)
void MainWindow::processInput(GLFWwindow* window, float deltaTime)
{ {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true); glfwSetWindowShouldClose(window, true);

View File

@ -18,7 +18,7 @@ private:
void framebufferSizeCallback(GLFWwindow* window, int width, int height); void framebufferSizeCallback(GLFWwindow* window, int width, int height);
void mouseCallback(GLFWwindow* window, double xpos, double ypos); void mouseCallback(GLFWwindow* window, double xpos, double ypos);
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset); void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow* window); void processInput(GLFWwindow* window, float deltaTime);
static constexpr int kWindowWidth = 1200; static constexpr int kWindowWidth = 1200;
static constexpr int kWindowHeight = 675; static constexpr int kWindowHeight = 675;
@ -27,11 +27,8 @@ private:
Camera camera; Camera camera;
Light light; Light light;
glm::vec3 mainLightRadiance = 40.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784)); glm::vec3 mainLightRadiance = 30.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784));
float exposure = 1; float exposure = 0.6f;
float deltaTime = 0.0f;
float lastFrame = 0.0f;
std::unique_ptr<GladGLContext> gl; std::unique_ptr<GladGLContext> gl;

View File

@ -1,9 +1,9 @@
#include "Mesh.h" #include "Mesh.h"
Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords) Vertex::Vertex(const glm::vec3& position, const glm::vec3& normal, const glm::vec2& texCoords)
: position(position.x, position.y, position.z) : position(position)
, normal(normal.x, normal.y, normal.z) , normal(normal)
, texCoords(texCoords.x, texCoords.y) , texCoords(texCoords)
{ {
for (std::size_t i = 0; i < kMaxBoneInfluence; i++) for (std::size_t i = 0; i < kMaxBoneInfluence; i++)
{ {
@ -12,6 +12,11 @@ Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVec
} }
} }
Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords)
: Vertex({position.x, position.y, position.z}, {normal.x, normal.y, normal.z}, {texCoords.x, texCoords.y})
{
}
void Vertex::setBoneData(int boneID, float weight) void Vertex::setBoneData(int boneID, float weight)
{ {
if (weight == 0) return; if (weight == 0) return;
@ -43,29 +48,12 @@ void Mesh::draw(Shader& shader)
shader.setUniformValue("baseColor", baseColor); shader.setUniformValue("baseColor", baseColor);
shader.setUniformValue("metallicRoughness", metallicRoughness); shader.setUniformValue("metallicRoughness", metallicRoughness);
gl->BindVertexArray(VAO); gl->BindVertexArray(VAO);
gl->DrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); gl->DrawElements(drawMode, indices.size(), GL_UNSIGNED_INT, 0);
gl->BindVertexArray(0); gl->BindVertexArray(0);
} }
void Mesh::setupMesh() void Mesh::setupMesh()
{ {
//for (auto& v : vertices)
//{
// if (v.boneIDs[0] == 6 && v.boneIDs[1] == 14 && v.boneIDs[2] == 18 && v.boneIDs[3] == 22)
// {
// v.boneIDs[0] = -1;
// v.boneIDs[1] = -1;
// v.boneIDs[2] = -1;
// v.boneIDs[3] = -1;
// }
// for (int i = 0; i < kMaxBoneInfluence; i++)
// {
// std::cout << v.boneIDs[i] << " ";
// }
// std::cout << std::endl;
//}
gl->GenVertexArrays(1, &VAO); gl->GenVertexArrays(1, &VAO);
gl->GenBuffers(1, &VBO); gl->GenBuffers(1, &VBO);
gl->GenBuffers(1, &EBO); gl->GenBuffers(1, &EBO);
@ -76,7 +64,6 @@ void Mesh::setupMesh()
gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
gl->BufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); gl->BufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
enum VertexAttribute : GLuint { enum VertexAttribute : GLuint {
kPosition = 0, kNormal = 1, kTexCoords = 2, kBoneIDs = 3, kBoneWeights = 4 kPosition = 0, kNormal = 1, kTexCoords = 2, kBoneIDs = 3, kBoneWeights = 4
}; };

View File

@ -16,6 +16,7 @@ struct Vertex {
int boneIDs[kMaxBoneInfluence]; int boneIDs[kMaxBoneInfluence];
float boneWeights[kMaxBoneInfluence]; float boneWeights[kMaxBoneInfluence];
Vertex(const glm::vec3& position, const glm::vec3& normal, const glm::vec2& texCoords);
Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords); Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords);
void setBoneData(int boneID, float weight); void setBoneData(int boneID, float weight);
}; };
@ -25,6 +26,7 @@ public:
glm::mat4 model; glm::mat4 model;
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
GLenum drawMode = GL_TRIANGLES;
GLuint textureBasecolor = 0; GLuint textureBasecolor = 0;
GLuint textureMetallicRoughness = 0; GLuint textureMetallicRoughness = 0;
GLuint textureNormal = 0; GLuint textureNormal = 0;
@ -32,12 +34,10 @@ public:
glm::vec2 metallicRoughness; glm::vec2 metallicRoughness;
unsigned int VAO; unsigned int VAO;
Mesh(GladGLContext* gl, const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices, const glm::mat4& model); Mesh(GladGLContext* gl, const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices, const glm::mat4& model = glm::mat4(1));
void draw(Shader& shader); void draw(Shader& shader);
void setupMesh(); void setupMesh();
private: private:
GladGLContext* gl; GladGLContext* gl;
unsigned int VBO, EBO; unsigned int VBO, EBO;
}; };

View File

@ -1,13 +1,76 @@
#include "Model.h" #include "Model.h"
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/ext/scalar_constants.hpp>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <stb_image.h> #include <stb_image.h>
Model::Model(GladGLContext* gl, std::string const& path) Model Model::createSphere(GladGLContext* gl, const glm::vec3& baseColor, const glm::vec2& metallicRoughness)
{
Model sphere(gl);
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
constexpr unsigned int kXSegments = 64;
constexpr unsigned int kYSegments = 64;
for (unsigned int x = 0; x <= kXSegments; ++x)
{
for (unsigned int y = 0; y <= kYSegments; ++y)
{
float xSegment = (float)x / (float)kXSegments;
float ySegment = (float)y / (float)kYSegments;
constexpr auto PI = glm::pi<float>();
float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
float yPos = std::cos(ySegment * PI);
float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
vertices.emplace_back(glm::vec3(xPos, yPos, zPos), glm::vec3(xPos, yPos, zPos), glm::vec2(xSegment, ySegment));
}
}
bool oddRow = false;
for (unsigned int y = 0; y < kYSegments; ++y)
{
if (!oddRow) // even rows: y == 0, y == 2; and so on
{
for (unsigned int x = 0; x <= kXSegments; ++x)
{
indices.push_back(y * (kXSegments + 1) + x);
indices.push_back((y + 1) * (kXSegments + 1) + x);
}
}
else
{
for (int x = kXSegments; x >= 0; --x)
{
indices.push_back((y + 1) * (kXSegments + 1) + x);
indices.push_back(y * (kXSegments + 1) + x);
}
}
oddRow = !oddRow;
}
auto mesh = std::make_unique<Mesh>(gl, vertices, indices);
mesh->drawMode = GL_TRIANGLE_STRIP;
mesh->baseColor = baseColor;
mesh->metallicRoughness = metallicRoughness;
sphere.meshes.emplace_back(std::move(mesh));
return sphere;
}
Model::Model(GladGLContext* gl)
: gl(gl) : gl(gl)
{
}
Model::Model(GladGLContext* gl, std::string const& path)
: Model(gl)
{ {
loadModel(path); loadModel(path);
} }

View File

@ -26,6 +26,8 @@ public:
std::map<std::string, BoneInfo> boneInfoMap; std::map<std::string, BoneInfo> boneInfoMap;
int boneCount = 0; int boneCount = 0;
static Model createSphere(GladGLContext* gl, const glm::vec3& baseColor = glm::vec3(0.5, 0, 0), const glm::vec2& metallicRoughness = glm::vec2(0, 0.5));
Model(GladGLContext* gl);
Model(GladGLContext* gl, std::string const& path); Model(GladGLContext* gl, std::string const& path);
void draw(Shader& shader); void draw(Shader& shader);
void setTransform(const glm::mat4& trans); void setTransform(const glm::mat4& trans);

View File

@ -0,0 +1,31 @@
#include "Particle.h"
Particle::Particle(float mass)
: Actor()
, mass(mass)
{
model = Model::createSphere(gl);
setScale(glm::vec3(0.5));
}
void Particle::logicalTick(float deltaTime)
{
auto pos = getPosition() + speed * deltaTime + 0.5f * resultantForce / mass * deltaTime * deltaTime;
speed += resultantForce / mass * deltaTime;
if (speed.y < 0 && pos.y < 0.5)
{
speed.y = -speed.y;
}
setPosition(pos);
}
void Particle::addForce(glm::vec3 force)
{
forces.push_back(force);
resultantForce += force;
}
float Particle::getMass()
{
return mass;
}

18
ToyEngine/src/Particle.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "Actor.h"
class Particle : public Actor
{
public:
Particle(float mass);
virtual ~Particle() = default;
virtual void logicalTick(float deltaTime);
void addForce(glm::vec3 force);
float getMass();
private:
float mass;
glm::vec3 speed = glm::vec3(0.f);
std::vector<glm::vec3> forces;
glm::vec3 resultantForce = glm::vec3(0);
};

View File

@ -73,7 +73,7 @@ void GeometryPass::dispatch()
glm::mat4 trans = glm::mat4(1.0f); glm::mat4 trans = glm::mat4(1.0f);
trans = glm::translate(trans, glm::vec3( trans = glm::translate(trans, glm::vec3(
(float)(col - (nrColumns / 2)) * spacing, (float)(col - (nrColumns / 2)) * spacing,
(float)(row - (nrRows / 2)) * spacing, (float)(row - (nrRows / 2)) * spacing + 5,
-2.0f -2.0f
)); ));
plainShader.setUniformValue("model", trans); plainShader.setUniformValue("model", trans);

View File

@ -1,9 +1,15 @@
#include "World.h" #include "World.h"
void World::tick(float deltaTime) void World::logicalTick(float deltaTime)
{ {
for (auto& actor : actors) for (auto& actor : actors)
actor->tick(deltaTime); actor->logicalTick(deltaTime);
}
void World::rendererTick(float deltaTime)
{
for (auto& actor : actors)
actor->rendererTick(deltaTime);
} }
void World::draw(Shader& shader) void World::draw(Shader& shader)
@ -28,4 +34,4 @@ std::pair<glm::vec3, glm::vec3> World::getAABB()
maxPos = glm::max(maxPos, max); maxPos = glm::max(maxPos, max);
} }
return { minPos, maxPos }; return { minPos, maxPos };
} }

View File

@ -5,7 +5,8 @@ class World
{ {
public: public:
std::vector<std::shared_ptr<Actor>> actors; std::vector<std::shared_ptr<Actor>> actors;
void tick(float deltaTime); virtual void logicalTick(float deltaTime);
virtual void rendererTick(float deltaTime);
void draw(Shader& shader); void draw(Shader& shader);
void addActor(std::shared_ptr<Actor> actor); void addActor(std::shared_ptr<Actor> actor);
std::pair<glm::vec3, glm::vec3> getAABB(); std::pair<glm::vec3, glm::vec3> getAABB();