Merge branch 'master' into Importer
# Conflicts: # src/Engine/Collision/Collision.cpp # src/Engine/Collision/CollisionSystem.cpp # src/Engine/Rendering/DrawFinalPass.cpp # src/Game/Systems/SpawnerSystem.cpp
This commit is contained in:
@@ -1,71 +1,355 @@
|
||||
#include "Rendering/AnimationSystem.h"
|
||||
|
||||
void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt)
|
||||
AnimationSystem::AnimationSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
if(!entity.HasComponent("Model")) {
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &AnimationSystem::OnEntityDeleted);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ESetBlendWeight, &AnimationSystem::OnSetBlendWeight);
|
||||
}
|
||||
|
||||
void AnimationSystem::Update(double dt)
|
||||
{
|
||||
UpdateAnimations(dt);
|
||||
CreateBlendTrees();
|
||||
UpdateWeights(dt);
|
||||
|
||||
|
||||
for(auto& autoBlendQueue : m_AutoBlendQueues) {
|
||||
autoBlendQueue.second.UpdateTime(dt);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationSystem::CreateBlendTrees()
|
||||
{
|
||||
auto modelComponents = m_World->GetComponents("Model");
|
||||
if (modelComponents == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& modelC : *modelComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, modelC.EntityID);
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
continue;;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity.HasComponent("Blend") || entity.HasComponent("BlendOverride") ||
|
||||
entity.HasComponent("BlendAdditive") || entity.HasComponent("Animation"))
|
||||
{
|
||||
std::shared_ptr<BlendTree> blendTree = std::shared_ptr<BlendTree>(new BlendTree(entity, skeleton));
|
||||
|
||||
if(blendTree->IsValid()) {
|
||||
skeleton->BlendTrees[entity] = blendTree;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationSystem::UpdateAnimations(double dt)
|
||||
{
|
||||
auto animationComponents = m_World->GetComponents("Animation");
|
||||
if(animationComponents == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& animationC : *animationComponents) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, animationC.EntityID);
|
||||
EntityWrapper modelEntity;
|
||||
if(!entity.HasComponent("Model")) {
|
||||
modelEntity = entity.FirstParentWithComponent("Model");
|
||||
} else {
|
||||
modelEntity = entity;
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
Field<std::string> res = modelEntity["Model"]["Resource"];
|
||||
model = ResourceManager::Load<::Model, true>(res);
|
||||
} catch (const std::exception&) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation(animationC["AnimationName"]);
|
||||
|
||||
if (animation == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double animationSpeed = (const double&)animationC["Speed"];
|
||||
|
||||
if((const bool&)animationC["Reverse"]) {
|
||||
animationSpeed *= -1;
|
||||
}
|
||||
|
||||
|
||||
if ((const bool&)animationC["Play"]) {
|
||||
|
||||
double nextTime = (Field<double>)animationC["Time"] + animationSpeed * dt;
|
||||
if (!(Field<bool>)animationC["Loop"]) {
|
||||
if (nextTime > animation->Duration) {
|
||||
nextTime = animation->Duration;
|
||||
(Field<bool>)animationC["Play"] = false;
|
||||
} else if (nextTime < 0) {
|
||||
nextTime = 0;
|
||||
(Field<bool>)animationC["Play"] = false;
|
||||
}
|
||||
} else {
|
||||
if (nextTime > animation->Duration) {
|
||||
|
||||
while (nextTime > animation->Duration) {
|
||||
nextTime -= animation->Duration;
|
||||
}
|
||||
} else if (nextTime < 0) {
|
||||
while (nextTime < 0) {
|
||||
nextTime += animation->Duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
(Field<double>)animationC["Time"] = nextTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationSystem::UpdateWeights(double dt)
|
||||
{
|
||||
for (auto it = m_AutoBlendQueues.begin(); it != m_AutoBlendQueues.end(); ) {
|
||||
//LOG_INFO("%s", it->first.Name().c_str());
|
||||
//it->second.PrintQueue();
|
||||
|
||||
if(it->second.HasActiveBlendJob()) {
|
||||
AutoBlendQueue::AutoBlendJob& blendJob = it->second.GetActiveBlendJob();
|
||||
//LOG_INFO("%s", blendJob.RootNode.Name().c_str());
|
||||
std::shared_ptr<BlendTree> blendTree = it->second.GetBlendTree();
|
||||
if (blendTree != nullptr) {
|
||||
if (blendJob.Duration != 0.0) {
|
||||
blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0);
|
||||
} else {
|
||||
blendJob.BlendInfo.progress = 1.0;
|
||||
}
|
||||
|
||||
blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo);
|
||||
} else {
|
||||
it = m_AutoBlendQueues.erase(it);
|
||||
}
|
||||
it++;
|
||||
} else {
|
||||
if (it->second.Empty()) {
|
||||
it = m_AutoBlendQueues.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e)
|
||||
{
|
||||
if (!e.RootNode.Valid()) {
|
||||
LOG_ERROR("%s, RootNode invalid %s", e.NodeName, e.RootNode.Name().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!e.RootNode.HasComponent("Model")) {
|
||||
LOG_ERROR("%s, RootNode has no model %s", e.NodeName, e.RootNode.Name().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]);
|
||||
model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return;
|
||||
LOG_ERROR("%s, RootNode model not finished loading %s", e.NodeName, e.RootNode.Name().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if(skeleton == nullptr) {
|
||||
return;
|
||||
if (skeleton == nullptr) {
|
||||
LOG_ERROR("%s, RootNode skeleton invalid %s", e.NodeName, e.RootNode.Name().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]);
|
||||
std::shared_ptr<BlendTree> blendTree;
|
||||
if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) {
|
||||
blendTree = skeleton->BlendTrees.at(e.RootNode);
|
||||
} else {
|
||||
LOG_ERROR("%s, No blendtree was found invalid %s", e.NodeName, e.RootNode.Name().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (animation == nullptr) {
|
||||
continue;;
|
||||
EntityWrapper subTreeRoot;
|
||||
|
||||
|
||||
if (e.SingleLevelBlend) {
|
||||
subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName);
|
||||
|
||||
if (!subTreeRoot.Valid()) {
|
||||
LOG_ERROR("%s, subTreeRoot invalid", e.NodeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)];
|
||||
AutoBlendQueue::AutoBlendJob abj;
|
||||
abj.AnimationEntity = e.AnimationEntity;
|
||||
abj.CurrentTime = 0.0;
|
||||
abj.Delay = e.Delay;
|
||||
abj.Duration = e.Duration;
|
||||
abj.RootNode = e.RootNode;
|
||||
|
||||
if (animationSpeed != 0.0) {
|
||||
double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt;
|
||||
abj.BlendInfo.NodeName = e.NodeName;
|
||||
abj.BlendInfo.progress = 0.0;
|
||||
abj.BlendInfo.Start = e.Start;
|
||||
abj.BlendInfo.SingleBlend = e.SingleLevelBlend;
|
||||
abj.BlendInfo.Weight = e.Weight;
|
||||
|
||||
std::vector<EntityWrapper> animationEntities = blendTree->GetEntitesByName(e.NodeName); // more than one
|
||||
for(auto entity : animationEntities)
|
||||
if (entity.Valid()) {
|
||||
if (entity.HasComponent("Animation")) {
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]);
|
||||
(Field<bool>)entity["Animation"]["Reverse"] = e.Reverse;
|
||||
|
||||
if (!(bool)animationComponent["Loop" + std::to_string(i)]) {
|
||||
if (nextTime > animation->Duration) {
|
||||
nextTime = animation->Duration;
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
} else if (nextTime < 0) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
nextTime = 0;
|
||||
}
|
||||
|
||||
(double&)animationComponent["Speed" + std::to_string(i)] = 0.0;
|
||||
|
||||
} else {
|
||||
if (nextTime > animation->Duration) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
nextTime -= animation->Duration;
|
||||
} else if (nextTime < 0) {
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
|
||||
m_EventBroker->Publish(e);
|
||||
nextTime += animation->Duration;
|
||||
if (e.Restart) {
|
||||
if (animation != nullptr) {
|
||||
if (e.Restart) {
|
||||
if (e.Reverse) {
|
||||
(Field<double>)entity["Animation"]["Time"] = animation->Duration;
|
||||
} else {
|
||||
(Field<double>)entity["Animation"]["Time"] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(double&)animationComponent["Time" + std::to_string(i)] = nextTime;
|
||||
}
|
||||
}
|
||||
m_AutoBlendQueues[subTreeRoot].Insert(abj);
|
||||
} else {
|
||||
std::vector<EntityWrapper> subtreeroots = blendTree->GetSingleLevelRoots(e.NodeName);
|
||||
|
||||
for(auto entity : subtreeroots) {
|
||||
subTreeRoot = entity;
|
||||
|
||||
if (!subTreeRoot.Valid()) {
|
||||
LOG_ERROR("%s, subTreeRoot invalid", e.NodeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoBlendQueue::AutoBlendJob abj;
|
||||
abj.AnimationEntity = e.AnimationEntity;
|
||||
abj.CurrentTime = 0.0;
|
||||
abj.Delay = e.Delay;
|
||||
abj.Duration = e.Duration;
|
||||
abj.RootNode = e.RootNode;
|
||||
|
||||
abj.BlendInfo.NodeName = e.NodeName;
|
||||
abj.BlendInfo.progress = 0.0;
|
||||
abj.BlendInfo.Start = e.Start;
|
||||
abj.BlendInfo.SingleBlend = e.SingleLevelBlend;
|
||||
abj.BlendInfo.Weight = e.Weight;
|
||||
m_AutoBlendQueues[subTreeRoot].Insert(abj);
|
||||
}
|
||||
|
||||
std::vector<EntityWrapper> animationEntities = blendTree->GetEntitesByName(e.NodeName); // more than one
|
||||
for (auto entity : animationEntities)
|
||||
if (entity.Valid()) {
|
||||
if (entity.HasComponent("Animation")) {
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation(entity["Animation"]["AnimationName"]);
|
||||
entity["Animation"]["Reverse"] = e.Reverse;
|
||||
|
||||
if (e.Restart) {
|
||||
if (animation != nullptr) {
|
||||
if (e.Restart) {
|
||||
if (e.Reverse) {
|
||||
entity["Animation"]["Time"] = animation->Duration;
|
||||
} else {
|
||||
entity["Animation"]["Time"] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AnimationSystem::OnEntityDeleted(Events::EntityDeleted& e)
|
||||
{
|
||||
EntityWrapper entity = e.DeletedEntity;
|
||||
|
||||
if (entity.HasComponent("Model")) {
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skeleton->BlendTrees.find(entity) != skeleton->BlendTrees.end()) {
|
||||
skeleton->BlendTrees.erase(entity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool AnimationSystem::OnSetBlendWeight(Events::SetBlendWeight& e)
|
||||
{
|
||||
if (!e.RootNode.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!e.RootNode.HasComponent("Model")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<BlendTree> blendTree;
|
||||
if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) {
|
||||
blendTree = skeleton->BlendTrees.at(e.RootNode);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(e.Weight >= 0 && e.Weight <= 1) {
|
||||
|
||||
blendTree->SetWeightByName(e.NodeName, e.Weight);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
#include "Rendering/AutoBlendQueue.h"
|
||||
|
||||
void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob)
|
||||
{
|
||||
if(!autoBlendJob.RootNode.HasComponent("Model")) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoblendNode blendNode;
|
||||
blendNode.BlendJob = autoBlendJob;
|
||||
blendNode.StartTime = autoBlendJob.Delay;
|
||||
blendNode.EndTime = autoBlendJob.Delay + autoBlendJob.Duration;
|
||||
|
||||
|
||||
|
||||
if (autoBlendJob.AnimationEntity.Valid()) {
|
||||
if (autoBlendJob.AnimationEntity.HasComponent("Animation")) {
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>((std::string)autoBlendJob.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation((std::string)autoBlendJob.AnimationEntity["Animation"]["AnimationName"]);
|
||||
|
||||
if (animation == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
double AnimationDuration = 0.0;
|
||||
|
||||
double animationSpeed = (double)autoBlendJob.AnimationEntity["Animation"]["Speed"];
|
||||
double animationTime = (double)autoBlendJob.AnimationEntity["Animation"]["Time"];
|
||||
|
||||
if (animationSpeed != 0) {
|
||||
if ((bool)autoBlendJob.AnimationEntity["Animation"]["Reverse"]) {
|
||||
AnimationDuration = (animation->Duration / animationSpeed) - (animation->Duration - animationTime);
|
||||
} else {
|
||||
AnimationDuration = (animation->Duration / animationSpeed) - animationTime;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
blendNode.StartTime += AnimationDuration;
|
||||
blendNode.EndTime += AnimationDuration;
|
||||
if (m_BlendQueue.size() == 0) {
|
||||
m_BlendQueue.push_back(blendNode);
|
||||
} else {
|
||||
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
|
||||
if (it->BlendJob.BlendInfo.NodeName == autoBlendJob.BlendInfo.NodeName) {
|
||||
(*it) = blendNode;
|
||||
}
|
||||
|
||||
if (next != m_BlendQueue.end()) {
|
||||
if (it->StartTime >= blendNode.StartTime && next->StartTime <= blendNode.StartTime) {
|
||||
m_BlendQueue.insert(next, blendNode);
|
||||
return;
|
||||
}
|
||||
} else if(it->StartTime > blendNode.StartTime){
|
||||
m_BlendQueue.push_front(blendNode);
|
||||
return;
|
||||
} else if (it->StartTime <= blendNode.StartTime) {
|
||||
m_BlendQueue.push_back(blendNode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_BlendQueue.clear();
|
||||
m_BlendQueue.push_back(blendNode);
|
||||
}
|
||||
|
||||
void AutoBlendQueue::UpdateTime(double dt)
|
||||
{
|
||||
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end();) {
|
||||
if (it->EndTime <= 0) {
|
||||
it = m_BlendQueue.erase(it);
|
||||
} else {
|
||||
it->EndTime -= dt;
|
||||
it->StartTime -= dt;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AutoBlendQueue::PrintQueue()
|
||||
{
|
||||
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) {
|
||||
LOG_INFO("Start: %f End: %f \t %s", it->StartTime, it->EndTime, it->BlendJob.BlendInfo.NodeName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AutoBlendQueue::HasActiveBlendJob()
|
||||
{
|
||||
if(m_BlendQueue.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
AutoblendNode blendNode = m_BlendQueue.front();
|
||||
if (blendNode.StartTime <= 0) {
|
||||
AutoBlendJob blendJob = blendNode.BlendJob;
|
||||
|
||||
if (!blendJob.RootNode.Valid()) {
|
||||
m_BlendQueue.pop_front();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!blendJob.RootNode.HasComponent("Model")) {
|
||||
m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
//m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
|
||||
if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) {
|
||||
return true;
|
||||
} else {
|
||||
m_BlendQueue.pop_front();
|
||||
return HasActiveBlendJob();
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<BlendTree> AutoBlendQueue::GetBlendTree()
|
||||
{
|
||||
AutoblendNode blendNode = m_BlendQueue.front();
|
||||
AutoBlendJob blendJob = blendNode.BlendJob;
|
||||
|
||||
if (!blendJob.RootNode.Valid()) {
|
||||
m_BlendQueue.pop_front();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!blendJob.RootNode.HasComponent("Model")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
if (skeleton == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) {
|
||||
return skeleton->BlendTrees.at(blendJob.RootNode);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
AutoBlendQueue::AutoBlendJob& AutoBlendQueue::GetActiveBlendJob()
|
||||
{
|
||||
AutoblendNode& blendNode = m_BlendQueue.front();
|
||||
blendNode.BlendJob.CurrentTime = -blendNode.StartTime;
|
||||
return blendNode.BlendJob;
|
||||
}
|
||||
@@ -0,0 +1,546 @@
|
||||
#include "Rendering/BlendTree.h"
|
||||
|
||||
BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
|
||||
{
|
||||
m_Skeleton = skeleton;
|
||||
|
||||
if (ModelEntity.HasComponent("Animation")) {
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation(ModelEntity["Animation"]["AnimationName"]);
|
||||
if (animation == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Root = new Node();
|
||||
m_Root->Entity = ModelEntity;
|
||||
m_Root->Name = ModelEntity.Name();
|
||||
m_Root->Pose = m_Skeleton->GetFrameBones(animation, (const double&)ModelEntity["Animation"]["Time"], (const bool&)ModelEntity["Animation"]["Additive"]);
|
||||
m_Root->Parent = nullptr;
|
||||
m_Root->Type = NodeType::Animation;
|
||||
|
||||
} else if (ModelEntity.HasComponent("Blend")) {
|
||||
m_Root = new Node();
|
||||
m_Root->Entity = ModelEntity;
|
||||
m_Root->Name = ModelEntity.Name();
|
||||
m_Root->Parent = nullptr;
|
||||
m_Root->Type = NodeType::Blend;
|
||||
m_Root->Weight = (const double&)ModelEntity["Blend"]["Weight"];
|
||||
m_Root->SubTreeRoot = (const bool&)ModelEntity["Blend"]["SubTreeRoot"];
|
||||
ModelEntity["Blend"]["Weight"] = glm::clamp((const double&)ModelEntity["Blend"]["Weight"], 0.0, 1.0);
|
||||
m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose1"], ModelEntity);
|
||||
m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose2"], ModelEntity);
|
||||
|
||||
} else if (ModelEntity.HasComponent("BlendOverride")) {
|
||||
m_Root = new Node();
|
||||
m_Root->Entity = ModelEntity;
|
||||
m_Root->Name = ModelEntity.Name();
|
||||
m_Root->Parent = nullptr;
|
||||
m_Root->Type = NodeType::Override;
|
||||
m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Master"], ModelEntity);
|
||||
m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Slave"], ModelEntity);
|
||||
|
||||
} else if (ModelEntity.HasComponent("BlendAdditive")) {
|
||||
m_Root = new Node();
|
||||
m_Root->Entity = ModelEntity;
|
||||
m_Root->Name = ModelEntity.Name();
|
||||
m_Root->Parent = nullptr;
|
||||
m_Root->Type = NodeType::Additive;
|
||||
m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Adder"], ModelEntity);
|
||||
m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Receiver"], ModelEntity);
|
||||
}
|
||||
|
||||
m_FinalPose = AccumulateFinalPose();
|
||||
// PrintTree();
|
||||
}
|
||||
|
||||
BlendTree::~BlendTree()
|
||||
{
|
||||
Node* currentNode = m_Root;
|
||||
if (currentNode != nullptr) {
|
||||
while (currentNode->Child[0] != nullptr) {
|
||||
currentNode = currentNode->Child[0];
|
||||
}
|
||||
|
||||
std::list<Node*> m_NodesToRemove;
|
||||
|
||||
while (currentNode != nullptr) {
|
||||
m_NodesToRemove.push_back(currentNode);
|
||||
currentNode = currentNode->Next();
|
||||
}
|
||||
|
||||
for (auto it = m_NodesToRemove.begin(); it != m_NodesToRemove.end(); it++) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 BlendTree::GetBoneTransform(int boneID)
|
||||
{
|
||||
if(m_FinalBoneTransforms.find(boneID) != m_FinalBoneTransforms.end()) {
|
||||
return m_FinalBoneTransforms.at(boneID);
|
||||
} else {
|
||||
return glm::mat4(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BlendTree::PrintTree()
|
||||
{
|
||||
Node* currentNode = m_Root;
|
||||
LOG_INFO("\n\n");
|
||||
|
||||
while(currentNode->Child[0] != nullptr) {
|
||||
currentNode = currentNode->Child[0];
|
||||
}
|
||||
|
||||
while (currentNode != nullptr)
|
||||
{
|
||||
LOG_INFO("%s", currentNode->Name.c_str());
|
||||
currentNode = currentNode->Next();
|
||||
}
|
||||
}
|
||||
|
||||
BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity)
|
||||
{
|
||||
EntityWrapper childEntity = parentEntity.FirstLevelChildByName(name); // Make first level child by name
|
||||
|
||||
if (!childEntity.Valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (childEntity.HasComponent("Animation")) {
|
||||
const Skeleton::Animation* animation = m_Skeleton->GetAnimation(childEntity["Animation"]["AnimationName"]);
|
||||
if (animation == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node* node = new Node();
|
||||
node->Entity = childEntity;
|
||||
node->Name = childEntity.Name();
|
||||
node->Pose = m_Skeleton->GetFrameBones(animation, (const double&)childEntity["Animation"]["Time"], (const bool&)childEntity["Animation"]["Additive"]);
|
||||
node->Parent = parentNode;
|
||||
node->Type = NodeType::Animation;
|
||||
return node;
|
||||
|
||||
} else if (childEntity.HasComponent("Blend")) {
|
||||
Node* node = new Node();
|
||||
node->Entity = childEntity;
|
||||
node->Name = childEntity.Name();
|
||||
node->Parent = parentNode;
|
||||
node->Type = NodeType::Blend;
|
||||
childEntity["Blend"]["Weight"] = glm::clamp((const double&)childEntity["Blend"]["Weight"], 0.0, 1.0);
|
||||
node->Weight = (const double&)childEntity["Blend"]["Weight"];
|
||||
node->SubTreeRoot = (const bool&)childEntity["Blend"]["SubTreeRoot"];
|
||||
//if (node->Weight < 1.f && node->Weight > 0.f) {
|
||||
node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity);
|
||||
node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity);
|
||||
/* } else if (node->Weight == 1.f) {
|
||||
node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity);
|
||||
} else if (node->Weight == 0.f) {
|
||||
node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity);
|
||||
}*/
|
||||
|
||||
if(node->Child[0] == nullptr && node->Child[1] == nullptr) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
|
||||
} else if (childEntity.HasComponent("BlendOverride")) {
|
||||
Node* node = new Node();
|
||||
node->Entity = childEntity;
|
||||
node->Name = childEntity.Name();
|
||||
node->Parent = parentNode;
|
||||
node->Type = NodeType::Override;
|
||||
node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Master"], childEntity);
|
||||
node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Slave"], childEntity);
|
||||
|
||||
if (node->Child[0] == nullptr && node->Child[1] == nullptr) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
} else if (childEntity.HasComponent("BlendAdditive")) {
|
||||
Node* node = new Node();
|
||||
node->Entity = childEntity;
|
||||
node->Name = childEntity.Name();
|
||||
node->Parent = parentNode;
|
||||
node->Type = NodeType::Additive;
|
||||
node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Adder"], childEntity);
|
||||
node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Receiver"], childEntity);
|
||||
|
||||
if(node->Child[0] == nullptr && node->Child[1] == nullptr) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
std::vector<BlendTree::Node*> BlendTree::FindNodesByName(std::string name)
|
||||
{
|
||||
std::vector<Node*> Nodes;
|
||||
Node* currentNode = m_Root;
|
||||
|
||||
while (currentNode->Child[0] != nullptr) {
|
||||
currentNode = currentNode->Child[0];
|
||||
}
|
||||
|
||||
while (currentNode != nullptr) {
|
||||
if(currentNode->Name == name) {
|
||||
Nodes.push_back(currentNode);
|
||||
}
|
||||
currentNode = currentNode->Next();
|
||||
}
|
||||
return Nodes;
|
||||
}
|
||||
|
||||
|
||||
BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
|
||||
{
|
||||
std::vector<Node*> goalNodes = FindNodesByName(blendInfo.NodeName);
|
||||
|
||||
if(blendInfo.Weight >= 0 && blendInfo.Weight <= 1.0) {
|
||||
for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) {
|
||||
EntityWrapper entity = (*it)->Entity;
|
||||
|
||||
if (entity.Valid()) {
|
||||
if (entity.HasComponent("Blend")) {
|
||||
entity["Blend"]["Weight"] = blendInfo.Weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
return blendInfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (blendInfo.Start) {
|
||||
for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) {
|
||||
EntityWrapper entity = (*it)->Entity;
|
||||
|
||||
if (entity.Valid()) {
|
||||
if (entity.HasComponent("Animation")) {
|
||||
entity["Animation"]["Play"] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(goalNodes.size() == 0) {
|
||||
return blendInfo;
|
||||
} else if(goalNodes.size() == 1) {
|
||||
Node* currentNode = goalNodes[0]->Parent;
|
||||
Node* lastNode = goalNodes[0];
|
||||
|
||||
while (currentNode != nullptr)
|
||||
{
|
||||
if(!currentNode->Entity.HasComponent("Blend")) {
|
||||
return blendInfo;
|
||||
}
|
||||
|
||||
double startWeight;
|
||||
if(blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) {
|
||||
startWeight = blendInfo.StartWeights.at(currentNode->Entity);
|
||||
} else {
|
||||
startWeight = currentNode->Weight;
|
||||
blendInfo.StartWeights[currentNode->Entity] = startWeight;
|
||||
}
|
||||
|
||||
double goalWeight;
|
||||
if(currentNode->Child[0] == lastNode) {
|
||||
goalWeight = 0.0;
|
||||
} else if (currentNode->Child[1] == lastNode) {
|
||||
goalWeight = 1.0;
|
||||
}
|
||||
|
||||
double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight;
|
||||
currentNode->Entity["Blend"]["Weight"] = weight;
|
||||
currentNode->Weight = weight;
|
||||
|
||||
lastNode = currentNode;
|
||||
currentNode = currentNode->Parent;
|
||||
|
||||
if (blendInfo.SingleBlend) {
|
||||
return blendInfo;;
|
||||
}
|
||||
}
|
||||
} else if(goalNodes.size() >= 2) {
|
||||
std::vector<Node*> sharedParents;
|
||||
std::vector<Node*> nodes = goalNodes;
|
||||
|
||||
for (auto it = nodes.begin(); it != nodes.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
if (next != nodes.end()) {
|
||||
Node* commonParent = FirstCommonParent((*it), (*next));
|
||||
sharedParents.push_back(commonParent);
|
||||
(*next) = commonParent;
|
||||
nodes.erase(it);
|
||||
it = nodes.begin();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) {
|
||||
|
||||
Node* currentNode = (*it)->Parent;
|
||||
Node* lastNode = (*it);
|
||||
|
||||
while (currentNode != nullptr) {
|
||||
if (!currentNode->Entity.HasComponent("Blend")) {
|
||||
return blendInfo;
|
||||
}
|
||||
|
||||
bool ShouldBreak = false;
|
||||
for (auto it = sharedParents.begin(); it != sharedParents.end(); it++) {
|
||||
if(currentNode == (*it)) {
|
||||
ShouldBreak = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(ShouldBreak) {
|
||||
break;
|
||||
}
|
||||
|
||||
double startWeight;
|
||||
if (blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) {
|
||||
startWeight = blendInfo.StartWeights.at(currentNode->Entity);
|
||||
} else {
|
||||
startWeight = currentNode->Weight;
|
||||
blendInfo.StartWeights[currentNode->Entity] = startWeight;
|
||||
}
|
||||
|
||||
double goalWeight;
|
||||
if (currentNode->Child[0] == lastNode) {
|
||||
goalWeight = 0.0;
|
||||
} else if (currentNode->Child[1] == lastNode) {
|
||||
goalWeight = 1.0;
|
||||
}
|
||||
|
||||
double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight;
|
||||
currentNode->Entity["Blend"]["Weight"] = weight;
|
||||
currentNode->Weight = weight;
|
||||
|
||||
lastNode = currentNode;
|
||||
currentNode = currentNode->Parent;
|
||||
if (blendInfo.SingleBlend) {
|
||||
return blendInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blendInfo;
|
||||
}
|
||||
|
||||
BlendTree::Node* BlendTree::GetCommonParent(std::string NodeName1, std::string NodeName2)
|
||||
{
|
||||
std::vector<Node*> nodes1 = FindNodesByName(NodeName1);
|
||||
std::vector<Node*> nodes2 = FindNodesByName(NodeName2);
|
||||
|
||||
for (auto it = nodes1.begin(); it != nodes1.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
if(next != nodes1.end()) {
|
||||
Node* commonParent = FirstCommonParent((*it), (*next));
|
||||
(*next) = commonParent;
|
||||
nodes1.erase(it);
|
||||
it = nodes1.begin();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = nodes2.begin(); it != nodes2.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
if (next != nodes2.end()) {
|
||||
Node* commonParent = FirstCommonParent((*it), (*next));
|
||||
(*next) = commonParent;
|
||||
nodes2.erase(it);
|
||||
it = nodes2.begin();
|
||||
}
|
||||
}
|
||||
|
||||
return FirstCommonParent(nodes1.front(), nodes2.front());;
|
||||
}
|
||||
|
||||
|
||||
BlendTree::Node* BlendTree::FirstCommonParent(Node* node1, Node* node2)
|
||||
{
|
||||
std::list<Node*> node1Parents;
|
||||
|
||||
Node* currentNode = node1;
|
||||
while (currentNode != nullptr) {
|
||||
node1Parents.push_back(currentNode);
|
||||
currentNode = currentNode->Parent;
|
||||
}
|
||||
|
||||
currentNode = node2;
|
||||
while (currentNode != nullptr) {
|
||||
for (auto it = node1Parents.begin(); it != node1Parents.end(); it++) {
|
||||
if (currentNode == (*it)) {
|
||||
return currentNode;
|
||||
}
|
||||
}
|
||||
currentNode = currentNode->Parent;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
EntityWrapper BlendTree::GetSubTreeRoot(std::string nodeName)
|
||||
{
|
||||
std::vector<Node*> nodes = FindNodesByName(nodeName);
|
||||
|
||||
if (nodes.size() == 0) {
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
std::vector<Node*> subTreeRoots;
|
||||
|
||||
for (auto it = nodes.begin(); it != nodes.end(); it++) {
|
||||
Node* currentNode = (*it)->Parent;
|
||||
while (!currentNode->SubTreeRoot) {
|
||||
currentNode = currentNode->Parent;
|
||||
}
|
||||
subTreeRoots.push_back(currentNode);
|
||||
}
|
||||
|
||||
|
||||
for (auto it = subTreeRoots.begin(); it != subTreeRoots.end(); it++) {
|
||||
auto next = std::next(it, 1);
|
||||
|
||||
if (next != subTreeRoots.end()) {
|
||||
Node* commonParent = FirstCommonParent((*it), (*next));
|
||||
(*next) = commonParent;
|
||||
subTreeRoots.erase(it);
|
||||
it = subTreeRoots.begin();
|
||||
}
|
||||
}
|
||||
|
||||
return subTreeRoots.front()->Entity;
|
||||
}
|
||||
|
||||
|
||||
std::vector<EntityWrapper> BlendTree::GetSingleLevelRoots(std::string name)
|
||||
{
|
||||
std::vector<Node*> nodes = FindNodesByName(name);
|
||||
std::vector<EntityWrapper> entities;
|
||||
|
||||
for (auto it = nodes.begin(); it != nodes.end(); it++) {
|
||||
Node* currentNode = (*it)->Parent;
|
||||
|
||||
if(currentNode->Entity.Valid()) {
|
||||
entities.push_back(currentNode->Entity);
|
||||
}
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
|
||||
std::vector<EntityWrapper> BlendTree::GetEntitesByName(std::string name)
|
||||
{
|
||||
std::vector<Node*> nodes = FindNodesByName(name);
|
||||
std::vector<EntityWrapper> entities;
|
||||
|
||||
for (auto it = nodes.begin(); it != nodes.end(); it++) {
|
||||
Node* currentNode = (*it);
|
||||
|
||||
if (currentNode->Entity.Valid()) {
|
||||
entities.push_back(currentNode->Entity);
|
||||
}
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
|
||||
void BlendTree::SetWeightByName(std::string name, double weight)
|
||||
{
|
||||
std::vector<Node*> nodes = FindNodesByName(name);
|
||||
|
||||
for (auto node : nodes) {
|
||||
EntityWrapper entity = node->Entity;
|
||||
|
||||
if(entity.HasComponent("Blend")) {
|
||||
entity["Blend"]["Weight"] = weight;
|
||||
node->Weight = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlendTree::Blend(std::map<int, Skeleton::PoseData>& pose)
|
||||
{
|
||||
Node* currentNode;
|
||||
Node* start = m_Root;
|
||||
while (start->Child[0] != nullptr) {
|
||||
start = start->Child[0];
|
||||
}
|
||||
|
||||
currentNode = start;
|
||||
|
||||
while (m_Root->Pose.size() == 0) {
|
||||
if(currentNode->Pose.size() == 0) {
|
||||
if (currentNode->Child[0] != nullptr && currentNode->Child[1] != nullptr) {
|
||||
if (currentNode->Child[0]->Pose.size() != 0 && currentNode->Child[1]->Pose.size() != 0) {
|
||||
switch (currentNode->Type) {
|
||||
case BlendTree::NodeType::Additive:
|
||||
currentNode->Pose = m_Skeleton->BlendPoseAdditive(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose);
|
||||
break;
|
||||
case BlendTree::NodeType::Blend:
|
||||
currentNode->Pose = m_Skeleton->BlendPoses(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose, currentNode->Weight);
|
||||
break;
|
||||
case BlendTree::NodeType::Override:
|
||||
currentNode->Pose = m_Skeleton->OverridePose(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose);
|
||||
break;
|
||||
case BlendTree::NodeType::Animation:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (currentNode->Child[0] != nullptr) {
|
||||
if (currentNode->Child[0]->Pose.size() != 0) {
|
||||
currentNode->Pose = currentNode->Child[0]->Pose;
|
||||
}
|
||||
} else if (currentNode->Child[1] != nullptr) {
|
||||
if (currentNode->Child[1]->Pose.size() != 0) {
|
||||
currentNode->Pose = currentNode->Child[1]->Pose;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentNode = currentNode->Next();
|
||||
|
||||
if (currentNode == nullptr) {
|
||||
currentNode = start;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pose = m_Root->Pose;
|
||||
}
|
||||
|
||||
std::vector<glm::mat4> BlendTree::AccumulateFinalPose()
|
||||
{
|
||||
std::vector<glm::mat4> finalPose;
|
||||
if (m_Skeleton == nullptr || m_Root == nullptr || (m_Root->Child[0] == nullptr && m_Root->Child[1] == nullptr)) {
|
||||
|
||||
for (int i = 0; i < m_Skeleton->Bones.size(); i++) {
|
||||
finalPose.push_back(glm::mat4(1));
|
||||
}
|
||||
return finalPose;
|
||||
}
|
||||
|
||||
std::map<int, Skeleton::PoseData> pose;
|
||||
Blend(pose);
|
||||
|
||||
m_Skeleton->GetFinalPose(pose, finalPose, m_FinalBoneTransforms);
|
||||
|
||||
return finalPose;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
#include "Rendering/BlurHUD.h"
|
||||
|
||||
BlurHUD::BlurHUD(IRenderer* renderer)
|
||||
: m_Renderer(renderer)
|
||||
{
|
||||
InitializeShaderPrograms();
|
||||
InitializeBuffers();
|
||||
InitializeTextures();
|
||||
}
|
||||
|
||||
void BlurHUD::InitializeTextures()
|
||||
{
|
||||
m_BlackTexture = CommonFunctions::TryLoadResource<Texture, false>("Textures/Core/Black.png");
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.mesh");
|
||||
}
|
||||
|
||||
void BlurHUD::InitializeShaderPrograms()
|
||||
{
|
||||
m_GaussianProgram_horiz = ResourceManager::Load<ShaderProgram>("##GaussianProgramHoriz");
|
||||
if (m_GaussianProgram_horiz->GetHandle() == 0) {
|
||||
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_horiz.vert.glsl")));
|
||||
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl")));
|
||||
m_GaussianProgram_horiz->Compile();
|
||||
m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor");
|
||||
m_GaussianProgram_horiz->Link();
|
||||
}
|
||||
|
||||
m_GaussianProgram_vert = ResourceManager::Load<ShaderProgram>("##GaussianProgramVert");
|
||||
if (m_GaussianProgram_vert->GetHandle() == 0) {
|
||||
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_vert.vert.glsl")));
|
||||
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_vert.frag.glsl")));
|
||||
m_GaussianProgram_vert->Compile();
|
||||
m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor");
|
||||
m_GaussianProgram_vert->Link();
|
||||
}
|
||||
m_FillDepthStencilProgram = ResourceManager::Load<ShaderProgram>("#FillDepthStencilProgram");
|
||||
if (m_FillDepthStencilProgram->GetHandle() == 0) {
|
||||
m_FillDepthStencilProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/FillDepthBuffer.vert.glsl")));
|
||||
m_FillDepthStencilProgram->Compile();
|
||||
m_FillDepthStencilProgram->Link();
|
||||
}
|
||||
m_CombineTexturesProgram = ResourceManager::Load<ShaderProgram>("#CombineTexturesProgram");
|
||||
if (m_CombineTexturesProgram->GetHandle() == 0) {
|
||||
m_CombineTexturesProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/CombineTexture.vert.glsl")));
|
||||
m_CombineTexturesProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/CombineTexture.frag.glsl")));
|
||||
m_CombineTexturesProgram->Compile();
|
||||
m_CombineTexturesProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_CombineTexturesProgram->BindFragDataLocation(1, "bloomColor");
|
||||
m_CombineTexturesProgram->Link();
|
||||
}
|
||||
GLERROR("Creating DepthFill program");
|
||||
}
|
||||
|
||||
void BlurHUD::InitializeBuffers()
|
||||
{
|
||||
glm::vec2 res = glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
glm::vec2 res2 = glm::vec2(m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality);
|
||||
|
||||
|
||||
CommonFunctions::GenerateTexture(&m_DepthStencil_horiz, GL_CLAMP_TO_BORDER, GL_NEAREST,
|
||||
res2, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
||||
CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_NEAREST,
|
||||
res2, GL_RGBA16F, GL_RGBA, GL_FLOAT);
|
||||
|
||||
if (m_GaussianFrameBuffer_horiz.GetHandle() == 0) {
|
||||
m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_DepthStencil_horiz, GL_DEPTH_STENCIL_ATTACHMENT)));
|
||||
m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0)));
|
||||
}
|
||||
m_GaussianFrameBuffer_horiz.Generate();
|
||||
|
||||
//CommonFunctions::GenerateTexture(&m_DepthStencil_vert, GL_CLAMP_TO_BORDER, GL_NEAREST,
|
||||
// res2, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
||||
CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_NEAREST,
|
||||
res2, GL_RGBA16F, GL_RGBA, GL_FLOAT);
|
||||
|
||||
if (m_GaussianFrameBuffer_vert.GetHandle() == 0) {
|
||||
m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_DepthStencil_horiz, GL_DEPTH_STENCIL_ATTACHMENT)));
|
||||
m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0)));
|
||||
}
|
||||
m_GaussianFrameBuffer_vert.Generate();
|
||||
|
||||
CommonFunctions::GenerateTexture(&m_CombinedTexture, GL_CLAMP_TO_BORDER, GL_NEAREST,
|
||||
res, GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
|
||||
if (m_CombinedTextureBuffer.GetHandle() == 0) {
|
||||
m_CombinedTextureBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_CombinedTexture, GL_COLOR_ATTACHMENT0)));
|
||||
}
|
||||
m_CombinedTextureBuffer.Generate();
|
||||
}
|
||||
|
||||
|
||||
void BlurHUD::ClearBuffer()
|
||||
{
|
||||
GLERROR("PRE");
|
||||
m_GaussianFrameBuffer_horiz.Bind();
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClearStencil(0x00);
|
||||
glStencilMask(~0);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
m_GaussianFrameBuffer_horiz.Unbind();
|
||||
m_GaussianFrameBuffer_vert.Bind();
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClearStencil(0x00);
|
||||
glStencilMask(~0);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
m_GaussianFrameBuffer_vert.Unbind();
|
||||
|
||||
m_CombinedTextureBuffer.Bind();
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
m_CombinedTextureBuffer.Unbind();
|
||||
GLERROR("END");
|
||||
}
|
||||
|
||||
//Returns the finished blurred texture
|
||||
GLuint BlurHUD::Draw(GLuint texture, RenderScene& scene)
|
||||
{
|
||||
GLERROR("DrawBloomPass::Draw: Pre");
|
||||
|
||||
bool shouldRun = false;
|
||||
for (auto& job : scene.Jobs.SpriteJob) {
|
||||
auto spriteJob = std::dynamic_pointer_cast<SpriteJob>(job);
|
||||
if (!spriteJob) {
|
||||
continue;
|
||||
}
|
||||
if (!spriteJob->BlurBackground) {
|
||||
continue;
|
||||
}
|
||||
shouldRun = true;
|
||||
break;
|
||||
}
|
||||
if(!shouldRun) {
|
||||
return m_BlackTexture->m_Texture;
|
||||
}
|
||||
FillStencil(scene);
|
||||
|
||||
RenderState state;
|
||||
state.Disable(GL_BLEND);
|
||||
state.Disable(GL_DEPTH_TEST);
|
||||
state.Disable(GL_CULL_FACE);
|
||||
|
||||
state.Enable(GL_STENCIL_TEST);
|
||||
state.StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
state.StencilFunc(GL_EQUAL, 1, 0xFF);
|
||||
state.StencilMask(0x00);
|
||||
state.DepthMask(GL_FALSE);
|
||||
state.Enable(GL_SCISSOR_TEST);
|
||||
|
||||
GLuint shaderHandle_horiz = m_GaussianProgram_horiz->GetHandle();
|
||||
GLuint shaderHandle_vert = m_GaussianProgram_vert->GetHandle();
|
||||
|
||||
//Horizontal pass, first use the given texture then save it to the horizontal framebuffer.
|
||||
m_GaussianFrameBuffer_horiz.Bind();
|
||||
|
||||
glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality);
|
||||
glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
|
||||
m_GaussianProgram_vert->Bind();
|
||||
glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), 0);
|
||||
m_GaussianProgram_horiz->Bind();
|
||||
glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), 0);
|
||||
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
//Iterate some times to make it more gaussian.
|
||||
for (int i = 1; i < m_Iterations; i++) {
|
||||
//Vertical pass
|
||||
m_GaussianFrameBuffer_vert.Bind();
|
||||
m_GaussianProgram_vert->Bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz);
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
//horizontal pass
|
||||
m_GaussianFrameBuffer_vert.Unbind();
|
||||
m_GaussianFrameBuffer_horiz.Bind();
|
||||
m_GaussianProgram_horiz->Bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_vert);
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
m_GaussianFrameBuffer_horiz.Unbind();
|
||||
}
|
||||
|
||||
//final vertical gaussian after the iterations are done
|
||||
|
||||
m_GaussianFrameBuffer_vert.Bind();
|
||||
m_GaussianProgram_vert->Bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz);
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
|
||||
GLERROR("DrawBloomPass::Draw: END");
|
||||
glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
|
||||
|
||||
return m_GaussianTexture_vert;
|
||||
}
|
||||
|
||||
|
||||
void BlurHUD::OnWindowResize()
|
||||
{
|
||||
InitializeBuffers();
|
||||
}
|
||||
|
||||
void BlurHUD::FillStencil(RenderScene& scene)
|
||||
{
|
||||
RenderState state;
|
||||
|
||||
state.BindFramebuffer(m_GaussianFrameBuffer_horiz.GetHandle());
|
||||
state.Enable(GL_DEPTH_TEST);
|
||||
state.Enable(GL_CULL_FACE);
|
||||
state.Enable(GL_STENCIL_TEST);
|
||||
state.StencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
state.StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
state.StencilMask(0xFF);
|
||||
|
||||
state.AlphaFunc(GL_GEQUAL, 0.95f);
|
||||
state.Enable(GL_ALPHA_TEST);
|
||||
|
||||
glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_BlurQuality, m_Renderer->GetViewportSize().Height/m_BlurQuality);
|
||||
|
||||
m_FillDepthStencilProgram->Bind();
|
||||
|
||||
GLuint shaderHandle = m_FillDepthStencilProgram->GetHandle();
|
||||
glm::mat4 VP = scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix();
|
||||
|
||||
|
||||
for (auto& job : scene.Jobs.SpriteJob) {
|
||||
auto spriteJob = std::dynamic_pointer_cast<SpriteJob>(job);
|
||||
if (!spriteJob) {
|
||||
continue;
|
||||
}
|
||||
if (!spriteJob->BlurBackground) {
|
||||
continue;
|
||||
}
|
||||
|
||||
glm::mat4 MVP = VP * spriteJob->Matrix;
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(MVP));
|
||||
|
||||
|
||||
glBindVertexArray(spriteJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex*sizeof(unsigned int)));
|
||||
}
|
||||
|
||||
//state.BindFramebuffer(m_GaussianFrameBuffer_vert.GetHandle());
|
||||
//for (auto& job : scene.Jobs.SpriteJob) {
|
||||
// auto spriteJob = std::dynamic_pointer_cast<SpriteJob>(job);
|
||||
// if (!spriteJob) {
|
||||
// continue;
|
||||
// }
|
||||
// if(!spriteJob->BlurBackground) {
|
||||
// continue;
|
||||
// }
|
||||
// glm::mat4 MVP = VP * spriteJob->Matrix;
|
||||
// glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(MVP));
|
||||
|
||||
// glBindVertexArray(spriteJob->Model->VAO);
|
||||
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer);
|
||||
// glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex*sizeof(unsigned int)));
|
||||
//}
|
||||
glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
}
|
||||
|
||||
//Texture 1 will be used if texture 2 is black at that texel, else texture 2 is used.
|
||||
GLuint BlurHUD::CombineTextures(GLuint texture1, GLuint texture2)
|
||||
{
|
||||
//RenderState state;
|
||||
//state.BindFramebuffer(m_CombinedTextureBuffer.GetHandle());
|
||||
//state.Disable(GL_DEPTH_TEST);
|
||||
//state.Disable(GL_STENCIL_TEST);
|
||||
|
||||
m_CombineTexturesProgram->Bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture2);
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
|
||||
return m_CombinedTexture;
|
||||
}
|
||||
@@ -8,10 +8,13 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
|
||||
return;
|
||||
}
|
||||
|
||||
auto parent = entity.FirstParentWithComponent("Animation");
|
||||
if (!parent.HasComponent("Model")) {
|
||||
auto parent = entity.FirstParentWithComponent("Model");
|
||||
|
||||
if(!parent.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]);
|
||||
@@ -35,66 +38,31 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<::Skeleton::AnimationData> Animations;
|
||||
::Skeleton::AnimationOffset AnimationOffset;
|
||||
glm::mat4 boneTransform;
|
||||
if (skeleton->BlendTrees.find(parent) != skeleton->BlendTrees.end()) {
|
||||
|
||||
if (parent.HasComponent("Animation")) {
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
::Skeleton::AnimationData animationData;
|
||||
animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["Animation"]["AnimationName" + std::to_string(i)]);
|
||||
if (animationData.animation == nullptr) {
|
||||
continue;
|
||||
}
|
||||
animationData.time = (double)parent["Animation"]["Time" + std::to_string(i)];
|
||||
animationData.weight = (double)parent["Animation"]["Weight" + std::to_string(i)];
|
||||
|
||||
Animations.push_back(animationData);
|
||||
}
|
||||
}
|
||||
glm::mat4 boneTransform = skeleton->BlendTrees.at(parent)->GetBoneTransform(id);
|
||||
|
||||
if (parent.HasComponent("AnimationOffset")) {
|
||||
AnimationOffset.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["AnimationOffset"]["AnimationName"]);
|
||||
AnimationOffset.time = (double)parent["AnimationOffset"]["Time"];
|
||||
glm::vec3 scale;
|
||||
glm::quat rotation;
|
||||
glm::vec3 translation;
|
||||
glm::vec3 skew;
|
||||
glm::vec4 perspective;
|
||||
glm::decompose(boneTransform, scale, rotation, translation, skew, perspective);
|
||||
|
||||
if(AnimationOffset.animation != nullptr) {
|
||||
boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, AnimationOffset, glm::mat4(1));
|
||||
} else {
|
||||
boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1));
|
||||
}
|
||||
rotation = glm::quat((glm::vec3)entity["BoneAttachment"]["OrientationOffset"]) * rotation;
|
||||
rotation = glm::inverse(rotation);
|
||||
glm::vec3 angles = glm::eulerAngles(rotation);
|
||||
|
||||
} else {
|
||||
boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1));
|
||||
if ((bool)entity["BoneAttachment"]["InheritPosition"]) {
|
||||
entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"];
|
||||
}
|
||||
if ((bool)entity["BoneAttachment"]["InheritOrientation"]) {
|
||||
entity["Transform"]["Orientation"] = angles;
|
||||
}
|
||||
if ((bool)entity["BoneAttachment"]["InheritScale"]) {
|
||||
entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::vec3 scale;
|
||||
glm::quat rotation;
|
||||
glm::vec3 translation;
|
||||
glm::vec3 skew;
|
||||
glm::vec4 perspective;
|
||||
glm::decompose(boneTransform, scale, rotation, translation, skew, perspective);
|
||||
|
||||
glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation));
|
||||
/*
|
||||
|
||||
angles.y = asin(-boneTransform[0][2]);
|
||||
if (cos(angles.y) != 0) {
|
||||
angles.x = atan2(boneTransform[1][2], boneTransform[2][2]);
|
||||
angles.z = atan2(boneTransform[0][1], boneTransform[0][0]);
|
||||
} else {
|
||||
angles.x = atan2(-boneTransform[2][0], boneTransform[1][1]);
|
||||
angles.z = 0;
|
||||
}*/
|
||||
|
||||
if ((bool)entity["BoneAttachment"]["InheritPosition"]) {
|
||||
(glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"];
|
||||
}
|
||||
if ((bool)entity["BoneAttachment"]["InheritOrientation"]) {
|
||||
(glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"];
|
||||
}
|
||||
if ((bool)entity["BoneAttachment"]["InheritScale"]) {
|
||||
(glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,16 @@ CubeMapPass::CubeMapPass(IRenderer* renderer)
|
||||
LoadTextures("Nevada");
|
||||
}
|
||||
|
||||
void CubeMapPass::LoadTextures(std::string input)
|
||||
void CubeMapPass::LoadTextures(std::string cubemapName)
|
||||
{
|
||||
if (m_PreviusCubeMapTexture != input) {
|
||||
if (m_PreviusCubeMapTexture != cubemapName) {
|
||||
m_CubeMapTextures.clear();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
std::string str;
|
||||
str = "Textures/Test/CubeMap/" + input + "/CubeMapTest0" + std::to_string(i) + ".png";
|
||||
Texture* img = ResourceManager::Load<Texture>(str);
|
||||
m_CubeMapTextures.push_back(img);
|
||||
std::string path = "Textures/Test/CubeMap/" + cubemapName + "/CubeMapTest0" + std::to_string(i) + ".png";
|
||||
m_CubeMapTextures.push_back(path);
|
||||
}
|
||||
GenerateCubeMapTexture();
|
||||
m_PreviusCubeMapTexture = input;
|
||||
m_PreviusCubeMapTexture = cubemapName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +27,9 @@ void CubeMapPass::GenerateCubeMapTexture()
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapTexture);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, m_CubeMapTextures[0]->Width, m_CubeMapTextures[0]->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_CubeMapTextures[i]->Data);
|
||||
PNG* img = ResourceManager::Load<PNG>(m_CubeMapTextures[i]);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, img->Width, img->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img->Data);
|
||||
ResourceManager::Release("PNG", m_CubeMapTextures[i]);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
@@ -9,9 +9,15 @@ DrawBloomPass::DrawBloomPass(IRenderer* renderer, ConfigFile* config)
|
||||
ChangeQuality(m_Config->Get<int>("GLOW.Quality", 2));
|
||||
}
|
||||
|
||||
DrawBloomPass::~DrawBloomPass() {
|
||||
CommonFunctions::DeleteTexture(&m_GaussianTexture_horiz);
|
||||
CommonFunctions::DeleteTexture(&m_GaussianTexture_vert);
|
||||
CommonFunctions::DeleteTexture(&m_FinalGaussianTexture);
|
||||
}
|
||||
|
||||
void DrawBloomPass::InitializeTextures()
|
||||
{
|
||||
m_BlackTexture = CommonFunctions::LoadTexture("Textures/Core/Black.png", false);
|
||||
m_BlackTexture = CommonFunctions::TryLoadResource<Texture, false>("Textures/Core/Black.png");
|
||||
}
|
||||
|
||||
void DrawBloomPass::ChangeQuality(int quality)
|
||||
@@ -25,9 +31,8 @@ void DrawBloomPass::ChangeQuality(int quality)
|
||||
|
||||
if (m_Quality == 0) {
|
||||
CommonFunctions::DeleteTexture(&m_GaussianTexture_horiz);
|
||||
CommonFunctions::DeleteTexture(&m_GaussianTexture_vert);
|
||||
m_GaussianTexture_horiz = 0;
|
||||
m_GaussianTexture_vert = 0;
|
||||
CommonFunctions::DeleteTexture(&m_GaussianTexture_vert);
|
||||
CommonFunctions::DeleteTexture(&m_FinalGaussianTexture);
|
||||
return;
|
||||
}
|
||||
InitializeTextures();
|
||||
@@ -45,6 +50,7 @@ void DrawBloomPass::InitializeShaderPrograms()
|
||||
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_horiz.vert.glsl")));
|
||||
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl")));
|
||||
m_GaussianProgram_horiz->Compile();
|
||||
m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor");
|
||||
m_GaussianProgram_horiz->Link();
|
||||
}
|
||||
|
||||
@@ -53,24 +59,53 @@ void DrawBloomPass::InitializeShaderPrograms()
|
||||
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_vert.vert.glsl")));
|
||||
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_vert.frag.glsl")));
|
||||
m_GaussianProgram_vert->Compile();
|
||||
m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor");
|
||||
m_GaussianProgram_vert->Link();
|
||||
}
|
||||
|
||||
m_GaussianCombineProgram = ResourceManager::Load<ShaderProgram>("#GaussianCombineProgram");
|
||||
if (m_GaussianCombineProgram->GetHandle() == 0) {
|
||||
m_GaussianCombineProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/CombineGaussianTexture.vert.glsl")));
|
||||
m_GaussianCombineProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/CombineGaussianTexture.frag.glsl")));
|
||||
m_GaussianCombineProgram->Compile();
|
||||
m_GaussianCombineProgram->BindFragDataLocation(0, "fragmentColor");
|
||||
m_GaussianCombineProgram->Link();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBloomPass::InitializeBuffers()
|
||||
{
|
||||
CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
CommonFunctions::GenerateMipMapTexture(
|
||||
&m_GaussianTexture_horiz, GL_CLAMP_TO_BORDER, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height),
|
||||
GL_RGB16F, GL_RGB, GL_FLOAT, m_BloomLod, GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST);
|
||||
CommonFunctions::GenerateMipMapTexture(
|
||||
&m_GaussianTexture_vert, GL_CLAMP_TO_BORDER, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height),
|
||||
GL_RGB16F, GL_RGB, GL_FLOAT, m_BloomLod, GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST);
|
||||
CommonFunctions::GenerateTexture(&m_FinalGaussianTexture, GL_CLAMP_TO_BORDER, GL_NEAREST, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
|
||||
if (m_GaussianFrameBuffer_horiz.GetHandle() == 0) {
|
||||
m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0)));
|
||||
}
|
||||
m_GaussianFrameBuffer_horiz.Generate();
|
||||
if (m_GaussianCombineBuffer.GetHandle() == 0) {
|
||||
m_GaussianCombineBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_FinalGaussianTexture, GL_COLOR_ATTACHMENT0)));
|
||||
}
|
||||
m_GaussianCombineBuffer.Generate();
|
||||
|
||||
CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
if (m_GaussianFrameBuffer_vert.GetHandle() == 0) {
|
||||
m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0)));
|
||||
}
|
||||
m_GaussianFrameBuffer_vert.Generate();
|
||||
if(m_GaussianFrameBuffer_horiz == nullptr) {
|
||||
m_GaussianFrameBuffer_horiz = new FrameBuffer[m_BloomLod];
|
||||
}
|
||||
if (m_GaussianFrameBuffer_vert == nullptr) {
|
||||
m_GaussianFrameBuffer_vert = new FrameBuffer[m_BloomLod];
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_BloomLod; i++) {
|
||||
if(m_GaussianFrameBuffer_horiz[i].GetHandle() == 0) {
|
||||
m_GaussianFrameBuffer_horiz[i].AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0, i)));
|
||||
}
|
||||
m_GaussianFrameBuffer_horiz[i].Generate();
|
||||
|
||||
if (m_GaussianFrameBuffer_vert[i].GetHandle() == 0) {
|
||||
m_GaussianFrameBuffer_vert[i].AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0, i)));
|
||||
}
|
||||
m_GaussianFrameBuffer_vert[i].Generate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,33 +115,64 @@ void DrawBloomPass::ClearBuffer()
|
||||
return;
|
||||
}
|
||||
GLERROR("PRE");
|
||||
m_GaussianFrameBuffer_horiz.Bind();
|
||||
for (int i = 0; i < m_BloomLod; i++) {
|
||||
m_GaussianFrameBuffer_horiz[i].Bind();
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
m_GaussianFrameBuffer_horiz[i].Unbind();
|
||||
m_GaussianFrameBuffer_vert[i].Bind();
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
m_GaussianFrameBuffer_vert[i].Unbind();
|
||||
|
||||
}
|
||||
m_GaussianCombineBuffer.Bind();
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
m_GaussianFrameBuffer_horiz.Unbind();
|
||||
m_GaussianFrameBuffer_vert.Bind();
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
m_GaussianFrameBuffer_vert.Unbind();
|
||||
m_GaussianCombineBuffer.Unbind();
|
||||
GLERROR("END");
|
||||
}
|
||||
|
||||
void DrawBloomPass::Draw(GLuint texture)
|
||||
{
|
||||
if (m_Quality == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_BloomLod; i++) {
|
||||
GaussianLodPass(i, texture);
|
||||
}
|
||||
CombineGaussianBlur();
|
||||
}
|
||||
|
||||
|
||||
void DrawBloomPass::OnWindowResize()
|
||||
{
|
||||
if (m_Quality == 0) {
|
||||
return;
|
||||
}
|
||||
GLERROR("DrawBloomPass::Draw: Pre");
|
||||
InitializeBuffers();
|
||||
}
|
||||
|
||||
void DrawBloomPass::GaussianLodPass(GLuint mipMap, GLuint texture)
|
||||
{
|
||||
GLERROR("DrawBloomPass::Draw: Pre");
|
||||
glViewport(0, 0, m_Renderer->GetViewportSize().Width/(glm::pow(2, mipMap)), m_Renderer->GetViewportSize().Height/(glm::pow(2, mipMap)));
|
||||
DrawBloomPassState state;
|
||||
|
||||
GLuint shaderHandle_horiz = m_GaussianProgram_horiz->GetHandle();
|
||||
GLuint shaderHandle_vert = m_GaussianProgram_vert->GetHandle();
|
||||
|
||||
m_GaussianProgram_vert->Bind();
|
||||
glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), mipMap);
|
||||
m_GaussianProgram_horiz->Bind();
|
||||
glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), mipMap);
|
||||
|
||||
|
||||
//Horizontal pass, first use the given texture then save it to the horizontal framebuffer.
|
||||
m_GaussianFrameBuffer_horiz.Bind();
|
||||
m_GaussianProgram_horiz->Bind();
|
||||
m_GaussianFrameBuffer_horiz[mipMap].Bind();
|
||||
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
@@ -116,55 +182,56 @@ void DrawBloomPass::Draw(GLuint texture)
|
||||
//Iterate some times to make it more gaussian.
|
||||
for (int i = 1; i < m_Iterations; i++) {
|
||||
//Vertical pass
|
||||
m_GaussianFrameBuffer_vert.Bind();
|
||||
m_GaussianFrameBuffer_vert[mipMap].Bind();
|
||||
m_GaussianProgram_vert->Bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz);
|
||||
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
//horizontal pass
|
||||
m_GaussianFrameBuffer_vert.Unbind();
|
||||
m_GaussianFrameBuffer_vert[mipMap].Unbind();
|
||||
|
||||
m_GaussianFrameBuffer_horiz.Bind();
|
||||
m_GaussianFrameBuffer_horiz[mipMap].Bind();
|
||||
m_GaussianProgram_horiz->Bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_vert);
|
||||
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
m_GaussianFrameBuffer_horiz.Unbind();
|
||||
m_GaussianFrameBuffer_horiz[mipMap].Unbind();
|
||||
}
|
||||
|
||||
//final vertical gaussian after the iterations are done
|
||||
|
||||
m_GaussianFrameBuffer_vert.Bind();
|
||||
m_GaussianFrameBuffer_vert[mipMap].Bind();
|
||||
m_GaussianProgram_vert->Bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz);
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
|
||||
GLERROR("DrawBloomPass::Draw: END");
|
||||
glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
m_GaussianFrameBuffer_vert[mipMap].Unbind();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DrawBloomPass::OnWindowResize()
|
||||
void DrawBloomPass::CombineGaussianBlur()
|
||||
{
|
||||
if (m_Quality == 0) {
|
||||
return;
|
||||
}
|
||||
CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
m_GaussianFrameBuffer_vert.Generate();
|
||||
CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
m_GaussianFrameBuffer_horiz.Generate();
|
||||
m_GaussianCombineBuffer.Bind();
|
||||
m_GaussianCombineProgram->Bind();
|
||||
glUniform1i(glGetUniformLocation(m_GaussianCombineProgram->GetHandle(), "MaxMipMap"), m_BloomLod);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_vert);
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,8 @@ DrawFinalPassState::DrawFinalPassState(GLuint frameBuffer)
|
||||
Enable(GL_DEPTH_TEST);
|
||||
DepthMask(GL_TRUE);
|
||||
Enable(GL_CULL_FACE);
|
||||
Enable(GL_ALPHA_TEST);
|
||||
AlphaFunc(GL_GEQUAL, 0.05f);
|
||||
// Enable(GL_STENCIL_TEST);
|
||||
// StencilFunc(GL_NOTEQUAL, 1, 0xFF);
|
||||
// StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
#include "Rendering/FrameBuffer.h"
|
||||
|
||||
|
||||
BufferResource::BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment)
|
||||
BufferResource::BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment, GLuint mipMapLod, bool multiSampling)
|
||||
{
|
||||
m_ResourceHandle = resourceHandle;
|
||||
m_ResourceType = resourceType;
|
||||
m_Attachment = attachment;
|
||||
m_MipMapLod = mipMapLod;
|
||||
m_MultiSampling = multiSampling;
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
@@ -14,14 +16,31 @@ Texture2D::~Texture2D()
|
||||
if (m_ResourceHandle != 0) {
|
||||
glDeleteTextures(1, m_ResourceHandle);
|
||||
}
|
||||
*m_ResourceHandle = 0;
|
||||
}
|
||||
|
||||
Texture2DMultiSample::~Texture2DMultiSample()
|
||||
{
|
||||
if (m_ResourceHandle != 0) {
|
||||
glDeleteTextures(1, m_ResourceHandle);
|
||||
}
|
||||
*m_ResourceHandle = 0;
|
||||
}
|
||||
|
||||
RenderBuffer::~RenderBuffer()
|
||||
{
|
||||
if (m_ResourceHandle != 0) {
|
||||
glDeleteRenderbuffers(1, m_ResourceHandle);
|
||||
}
|
||||
*m_ResourceHandle = 0;
|
||||
}
|
||||
|
||||
Texture2DArray::~Texture2DArray()
|
||||
{
|
||||
if (m_ResourceHandle != 0) {
|
||||
glDeleteTextures(1, m_ResourceHandle);
|
||||
}
|
||||
*m_ResourceHandle = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +53,14 @@ FrameBuffer::~FrameBuffer()
|
||||
|
||||
void FrameBuffer::AddResource(std::shared_ptr<BufferResource> resource)
|
||||
{
|
||||
//m_MultiSampling is true when initialized
|
||||
if (m_MultiSampling != resource->m_MultiSampling) {
|
||||
if (m_MultiSampling == false) {
|
||||
GLERROR("All renderbuffers is/is not using multisampling");
|
||||
} else {
|
||||
m_MultiSampling = false;
|
||||
}
|
||||
}
|
||||
m_Resources.push_back(resource);
|
||||
}
|
||||
|
||||
@@ -47,17 +74,23 @@ void FrameBuffer::Generate()
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_BufferHandle);
|
||||
GLERROR("1");
|
||||
|
||||
for (auto it = m_Resources.begin(); it != m_Resources.end(); it++) {
|
||||
switch ((*it)->m_ResourceType) {
|
||||
case GL_TEXTURE_2D_MULTISAMPLE:
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, GL_TEXTURE_2D_MULTISAMPLE, 0, 0);
|
||||
GLERROR("FrameBuffer generate: GL_TEXTURE_2D_MULTISAMPLE");
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0);
|
||||
GLERROR("FrameBuffer generate: glFramebufferTexture2D");
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, (*it)->m_Attachment, *(*it)->m_ResourceHandle, (*it)->m_MipMapLod);
|
||||
GLERROR("FrameBuffer generate: GL_TEXTURE_2D");
|
||||
break;
|
||||
case GL_RENDERBUFFER:
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle);
|
||||
GLERROR("FrameBuffer generate: glFramebufferRenderbuffer");
|
||||
GLERROR("FrameBuffer generate: GL_RENDERBUFFER");
|
||||
break;
|
||||
case GL_TEXTURE_2D_ARRAY:
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, (*it)->m_Attachment, *(*it)->m_ResourceHandle, 0);
|
||||
GLERROR("FrameBuffer generate: GL_TEXTURE_2D_ARRAY");
|
||||
break;
|
||||
}
|
||||
GLERROR("2");
|
||||
@@ -66,11 +99,11 @@ void FrameBuffer::Generate()
|
||||
attachments.push_back((*it)->m_Attachment);
|
||||
}
|
||||
GLERROR("Attachment");
|
||||
|
||||
}
|
||||
|
||||
GLERROR("3");
|
||||
|
||||
GLenum* bufferTextures = &attachments[0];
|
||||
GLenum* bufferTextures = attachments.data();
|
||||
glDrawBuffers(attachments.size(), bufferTextures);
|
||||
if (GLERROR("GLBufferAttachement error")) {
|
||||
printf(": AttachmentSize %i", attachments.size());
|
||||
@@ -78,7 +111,7 @@ void FrameBuffer::Generate()
|
||||
|
||||
if (GLenum frameBufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
GLERROR("Framebuffer incomplete");
|
||||
//LOG_ERROR("FrameBuffer incomplete: 0x%x\n", frameBufferStatus);
|
||||
LOG_ERROR("FrameBuffer incomplete: 0x%x\n", glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
GLERROR("END");
|
||||
@@ -99,3 +132,11 @@ GLuint FrameBuffer::GetHandle()
|
||||
{
|
||||
return m_BufferHandle;
|
||||
}
|
||||
|
||||
void FrameBuffer::Read() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_BufferHandle);
|
||||
}
|
||||
|
||||
void FrameBuffer::Draw() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_BufferHandle);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,15 @@ void LightCullingPass::SetSSBOSizes()
|
||||
{
|
||||
m_NumberOfTiles = (int)(m_Renderer->GetViewportSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewportSize().Height/TILE_SIZE);
|
||||
|
||||
if (m_Frustums != nullptr) {
|
||||
delete[] m_Frustums;
|
||||
}
|
||||
if (m_LightGrid != nullptr) {
|
||||
delete[] m_LightGrid;
|
||||
}
|
||||
if (m_LightIndex != nullptr) {
|
||||
delete[] m_LightIndex;
|
||||
}
|
||||
m_Frustums = new Frustum[m_NumberOfTiles];
|
||||
m_LightGrid = new LightGrid[m_NumberOfTiles];
|
||||
m_LightIndex = new float[m_NumberOfTiles*MAX_LIGHTS_PER_TILE];
|
||||
|
||||
@@ -10,31 +10,31 @@ Model::Model(std::string fileName)
|
||||
case RawModel::MaterialType::SingleTextures:
|
||||
{
|
||||
RawModel::MaterialSingleTextures* materialSingleTexture = static_cast<RawModel::MaterialSingleTextures*>(materialProperty.material);
|
||||
materialSingleTexture->ColorMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->ColorMap.TexturePath, false);
|
||||
materialSingleTexture->NormalMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->NormalMap.TexturePath, false);
|
||||
materialSingleTexture->SpecularMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->SpecularMap.TexturePath, false);
|
||||
materialSingleTexture->IncandescenceMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->IncandescenceMap.TexturePath, false);
|
||||
materialSingleTexture->ColorMap.Texture = CommonFunctions::TryLoadResource<Texture, false>(materialSingleTexture->ColorMap.TexturePath);
|
||||
materialSingleTexture->NormalMap.Texture = CommonFunctions::TryLoadResource<Texture, false>(materialSingleTexture->NormalMap.TexturePath);
|
||||
materialSingleTexture->SpecularMap.Texture = CommonFunctions::TryLoadResource<Texture, false>(materialSingleTexture->SpecularMap.TexturePath);
|
||||
materialSingleTexture->IncandescenceMap.Texture = CommonFunctions::TryLoadResource<Texture, false>(materialSingleTexture->IncandescenceMap.TexturePath);
|
||||
}
|
||||
break;
|
||||
case RawModel::MaterialType::SplatMapping:
|
||||
{
|
||||
RawModel::MaterialSplatMapping* materialSplatMapping = static_cast<RawModel::MaterialSplatMapping*>(materialProperty.material);
|
||||
materialSplatMapping->SplatMap.Texture = CommonFunctions::LoadTexture(materialSplatMapping->SplatMap.TexturePath, false);
|
||||
materialSplatMapping->SplatMap.Texture = CommonFunctions::TryLoadResource<Texture, false>(materialSplatMapping->SplatMap.TexturePath);
|
||||
for (auto& texture : materialSplatMapping->ColorMaps)
|
||||
{
|
||||
texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false);
|
||||
texture.Texture = CommonFunctions::TryLoadResource<Texture, false>(texture.TexturePath);
|
||||
}
|
||||
for (auto& texture : materialSplatMapping->NormalMaps)
|
||||
{
|
||||
texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false);
|
||||
texture.Texture = CommonFunctions::TryLoadResource<Texture, false>(texture.TexturePath);
|
||||
}
|
||||
for (auto& texture : materialSplatMapping->SpecularMaps)
|
||||
{
|
||||
texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false);
|
||||
texture.Texture = CommonFunctions::TryLoadResource<Texture, false>(texture.TexturePath);
|
||||
}
|
||||
for (auto& texture : materialSplatMapping->IncandescenceMaps)
|
||||
{
|
||||
texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false);
|
||||
texture.Texture = CommonFunctions::TryLoadResource<Texture, false>(texture.TexturePath);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -12,7 +12,8 @@ PickingPass::PickingPass(IRenderer* renderer, EventBroker* eb)
|
||||
|
||||
PickingPass::~PickingPass()
|
||||
{
|
||||
|
||||
CommonFunctions::DeleteTexture(&m_PickingTexture);
|
||||
CommonFunctions::DeleteTexture(&m_DepthBuffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +24,7 @@ void PickingPass::InitializeTextures()
|
||||
glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
||||
|
||||
CommonFunctions::GenerateTexture(&m_DepthBuffer, GL_CLAMP_TO_BORDER, GL_NEAREST,
|
||||
glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
|
||||
glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
|
||||
}
|
||||
|
||||
void PickingPass::InitializeFrameBuffers()
|
||||
@@ -61,8 +62,9 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
GLuint shaderHandle = m_PickingProgram->GetHandle();
|
||||
GLuint shaderSkinnedHandle = m_PickingSkinnedProgram->GetHandle();
|
||||
GLuint lastShader = 0;
|
||||
unsigned int lastModel = 0;
|
||||
m_PickingProgram->Bind();
|
||||
|
||||
if (scene.ClearDepth) {
|
||||
//glClear(GL_DEPTH_BUFFER_BIT);
|
||||
state->Disable(GL_DEPTH_TEST);
|
||||
@@ -74,6 +76,11 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
if (modelJob) {
|
||||
if(modelJob->NotPickable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] };
|
||||
|
||||
PickingInfo pickInfo;
|
||||
@@ -98,32 +105,36 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo;
|
||||
|
||||
if (modelJob->Model->IsSkinned()) {
|
||||
m_PickingSkinnedProgram->Bind();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
if (lastShader != m_PickingSkinnedProgram->GetHandle()) {
|
||||
m_PickingSkinnedProgram->Bind();
|
||||
lastShader = m_PickingSkinnedProgram->GetHandle();
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix));
|
||||
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
std::vector<glm::mat4> frameBones;
|
||||
if (modelJob->AnimationOffset.animation != nullptr) {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
|
||||
} else {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
std::vector<glm::mat4> frameBones;
|
||||
if (modelJob->BlendTree != nullptr) {
|
||||
frameBones = modelJob->BlendTree->GetFinalPose();
|
||||
} else {
|
||||
frameBones = modelJob->Skeleton->GetTPose();
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
|
||||
|
||||
} else {
|
||||
m_PickingProgram->Bind();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
if (lastShader != m_PickingProgram->GetHandle()) {
|
||||
m_PickingProgram->Bind();
|
||||
lastShader = m_PickingProgram->GetHandle();
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix));
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
}
|
||||
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
if (lastModel != modelJob->ModelID) {
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
lastModel = modelJob->ModelID;
|
||||
}
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
@@ -162,13 +173,11 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
std::vector<glm::mat4> frameBones;
|
||||
if (modelJob->AnimationOffset.animation != nullptr) {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
|
||||
} else {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
|
||||
if (modelJob->BlendTree != nullptr) {
|
||||
std::vector<glm::mat4> frameBones;
|
||||
frameBones = modelJob->BlendTree->GetFinalPose();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
} else {
|
||||
m_PickingProgram->Bind();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
@@ -211,34 +220,41 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo;
|
||||
|
||||
if (modelJob->Model->IsSkinned()) {
|
||||
m_PickingSkinnedProgram->Bind();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
if (lastShader != m_PickingSkinnedProgram->GetHandle()) {
|
||||
m_PickingSkinnedProgram->Bind();
|
||||
lastShader = m_PickingSkinnedProgram->GetHandle();
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix));
|
||||
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
std::vector<glm::mat4> frameBones;
|
||||
if (modelJob->AnimationOffset.animation != nullptr) {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
|
||||
if (modelJob->BlendTree != nullptr) {
|
||||
frameBones = modelJob->BlendTree->GetFinalPose();
|
||||
} else {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
|
||||
frameBones = modelJob->Skeleton->GetTPose();
|
||||
}
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
|
||||
} else {
|
||||
m_PickingProgram->Bind();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
if (lastShader != m_PickingProgram->GetHandle()) {
|
||||
m_PickingProgram->Bind();
|
||||
lastShader = m_PickingProgram->GetHandle();
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * modelJob->Matrix));
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
}
|
||||
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
if (lastModel != modelJob->ModelID) {
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
lastModel = modelJob->ModelID;
|
||||
}
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
|
||||
m_PickingProgram->Bind();
|
||||
for (auto& job : scene.Jobs.SpriteJob) {
|
||||
auto spriteJob = std::dynamic_pointer_cast<SpriteJob>(job);
|
||||
if (!spriteJob->Pickable) {
|
||||
@@ -273,14 +289,11 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
|
||||
m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo;
|
||||
|
||||
m_PickingProgram->Bind();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix() * scene.Camera->ViewMatrix() * spriteJob->Matrix));
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
glBindVertexArray(spriteJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer);
|
||||
glBindVertexArray(spriteJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
@@ -322,16 +335,10 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (modelJob->BlendTree != nullptr) {
|
||||
std::vector<glm::mat4> frameBones;
|
||||
if (modelJob->AnimationOffset.animation != nullptr) {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
|
||||
} else {
|
||||
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
|
||||
}
|
||||
frameBones = modelJob->BlendTree->GetFinalPose();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
|
||||
}
|
||||
} else {
|
||||
m_PickingProgram->Bind();
|
||||
|
||||
@@ -149,14 +149,29 @@ void RawModelCustom::ReadMaterialSingle(std::size_t& offset, char* fileData, con
|
||||
case MaterialType::Basic:
|
||||
newMaterialProperty.material = new MaterialBasic();
|
||||
ReadMaterialBasic(newMaterialProperty.material, offset, fileData, fileByteSize);
|
||||
if(hasSkin){
|
||||
newMaterialProperty.ShaderID = ResourceManager::Load<ShaderProgram>("#ForwardPlusSkinnedProgram")->ResourceID;
|
||||
} else {
|
||||
newMaterialProperty.ShaderID = ResourceManager::Load<ShaderProgram>("#ForwardPlusProgram")->ResourceID;
|
||||
}
|
||||
break;
|
||||
case MaterialType::SplatMapping:
|
||||
newMaterialProperty.material = new MaterialSplatMapping();
|
||||
ReadMaterialSplatMapping(static_cast<MaterialSplatMapping*>(newMaterialProperty.material), offset, fileData, fileByteSize);
|
||||
if (hasSkin){
|
||||
newMaterialProperty.ShaderID = ResourceManager::Load<ShaderProgram>("#ForwardPlusSplatMapSkinnedProgram")->ResourceID;
|
||||
} else {
|
||||
newMaterialProperty.ShaderID = ResourceManager::Load<ShaderProgram>("#ForwardPlusSplatMapProgram")->ResourceID;
|
||||
}
|
||||
break;
|
||||
case MaterialType::SingleTextures:
|
||||
newMaterialProperty.material = new MaterialSingleTextures();
|
||||
ReadMaterialSingleTexture(static_cast<MaterialSingleTextures*>(newMaterialProperty.material), offset, fileData, fileByteSize);
|
||||
if (hasSkin){
|
||||
newMaterialProperty.ShaderID = ResourceManager::Load<ShaderProgram>("#ForwardPlusSkinnedProgram")->ResourceID;
|
||||
} else {
|
||||
newMaterialProperty.ShaderID = ResourceManager::Load<ShaderProgram>("#ForwardPlusProgram")->ResourceID;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw Resource::FailedLoadingException("Material contains an unknown MaterialType");
|
||||
|
||||
@@ -9,10 +9,11 @@ RenderSystem::RenderSystem(SystemParams params, const IRenderer* renderer, Rende
|
||||
, m_Octree(frustumCullOctree)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EResolutionChanged, &RenderSystem::OnResolutionChanged);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &RenderSystem::OnPlayerSpawned);
|
||||
|
||||
m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 5000.f);
|
||||
m_Camera = new Camera((float)m_Renderer->GetViewportSize().Width / m_Renderer->GetViewportSize().Height, glm::radians(45.f), 0.01f, 5000.f);
|
||||
}
|
||||
|
||||
RenderSystem::~RenderSystem()
|
||||
@@ -20,11 +21,18 @@ RenderSystem::~RenderSystem()
|
||||
delete m_Camera;
|
||||
}
|
||||
|
||||
bool RenderSystem::OnResolutionChanged(Events::ResolutionChanged& e)
|
||||
{
|
||||
// Update camera aspect ration on resolution change
|
||||
m_Camera->SetAspectRatio((float)e.NewResolution.Width / e.NewResolution.Height);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderSystem::OnSetCamera(Events::SetCamera& e)
|
||||
{
|
||||
ComponentWrapper cTransform = e.CameraEntity["Transform"];
|
||||
ComponentWrapper cCamera = e.CameraEntity["Camera"];
|
||||
m_Camera->SetFOV((double)cCamera["FOV"]);
|
||||
m_Camera->SetFOV(glm::radians((double)cCamera["FOV"]));
|
||||
m_Camera->SetNearClip((double)cCamera["NearClip"]);
|
||||
m_Camera->SetFarClip((double)cCamera["FarClip"]);
|
||||
m_Camera->SetPosition(cTransform["Position"]);
|
||||
@@ -63,7 +71,7 @@ void RenderSystem::fillSprites(std::list<std::shared_ptr<RenderJob>>& jobs, Worl
|
||||
float minScale = (float)(double)indicator["MinScale"];
|
||||
bool hasTeam = indicator["VisibleForSingleTeamOnly"];
|
||||
isIndicator = true;
|
||||
glm::vec3 pos = Transform::AbsolutePosition(entity);
|
||||
glm::vec3 pos = TransformSystem::AbsolutePosition(entity);
|
||||
|
||||
|
||||
EntityWrapper entityTeam;
|
||||
@@ -130,7 +138,7 @@ void RenderSystem::fillSprites(std::list<std::shared_ptr<RenderJob>>& jobs, Worl
|
||||
modelMatrix[3][2] = pos.z;
|
||||
modelMatrix[3][3] = 1.0f;
|
||||
|
||||
glm::mat4 tranformationMatrix = modelMatrix * glm::scale(Transform::AbsoluteScale(entity));
|
||||
glm::mat4 tranformationMatrix = modelMatrix * glm::scale(TransformSystem::AbsoluteScale(entity));
|
||||
glm::vec4 tmp = tranformationMatrix * glm::vec4(glm::vec3(0.5, 0.5, 0), 1.0f);
|
||||
glm::vec2 projectedTopRight = m_Camera->WorldToScreen(glm::vec3(tmp), m_Renderer->GetViewportSize());
|
||||
tmp = tranformationMatrix * glm::vec4(glm::vec3(-0.5, -0.5, 0), 1.0f);
|
||||
@@ -143,7 +151,7 @@ void RenderSystem::fillSprites(std::list<std::shared_ptr<RenderJob>>& jobs, Worl
|
||||
modelMatrix = tranformationMatrix;
|
||||
}
|
||||
else {
|
||||
modelMatrix = Transform::ModelMatrix(entity.ID, world);
|
||||
modelMatrix = TransformSystem::ModelMatrix(entity.ID, world);
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +184,7 @@ bool RenderSystem::isEntityVisible(EntityWrapper& entity)
|
||||
}
|
||||
|
||||
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
|
||||
bool outOfBodyExperience = ResourceManager::Load<ConfigFile>("Config.ini")->Get<bool>("Debug.OutOfBodyExperience", false);
|
||||
bool outOfBodyExperience = false; // ResourceManager::Load<ConfigFile>("Config.ini")->Get<bool>("Debug.OutOfBodyExperience", false);
|
||||
if (
|
||||
(entity.HasComponent("HiddenForLocalPlayer") || entity.FirstParentWithComponent("HiddenForLocalPlayer").Valid())
|
||||
&& (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))
|
||||
@@ -242,7 +250,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs)
|
||||
|
||||
bool isShielded = m_World->HasComponent(cModel.EntityID, "Shielded") || m_World->HasComponent(cModel.EntityID, "Player");
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World);
|
||||
glm::mat4 modelMatrix = TransformSystem::ModelMatrix(cModel.EntityID, m_World);
|
||||
//Loop through all materialgroups of a model
|
||||
for (auto matGroup : model->MaterialGroups()) {
|
||||
//If the model has an explosioneffect component, we will add an explosioneffectjob
|
||||
@@ -258,7 +266,8 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs)
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage,
|
||||
isShielded
|
||||
isShielded,
|
||||
false
|
||||
));
|
||||
if (m_World->HasComponent(cModel.EntityID, "Shield")){
|
||||
explosionEffectJob->CalculateHash();
|
||||
@@ -296,7 +305,8 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs)
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage,
|
||||
isShielded
|
||||
isShielded,
|
||||
(bool)cModel["Shadow"]
|
||||
));
|
||||
if (m_World->HasComponent(cModel.EntityID, "Shield")) {
|
||||
modelJob->CalculateHash();
|
||||
@@ -352,6 +362,11 @@ void RenderSystem::fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs,
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityWrapper entity(world, pointlightC.EntityID);
|
||||
if (!isEntityVisible(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::shared_ptr<PointLightJob> pointLightJob = std::shared_ptr<PointLightJob>(new PointLightJob(transformC, pointlightC, m_World));
|
||||
jobs.push_back(pointLightJob);
|
||||
}
|
||||
@@ -412,7 +427,7 @@ void RenderSystem::fillText(std::list<std::shared_ptr<RenderJob>>& jobs, World*
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(textComponent.EntityID, world);
|
||||
glm::mat4 modelMatrix = TransformSystem::ModelMatrix(textComponent.EntityID, world);
|
||||
std::shared_ptr<TextJob> textJob = std::shared_ptr<TextJob>(new TextJob(modelMatrix, font, textComponent));
|
||||
jobs.push_back(textJob);
|
||||
|
||||
@@ -430,11 +445,12 @@ void RenderSystem::Update(double dt)
|
||||
|
||||
// Update the current camera used for rendering
|
||||
if (m_CurrentCamera.Valid()) {
|
||||
m_Camera->SetPosition(Transform::AbsolutePosition(m_CurrentCamera));
|
||||
m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera));
|
||||
m_Camera->SetPosition(TransformSystem::AbsolutePosition(m_CurrentCamera));
|
||||
m_Camera->SetOrientation(TransformSystem::AbsoluteOrientation(m_CurrentCamera));
|
||||
}
|
||||
|
||||
RenderScene scene;
|
||||
scene.ShouldBlur = true;
|
||||
scene.Camera = m_Camera;
|
||||
scene.Viewport = Rectangle(1280, 720);
|
||||
|
||||
@@ -448,7 +464,7 @@ void RenderSystem::Update(double dt)
|
||||
fillModels(scene.Jobs);
|
||||
fillPointLights(scene.Jobs.PointLight, m_World);
|
||||
//TODO: Make sure all objects needed are also sorted.
|
||||
scene.Jobs.OpaqueObjects.sort();
|
||||
scene.Jobs.OpaqueObjects.sort([](auto& a, auto& b) {return *a < *b; });
|
||||
fillSprites(scene.Jobs.SpriteJob, m_World);
|
||||
fillDirectionalLights(scene.Jobs.DirectionalLight, m_World);
|
||||
fillText(scene.Jobs.Text, m_World);
|
||||
|
||||
@@ -2,6 +2,19 @@
|
||||
|
||||
std::unordered_map<GLFWwindow*, Renderer*> Renderer::m_WindowToRenderer;
|
||||
|
||||
Renderer::~Renderer() {
|
||||
delete m_PickingPass;
|
||||
delete m_LightCullingPass;
|
||||
delete m_ImGuiRenderPass;
|
||||
delete m_DrawFinalPass;
|
||||
delete m_DrawScreenQuadPass;
|
||||
delete m_DrawBloomPass;
|
||||
delete m_DrawColorCorrectionPass;
|
||||
delete m_SSAOPass;
|
||||
delete m_CubeMapPass;
|
||||
delete m_TextPass;
|
||||
}
|
||||
|
||||
void Renderer::Initialize()
|
||||
{
|
||||
m_SSAO_Quality = m_Config->Get<int>("SSAO.Quality", 0);
|
||||
@@ -17,22 +30,30 @@ void Renderer::Initialize()
|
||||
m_TextPass->Initialize();
|
||||
|
||||
/* m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
||||
m_UnitQuad = ResourceManager::Load<Model>(sModels/Core/UnitQuad.obj");
|
||||
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");*/
|
||||
|
||||
m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker);
|
||||
}
|
||||
|
||||
void Renderer::glfwWindowSizeCallback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
m_WindowToRenderer[window]->setWindowSize(Rectangle(width, height));
|
||||
}
|
||||
|
||||
void Renderer::glfwFrameBufferCallback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
Renderer* currentRenderer = m_WindowToRenderer[window];
|
||||
currentRenderer->m_ViewportSize = Rectangle(width, height);
|
||||
currentRenderer->m_PickingPass->OnWindowResize();
|
||||
currentRenderer->m_DrawFinalPass->OnWindowResize();
|
||||
currentRenderer->m_LightCullingPass->OnWindowResize();
|
||||
currentRenderer->m_DrawBloomPass->OnWindowResize();
|
||||
currentRenderer->m_SSAOPass->OnWindowResize();
|
||||
m_WindowToRenderer[window]->updateFramebufferSize();
|
||||
}
|
||||
|
||||
void Renderer::SetResolution(const Rectangle& resolution)
|
||||
{
|
||||
m_Resolution = resolution;
|
||||
|
||||
if (m_Window != nullptr) {
|
||||
setWindowSize(resolution);
|
||||
updateFramebufferSize();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::InitializeWindow()
|
||||
@@ -46,14 +67,24 @@ void Renderer::InitializeWindow()
|
||||
// Create a window
|
||||
GLFWmonitor* monitor = nullptr;
|
||||
if (m_Fullscreen) {
|
||||
monitor = glfwGetPrimaryMonitor();
|
||||
//monitor = glfwGetPrimaryMonitor();
|
||||
//const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
|
||||
//glfwWindowHint(GLFW_RED_BITS, mode->redBits);
|
||||
//glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
|
||||
//glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
|
||||
//glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
|
||||
glfwWindowHint(GLFW_DECORATED, false);
|
||||
glfwWindowHint(GLFW_AUTO_ICONIFY, false);
|
||||
}
|
||||
//glfwWindowHint(GLFW_SAMPLES, 8);
|
||||
m_Window = glfwCreateWindow(m_Resolution.Width, m_Resolution.Height, "daydream", monitor, nullptr);
|
||||
|
||||
//glfwWindowHint(GLFW_SAMPLES, 8);
|
||||
m_Window = glfwCreateWindow(m_Resolution.Width, m_Resolution.Height + 1, "daydream", monitor, nullptr);
|
||||
if (!m_Window) {
|
||||
LOG_ERROR("GLFW: Failed to create window");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
glfwSetWindowSizeCallback(m_Window, &glfwWindowSizeCallback);
|
||||
glfwSetFramebufferSizeCallback(m_Window, &glfwFrameBufferCallback);
|
||||
glfwMakeContextCurrent(m_Window);
|
||||
|
||||
@@ -98,6 +129,32 @@ void Renderer::InputUpdate(double dt)
|
||||
|
||||
}
|
||||
|
||||
void Renderer::setWindowSize(Rectangle size)
|
||||
{
|
||||
m_Resolution = size;
|
||||
glfwSetWindowSize(m_Window, size.Width, size.Height);
|
||||
}
|
||||
|
||||
void Renderer::updateFramebufferSize()
|
||||
{
|
||||
Events::ResolutionChanged e;
|
||||
e.OldResolution = m_ViewportSize;
|
||||
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(m_Window, &width, &height);
|
||||
glViewport(0, 0, width, height);
|
||||
m_ViewportSize = Rectangle(width, height);
|
||||
m_PickingPass->OnWindowResize();
|
||||
m_DrawFinalPass->OnWindowResize();
|
||||
m_LightCullingPass->OnWindowResize();
|
||||
m_DrawBloomPass->OnWindowResize();
|
||||
m_SSAOPass->OnWindowResize();
|
||||
m_BlurHUDPass->OnWindowResize();
|
||||
|
||||
e.NewResolution = m_ViewportSize;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
void Renderer::Update(double dt)
|
||||
{
|
||||
m_EventBroker->Process<Renderer>();
|
||||
@@ -110,7 +167,7 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
{
|
||||
GLERROR("PRE");
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0Gaussian\0Picking\0Ambient Occlusion");
|
||||
ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0Gaussian\0Picking\0Ambient Occlusion\0Combined Scene Texture\0Full Blurred Texture");
|
||||
ImGui::Combo("CubeMap", &m_CubeMapTexture, "Nevada(512)\0Sky(1024)");
|
||||
if(m_CubeMapTexture == 0) {
|
||||
m_CubeMapPass->LoadTextures("Nevada");
|
||||
@@ -120,8 +177,10 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
|
||||
ImGui::SliderInt("SSAO Quality", &m_SSAO_Quality, 0, 3);
|
||||
ImGui::SliderInt("Glow Quality", &m_GLOW_Quality, 0, 3);
|
||||
ImGui::SliderInt("MSAA Level", (int*)&m_MSAA_Level, 0, 16);
|
||||
m_SSAOPass->ChangeQuality(m_SSAO_Quality);
|
||||
m_DrawBloomPass->ChangeQuality(m_GLOW_Quality);
|
||||
m_DrawFinalPass->setMSAA(m_MSAA_Level);
|
||||
GLERROR("SSAO Settings");
|
||||
//clear buffer 0
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
@@ -133,6 +192,9 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
m_DrawFinalPass->ClearBuffer();
|
||||
m_DrawBloomPass->ClearBuffer();
|
||||
m_SSAOPass->ClearBuffer();
|
||||
m_ShadowPass->ClearBuffer();
|
||||
m_BlurHUDPass->ClearBuffer();
|
||||
m_ShadowPass->DebugGUI();
|
||||
PerformanceTimer::StopTimer("Renderer-ClearBuffers");
|
||||
GLERROR("ClearBuffers");
|
||||
for (auto scene : frame.RenderScenes) {
|
||||
@@ -148,6 +210,9 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
PerformanceTimer::StartTimer("Renderer-Depth");
|
||||
SortRenderJobsByDepth(*scene);
|
||||
GLERROR("SortByDepth");
|
||||
PerformanceTimer::StartTimerAndStopPrevious("Draw shadow maps");
|
||||
m_ShadowPass->Draw(*scene);
|
||||
GLERROR("Draw shadow maps");
|
||||
PerformanceTimer::StartTimerAndStopPrevious("Renderer-Generate Frustrums");
|
||||
m_LightCullingPass->GenerateNewFrustum(*scene);
|
||||
GLERROR("Generate frustums");
|
||||
@@ -158,7 +223,7 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
m_LightCullingPass->CullLights(*scene);
|
||||
GLERROR("LightCulling");
|
||||
PerformanceTimer::StartTimerAndStopPrevious("Renderer-Draw Geometry+Light");
|
||||
m_DrawFinalPass->Draw(*scene);
|
||||
m_DrawFinalPass->Draw(*scene, m_BlurHUDPass);
|
||||
GLERROR("Draw Geometry+Light");
|
||||
//m_DrawScenePass->Draw(*scene);
|
||||
|
||||
@@ -174,7 +239,8 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
|
||||
if (m_DebugTextureToDraw == 0) {
|
||||
PerformanceTimer::StartTimer("Renderer-Color Correction Pass");
|
||||
m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), frame.Gamma, frame.Exposure);
|
||||
GLuint test = m_DrawFinalPass->SceneTexture();
|
||||
m_DrawColorCorrectionPass->Draw(test, m_DrawBloomPass->GaussianTexture(), frame.Gamma, frame.Exposure);
|
||||
PerformanceTimer::StopTimer("Renderer-Color Correction Pass");
|
||||
}
|
||||
|
||||
@@ -194,6 +260,12 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
if (m_DebugTextureToDraw == 5) {
|
||||
m_DrawScreenQuadPass->Draw(m_SSAOPass->SSAOTexture());
|
||||
}
|
||||
if (m_DebugTextureToDraw == 6) {
|
||||
m_DrawScreenQuadPass->Draw(m_DrawFinalPass->CombinedSceneTexture());
|
||||
}
|
||||
if (m_DebugTextureToDraw == 7) {
|
||||
m_DrawScreenQuadPass->Draw(m_DrawFinalPass->FullBlurredTexture());
|
||||
}
|
||||
PerformanceTimer::StopTimer("Renderer-Misc Debug Draws");
|
||||
|
||||
PerformanceTimer::StartTimer("Renderer-ImGuiRenderPass");
|
||||
@@ -213,8 +285,8 @@ PickData Renderer::Pick(glm::vec2 screenCoord)
|
||||
|
||||
void Renderer::InitializeTextures()
|
||||
{
|
||||
m_ErrorTexture = CommonFunctions::LoadTexture("Textures/Core/ErrorTexture.png", false);
|
||||
m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false);
|
||||
m_ErrorTexture = CommonFunctions::TryLoadResource<Texture, false>("Textures/Core/ErrorTexture.png");
|
||||
m_WhiteTexture = CommonFunctions::TryLoadResource<Texture, false>("Textures/Core/White.png");
|
||||
}
|
||||
|
||||
|
||||
@@ -238,15 +310,18 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin
|
||||
GLERROR("Texture initialization failed");
|
||||
}
|
||||
|
||||
|
||||
void Renderer::InitializeRenderPasses()
|
||||
{
|
||||
m_PickingPass = new PickingPass(this, m_EventBroker);
|
||||
m_LightCullingPass = new LightCullingPass(this);
|
||||
m_CubeMapPass = new CubeMapPass(this);
|
||||
m_SSAOPass = new SSAOPass(this, m_Config);
|
||||
m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass, m_CubeMapPass, m_SSAOPass);
|
||||
m_ShadowPass = new ShadowPass(this);
|
||||
m_BlurHUDPass = new BlurHUD(this);
|
||||
m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass, m_CubeMapPass, m_SSAOPass, m_ShadowPass, m_Config);
|
||||
m_DrawScreenQuadPass = new DrawScreenQuadPass(this);
|
||||
m_DrawBloomPass = new DrawBloomPass(this, m_Config);
|
||||
m_DrawColorCorrectionPass = new DrawColorCorrectionPass(this);
|
||||
|
||||
|
||||
}
|
||||
@@ -4,12 +4,19 @@ SSAOPass::SSAOPass(IRenderer* renderer, ConfigFile* config)
|
||||
: m_Renderer(renderer)
|
||||
, m_Config(config)
|
||||
{
|
||||
m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false);
|
||||
m_WhiteTexture = CommonFunctions::TryLoadResource<Texture, false>("Textures/Core/White.png");
|
||||
|
||||
ChangeQuality(m_Config->Get<int>("SSAO.Quality", 0));
|
||||
|
||||
}
|
||||
|
||||
SSAOPass::~SSAOPass() {
|
||||
CommonFunctions::DeleteTexture(&m_SSAOTexture);
|
||||
CommonFunctions::DeleteTexture(&m_SSAOViewSpaceZTexture);
|
||||
CommonFunctions::DeleteTexture(&m_Gaussian_horiz);
|
||||
CommonFunctions::DeleteTexture(&m_Gaussian_vert);
|
||||
}
|
||||
|
||||
void SSAOPass::ChangeQuality(int quality)
|
||||
{
|
||||
if (m_Quality == quality) {
|
||||
@@ -56,6 +63,7 @@ void SSAOPass::InitializeShaderProgram()
|
||||
m_SSAOProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/SSAO.vert.glsl")));
|
||||
m_SSAOProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/SSAO.frag.glsl")));
|
||||
m_SSAOProgram->Compile();
|
||||
m_SSAOProgram->BindFragDataLocation(0, "AO");
|
||||
m_SSAOProgram->Link();
|
||||
}
|
||||
|
||||
@@ -64,6 +72,7 @@ void SSAOPass::InitializeShaderProgram()
|
||||
m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/SSAO.vert.glsl")));
|
||||
m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/SSAOViewSpaceZ.frag.glsl")));
|
||||
m_SSAOViewSpaceZProgram->Compile();
|
||||
m_SSAOViewSpaceZProgram->BindFragDataLocation(0, "depthLinear");
|
||||
m_SSAOViewSpaceZProgram->Link();
|
||||
}
|
||||
|
||||
@@ -72,6 +81,7 @@ void SSAOPass::InitializeShaderProgram()
|
||||
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_horiz.vert.glsl")));
|
||||
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl")));
|
||||
m_GaussianProgram_horiz->Compile();
|
||||
m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor");
|
||||
m_GaussianProgram_horiz->Link();
|
||||
}
|
||||
|
||||
@@ -80,6 +90,7 @@ void SSAOPass::InitializeShaderProgram()
|
||||
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_vert.vert.glsl")));
|
||||
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_vert.frag.glsl")));
|
||||
m_GaussianProgram_vert->Compile();
|
||||
m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor");
|
||||
m_GaussianProgram_vert->Link();
|
||||
}
|
||||
}
|
||||
@@ -222,6 +233,11 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
|
||||
GLuint shaderHandle_horiz = m_GaussianProgram_horiz->GetHandle();
|
||||
GLuint shaderHandle_vert = m_GaussianProgram_vert->GetHandle();
|
||||
|
||||
m_GaussianProgram_vert->Bind();
|
||||
glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), 0);
|
||||
m_GaussianProgram_horiz->Bind();
|
||||
glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), 0);
|
||||
|
||||
m_GaussianFrameBuffer_horiz.Bind();
|
||||
m_GaussianProgram_horiz->Bind();
|
||||
|
||||
@@ -241,8 +257,6 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_Gaussian_horiz);
|
||||
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex + 1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
//horizontal pass
|
||||
@@ -254,8 +268,6 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_Gaussian_vert);
|
||||
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex + 1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
m_GaussianFrameBuffer_horiz.Unbind();
|
||||
@@ -268,8 +280,7 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_Gaussian_horiz);
|
||||
glBindVertexArray(m_ScreenQuad->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer);
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex + 1
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex);
|
||||
|
||||
|
||||
@@ -4,22 +4,32 @@ GLuint Shader::CompileShader(GLenum shaderType, std::string fileName)
|
||||
{
|
||||
LOG_INFO("Compiling shader \"%s\"", fileName.c_str());
|
||||
|
||||
std::string shaderFile;
|
||||
std::ifstream in(fileName, std::ios::in);
|
||||
if (!in) {
|
||||
LOG_ERROR("Error: Failed to open shader file \"%s\"", fileName.c_str());
|
||||
return 0;
|
||||
}
|
||||
in.seekg(0, std::ios::end);
|
||||
shaderFile.resize((int)in.tellg());
|
||||
in.seekg(0, std::ios::beg);
|
||||
in.read(&shaderFile[0], shaderFile.size());
|
||||
in.close();
|
||||
std::string shaderFile = ReadFile(fileName);
|
||||
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
if (GLERROR("glCreateShader"))
|
||||
return 0;
|
||||
|
||||
std::size_t startPos = 0;
|
||||
std::size_t SEofNewFile[2];
|
||||
std::string key = "#include";
|
||||
while((startPos = shaderFile.find(key, startPos)) != std::string::npos)
|
||||
{
|
||||
SEofNewFile[0] = shaderFile.find('"', startPos+key.length())+1;
|
||||
SEofNewFile[1] = shaderFile.find('"', SEofNewFile[0]);
|
||||
if (SEofNewFile[0] == std::string::npos || SEofNewFile[1] == std::string::npos)
|
||||
return 0;
|
||||
|
||||
std::string replacementFileName = shaderFile.substr(SEofNewFile[0], SEofNewFile[1] - SEofNewFile[0]);
|
||||
std::string replacementString = ReadFile(replacementFileName);
|
||||
size_t firstof = replacementString.find_first_of((char)0);
|
||||
replacementString.erase(firstof, replacementString.size() - firstof);
|
||||
if (replacementString.length() <= 0)
|
||||
return 0;
|
||||
shaderFile.replace(startPos, SEofNewFile[1]+2 - startPos, replacementString + "\n");
|
||||
startPos += replacementString.length(); //This might not be wanted.
|
||||
}
|
||||
|
||||
const GLchar* shaderFiles = shaderFile.c_str();
|
||||
const GLint length = static_cast<GLint>(shaderFile.length());
|
||||
glShaderSource(shader, 1, &shaderFiles, &length);
|
||||
@@ -46,6 +56,24 @@ GLuint Shader::CompileShader(GLenum shaderType, std::string fileName)
|
||||
return shader;
|
||||
}
|
||||
|
||||
std::string Shader::ReadFile(std::string fileName)
|
||||
{
|
||||
std::string shaderFile;
|
||||
std::ifstream in(fileName, std::ios::in);
|
||||
if (!in) {
|
||||
LOG_ERROR("Error: Failed to open shader file \"%s\"", fileName.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
in.seekg(0, std::ios::end);
|
||||
shaderFile.resize((int)in.tellg());
|
||||
in.seekg(0, std::ios::beg);
|
||||
in.read(&shaderFile[0], shaderFile.size());
|
||||
in.close();
|
||||
return shaderFile;
|
||||
}
|
||||
|
||||
|
||||
Shader::Shader(GLenum shaderType, std::string fileName) : m_ShaderType(shaderType), m_FileName(fileName)
|
||||
{
|
||||
m_ShaderHandle = 0;
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
#include "Rendering/ShadowPass.h"
|
||||
|
||||
ShadowPass::ShadowPass(IRenderer * renderer, int shadow_res_x, int shadow_res_y)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
m_ResolutionSizeWidth = shadow_res_x;
|
||||
m_ResolutionSizeHeight = shadow_res_y;
|
||||
|
||||
InitializeFrameBuffers();
|
||||
InitializeShaderPrograms();
|
||||
}
|
||||
|
||||
ShadowPass::ShadowPass(IRenderer * renderer)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
|
||||
InitializeFrameBuffers();
|
||||
InitializeShaderPrograms();
|
||||
}
|
||||
|
||||
ShadowPass::~ShadowPass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ShadowPass::DebugGUI()
|
||||
{
|
||||
ImGui::Checkbox("EnableShadows", &m_EnableShadows);
|
||||
ImGui::DragFloat2("ShadowMapNearFar", m_NearFarPlane, 1.f, -1000.f, 1000.f);
|
||||
ImGui::DragFloat("ShadowClippingWeight", &m_SplitWeight, 0.001f, 0.f, 1.f);
|
||||
ImGui::Checkbox("ShadowTransparentObjects", &m_TransparentObjects);
|
||||
ImGui::Checkbox("ShadowOnTextureAlphas", &m_TexturedShadows);
|
||||
}
|
||||
|
||||
void ShadowPass::InitializeCameras(RenderScene & scene)
|
||||
{
|
||||
for (int i = 0; i < m_CurrentNrOfSplits; i++) {
|
||||
m_shadowFrusta[i].AspectRatio = scene.Camera->AspectRatio();
|
||||
m_shadowFrusta[i].FOV = scene.Camera->FOV();
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateSplitDist computes the near and far distances for every frustum slice
|
||||
// in camera eye space - that is, at what distance does a slice start and end
|
||||
void ShadowPass::UpdateSplitDist(std::array<ShadowFrustum, MAX_SPLITS>& frusta, float near_distance, float far_distance)
|
||||
{
|
||||
float lambda = m_SplitWeight;
|
||||
float ratio = far_distance / near_distance;
|
||||
|
||||
frusta[0].NearClip = near_distance;
|
||||
|
||||
for (int i = 1; i < m_CurrentNrOfSplits; i++) {
|
||||
float si = i / static_cast<float>(m_CurrentNrOfSplits);
|
||||
|
||||
frusta[i].NearClip = lambda * (near_distance * powf(ratio, si)) + (1 - lambda) * (near_distance + (far_distance - near_distance) * si);
|
||||
frusta[i - 1].FarClip = frusta[i].NearClip * 1.005f;
|
||||
}
|
||||
|
||||
frusta[m_CurrentNrOfSplits - 1].FarClip = far_distance;
|
||||
}
|
||||
|
||||
void ShadowPass::UpdateFrustumPoints(ShadowFrustum& frustum, glm::mat4 p, glm::mat4 v)
|
||||
{
|
||||
std::array<glm::vec4, 8> CornerPoint = {
|
||||
glm::vec4(-1.f, -1.f, -1.f, 1.f),
|
||||
glm::vec4(-1.f, 1.f, -1.f, 1.f),
|
||||
glm::vec4(1.f, 1.f, -1.f, 1.f),
|
||||
glm::vec4(1.f, -1.f, -1.f, 1.f),
|
||||
glm::vec4(-1.f, -1.f, 1.f, 1.f),
|
||||
glm::vec4(-1.f, 1.f, 1.f, 1.f),
|
||||
glm::vec4(1.f, 1.f, 1.f, 1.f),
|
||||
glm::vec4(1.f, -1.f, 1.f, 1.f)
|
||||
};
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
glm::vec4 NDC = glm::inverse(p) * CornerPoint[i];
|
||||
NDC = NDC / NDC.w;
|
||||
frustum.CornerPoint[i] = glm::vec3(glm::inverse(v) * NDC);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the 8 corner points of the current view frustum in world space
|
||||
void ShadowPass::UpdateFrustumPoints(ShadowFrustum& frustum, glm::vec3 camera_position, glm::vec3 view_dir)
|
||||
{
|
||||
glm::vec3 up = glm::vec3(0.f, 1.f, 0.f);
|
||||
glm::vec3 right = glm::normalize(glm::cross(view_dir, up));
|
||||
|
||||
glm::vec3 far_center = camera_position + glm::normalize(view_dir) * frustum.FarClip;
|
||||
glm::vec3 near_center = camera_position + glm::normalize(view_dir) * frustum.NearClip;
|
||||
frustum.MiddlePoint = near_center + (far_center - near_center) * 0.5f;
|
||||
|
||||
up = glm::normalize(glm::cross(right, view_dir));
|
||||
|
||||
// these heights and widths are half the heights and widths of the near and far plane rectangles.
|
||||
float near_height = tan(frustum.FOV / 2.f) * frustum.NearClip;
|
||||
float near_width = near_height * frustum.AspectRatio;
|
||||
float far_height = tan(frustum.FOV / 2.f) * frustum.FarClip;
|
||||
float far_width = far_height * frustum.AspectRatio;
|
||||
|
||||
frustum.CornerPoint[0] = near_center - up * near_height - right * near_width;
|
||||
frustum.CornerPoint[1] = near_center + up * near_height - right * near_width;
|
||||
frustum.CornerPoint[2] = near_center + up * near_height + right * near_width;
|
||||
frustum.CornerPoint[3] = near_center - up * near_height + right * near_width;
|
||||
|
||||
frustum.CornerPoint[4] = far_center - up * far_height - right * far_width;
|
||||
frustum.CornerPoint[5] = far_center + up * far_height - right * far_width;
|
||||
frustum.CornerPoint[6] = far_center + up * far_height + right * far_width;
|
||||
frustum.CornerPoint[7] = far_center - up * far_height + right * far_width;
|
||||
}
|
||||
|
||||
float ShadowPass::FindRadius(ShadowFrustum& frustum)
|
||||
{
|
||||
float radius = 0.f;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
float distance = glm::distance(frustum.MiddlePoint, frustum.CornerPoint[i]);
|
||||
if (distance > radius) {
|
||||
radius = distance;
|
||||
}
|
||||
}
|
||||
|
||||
frustum.Radius = radius;
|
||||
return radius;
|
||||
}
|
||||
|
||||
void ShadowPass::InitializeFrameBuffers()
|
||||
{
|
||||
// Depth texture
|
||||
glGenTextures(1, &m_DepthMap);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_DepthMap);
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH_COMPONENT16, m_ResolutionSizeWidth, m_ResolutionSizeHeight, m_CurrentNrOfSplits);
|
||||
|
||||
//glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, m_ResolutionSizeWidth, m_ResolutionSizeHeight, m_CurrentNrOfSplits, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||
glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, glm::vec4(1.f).data);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||
|
||||
m_DepthBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2DArray(&m_DepthMap, GL_DEPTH_ATTACHMENT)));
|
||||
m_DepthBuffer.Generate();
|
||||
|
||||
GLERROR("depthMap failed END");
|
||||
}
|
||||
|
||||
void ShadowPass::InitializeShaderPrograms()
|
||||
{
|
||||
m_ShadowProgram = ResourceManager::Load<ShaderProgram>("#ShadowProgram");
|
||||
m_ShadowProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Shadow.vert.glsl")));
|
||||
m_ShadowProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Shadow.frag.glsl")));
|
||||
m_ShadowProgram->Compile();
|
||||
m_ShadowProgram->BindFragDataLocation(0, "ShadowMap");
|
||||
m_ShadowProgram->Link();
|
||||
|
||||
m_ShadowProgramSkinned = ResourceManager::Load<ShaderProgram>("#ShadowProgramSkinned");
|
||||
m_ShadowProgramSkinned->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ShadowSkinned.vert.glsl")));
|
||||
m_ShadowProgramSkinned->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Shadow.frag.glsl")));
|
||||
m_ShadowProgramSkinned->Compile();
|
||||
m_ShadowProgramSkinned->BindFragDataLocation(0, "ShadowMap");
|
||||
m_ShadowProgramSkinned->Link();
|
||||
}
|
||||
|
||||
void ShadowPass::ClearBuffer()
|
||||
{
|
||||
m_DepthBuffer.Bind();
|
||||
|
||||
for (int i = 0; i < m_CurrentNrOfSplits; i++) {
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_DepthMap, 0, i);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
m_DepthBuffer.Unbind();
|
||||
}
|
||||
|
||||
void ShadowPass::PointsToLightspace(ShadowFrustum& frustum, glm::mat4 v)
|
||||
{
|
||||
float left = INFINITY;
|
||||
float right = -INFINITY;
|
||||
float bottom = INFINITY;
|
||||
float top = -INFINITY;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
glm::vec3 tempPoint = glm::vec3(v * glm::vec4(frustum.CornerPoint[i], 1.f));
|
||||
|
||||
if (tempPoint.x < left) { left = tempPoint.x; }
|
||||
if (tempPoint.x > right) { right = tempPoint.x; }
|
||||
if (tempPoint.y < bottom) { bottom = tempPoint.y; }
|
||||
if (tempPoint.y > top) { top = tempPoint.y; }
|
||||
}
|
||||
|
||||
frustum.LRBT = { left, right, bottom, top };
|
||||
}
|
||||
|
||||
void ShadowPass::RadiusToLightspace(ShadowFrustum& frustum)
|
||||
{
|
||||
float quantizationStep = 1.0f / m_ResolutionSizeHeight;
|
||||
|
||||
float left = -frustum.Radius;
|
||||
float right = frustum.Radius;
|
||||
float bottom = -frustum.Radius;
|
||||
float top = frustum.Radius;
|
||||
|
||||
frustum.LRBT = { left, right, bottom, top };
|
||||
}
|
||||
|
||||
void ShadowPass::Draw(RenderScene & scene)
|
||||
{
|
||||
if (m_EnableShadows) {
|
||||
InitializeCameras(scene);
|
||||
UpdateSplitDist(m_shadowFrusta, scene.Camera->NearClip(), scene.Camera->FarClip());
|
||||
|
||||
ShadowPassState* state = new ShadowPassState(m_DepthBuffer.GetHandle());
|
||||
|
||||
|
||||
glViewport(0, 0, m_ResolutionSizeWidth, m_ResolutionSizeHeight);
|
||||
|
||||
for (int i = 0; i < m_CurrentNrOfSplits; i++) {
|
||||
UpdateFrustumPoints(m_shadowFrusta[i], scene.Camera->Position(), scene.Camera->Forward());
|
||||
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_DepthMap, 0, i);
|
||||
|
||||
|
||||
GLuint shaderHandle = 0;
|
||||
GLuint lastModel = 0;
|
||||
for (auto &job : scene.Jobs.DirectionalLight) {
|
||||
|
||||
auto directionalLightJob = std::dynamic_pointer_cast<DirectionalLightJob>(job);
|
||||
|
||||
if (directionalLightJob) {
|
||||
m_LightView[i] = glm::lookAt(glm::vec3(-directionalLightJob->Direction) + m_shadowFrusta[i].MiddlePoint, m_shadowFrusta[i].MiddlePoint, glm::vec3(0.f, 1.f, 0.f));
|
||||
|
||||
PointsToLightspace(m_shadowFrusta[i], m_LightView[i]);
|
||||
//FindRadius(m_shadowFrusta[i]);
|
||||
//RadiusToLightspace(m_shadowFrusta[i]);
|
||||
m_LightProjection[i] = glm::ortho(m_shadowFrusta[i].LRBT[LEFT], m_shadowFrusta[i].LRBT[RIGHT], m_shadowFrusta[i].LRBT[BOTTOM], m_shadowFrusta[i].LRBT[TOP], m_NearFarPlane[NEAR], m_NearFarPlane[FAR]);
|
||||
|
||||
GLERROR("ShadowLight ERROR");
|
||||
|
||||
for (auto &objectJob : scene.Jobs.OpaqueObjects) {
|
||||
if (!std::dynamic_pointer_cast<ExplosionEffectJob>(objectJob)) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(objectJob);
|
||||
|
||||
if (!modelJob->Shadow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(modelJob->Model->IsSkinned()) {
|
||||
if (shaderHandle != m_ShadowProgramSkinned->GetHandle()) {
|
||||
m_ShadowProgramSkinned->Bind();
|
||||
shaderHandle = m_ShadowProgramSkinned->GetHandle();
|
||||
}
|
||||
|
||||
std::vector<glm::mat4> frameBones;
|
||||
if (modelJob->BlendTree != nullptr) {
|
||||
frameBones = modelJob->BlendTree->GetFinalPose();
|
||||
} else {
|
||||
frameBones = modelJob->Skeleton->GetTPose();
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
|
||||
} else {
|
||||
if (shaderHandle != m_ShadowProgram->GetHandle()) {
|
||||
m_ShadowProgram->Bind();
|
||||
shaderHandle = m_ShadowProgram->GetHandle();
|
||||
}
|
||||
}
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(m_LightProjection[i] * m_LightView[i] * modelJob->Matrix));
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "Alpha"), 1.f);
|
||||
|
||||
if (lastModel != modelJob->ModelID) {
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
}
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
|
||||
GLERROR("Shadow Draw ERROR");
|
||||
}
|
||||
}
|
||||
if (m_TransparentObjects) {
|
||||
state->CullFace(GL_BACK);
|
||||
for (auto &objectJob : scene.Jobs.TransparentObjects) {
|
||||
if (!std::dynamic_pointer_cast<ExplosionEffectJob>(objectJob)) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(objectJob);
|
||||
|
||||
if (!modelJob->Shadow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (modelJob->Model->IsSkinned()) {
|
||||
if (shaderHandle != m_ShadowProgramSkinned->GetHandle()) {
|
||||
m_ShadowProgramSkinned->Bind();
|
||||
shaderHandle = m_ShadowProgramSkinned->GetHandle();
|
||||
}
|
||||
|
||||
std::vector<glm::mat4> frameBones;
|
||||
if (modelJob->BlendTree != nullptr) {
|
||||
frameBones = modelJob->BlendTree->GetFinalPose();
|
||||
} else {
|
||||
frameBones = modelJob->Skeleton->GetTPose();
|
||||
}
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
|
||||
} else {
|
||||
if (shaderHandle != m_ShadowProgram->GetHandle()) {
|
||||
m_ShadowProgram->Bind();
|
||||
shaderHandle = m_ShadowProgram->GetHandle();
|
||||
}
|
||||
}
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "PVM"), 1, GL_FALSE, glm::value_ptr(m_LightProjection[i] * m_LightView[i] * modelJob->Matrix));
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "Alpha"), modelJob->Color.a);
|
||||
|
||||
if (m_TexturedShadows) {
|
||||
switch (modelJob->Type) {
|
||||
case RawModel::MaterialType::SingleTextures:
|
||||
case RawModel::MaterialType::Basic:
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE24);
|
||||
if (modelJob->DiffuseTexture.size() > 0 && modelJob->DiffuseTexture[0]->Texture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture[0]->Texture->m_Texture);
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(modelJob->DiffuseTexture[0]->UVRepeat));
|
||||
}
|
||||
else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RawModel::MaterialType::SplatMapping:
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE24);
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lastModel != modelJob->ModelID) {
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
}
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
|
||||
GLERROR("Shadow Draw ERROR");
|
||||
}
|
||||
}
|
||||
state->CullFace(GL_FRONT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
m_DepthBuffer.Unbind();
|
||||
delete state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "Rendering/ShadowPassState.h"
|
||||
|
||||
ShadowPassState::ShadowPassState(GLuint frameBuffer)
|
||||
{
|
||||
BindFramebuffer(frameBuffer);
|
||||
Enable(GL_DEPTH_TEST);
|
||||
Enable(GL_CULL_FACE);
|
||||
Disable(GL_BLEND);
|
||||
Disable(GL_TEXTURE_2D);
|
||||
CullFace(GL_FRONT);
|
||||
ClearColor(glm::vec4(0.f, 0.f, 0.f, 0.f));
|
||||
//Enable(GL_ALPHA_TEST);
|
||||
//glAlphaFunc(GL_GREATER, 0.9f);
|
||||
}
|
||||
|
||||
ShadowPassState::~ShadowPassState()
|
||||
{
|
||||
|
||||
}
|
||||
+255
-659
@@ -1,372 +1,149 @@
|
||||
#include "Rendering/Skeleton.h"
|
||||
|
||||
int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix)
|
||||
std::map<int, Skeleton::PoseData> Skeleton::GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion /*= false*/)
|
||||
{
|
||||
if (m_BonesByName.find(name) != m_BonesByName.end()) {
|
||||
return m_BonesByName.at(name)->ID;
|
||||
} else {
|
||||
Bone* bone;
|
||||
|
||||
if (parentID == -1) {
|
||||
bone = new Bone(ID, nullptr, name, offsetMatrix);
|
||||
RootBone = bone;
|
||||
} else {
|
||||
Bone* parent = Bones[parentID];
|
||||
bone = new Bone(ID, parent, name, offsetMatrix);
|
||||
parent->Children.push_back(bone);
|
||||
}
|
||||
|
||||
Bones[ID] = bone;
|
||||
m_BonesByName[name] = bone;
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
|
||||
Skeleton::~Skeleton()
|
||||
{
|
||||
for (auto &kv : Bones) {
|
||||
delete kv.second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
|
||||
{
|
||||
auto it = Animations.find(name);
|
||||
if (it != Animations.end()) {
|
||||
return const_cast<const Animation*>(&it->second);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<glm::mat4> Skeleton::GetFrameBones(std::vector<AnimationData> animations, bool noRootMotion /*= false*/)
|
||||
{
|
||||
if (animations.size() <= 0) {
|
||||
std::vector<glm::mat4> finalMatrices;
|
||||
if (animation == nullptr) {
|
||||
std::map<int, PoseData> finalMatrices;
|
||||
for (auto& b : Bones) {
|
||||
finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix);
|
||||
PoseData poseData;
|
||||
poseData.Translation = glm::vec3(0);
|
||||
poseData.Orientation = glm::quat();
|
||||
poseData.Scale = glm::vec3(1);
|
||||
|
||||
|
||||
finalMatrices[b.second->ID] = poseData;
|
||||
}
|
||||
return finalMatrices;
|
||||
}
|
||||
|
||||
std::map<int, glm::mat4> frameBones;
|
||||
AccumulateBoneTransforms(true, animations, frameBones, RootBone, glm::mat4(1));
|
||||
|
||||
std::vector<glm::mat4> finalMatrices;
|
||||
for (auto &kv : frameBones) {
|
||||
finalMatrices.push_back(kv.second);
|
||||
std::map<int, PoseData> frameBones;
|
||||
|
||||
if(!additive) {
|
||||
AccumulateBoneTransforms(true, animation, time, frameBones, RootBone);
|
||||
} else {
|
||||
AdditiveBoneTransforms(animation, time, frameBones, RootBone);
|
||||
}
|
||||
return finalMatrices;
|
||||
|
||||
return frameBones;
|
||||
}
|
||||
|
||||
std::vector<glm::mat4> Skeleton::GetFrameBones(std::vector<AnimationData> animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/)
|
||||
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map<int, PoseData>& boneMatrices, const Bone* bone)
|
||||
{
|
||||
if (animations.size() <= 0 || animationOffset.animation == nullptr) {
|
||||
std::vector<glm::mat4> finalMatrices;
|
||||
for (auto& b : Bones) {
|
||||
finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix);
|
||||
}
|
||||
return finalMatrices;
|
||||
}
|
||||
|
||||
PoseData poseData;
|
||||
|
||||
std::map<int, glm::mat4> frameBones;
|
||||
AccumulateBoneTransforms(true, animations, animationOffset, frameBones, RootBone, glm::mat4(1));
|
||||
|
||||
std::vector<glm::mat4> finalMatrices;
|
||||
for (auto &kv : frameBones) {
|
||||
finalMatrices.push_back(kv.second);
|
||||
}
|
||||
return finalMatrices;
|
||||
}
|
||||
|
||||
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, std::map<int, glm::mat4>& boneMatrices, const Bone* bone, glm::mat4 parentMatrix)
|
||||
{
|
||||
glm::mat4 boneMatrix;
|
||||
std::vector<JointFrameTransform> JointTransforms;
|
||||
|
||||
for (const AnimationData animationData : animations) {
|
||||
const Animation* animation = animationData.animation;
|
||||
const float time = animationData.time;
|
||||
|
||||
JointFrameTransform jointTransform;
|
||||
jointTransform.Weight = animationData.weight;;
|
||||
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
|
||||
Animation::Keyframe currentFrame;
|
||||
Animation::Keyframe nextFrame;
|
||||
|
||||
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
|
||||
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
|
||||
if (time >= boneKeyFrames.at(index).Time) {
|
||||
currentFrame = boneKeyFrames.at(index);
|
||||
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float progress;
|
||||
|
||||
if (nextFrame.Index == 0) {
|
||||
nextFrame = currentFrame;
|
||||
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
|
||||
} else {
|
||||
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
|
||||
|
||||
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
|
||||
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
|
||||
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
|
||||
|
||||
// Flag for no root motion
|
||||
if (bone == RootBone && noRootMotion) {
|
||||
jointTransform.PositionInterp.x = 0;
|
||||
jointTransform.PositionInterp.z = 0;
|
||||
}
|
||||
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
} else { // 1 keyframes for the current bone
|
||||
currentFrame = boneKeyFrames.at(0);
|
||||
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
|
||||
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
|
||||
jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale;
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
}
|
||||
} else { // 0 keyframes for the current bone
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (JointTransforms.size() <= 0) {
|
||||
if (bone->Parent) {
|
||||
boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix;
|
||||
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
|
||||
} else {
|
||||
boneMatrix = glm::inverse(bone->OffsetMatrix);
|
||||
boneMatrices[bone->ID] = parentMatrix;
|
||||
}
|
||||
} else if (JointTransforms.size() == 1) {
|
||||
boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp));
|
||||
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
|
||||
} else {
|
||||
|
||||
glm::vec3 finalPosInterp;
|
||||
glm::quat finalRotInterp;
|
||||
glm::vec3 finalScaleInterp;
|
||||
float totalWeight = 0;
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
totalWeight += jointTransform.Weight;
|
||||
}
|
||||
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
if (jointTransform.Weight == 1.0f) {
|
||||
finalPosInterp = jointTransform.PositionInterp;
|
||||
finalRotInterp = jointTransform.RotationInterp;
|
||||
finalScaleInterp = jointTransform.ScaleInterp;
|
||||
break;
|
||||
} else {
|
||||
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
|
||||
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
|
||||
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp));
|
||||
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (auto &child : bone->Children) {
|
||||
AccumulateBoneTransforms(noRootMotion, animations, boneMatrices, child, boneMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, AnimationOffset animationOffset, std::map<int, glm::mat4>& boneMatrices, const Bone* bone, glm::mat4 parentMatrix)
|
||||
{
|
||||
glm::mat4 boneMatrix;
|
||||
|
||||
std::vector<JointFrameTransform> JointTransforms;
|
||||
|
||||
for (const AnimationData animationData : animations) {
|
||||
const Animation* animation = animationData.animation;
|
||||
const float time = animationData.time;
|
||||
|
||||
JointFrameTransform jointTransform;
|
||||
jointTransform.Weight = animationData.weight;;
|
||||
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
|
||||
Animation::Keyframe currentFrame;
|
||||
Animation::Keyframe nextFrame;
|
||||
|
||||
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
|
||||
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
|
||||
if (time >= boneKeyFrames.at(index).Time) {
|
||||
currentFrame = boneKeyFrames.at(index);
|
||||
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float progress;
|
||||
|
||||
if (nextFrame.Index == 0) {
|
||||
nextFrame = currentFrame;
|
||||
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
|
||||
} else {
|
||||
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
|
||||
|
||||
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
|
||||
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
|
||||
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
|
||||
|
||||
// Flag for no root motion
|
||||
if (bone == RootBone && noRootMotion) {
|
||||
jointTransform.PositionInterp.x = 0;
|
||||
jointTransform.PositionInterp.z = 0;
|
||||
}
|
||||
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
} else { // 1 keyframes for the current bone
|
||||
currentFrame = boneKeyFrames.at(0);
|
||||
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
|
||||
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
|
||||
jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale;
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
}
|
||||
} else { // 0 keyframes for the current bone
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 offset = GetOffsetTransform(bone, animationOffset);
|
||||
|
||||
if (JointTransforms.size() == 0) {
|
||||
if (bone->Parent) {
|
||||
if (offset != glm::mat4(1)) {
|
||||
boneMatrix = parentMatrix * offset;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
|
||||
} else {
|
||||
boneMatrix = parentMatrix *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
|
||||
|
||||
}
|
||||
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
|
||||
} else {
|
||||
boneMatrix = offset * glm::inverse(bone->OffsetMatrix);
|
||||
boneMatrices[bone->ID] = parentMatrix;
|
||||
}
|
||||
} else {
|
||||
|
||||
glm::vec3 finalPosInterp;
|
||||
glm::quat finalRotInterp;
|
||||
glm::vec3 finalScaleInterp;
|
||||
float totalWeight = 0;
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
totalWeight += jointTransform.Weight;
|
||||
}
|
||||
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
if (jointTransform.Weight == 1.0f) {
|
||||
finalPosInterp = jointTransform.PositionInterp;
|
||||
finalRotInterp = jointTransform.RotationInterp;
|
||||
finalScaleInterp = jointTransform.ScaleInterp;
|
||||
break;
|
||||
} else {
|
||||
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
|
||||
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
|
||||
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (offset != glm::mat4(1)) {
|
||||
boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset);
|
||||
} else {
|
||||
boneMatrix = parentMatrix * (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp));
|
||||
}
|
||||
|
||||
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
|
||||
}
|
||||
|
||||
for (auto &child : bone->Children) {
|
||||
AccumulateBoneTransforms(noRootMotion, animations, animationOffset, boneMatrices, child, boneMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset)
|
||||
{
|
||||
const Animation* animation = animationOffset.animation;
|
||||
float time = animationOffset.time;
|
||||
|
||||
glm::vec3 position = glm::vec3(0);
|
||||
glm::quat rotation = glm::quat();
|
||||
glm::vec3 scale = glm::vec3(1);
|
||||
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
const std::vector<Animation::Keyframe>& boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
|
||||
Animation::Keyframe currentFrame;
|
||||
Animation::Keyframe nextFrame;
|
||||
const Animation::Keyframe* currentFrame;
|
||||
const Animation::Keyframe* nextFrame;
|
||||
|
||||
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
|
||||
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
|
||||
if (time >= boneKeyFrames.at(index).Time) {
|
||||
currentFrame = boneKeyFrames.at(index);
|
||||
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
currentFrame = &boneKeyFrames.at(index);
|
||||
nextFrame = &boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float progress;
|
||||
|
||||
if (nextFrame.Index == 0) {
|
||||
if (nextFrame->Index == 0) {
|
||||
nextFrame = currentFrame;
|
||||
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
|
||||
progress = (time - currentFrame->Time) / (animation->Duration - currentFrame->Time);
|
||||
} else {
|
||||
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
progress = (time - currentFrame->Time) / (nextFrame->Time - currentFrame->Time);
|
||||
|
||||
}
|
||||
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
const Animation::Keyframe::BoneProperty& currentBoneProperty = currentFrame->BoneProperties;
|
||||
const Animation::Keyframe::BoneProperty& nextBoneProperty = nextFrame->BoneProperties;
|
||||
|
||||
glm::vec3 position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
|
||||
glm::quat rotation = glm::normalize(glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress));
|
||||
glm::vec3 scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
|
||||
|
||||
// Flag for no root motion
|
||||
if (bone == RootBone && noRootMotion) {
|
||||
position.x = 0;
|
||||
position.z = 0;
|
||||
}
|
||||
|
||||
poseData.Translation = position;
|
||||
poseData.Orientation = rotation;
|
||||
poseData.Scale = scale;
|
||||
boneMatrices[bone->ID] = poseData;
|
||||
|
||||
} else { // 1 keyframes for the current bone
|
||||
currentFrame = &boneKeyFrames.at(0);
|
||||
poseData.Translation = currentFrame->BoneProperties.Position;
|
||||
poseData.Orientation = currentFrame->BoneProperties.Rotation;
|
||||
poseData.Scale = currentFrame->BoneProperties.Scale;
|
||||
boneMatrices[bone->ID] = poseData;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &child : bone->Children) {
|
||||
AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, std::map<int, PoseData>& boneMatrices, const Bone* bone)
|
||||
{
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
PoseData refPose = GetAdditiveBonePose(bone, animation, 0.0);
|
||||
PoseData srcPose = GetAdditiveBonePose(bone, animation, time + 1.0/60.0);
|
||||
|
||||
PoseData finalPose;
|
||||
finalPose.Translation = srcPose.Translation - refPose.Translation;
|
||||
finalPose.Orientation = srcPose.Orientation * glm::inverse(refPose.Orientation);
|
||||
finalPose.Scale = srcPose.Scale - refPose.Scale;
|
||||
|
||||
boneMatrices[bone->ID] = finalPose;
|
||||
}
|
||||
|
||||
for (auto &child : bone->Children) {
|
||||
AdditiveBoneTransforms(animation, time, boneMatrices, child);
|
||||
}
|
||||
}
|
||||
|
||||
Skeleton::PoseData Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time)
|
||||
{
|
||||
glm::vec3 position = glm::vec3(0);
|
||||
glm::quat rotation = glm::quat();
|
||||
glm::vec3 scale = glm::vec3(1);
|
||||
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
const std::vector<Animation::Keyframe>& boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
|
||||
const Animation::Keyframe* currentFrame;
|
||||
const Animation::Keyframe* nextFrame;
|
||||
|
||||
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
|
||||
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
|
||||
if (time >= boneKeyFrames.at(index).Time) {
|
||||
currentFrame = &boneKeyFrames.at(index);
|
||||
nextFrame = &boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float progress;
|
||||
|
||||
if (nextFrame->Index == 0) {
|
||||
nextFrame = currentFrame;
|
||||
progress = (time - currentFrame->Time) / (animation->Duration - currentFrame->Time);
|
||||
} else {
|
||||
progress = (time - currentFrame->Time) / (nextFrame->Time - currentFrame->Time);
|
||||
}
|
||||
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
|
||||
const Animation::Keyframe::BoneProperty& currentBoneProperty = currentFrame->BoneProperties;
|
||||
const Animation::Keyframe::BoneProperty& nextBoneProperty = nextFrame->BoneProperties;
|
||||
|
||||
position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
|
||||
rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
|
||||
@@ -374,315 +151,137 @@ glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animati
|
||||
|
||||
|
||||
} else { // 1 keyframes for the current bone
|
||||
currentFrame = boneKeyFrames.at(0);
|
||||
position = currentFrame.BoneProperties.Position;
|
||||
rotation = currentFrame.BoneProperties.Rotation;
|
||||
scale = currentFrame.BoneProperties.Scale;
|
||||
currentFrame = &boneKeyFrames.at(0);
|
||||
position = currentFrame->BoneProperties.Position;
|
||||
rotation = currentFrame->BoneProperties.Rotation;
|
||||
scale = currentFrame->BoneProperties.Scale;
|
||||
}
|
||||
}
|
||||
|
||||
return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale));
|
||||
PoseData finalPose;
|
||||
finalPose.Translation = position;
|
||||
finalPose.Orientation = rotation;
|
||||
finalPose.Scale = scale;
|
||||
|
||||
return finalPose;
|
||||
}
|
||||
|
||||
std::map<int, Skeleton::PoseData> Skeleton::BlendPoses(const std::map<int, PoseData>& pose1, const std::map<int, PoseData>& pose2, double weight)
|
||||
{
|
||||
std::map<int, PoseData> finalPose;
|
||||
|
||||
float weight1 = (float)(1.0 - weight);
|
||||
float weight2 = (float)(weight);
|
||||
|
||||
for (auto& b : Bones) {
|
||||
int boneID = b.second->ID;
|
||||
PoseData blendedPose;
|
||||
blendedPose.Translation = glm::vec3(0);
|
||||
blendedPose.Orientation = glm::quat();
|
||||
blendedPose.Scale = glm::vec3(1);
|
||||
|
||||
if(pose1.find(boneID) != pose1.end() && pose2.find(boneID) != pose2.end()) {
|
||||
blendedPose.Translation = pose1.at(boneID).Translation * weight1 + pose2.at(boneID).Translation * weight2;
|
||||
blendedPose.Orientation = glm::slerp(pose1.at(boneID).Orientation, pose2.at(boneID).Orientation, weight2);
|
||||
blendedPose.Scale = pose1.at(boneID).Scale * weight1 + pose2.at(boneID).Scale * weight2;
|
||||
finalPose[boneID] = blendedPose;
|
||||
} else if(pose1.find(boneID) != pose1.end()) {
|
||||
finalPose[boneID] = pose1.at(boneID);
|
||||
} else if (pose2.find(boneID) != pose2.end()) {
|
||||
finalPose[boneID] = pose2.at(boneID);
|
||||
}
|
||||
}
|
||||
|
||||
return finalPose;
|
||||
}
|
||||
|
||||
std::map<int, Skeleton::PoseData> Skeleton::OverridePose(const std::map<int, PoseData>& overridePose, const std::map<int, PoseData>& targetPose)
|
||||
{
|
||||
std::map<int, PoseData> finalPose;
|
||||
|
||||
for (auto& b : Bones) {
|
||||
int boneID = b.second->ID;
|
||||
if (overridePose.find(boneID) != overridePose.end()) {
|
||||
finalPose[boneID] = overridePose.at(boneID);
|
||||
} else if (targetPose.find(boneID) != targetPose.end()) {
|
||||
finalPose[boneID] = targetPose.at(boneID);
|
||||
}
|
||||
}
|
||||
return finalPose;
|
||||
}
|
||||
|
||||
std::map<int, Skeleton::PoseData> Skeleton::BlendPoseAdditive(const std::map<int, PoseData>& additivePose, const std::map<int, PoseData>& targetPose)
|
||||
{
|
||||
std::map<int, PoseData> finalPose;
|
||||
|
||||
for (auto& b : Bones) {
|
||||
int boneID = b.second->ID;
|
||||
PoseData blendedPose;
|
||||
blendedPose.Translation = glm::vec3(0);
|
||||
blendedPose.Orientation = glm::quat();
|
||||
blendedPose.Scale = glm::vec3(1);
|
||||
|
||||
if (additivePose.find(boneID) != additivePose.end() && targetPose.find(boneID) != targetPose.end()) {
|
||||
blendedPose.Translation = additivePose.at(boneID).Translation + targetPose.at(boneID).Translation;
|
||||
blendedPose.Orientation = additivePose.at(boneID).Orientation * targetPose.at(boneID).Orientation;
|
||||
blendedPose.Scale = additivePose.at(boneID).Scale + targetPose.at(boneID).Scale;
|
||||
finalPose[boneID] = blendedPose;
|
||||
} else if (additivePose.find(boneID) != additivePose.end()) {
|
||||
finalPose[boneID] = additivePose.at(boneID);
|
||||
} else if (targetPose.find(boneID) != targetPose.end()) {
|
||||
finalPose[boneID] = targetPose.at(boneID);
|
||||
}
|
||||
}
|
||||
|
||||
return finalPose;
|
||||
}
|
||||
|
||||
void Skeleton::GetFinalPose(std::map<int, Skeleton::PoseData>& poseDatas, std::vector<glm::mat4>& finalPose, std::map<int, glm::mat4>& boneTransforms)
|
||||
{
|
||||
|
||||
std::map<int, glm::mat4> boneMatrices;
|
||||
|
||||
AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, RootBone, glm::mat4(1));
|
||||
|
||||
for(auto& b : boneMatrices) {
|
||||
finalPose.push_back(b.second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix)
|
||||
std::vector<glm::mat4> Skeleton::GetTPose()
|
||||
{
|
||||
glm::mat4 boneMatrix;
|
||||
std::vector<glm::mat4> finalMatrices;
|
||||
|
||||
Animation::Keyframe currentFrame;
|
||||
Animation::Keyframe nextFrame;
|
||||
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
|
||||
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
|
||||
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
|
||||
if (time >= boneKeyFrames.at(index).Time) {
|
||||
currentFrame = boneKeyFrames.at(index);
|
||||
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float progress;
|
||||
|
||||
if (nextFrame.Index == 0) {
|
||||
nextFrame = currentFrame;
|
||||
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
|
||||
} else {
|
||||
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
}
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
LOG_INFO("Progress %f", progress);
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
|
||||
|
||||
glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
|
||||
glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
|
||||
glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
|
||||
|
||||
boneMatrix = (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)) * childMatrix;
|
||||
|
||||
} else { // 1 keyframes for the current bone
|
||||
currentFrame = boneKeyFrames.at(0);
|
||||
boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)) * childMatrix;
|
||||
|
||||
}
|
||||
} else { // 0 keyframes for the current bone
|
||||
if (bone->Parent) {
|
||||
boneMatrix = bone->Parent->OffsetMatrix * glm::inverse(bone->OffsetMatrix) * childMatrix;
|
||||
} else {
|
||||
boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix;
|
||||
}
|
||||
for (auto b : Bones) {
|
||||
finalMatrices.push_back(glm::mat4(1));
|
||||
}
|
||||
|
||||
if (bone->Parent) {
|
||||
return GetBoneTransform(bone->Parent, animation, time, boneMatrix);
|
||||
} else {
|
||||
return boneMatrix;
|
||||
}
|
||||
return finalMatrices;
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector<AnimationData> animations, AnimationOffset animationOffset, glm::mat4 childMatrix)
|
||||
void Skeleton::AccumulateFinalPose(std::map<int, glm::mat4>& boneMatrices, std::map<int, Skeleton::PoseData>& poseDatas, std::map<int, glm::mat4>& boneTransforms, const Bone* bone, glm::mat4 parentMatrix)
|
||||
{
|
||||
glm::mat4 boneMatrix;
|
||||
|
||||
std::vector<JointFrameTransform> JointTransforms;
|
||||
|
||||
for (const AnimationData animationData : animations) {
|
||||
const Animation* animation = animationData.animation;
|
||||
const float time = animationData.time;
|
||||
|
||||
JointFrameTransform jointTransform;
|
||||
jointTransform.Weight = animationData.weight;;
|
||||
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
|
||||
Animation::Keyframe currentFrame;
|
||||
Animation::Keyframe nextFrame;
|
||||
|
||||
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
|
||||
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
|
||||
if (time >= boneKeyFrames.at(index).Time) {
|
||||
currentFrame = boneKeyFrames.at(index);
|
||||
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float progress;
|
||||
|
||||
if (nextFrame.Index == 0) {
|
||||
nextFrame = currentFrame;
|
||||
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
|
||||
} else {
|
||||
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
|
||||
|
||||
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
|
||||
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
|
||||
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
|
||||
|
||||
// Flag for no root motion
|
||||
if (bone == RootBone && noRootMotion) {
|
||||
jointTransform.PositionInterp.x = 0;
|
||||
jointTransform.PositionInterp.z = 0;
|
||||
}
|
||||
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
} else { // 1 keyframes for the current bone
|
||||
currentFrame = boneKeyFrames.at(0);
|
||||
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
|
||||
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
|
||||
jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale;
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
}
|
||||
} else { // 0 keyframes for the current bone
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 offset = GetOffsetTransform(bone, animationOffset);
|
||||
|
||||
if (JointTransforms.size() == 0) {
|
||||
if (poseDatas.find(bone->ID) != poseDatas.end()) {
|
||||
boneMatrix = parentMatrix * (glm::translate(poseDatas.at(bone->ID).Translation) * glm::mat4(poseDatas.at(bone->ID).Orientation) * glm::scale(poseDatas.at(bone->ID).Scale));
|
||||
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
|
||||
} else {
|
||||
if (bone->Parent) {
|
||||
if (offset != glm::mat4(1)) {
|
||||
boneMatrix = offset * childMatrix;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
|
||||
} else {
|
||||
boneMatrix = ((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)) * childMatrix;
|
||||
}
|
||||
boneMatrix = parentMatrix * bone->BindTransformMatrix * bone->Parent->OffsetMatrix;
|
||||
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
|
||||
} else {
|
||||
boneMatrix = offset * glm::inverse(bone->OffsetMatrix);
|
||||
}
|
||||
} else {
|
||||
|
||||
glm::vec3 finalPosInterp;
|
||||
glm::quat finalRotInterp;
|
||||
glm::vec3 finalScaleInterp;
|
||||
float totalWeight = 0;
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
totalWeight += jointTransform.Weight;
|
||||
}
|
||||
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
if (jointTransform.Weight == 1.0f) {
|
||||
finalPosInterp = jointTransform.PositionInterp;
|
||||
finalRotInterp = jointTransform.RotationInterp;
|
||||
finalScaleInterp = jointTransform.ScaleInterp;
|
||||
break;
|
||||
} else {
|
||||
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
|
||||
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
|
||||
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (offset != glm::mat4(1)) {
|
||||
boneMatrix = ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset) * childMatrix;
|
||||
} else {
|
||||
boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix;
|
||||
boneMatrix = bone->BindTransformMatrix;
|
||||
boneMatrices[bone->ID] = parentMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
if (bone->Parent != nullptr) {
|
||||
return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix);
|
||||
} else {
|
||||
return boneMatrix;
|
||||
}
|
||||
}
|
||||
boneTransforms[bone->ID] = boneMatrix;
|
||||
|
||||
|
||||
glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector<AnimationData> animations, glm::mat4 childMatrix)
|
||||
{
|
||||
glm::mat4 boneMatrix;
|
||||
std::vector<JointFrameTransform> JointTransforms;
|
||||
|
||||
for (const AnimationData animationData : animations) {
|
||||
const Animation* animation = animationData.animation;
|
||||
const float time = animationData.time;
|
||||
|
||||
JointFrameTransform jointTransform;
|
||||
jointTransform.Weight = animationData.weight;;
|
||||
|
||||
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
|
||||
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
|
||||
|
||||
Animation::Keyframe currentFrame;
|
||||
Animation::Keyframe nextFrame;
|
||||
|
||||
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
|
||||
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
|
||||
if (time >= boneKeyFrames.at(index).Time) {
|
||||
currentFrame = boneKeyFrames.at(index);
|
||||
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float progress;
|
||||
|
||||
if (nextFrame.Index == 0) {
|
||||
nextFrame = currentFrame;
|
||||
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
|
||||
} else {
|
||||
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
}
|
||||
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
|
||||
|
||||
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
|
||||
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
|
||||
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
|
||||
|
||||
// Flag for no root motion
|
||||
if (bone == RootBone && noRootMotion) {
|
||||
jointTransform.PositionInterp.x = 0;
|
||||
jointTransform.PositionInterp.z = 0;
|
||||
}
|
||||
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
} else { // 1 keyframes for the current bone
|
||||
currentFrame = boneKeyFrames.at(0);
|
||||
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
|
||||
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
|
||||
jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale;
|
||||
JointTransforms.push_back(jointTransform);
|
||||
|
||||
}
|
||||
} else { // 0 keyframes for the current bone
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (JointTransforms.size() <= 0) {
|
||||
if (bone->Parent) {
|
||||
boneMatrix = glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix * childMatrix;
|
||||
} else {
|
||||
boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix;
|
||||
}
|
||||
} else if (JointTransforms.size() == 1) {
|
||||
boneMatrix = (glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)) * childMatrix;
|
||||
} else {
|
||||
|
||||
glm::vec3 finalPosInterp;
|
||||
glm::quat finalRotInterp;
|
||||
glm::vec3 finalScaleInterp;
|
||||
float totalWeight = 0;
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
totalWeight += jointTransform.Weight;
|
||||
}
|
||||
|
||||
|
||||
for (JointFrameTransform jointTransform : JointTransforms) {
|
||||
if (jointTransform.Weight == 1.0f) {
|
||||
finalPosInterp = jointTransform.PositionInterp;
|
||||
finalRotInterp = jointTransform.RotationInterp;
|
||||
finalScaleInterp = jointTransform.ScaleInterp;
|
||||
break;
|
||||
} else {
|
||||
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
|
||||
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
|
||||
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
|
||||
}
|
||||
}
|
||||
|
||||
boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (bone->Parent != nullptr) {
|
||||
return GetBoneTransform(noRootMotion, bone->Parent, animations, boneMatrix);
|
||||
} else {
|
||||
return boneMatrix;
|
||||
for (auto &child : bone->Children) {
|
||||
AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, child, boneMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,46 +294,43 @@ int Skeleton::GetBoneID(std::string name)
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::PrintSkeleton()
|
||||
int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix)
|
||||
{
|
||||
if (LOG_LEVEL < LOG_LEVEL_DEBUG) {
|
||||
return;
|
||||
}
|
||||
PrintSkeleton(RootBone, 0);
|
||||
if (m_BonesByName.find(name) != m_BonesByName.end()) {
|
||||
return m_BonesByName.at(name)->ID;
|
||||
} else {
|
||||
Bone* bone;
|
||||
|
||||
if (parentID == -1) {
|
||||
bone = new Bone(ID, nullptr, name, offsetMatrix);
|
||||
RootBone = bone;
|
||||
} else {
|
||||
Bone* parent = Bones[parentID];
|
||||
bone = new Bone(ID, parent, name, offsetMatrix);
|
||||
parent->Children.push_back(bone);
|
||||
}
|
||||
|
||||
Bones[ID] = bone;
|
||||
m_BonesByName[name] = bone;
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::PrintSkeleton(const Bone* bone, int depthCount)
|
||||
Skeleton::~Skeleton()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::string(depthCount, ' ');
|
||||
ss << bone->ID << ": " << bone->Name;
|
||||
std::cout << ss.str() << std::endl;
|
||||
|
||||
depthCount++;
|
||||
for (auto &kv : Bones) {
|
||||
delete kv.second;
|
||||
}
|
||||
|
||||
for (auto &child : bone->Children) {
|
||||
PrintSkeleton(child, depthCount);
|
||||
}
|
||||
BlendTrees.clear();
|
||||
}
|
||||
|
||||
int Skeleton::GetKeyframe(const Animation& animation, double time)
|
||||
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
|
||||
{
|
||||
|
||||
/*
|
||||
if (time < 0) {
|
||||
time = 0;
|
||||
}
|
||||
if (time >= animation.Duration) {
|
||||
return animation..size() - 1;
|
||||
}
|
||||
|
||||
for (int keyframe = 0; keyframe < animation.Keyframes.size(); ++keyframe) {
|
||||
if (animation.Keyframes[keyframe].Time > time) {
|
||||
return (keyframe - 1) % animation.Keyframes.size();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
auto it = Animations.find(name);
|
||||
if (it != Animations.end()) {
|
||||
return const_cast<const Animation*>(&it->second);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -7,23 +7,23 @@ TextPass::TextPass()
|
||||
|
||||
void TextPass::Initialize()
|
||||
{
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
m_TextProgram = ResourceManager::Load<ShaderProgram>("#TextProgram");
|
||||
m_TextProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Text.vert.glsl")));
|
||||
m_TextProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Text.frag.glsl")));
|
||||
m_TextProgram->Compile();
|
||||
m_TextProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_TextProgram->BindFragDataLocation(1, "bloomColor");
|
||||
m_TextProgram->Link();
|
||||
m_TextProgram = ResourceManager::Load<ShaderProgram>("#TextProgram");
|
||||
m_TextProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Text.vert.glsl")));
|
||||
m_TextProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Text.frag.glsl")));
|
||||
m_TextProgram->Compile();
|
||||
m_TextProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_TextProgram->BindFragDataLocation(1, "bloomColor");
|
||||
m_TextProgram->Link();
|
||||
}
|
||||
|
||||
void TextPass::Update()
|
||||
@@ -33,81 +33,180 @@ void TextPass::Update()
|
||||
|
||||
void TextPass::Draw(RenderScene& scene, FrameBuffer& frameBuffer)
|
||||
{
|
||||
GLERROR("Derp1");
|
||||
TextPassState* state = new TextPassState(frameBuffer.GetHandle());
|
||||
for (auto &job : scene.Jobs.Text) {
|
||||
auto textJob = std::dynamic_pointer_cast<TextJob>(job);
|
||||
if (textJob) {
|
||||
GLERROR("Derp1");
|
||||
TextPassState* state = new TextPassState(frameBuffer.GetHandle());
|
||||
for (auto &job : scene.Jobs.Text) {
|
||||
auto textJob = std::dynamic_pointer_cast<TextJob>(job);
|
||||
if (textJob) {
|
||||
|
||||
renderText(textJob->Content, textJob->Resource, textJob->Alignment, textJob->Color, textJob->Matrix, scene.Camera->ProjectionMatrix(), scene.Camera->ViewMatrix());
|
||||
}
|
||||
}
|
||||
GLERROR("Derp2");
|
||||
delete state;
|
||||
renderText(textJob->Content, textJob->Resource, textJob->Alignment, textJob->Color, textJob->Matrix, scene.Camera->ProjectionMatrix(), scene.Camera->ViewMatrix());
|
||||
}
|
||||
}
|
||||
GLERROR("Derp2");
|
||||
delete state;
|
||||
}
|
||||
|
||||
std::string TextPass::parseColors(std::string text, std::map<int, glm::vec4>& colorChanges, glm::vec4 originalColor)
|
||||
{
|
||||
std::string parsedString = text;
|
||||
glm::vec4 newColor = originalColor;
|
||||
bool colorChange = false;
|
||||
|
||||
for (std::string::const_iterator c = parsedString.begin(); c != parsedString.end(); c++) {
|
||||
if (*c == char(92)) { // Backlash
|
||||
if ((c + 1) != parsedString.end()) {
|
||||
if (*(c + 1) == char('C')) { // C for Color
|
||||
if ((c + 7) != parsedString.end()) {
|
||||
bool hasCorrectFormat = true;
|
||||
|
||||
for (std::string::const_iterator colorC = c + 2; colorC != c + 8; colorC++) {
|
||||
if (*colorC < '0' || *colorC > 'F') {
|
||||
hasCorrectFormat = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCorrectFormat == true) {
|
||||
colorChange = true;
|
||||
|
||||
std::array<int, 3> hexToInt = {
|
||||
std::stoi(std::string(c + 2, c + 4), 0, 16),
|
||||
std::stoi(std::string(c + 4, c + 6), 0, 16),
|
||||
std::stoi(std::string(c + 6, c + 8), 0, 16)
|
||||
};
|
||||
|
||||
newColor = glm::vec4(
|
||||
float(hexToInt[0]) / 255.f,
|
||||
float(hexToInt[1]) / 255.f,
|
||||
float(hexToInt[2]) / 255.f,
|
||||
newColor.a);
|
||||
|
||||
parsedString.erase(c, (c + 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*(c + 1) == char('A')) { // A for Alpha
|
||||
if ((c + 3) != parsedString.end()) {
|
||||
bool hasCorrectFormat = true;
|
||||
|
||||
for (std::string::const_iterator colorC = c + 2; colorC != c + 4; colorC++) {
|
||||
if (*colorC < '0' || *colorC > 'F') {
|
||||
hasCorrectFormat = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCorrectFormat == true) {
|
||||
colorChange = true;
|
||||
|
||||
int hexToInt = std::stoi(std::string(c + 2, c + 4), 0, 16);
|
||||
|
||||
newColor = glm::vec4(
|
||||
newColor.r,
|
||||
newColor.g,
|
||||
newColor.b,
|
||||
float(hexToInt) / 255.f);
|
||||
|
||||
parsedString.erase(c, (c + 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((*(c + 1) >= '1' && *(c + 1) <= '9') || *(c + 1) == 'B' || *(c + 1) == 'E' || *(c + 1) == 'F') { // Icons
|
||||
if (*(c + 1) >= '1' && *(c + 1) <= '9') {
|
||||
parsedString.replace(c, (c + 2), 1, (*(c + 1) - 48));
|
||||
}
|
||||
else {
|
||||
parsedString.replace(c, (c + 2), 1, (*(c + 1) - 55));
|
||||
}
|
||||
}
|
||||
|
||||
if (colorChange) {
|
||||
colorChanges[c - parsedString.begin()] = newColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return parsedString;
|
||||
}
|
||||
|
||||
void TextPass::renderText(std::string text, Font* font, TextJob::AlignmentEnum alignment, glm::vec4 color, glm::mat4 modelMatrix, glm::mat4 projectionMatrix, glm::mat4 viewMatrix)
|
||||
{
|
||||
GLfloat penX = 0;
|
||||
GLfloat penY = 0;
|
||||
GLfloat scale = 1.0/font->FontSize;
|
||||
GLfloat penX = 0;
|
||||
GLfloat penY = 0;
|
||||
GLfloat scale = 1.0 / font->FontSize;
|
||||
|
||||
GLfloat stringWidth = 0.f;
|
||||
GLfloat stringWidth = 0.f;
|
||||
|
||||
for (std::string::const_iterator c = text.begin(); c != text.end(); c++) {
|
||||
Font::Character ch = font->m_Characters[*c];
|
||||
stringWidth += (ch.Advance >> 6) * scale;
|
||||
}
|
||||
std::map<int, glm::vec4> colorChanges;
|
||||
std::string parsedText = parseColors(text, colorChanges, color);
|
||||
|
||||
if(alignment == TextJob::AlignmentEnum::Center) {
|
||||
penX = -stringWidth/2.f;
|
||||
} else if (alignment == TextJob::AlignmentEnum::Right) {
|
||||
penX = -stringWidth;
|
||||
} else {
|
||||
penX = 0;
|
||||
}
|
||||
|
||||
|
||||
for (std::string::const_iterator c = parsedText.begin(); c != parsedText.end(); c++) {
|
||||
Font::Character ch = font->m_Characters[*c];
|
||||
stringWidth += (ch.Advance >> 6) * scale;
|
||||
}
|
||||
|
||||
m_TextProgram->Bind();
|
||||
glUniform4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "textColor"), 1, glm::value_ptr(color));
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindVertexArray(VAO);
|
||||
if (alignment == TextJob::AlignmentEnum::Center) {
|
||||
penX = -stringWidth / 2.f;
|
||||
}
|
||||
else if (alignment == TextJob::AlignmentEnum::Right) {
|
||||
penX = -stringWidth;
|
||||
}
|
||||
else {
|
||||
penX = 0;
|
||||
}
|
||||
|
||||
|
||||
for (std::string::const_iterator c = text.begin(); c != text.end(); c++) {
|
||||
Font::Character ch = font->m_Characters[*c];
|
||||
|
||||
GLfloat xpos = penX + ch.Bearing.x * scale;
|
||||
GLfloat ypos = penY - (ch.Size.y - ch.Bearing.y) * scale;
|
||||
m_TextProgram->Bind();
|
||||
glUniform4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "textColor"), 1, glm::value_ptr(color));
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
GLfloat w = ch.Size.x * scale;
|
||||
GLfloat h = ch.Size.y * scale;
|
||||
|
||||
GLfloat vertices[6][4] = {
|
||||
{ xpos, ypos + h, 0.0, 0.0 },
|
||||
{ xpos, ypos, 0.0, 1.0 },
|
||||
{ xpos + w, ypos, 1.0, 1.0 },
|
||||
for (std::string::const_iterator c = parsedText.begin(); c != parsedText.end(); c++) {
|
||||
|
||||
{ xpos, ypos + h, 0.0, 0.0 },
|
||||
{ xpos + w, ypos, 1.0, 1.0 },
|
||||
{ xpos + w, ypos + h, 1.0, 0.0 }
|
||||
};
|
||||
auto it = colorChanges.find(c - parsedText.begin());
|
||||
if (it != colorChanges.end()) {
|
||||
glUniform4fv(glGetUniformLocation(m_TextProgram->GetHandle(), "textColor"), 1, glm::value_ptr(it->second));
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
|
||||
Font::Character ch = font->m_Characters[*c];
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
penX += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64)
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
GLfloat xpos = penX + ch.Bearing.x * scale;
|
||||
GLfloat ypos = penY - (ch.Size.y - ch.Bearing.y) * scale;
|
||||
|
||||
GLERROR("Text rendering Error");
|
||||
GLfloat w = ch.Size.x * scale;
|
||||
GLfloat h = ch.Size.y * scale;
|
||||
|
||||
GLfloat vertices[6][4] = {
|
||||
{ xpos, ypos + h, 0.0, 0.0 },
|
||||
{ xpos, ypos, 0.0, 1.0 },
|
||||
{ xpos + w, ypos, 1.0, 1.0 },
|
||||
|
||||
{ xpos, ypos + h, 0.0, 0.0 },
|
||||
{ xpos + w, ypos, 1.0, 1.0 },
|
||||
{ xpos + w, ypos + h, 1.0, 0.0 }
|
||||
};
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
penX += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64)
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
GLERROR("Text rendering Error");
|
||||
}
|
||||
|
||||
|
||||
@@ -4,18 +4,6 @@ Texture::Texture(std::string path)
|
||||
{
|
||||
PNG* img = ResourceManager::Load<PNG, true>(path); //TODO: Make this threaded. Catch exeptions in all other load places.
|
||||
|
||||
//PNG image(path);
|
||||
|
||||
//if (img->Width == 0 && img->Height == 0 || img->Format == Image::ImageFormat::Unknown) {
|
||||
// //image = PNG("Textures/Core/ErrorTexture.png");
|
||||
// //return; // Temporary fix to remove crash
|
||||
|
||||
// if (img->Width == 0 && img->Height == 0 || img->Format == Image::ImageFormat::Unknown) {
|
||||
// LOG_ERROR("Couldn't even load the error texture. This is a dark day indeed.");
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
|
||||
this->Width = img->Width;
|
||||
this->Height = img->Height;
|
||||
this->Data = img->Data;
|
||||
@@ -29,8 +17,7 @@ Texture::Texture(std::string path)
|
||||
format = GL_RGBA;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Construct the OpenGL texture
|
||||
glGenTextures(1, &m_Texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_Texture);
|
||||
@@ -42,6 +29,8 @@ Texture::Texture(std::string path)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
GLERROR("Texture load");
|
||||
|
||||
ResourceManager::Release("PNG", path);
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "Rendering/TextureSprite.h"
|
||||
|
||||
TextureSprite::TextureSprite(std::string path)
|
||||
:Texture(path)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
GLERROR("Texture load");
|
||||
}
|
||||
@@ -1,23 +1,5 @@
|
||||
#include "Rendering/Util/CommonFunctions.h"
|
||||
|
||||
Texture* CommonFunctions::LoadTexture(std::string path, bool threaded)
|
||||
{
|
||||
Texture* img;
|
||||
try {
|
||||
if(threaded) {
|
||||
img = ResourceManager::Load<Texture, true>(path);
|
||||
} else {
|
||||
img = ResourceManager::Load<Texture, false>(path);
|
||||
}
|
||||
} catch (const Resource::StillLoadingException&) {
|
||||
img = ResourceManager::Load<Texture>("Textures/Core/ErrorTexture.png");
|
||||
} catch (const std::exception&) {
|
||||
img = nullptr;
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void CommonFunctions::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
|
||||
{
|
||||
glDeleteTextures(1, texture);
|
||||
@@ -35,23 +17,26 @@ void CommonFunctions::GenerateMultiSampleTexture(GLuint* texture, int numSamples
|
||||
{
|
||||
glDeleteTextures(1, texture);
|
||||
glGenTextures(1, texture);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, *texture);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, internalFormat, dimensions.x, dimensions.y, false);
|
||||
glBindTexture(GL_TEXTURE_2D, *texture);
|
||||
GLERROR("Texture initialization failed 1");
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, internalFormat, dimensions.x, dimensions.y, GL_FALSE);
|
||||
GLERROR("Texture initialization failed");
|
||||
}
|
||||
|
||||
|
||||
void CommonFunctions::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps)
|
||||
void CommonFunctions::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type, GLint numMipMaps, GLint MAGFilter, GLint MINFilter)
|
||||
{
|
||||
glDeleteTextures(1, texture);
|
||||
glGenTextures(1, texture);
|
||||
glBindTexture(GL_TEXTURE_2D, *texture);
|
||||
glTexStorage2D(GL_TEXTURE_2D, numMipMaps, GL_RGBA8, dimensions.x, dimensions.y);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dimensions.x, dimensions.y, format, type, texture);
|
||||
glTexStorage2D(GL_TEXTURE_2D, numMipMaps, internalFormat, dimensions.x, dimensions.y);
|
||||
//glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dimensions.x, dimensions.y, format, type, NULL);
|
||||
GLERROR("MipMap Texture glTexSubImage2D failed");
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MAGFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MINFilter);
|
||||
GLERROR("MipMap Texture initialization failed");
|
||||
}
|
||||
|
||||
|
||||
@@ -36,10 +36,6 @@ ScreenCoords::PixelData ScreenCoords::ToPixelData(float x, float y, FrameBuffer*
|
||||
unsigned char pdata[3];
|
||||
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pdata);
|
||||
GLERROR("glReadPixels(pdata) Error");
|
||||
PickDataBuffer->Unbind();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer);
|
||||
GLERROR("glBindFramebuffer(DepthBuffer) Error");
|
||||
float depthData;
|
||||
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData);
|
||||
GLERROR("glReadPixels(depthData) Error");
|
||||
|
||||
Reference in New Issue
Block a user