Merge remote-tracking branch 'origin/master' into Sound

# Conflicts:
#	resources/Schema/Types/Entity.xsd
This commit is contained in:
stiffly
2016-01-15 16:25:32 +01:00
46 changed files with 1306 additions and 347 deletions
+4 -4
View File
@@ -7,10 +7,10 @@
#include <vector>
#include "Core/Ray.h"
#include "Core/AABB.h"
#include "Engine/Rendering/RawModel.h"
#include "Core/Entity.h"
#include "../Core/Ray.h"
#include "../Core/AABB.h"
#include "../Rendering/RawModel.h"
#include "../Core/Entity.h"
class World;
struct ComponentWrapper;
+4 -4
View File
@@ -4,10 +4,10 @@
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Core/EventBroker.h"
#include "Core/EKeyUp.h"
#include "../Common.h"
#include "../Core/System.h"
#include "../Core/EventBroker.h"
#include "../Core/EKeyUp.h"
class CollisionSystem : public PureSystem
{
+2 -2
View File
@@ -4,8 +4,8 @@
#include <glm/common.hpp>
#include <unordered_set>
#include "Core/System.h"
#include "Core/EventBroker.h"
#include "../Core/System.h"
#include "../Core/EventBroker.h"
#include "ETrigger.h"
class AABB;
+1 -1
View File
@@ -2,7 +2,7 @@
#define Ray_h__
#include "../GLM.h"
#include "Common.h"
#include "../Common.h"
class Ray
{
+132 -39
View File
@@ -12,7 +12,6 @@
/** Base Resource class.
Implement this class for every resource to be handled by the resource manager.
Implement Create() to return a new object of that type.
*/
class Resource
{
@@ -22,6 +21,23 @@ protected:
Resource() { }
public:
//Should be thrown in a Resource's constructor if it cannot complete because another resource is still loading.
//Not actually an error, just a message to the ResourceManager.
struct StillLoadingException : public std::exception
{
virtual const char* what() const throw()
{
return "Resource is still loading.";
}
};
struct FailedLoadingException : public std::exception
{
virtual const char* what() const throw()
{
return "Resource is failed to load.";
}
};
// Pretend that this is a pure virtual function that you have to implement
// FIXME: Why did we do this again instead of just using the constructor?
// static Resource* Create(std::string resourceName);
@@ -33,6 +49,15 @@ public:
unsigned int ResourceID;
};
//Any class inheriting from this class will always be loaded on the master thread, not on a parallel worker thread.
//This is important in case some instructions must be executed on the main thread, e.g. OpenGL commands, like glBindBuffer.
//This resource can still be loaded asyncronously, but it will not be loaded in a thread, instead it's constructor will
//be called once on every ResourceManager::Load, just throw StillLoadingException in the constructor if it is not done yet.
class ThreadUnsafeResource : public Resource
{
friend class ResourceManager;
};
/** Singleton resource manager to keep track of and cache any external engine assets */
class ResourceManager
{
@@ -40,6 +65,7 @@ private:
ResourceManager();
public:
static bool UseThreading;
/*static ResourceManager& Instance()
{
static ResourceManager s;
@@ -49,15 +75,6 @@ public:
template <typename T>
static void RegisterType(std::string typeName);
/** Preloads a resource and caches it for future use
@tparam T Resource type.
@param resourceName Fully qualified name of the resource to preload.
*/
template <typename T>
static void Preload(std::string resourceName);
static void Preload(std::string resourceType, std::string resourceName);
/** Checks if a resource is in cache
@param resourceType Resource type as string.
@@ -65,15 +82,20 @@ public:
*/
// TODO: Templateify
static bool IsResourceLoaded(std::string resourceType, std::string resourceName);
/** Return value should always be a valid pointer, will throw an exception on error.
If the resource has been loaded already, returns a pointer to it.
/** Hot-loads a resource and caches it for future use
If Async is false: Hot-loads a resource, caches it for future use, and returns a pointer to it.
If Async is true: If the resource is not loaded yet, starts loading the resource
in the background and throws Resource::StillLoadingException immediately.
@tparam T Resource type.
@tparam async Set this to true if the resource should be loaded asyncronously.
@param resourceName Fully qualified name of the resource to load.
*/
template <typename T>
static T* Load(std::string resourceName, Resource* parent = nullptr);
static Resource* Load(std::string resourceType, std::string resourceName, Resource* parent = nullptr);
template <typename T, bool async = false>
static T* Load(const std::string& resourceName, Resource* parent = nullptr);
/** Reloads an already loaded resource, keeping its resource ID intact.
@@ -87,19 +109,31 @@ public:
static void Update();
private:
//This is a haxy way to make sure that IsMainThread is run when the program starts, so the master thread id is set.
struct MasterThreadChecker
{
MasterThreadChecker()
{
ResourceManager::IsMainThread();
}
};
const static MasterThreadChecker m_Checker;
static std::unordered_map<std::string, std::string> m_CompilerTypenameToResourceType;
static std::unordered_map<std::string, std::function<Resource*(std::string)>> m_FactoryFunctions; // type -> factory function
static std::unordered_map<std::pair<std::string, std::string>, Resource*> m_ResourceCache; // (type, name) -> resource
static std::unordered_map<std::string, Resource*> m_ResourceFromName; // name -> resource
static std::unordered_map<Resource*, Resource*> m_ResourceParents; // resource -> parent resource
static std::unordered_map<std::pair<std::string, std::string>, boost::thread> m_LoadingThreads; // (type, name) -> loading thread
static std::unordered_map<std::pair<std::string, std::string>, std::exception_ptr> m_LoadingThreadExceptions; // (type, name) -> exceptions
static boost::recursive_mutex m_Mutex;
// TODO: Getters for IDs
static unsigned int m_CurrentResourceTypeID;
static std::unordered_map<std::string, unsigned int> m_ResourceTypeIDs;
// Number of resources of a type. Doubles as local ID.
static std::unordered_map<unsigned int, unsigned int> m_ResourceCount;
// Flag to suppress hot-load warnings when a preloading resource chain loads another resource
static bool m_Preloading;
static FileWatcher m_FileWatcher;
static void fileWatcherCallback(std::string path, FileWatcher::FileEventFlags flags);
@@ -108,22 +142,13 @@ private:
static unsigned int GetNewResourceID(unsigned int typeID);
// Internal: Create a resource and cache it
static Resource* CreateResource(std::string resourceType, std::string resourceName, Resource* parent);
static Resource* createResourceThrowing(const std::string& resourceType, const std::string& resourceName, Resource* parent);
static Resource* createResource(const std::string& resourceType, const std::string& resourceName, Resource* parent, std::exception_ptr& exception);
static Resource* cacheResource(Resource* resource, const std::string& resourceType, const std::string& resourceName, Resource* parent);
static bool IsMainThread();
};
template <typename T>
T* ResourceManager::Load(std::string resourceName, Resource* parent /* = nullptr */)
{
auto resourceTypename = typeid(T).name();
auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
if (it == m_CompilerTypenameToResourceType.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
return nullptr;
}
return static_cast<T*>(Load(it->second, resourceName, parent));
}
template <typename T>
void ResourceManager::RegisterType(std::string typeName)
{
@@ -131,17 +156,85 @@ void ResourceManager::RegisterType(std::string typeName)
m_FactoryFunctions[typeName] = [](std::string resourceName) { return new T(resourceName); };
}
template <typename T>
void ResourceManager::Preload(std::string resourceName)
template <typename T, bool async>
static T* ResourceManager::Load(const std::string& resourceName, Resource* parent /* = nullptr */)
{
auto resourceTypename = typeid(T).name();
auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
if (it == m_CompilerTypenameToResourceType.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
return;
}
auto resourceTypename = typeid(T).name();
auto iter = m_CompilerTypenameToResourceType.find(resourceTypename);
if (iter == m_CompilerTypenameToResourceType.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
throw Resource::FailedLoadingException();
}
Preload(it->second, resourceName);
std::string resourceType = iter->second;
constexpr bool mustNotLoadInThread = std::is_base_of<ThreadUnsafeResource, T>::value;
if (mustNotLoadInThread && !IsMainThread()) {
LOG_ERROR("Failed to Load \"%s\": ThreadUnsafeResource type \"%s\" load in the constructor of another resource that is loaded asyncronously.", resourceName.c_str(), iter->second.c_str());
throw Resource::FailedLoadingException();
}
auto cacheKey = std::make_pair(resourceType, resourceName);
decltype(m_ResourceCache)::iterator it;
//If a thread has already been launched to load this resource.
auto tIt = m_LoadingThreads.find(cacheKey);
if (UseThreading && tIt != m_LoadingThreads.end()) {
if (async) {
//Throw StillLoadingException if the thread is still working.
if (!tIt->second.try_join_for(boost::chrono::nanoseconds(1))) {
throw Resource::StillLoadingException();
}
//Else we know the thread has completed.
} else {
//Wait for the thread to finish loading.
tIt->second.join();
}
//When the thread is done, delete the thread.
m_LoadingThreads.erase(tIt);
//Rethrow the thread exception if it threw any.
auto excIt = m_LoadingThreadExceptions.find(cacheKey);
std::exception_ptr exception = excIt->second;
m_LoadingThreadExceptions.erase(excIt);
if (exception) {
std::rethrow_exception(exception);
}
}
//If resource has already been cached and completely loaded.
it = m_ResourceCache.find(cacheKey);
if (it != m_ResourceCache.end()) {
if (it->second != nullptr) {
return static_cast<T*>(it->second);
} else {
//Don't return null on failure, exception instead.
throw Resource::FailedLoadingException();
}
}
//If resource is not cached..
if (UseThreading && async) {
if (mustNotLoadInThread) {
try {
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
} catch (const Resource::StillLoadingException&) {
throw;
}
} else {
//Create a thread that loads the resource into cache.
m_LoadingThreads[cacheKey] = boost::thread(createResource, resourceType, resourceName, parent, m_LoadingThreadExceptions[cacheKey]);
throw Resource::StillLoadingException();
}
} else {
//load and return the resource.
while (true) {
try {
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
} catch (const Resource::StillLoadingException&) {
continue;
} catch (const std::exception&) {
throw;
}
}
}
}
#endif
+1 -1
View File
@@ -3,7 +3,7 @@
#include "../Core/ResourceManager.h"
class BaseTexture : public Resource
class BaseTexture : public ThreadUnsafeResource
{
friend class ResourceManager;
+38
View File
@@ -0,0 +1,38 @@
#ifndef DrawFinalPass_h__
#define DrawFinalPass_h__
#include "IRenderer.h"
#include "DrawFinalPassState.h"
#include "LightCullingPass.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawFinalPass
{
public:
DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass);
~DrawFinalPass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderScene& scene);
//Getters
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
Texture* m_WhiteTexture;
const IRenderer* m_Renderer;
const LightCullingPass* m_LightCullingPass;
ShaderProgram* m_ForwardPlusProgram;
};
#endif
@@ -0,0 +1,15 @@
#ifndef DrawFinalPassState_h__
#define DrawFinalPassState_h__
#include "Rendering/RenderState.h"
class DrawFinalPassState : public RenderState
{
public:
DrawFinalPassState();
~DrawFinalPassState();
private:
};
#endif
+4
View File
@@ -9,6 +9,8 @@
#include "Camera.h"
#include "RenderQueue.h"
#include "Model.h"
#include "../Core/World.h" //So temp
struct PickData
{
@@ -43,6 +45,8 @@ public:
virtual void Draw(RenderFrame& rq) = 0;
virtual PickData Pick(glm::vec2 screenCord) = 0;
World* m_World; //Temp world, untill viktor merge.
protected:
Rectangle m_Resolution = Rectangle::Rectangle(1280, 720);
bool m_Fullscreen = false;
@@ -0,0 +1,83 @@
#ifndef LightCullingPass_h__
#define LightCullingPass_h__
#define TILE_SIZE 16
#define MAX_LIGHTS_PER_TILE 200
#include "IRenderer.h"
#include "LightCullingPassState.h"
#include "ShaderProgram.h"
#include "RenderQueue.h"
class LightCullingPass
{
public:
LightCullingPass(IRenderer* renderer);
~LightCullingPass();
void GenerateNewFrustum(RenderScene& scene);
void OnResolutionChange();
void SetSSBOSizes();
void CullLights(RenderScene& scene);
void FillLightList(RenderScene& scene);
GLuint FrustumSSBO() const { return m_FrustumSSBO; }
GLuint LightSSBO() const { return m_LightSSBO; }
GLuint LightGridSSBO() const { return m_LightGridSSBO; }
GLuint LightOffsetSSBO() const { return m_LightOffsetSSBO; }
GLuint LightIndexSSBO() const { return m_LightIndexSSBO; }
private:
void InitializeSSBOs();
void InitializeShaderPrograms();
const IRenderer* m_Renderer;
GLuint m_FrustumSSBO = 0;
GLuint m_LightSSBO = 0;
GLuint m_LightGridSSBO = 0;
GLuint m_LightOffsetSSBO = 0;
GLuint m_LightIndexSSBO = 0;
ShaderProgram* m_CalculateFrustumProgram;
ShaderProgram* m_LightCullProgram;
int m_NumberOfTiles = 0;
struct Plane {
glm::vec3 Normal;
float d;
};
struct Frustum {
Plane Planes[4];
};
Frustum* m_Frustums;
//This should be a component
struct PointLight {
glm::vec4 Position = glm::vec4(0.f);
glm::vec4 Color = glm::vec4(1.f);
float Radius = 5.f;
float Intensity = 0.8f;
float Falloff = 0.3f;
float Padding = 1337;
};
std::vector<PointLight> m_PointLights;
struct LightGrid {
float Start;
float Amount;
glm::vec2 Padding;
};
LightGrid* m_LightGrid;
int m_LightOffset = 0;
float* m_LightIndex;
};
#endif
+5 -1
View File
@@ -4,7 +4,7 @@
#include "RawModel.h"
#include "../OpenGL.h"
class Model : public RawModel
class Model : public ThreadUnsafeResource
{
friend class ResourceManager;
@@ -13,11 +13,15 @@ private:
public:
~Model();
const std::vector<RawModel::MaterialGroup>& MaterialGroups() const { return m_RawModel->MaterialGroups; }
const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; }
const std::vector<RawModel::Vertex>& Vertices() const { return m_RawModel->m_Vertices; }
GLuint VAO;
GLuint ElementBuffer;
private:
RawModel* m_RawModel;
GLuint VertexBuffer;
GLuint DiffuseVertexColorBuffer;
GLuint SpecularVertexColorBuffer;
+8 -8
View File
@@ -15,16 +15,16 @@
struct ModelJob : RenderJob
{
ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::Model::MaterialGroup texGroup, ComponentWrapper modelComponent, World* world)
ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, World* world)
: RenderJob()
{
Model = model;
TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0;
DiffuseTexture = texGroup.Texture.get();
NormalTexture = texGroup.NormalMap.get();
SpecularTexture = texGroup.SpecularMap.get();
StartIndex = texGroup.StartIndex;
EndIndex = texGroup.EndIndex;
TextureID = (matGroup.Texture) ? matGroup.Texture->ResourceID : 0;
DiffuseTexture = matGroup.Texture.get();
NormalTexture = matGroup.NormalMap.get();
SpecularTexture = matGroup.SpecularMap.get();
StartIndex = matGroup.StartIndex;
EndIndex = matGroup.EndIndex;
Matrix = matrix;
Color = modelComponent["Color"];
Entity = modelComponent.EntityID;
@@ -44,7 +44,7 @@ struct ModelJob : RenderJob
const ::Model* Model = nullptr;
unsigned int StartIndex = 0;
unsigned int EndIndex = 0;
const World* World;
World* World;
void CalculateHash() override
{
+4 -1
View File
@@ -1,6 +1,8 @@
#ifndef PickingPass_h__
#define PickingPass_h__
#include "IRenderer.h"
#include "PickingPassState.h"
#include "FrameBuffer.h"
@@ -9,6 +11,8 @@
#include "../Core/EventBroker.h"
#include "../Core/World.h"
class PickingPass
{
public:
@@ -21,7 +25,6 @@ public:
void Draw(RenderScene& scene);
void ClearPicking();
//Getters
const ShaderProgram& PickingProgram() const { return *m_PickingProgram; }
//const std::unordered_map<glm::ivec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; }
+39
View File
@@ -0,0 +1,39 @@
#ifndef PointLightJob_h__
#define PointLightJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "RenderJob.h"
#include "../Core/Transform.h"
#include "../Core/World.h"
struct PointLightJob : RenderJob
{
PointLightJob(ComponentWrapper transformComponent, ComponentWrapper pointLightComponent, World* m_World)
: RenderJob()
{
Position = glm::vec4((glm::vec3)transformComponent["Position"], 1.0f);
Position = glm::vec4(Transform::AbsolutePosition(m_World, transformComponent.EntityID), 1.f);
Color = (glm::vec4)pointLightComponent["Color"];
Radius = (double)pointLightComponent["Radius"];
Intensity = (double)pointLightComponent["Intensity"];
Falloff = (double)pointLightComponent["Falloff"];
};
glm::vec4 Position;
glm::vec4 Color;
float Radius;
float Intensity;
float Falloff;
float padding = 123;
void CalculateHash() override
{
Hash = 0;
}
};
#endif
+4 -1
View File
@@ -47,14 +47,17 @@ public:
{
float Shininess;
float Transparency;
std::string TexturePath;
std::shared_ptr<::Texture> Texture;
std::string NormalMapPath;
std::shared_ptr<::Texture> NormalMap;
std::string SpecularMapPath;
std::shared_ptr<::Texture> SpecularMap;
unsigned int StartIndex;
unsigned int EndIndex;
};
std::vector<MaterialGroup> TextureGroups;
std::vector<MaterialGroup> MaterialGroups;
std::vector<Vertex> m_Vertices;
std::vector<unsigned int> m_Indices;
+9 -8
View File
@@ -11,7 +11,7 @@
#include "Camera.h"
#include "RenderJob.h"
#include "ModelJob.h"
#include "PointLightJob.h"
/*
@@ -34,11 +34,12 @@ struct SpriteJob : RenderJob
struct PointLightJob : RenderJob
{
glm::vec3 Position;
glm::vec3 SpecularColor = glm::vec3(1, 1, 1);
glm::vec3 DiffuseColor = glm::vec3(1, 1, 1);
float Radius = 1.f;
float Intensity = 0.8f;
glm::vec4 Position;
glm::vec4 Color;
float Radius;
float Intensity;
float Falloff;
float padding = 123;
void CalculateHash() override
{
@@ -51,13 +52,13 @@ struct RenderScene
{
::Camera* Camera;
std::list<std::shared_ptr<RenderJob>> ForwardJobs;
std::list<std::shared_ptr<RenderJob>> LightJobs;
std::list<std::shared_ptr<RenderJob>> PointLightJobs;
Rectangle Viewport;
void Clear()
{
ForwardJobs.clear();
LightJobs.clear();
PointLightJobs.clear();
}
};
+2
View File
@@ -13,6 +13,7 @@
#include "Camera.h"
#include "ModelJob.h"
#include "Renderer.h"
#include "PointLightJob.h"
#include "../Core/Transform.h"
#include "DebugCameraInputController.h"
@@ -45,6 +46,7 @@ private:
void updateProjectionMatrix(ComponentWrapper& cameraComponent);
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
+7 -2
View File
@@ -12,9 +12,12 @@
#include "../Core/World.h"
#include "PickingPass.h"
#include "DrawScenePass.h"
#include "LightCullingPass.h"
#include "DrawFinalPass.h"
#include "../Core/EventBroker.h"
#include "ImGuiRenderPass.h"
#include "Camera.h"
#include "../Core/Transform.h"
class Renderer : public IRenderer
{
@@ -44,24 +47,26 @@ private:
DrawScenePass* m_DrawScenePass;
PickingPass* m_PickingPass;
LightCullingPass* m_LightCullingPass;
ImGuiRenderPass* m_ImGuiRenderPass;
DrawFinalPass* m_DrawFinalPass;
//----------------------Functions----------------------//
void InitializeWindow();
void InitializeShaders();
void InitializeTextures();
void InitializeSSBOs();
void InitializeRenderPasses();
//TODO: Renderer: Get InputUpdate out of renderer
void InputUpdate(double dt);
//void PickingPass(RenderQueueCollection& rq);
void DrawScreenQuad(GLuint textureToDraw);
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j) { return (i->Depth < j->Depth); }
void FillDepth(RenderScene& scene);
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
//--------------------ShaderPrograms-------------------//
ShaderProgram* m_BasicForwardProgram;
ShaderProgram* m_DrawScreenQuadProgram;
};
#endif