diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index c963e6b8..9cd2fe63 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -15,11 +15,11 @@ class CollisionSystem : public PureSystem public: CollisionSystem(SystemParams params, Octree* octree) : System(params) - , PureSystem("Collidable") + , PureSystem("Physics") , m_Octree(octree) { } - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPhysics, double dt) override; private: Octree* m_Octree; diff --git a/include/Engine/Core/ComponentInfo.h b/include/Engine/Core/ComponentInfo.h index d9799059..137a44d8 100644 --- a/include/Engine/Core/ComponentInfo.h +++ b/include/Engine/Core/ComponentInfo.h @@ -2,6 +2,7 @@ #define ComponentInfo_h__ #include "../Common.h" +#include struct ComponentInfo { @@ -27,8 +28,9 @@ struct ComponentInfo std::string Name; std::unordered_map Fields; std::vector FieldsInOrder; + std::vector StringFields; unsigned int Stride = 0; - std::shared_ptr Defaults = nullptr; + boost::shared_array Defaults = nullptr; std::shared_ptr Meta = nullptr; }; diff --git a/include/Engine/Core/ComponentPool.h b/include/Engine/Core/ComponentPool.h index 957b8756..aedfd06b 100644 --- a/include/Engine/Core/ComponentPool.h +++ b/include/Engine/Core/ComponentPool.h @@ -1,6 +1,7 @@ #ifndef ComponentPool_h__ #define ComponentPool_h__ +#include #include "MemoryPool.h" #include "ComponentInfo.h" #include "ComponentWrapper.h" @@ -45,7 +46,8 @@ public: : m_ComponentInfo(ci) , m_Pool(ci.Meta->Allocation, sizeof(EntityID) + ci.Stride) { } - ComponentPool(const ComponentPool& other) = delete; + ~ComponentPool(); + ComponentPool(const ComponentPool& other); ComponentPool(const ComponentPool&& other) = delete; const ::ComponentInfo& ComponentInfo() const { return m_ComponentInfo; } diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index 0b9f7357..7897e874 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -2,11 +2,29 @@ #define ComponentWrapper_h__ #include +#include #include "../Common.h" #include "Entity.h" #include "ComponentInfo.h" #include "Util/Any.h" +template +struct ComponentField { }; + +template +struct ComponentField::value>::type> +{ + static T& Get(const ComponentInfo::Field_t& info, char* data) { return *reinterpret_cast(data); } + static void Set(const ComponentInfo::Field_t& info, char* data, const T& value) { Get(data) = value; } +}; + +template <> +struct ComponentField +{ + static std::string& Get(const ComponentInfo::Field_t& info, char* data) { return **reinterpret_cast(data); } + static void Set(const ComponentInfo::Field_t& info, char* data, const std::string& value) { Get(info, data) = value; } +}; + struct ComponentWrapper { ComponentWrapper(const ComponentInfo& componentInfo, char* data) @@ -47,7 +65,31 @@ struct ComponentWrapper void Copy(ComponentWrapper& destination) { - memcpy(destination.Data, this->Data, Info.Stride); + // Copy trivial data + memcpy(destination.Data, Data, Info.Stride); + // Duplicate strings + SolidifyStrings(destination); + } + + // When component data has been copied, strings need to be reconstructed or they'll refer to the same data! + static void SolidifyStrings(ComponentWrapper& component) + { + for (auto& name : component.Info.StringFields) { + std::size_t offset = component.Info.Fields.at(name).Offset; + std::string value = *reinterpret_cast(component.Data + offset); + new (component.Data + offset) std::string(value); + } + } + + // This needs to be called to properly free component data, because strings. + static void Destroy(ComponentInfo info, char* data) + { + // Call std::string destructors + for (auto& name : info.StringFields) { + std::size_t offset = info.Fields.at(name).Offset; + auto field = reinterpret_cast(data + offset); + field->~basic_string(); + } } struct SubscriptProxy @@ -102,26 +144,38 @@ public: ComponentWrapperFactory(std::string componentTypeName, unsigned int allocation = 0) { m_ComponentInfo.Name = componentTypeName; + m_ComponentInfo.Meta = std::make_shared(); m_ComponentInfo.Meta->Allocation = allocation; } template void AddProperty(std::string fieldName, T defaultValue) { - m_DefaultValues.push_back(defaultValue); - m_ComponentInfo.Fields[fieldName].Type = typeid(T).name(); - m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Stride; - m_ComponentInfo.Fields[fieldName].Stride = sizeof(T); + auto& field = m_ComponentInfo.Fields[fieldName]; + field.Name = fieldName; + field.Type = typeid(T).name(); + field.Offset = m_ComponentInfo.Stride; + field.Stride = sizeof(T); + m_ComponentInfo.FieldsInOrder.push_back(field.Name); + if (field.Type == typeid(std::string).name()) { + field.Type = "string"; + m_ComponentInfo.StringFields.push_back(field.Name); + } m_ComponentInfo.Stride += sizeof(T); + m_DefaultValues.push_back(std::make_pair(field, defaultValue)); } - + ComponentInfo& Finalize() { - m_ComponentInfo.Defaults = std::shared_ptr(new char[m_ComponentInfo.Stride]); + m_ComponentInfo.Defaults = boost::shared_array(new char[m_ComponentInfo.Stride]); std::size_t offset = 0; - for (auto& val : m_DefaultValues) { - memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size); - offset += val.Size; + for (auto& pair : m_DefaultValues) { + if (pair.first.Type == "string") { + new (m_ComponentInfo.Defaults.get() + offset) std::string(*reinterpret_cast(pair.second.Data.get())); + } else { + memcpy(m_ComponentInfo.Defaults.get() + offset, pair.second.Data.get(), pair.second.Size); + } + offset += pair.second.Size; } return m_ComponentInfo; @@ -131,7 +185,7 @@ public: private: ComponentInfo m_ComponentInfo; - std::vector m_DefaultValues; + std::vector> m_DefaultValues; }; #endif diff --git a/include/Engine/Core/MemoryPool.h b/include/Engine/Core/MemoryPool.h index f4073294..053e75aa 100644 --- a/include/Engine/Core/MemoryPool.h +++ b/include/Engine/Core/MemoryPool.h @@ -66,9 +66,25 @@ public: , m_LowestAllocatedSlot(m_NumSlots) { } - //We may get problems with memory being released - //prematurely, etc. if we allow copies. - MemoryPool(const MemoryPool& other) = delete; + MemoryPool(const MemoryPool& other) + : m_StartAddress(new char[other.m_NumSlots*other.m_Stride]) + , m_SlotIsAllocated(other.m_SlotIsAllocated) + , m_ExtraMemory() + , m_NumSlots(other.m_NumSlots) + , m_LowestAllocatedSlot(other.m_LowestAllocatedSlot) + , m_NumAllocatedSlots(other.m_NumAllocatedSlots) + , m_Stride(other.m_Stride) + , m_CurrentAllocSlot(other.m_CurrentAllocSlot) + { + // Copy statically allocated pool + memcpy(m_StartAddress, other.m_StartAddress, m_NumSlots*m_Stride); + // Copy dynamically allocated memory + for (char* otherAddr : other.m_ExtraMemory) { + char* addr = (char*)malloc(m_Stride); + memcpy(addr, otherAddr, m_Stride); + m_ExtraMemory.push_back(addr); + } + } MemoryPool(const MemoryPool&& other) = delete; //Free all memory that has been allocated. @@ -78,8 +94,9 @@ public: delete[] m_StartAddress; m_StartAddress = nullptr; } - for (char* addr : m_ExtraMemory) - free(addr); + for (char* addr : m_ExtraMemory) { + free(addr); + } m_ExtraMemory.clear(); } diff --git a/include/Engine/Core/Util/Any.h b/include/Engine/Core/Util/Any.h index f0f90737..e7b93dfb 100644 --- a/include/Engine/Core/Util/Any.h +++ b/include/Engine/Core/Util/Any.h @@ -2,6 +2,7 @@ #define Util_Any_h__ #include +#include struct Any { @@ -10,7 +11,7 @@ struct Any template Any(const T& value) { - Data = std::shared_ptr(new char[sizeof(T)]); + Data = boost::shared_array(new char[sizeof(T)]); Size = sizeof(T); memcpy(Data.get(), &value, Size); } @@ -18,7 +19,7 @@ struct Any template Any(T&& value) { - Data = std::shared_ptr(new char[sizeof(T)]); + Data = boost::shared_array(new char[sizeof(T)]); Size = sizeof(T); memcpy(Data.get(), &value, Size); } @@ -35,7 +36,7 @@ struct Any return Any(value); } - std::shared_ptr Data = nullptr; + boost::shared_array Data = nullptr; std::size_t Size = 0; }; diff --git a/include/Engine/Core/World.h b/include/Engine/Core/World.h index 35394b9f..1604df37 100644 --- a/include/Engine/Core/World.h +++ b/include/Engine/Core/World.h @@ -15,6 +15,7 @@ public: : m_EventBroker(eventBroker) { } ~World(); + World(const World& other); // Create empty entity EntityID CreateEntity(EntityID parent = 0); diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index 1d91f6a2..e3389471 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -18,7 +18,7 @@ public: void InitializeTextures(); void InitializeFrameBuffers(); void InitializeShaderPrograms(); - void Draw(RenderScene& scene); + void Draw(RenderScene& scene, GLuint SSAOTexture); void ClearBuffer(); void OnWindowResize(); @@ -37,7 +37,7 @@ private: void GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps) const; void DrawSprites(std::list>&jobs, RenderScene& scene); - void DrawModelRenderQueues(std::list>& jobs, RenderScene& scene); + void DrawModelRenderQueues(std::list>& jobs, RenderScene& scene, GLuint SSAOTexture); void DrawShieldToStencilBuffer(std::list>& jobs, RenderScene& scene); void DrawShieldedModelRenderQueue(std::list>& jobs, RenderScene& scene); void DrawToDepthBuffer(std::list>& jobs, RenderScene& scene); diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 2f42bad2..aa87536b 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -16,6 +16,7 @@ #include "DrawScreenQuadPass.h" #include "DrawBloomPass.h" #include "DrawColorCorrectionPass.h" +#include "SSAOPass.h" #include "../Core/EventBroker.h" #include "ImGuiRenderPass.h" #include "Camera.h" @@ -58,6 +59,12 @@ private: int m_DebugTextureToDraw = 0; bool m_ResizeWindow = false; + float m_SSAO_Radius = 1.0f; + float m_SSAO_Bias = 0.05f; + float m_SSAO_Contrast = 1.5f; + float m_SSAO_IntensityScale = 1.0f; + int m_SSAO_NumOfSamples = 24; + int m_SSAO_NumOfTurns = 7; PickingPass* m_PickingPass; LightCullingPass* m_LightCullingPass; @@ -66,6 +73,7 @@ private: DrawScreenQuadPass* m_DrawScreenQuadPass; DrawBloomPass* m_DrawBloomPass; DrawColorCorrectionPass* m_DrawColorCorrectionPass; + SSAOPass* m_SSAOPass; //----------------------Functions----------------------// void InitializeWindow(); diff --git a/include/Engine/Rendering/SSAOPass.h b/include/Engine/Rendering/SSAOPass.h new file mode 100644 index 00000000..f15e20d3 --- /dev/null +++ b/include/Engine/Rendering/SSAOPass.h @@ -0,0 +1,61 @@ +#ifndef SSAOPass_h__ +#define SSAOPass_h__ + +#include "IRenderer.h" +#include "SSAOPassState.h" +//#include "LightCullingPass.h" Finalpass om den skall skickas in +#include "FrameBuffer.h" +#include "ShaderProgram.h" +#include "DrawBloomPass.h" +//#include "Util/UnorderedMapVec2.h" +#include "Texture.h" + +class SSAOPass +{ +public: + SSAOPass(IRenderer* rendere); + ~SSAOPass() { }; + + void Draw(GLuint depthBuffer, Camera* camera); + void Setting(float radius, float bias, float contrast, float intensityScale, int numOfSamples, int NumOfTurns); + void ClearBuffer(); + + //Return the SSAO of the texture sent to Draw + GLuint SSAOTexture() const { return m_DrawBloomPass->GaussianTexture(); } + +private: + void InitializeTexture(); + void InitializeFrameBuffer(); + void InitializeShaderProgram(); + void InitializeBuffer(); + + void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; + + void ComputeAO(GLuint depthBuffer, Camera* camera); + //void blurHorizontal(GLuint depthBuffer); + //void blurVertical(GLuint depthBuffer); + + Model* m_ScreenQuad; + + const IRenderer* m_Renderer; + + float m_Radius; + float m_Bias; + float m_Contrast; + float m_IntensityScale; + int m_NumOfSamples; + int m_NumOfTurns; + + GLuint m_SSAOTexture; + FrameBuffer m_SSAOFramBuffer; + + GLuint m_SSAOViewSpaceZTexture; + FrameBuffer m_SSAOViewSpaceZFramBuffer; + + ShaderProgram* m_SSAOProgram; + ShaderProgram* m_SSAOViewSpaceZProgram; + + DrawBloomPass* m_DrawBloomPass; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/SSAOPassState.h b/include/Engine/Rendering/SSAOPassState.h new file mode 100644 index 00000000..115fdcf7 --- /dev/null +++ b/include/Engine/Rendering/SSAOPassState.h @@ -0,0 +1,15 @@ +#ifndef SSAOPassState_h__ +#define SSAOPassState_h__ + +#include "Rendering/RenderState.h" + +class SSAOPassState : public RenderState +{ +public: + SSAOPassState(); + ~SSAOPassState(); +private: + +}; + +#endif \ No newline at end of file diff --git a/resources/Schema/Components/Physics.xml b/resources/Schema/Components/Physics.xml index 6cb73c75..84b6aba3 100644 --- a/resources/Schema/Components/Physics.xml +++ b/resources/Schema/Components/Physics.xml @@ -2,6 +2,7 @@ true + false 0.33 diff --git a/resources/Schema/Components/Physics.xsd b/resources/Schema/Components/Physics.xsd index 7fed1fb5..206e2a23 100644 --- a/resources/Schema/Components/Physics.xsd +++ b/resources/Schema/Components/Physics.xsd @@ -13,6 +13,7 @@ m/s^2 + The largest height of a "stair-step" that can be walked over diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index be6009ba..d4485112 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -349,13 +349,12 @@ Idle - 1.6050530664521858 + 1.8314163732853146 1 Models/Characters/Assault/FirstPerson.mesh - true @@ -367,11 +366,10 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - true - - + + @@ -477,7 +475,7 @@ Idle - 1.620305457513453 + 0.16333512901638159 1 @@ -501,8 +499,8 @@ Models/Weapons/Blue/AssaultWeaponBlue.mesh - - + + diff --git a/resources/Schema/Entities/PlayerRed.xml b/resources/Schema/Entities/PlayerRed.xml index d9839e9f..4be8fc26 100644 --- a/resources/Schema/Entities/PlayerRed.xml +++ b/resources/Schema/Entities/PlayerRed.xml @@ -349,13 +349,12 @@ Idle - 1.6050530664521858 + 0.018170670865885086 1 Models/Characters/Assault/FirstPerson.mesh - true @@ -367,11 +366,10 @@ Models/Weapons/Red/AssaultWeaponRed.mesh - true - - + + @@ -477,7 +475,7 @@ Idle - 1.620305457513453 + 0.11675631578762591 1 @@ -501,8 +499,8 @@ Models/Weapons/Red/AssaultWeaponRed.mesh - - + + diff --git a/resources/Shaders/DrawColorCorrection.frag.glsl b/resources/Shaders/DrawColorCorrection.frag.glsl index 76db3e82..bae50887 100644 --- a/resources/Shaders/DrawColorCorrection.frag.glsl +++ b/resources/Shaders/DrawColorCorrection.frag.glsl @@ -19,6 +19,8 @@ void main() vec4 bloomColor = texture(BloomTexture, Input.TextureCoordinate); vec4 hdrColorLowRes = texture(SceneTextureLowRes, Input.TextureCoordinate); vec4 bloomColorLowRes = texture(BloomTextureLowRes, Input.TextureCoordinate); + + //hdrColor = hdrColor * SSAO; hdrColor += bloomColor; hdrColorLowRes; @@ -33,7 +35,6 @@ void main() //gamme correction result = pow(result, vec3(1.0 / Gamma)); - fragmentColor = vec4(result, 1.0); //fragmentColor = hdrColor; //fragmentColor = bloomColor; diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 2db0295c..f9b93091 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -1,5 +1,7 @@ #version 430 +#define MIN_AMBIENT_LIGHT 0.3 + uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -15,10 +17,11 @@ uniform vec2 DiffuseUVRepeat; uniform vec2 NormalUVRepeat; uniform vec2 SpecularUVRepeat; uniform vec2 GlowUVRepeat; -layout (binding = 0) uniform sampler2D DiffuseTexture; -layout (binding = 1) uniform sampler2D NormalMapTexture; -layout (binding = 2) uniform sampler2D SpecularMapTexture; -layout (binding = 3) uniform sampler2D GlowMapTexture; +layout (binding = 0) uniform sampler2D AOTexture; +layout (binding = 1) uniform sampler2D DiffuseTexture; +layout (binding = 2) uniform sampler2D NormalMapTexture; +layout (binding = 3) uniform sampler2D SpecularMapTexture; +layout (binding = 4) uniform sampler2D GlowMapTexture; #define TILE_SIZE 16 @@ -120,6 +123,8 @@ vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textu void main() { + float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy), 0).r; + ao = (clamp(1.0 - (1.0 - ao), 0.0, 1.0) + MIN_AMBIENT_LIGHT) / (1.0 + MIN_AMBIENT_LIGHT); vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate * DiffuseUVRepeat); vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate * GlowUVRepeat); vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate * SpecularUVRepeat); @@ -134,7 +139,7 @@ void main() tilePos.y = int(gl_FragCoord.y/TILE_SIZE); LightResult totalLighting; - totalLighting.Diffuse = vec4(AmbientColor.rgb, 1.0); + totalLighting.Diffuse = vec4(AmbientColor.rgb * ao, 1.0); int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); int start = int(LightGrids.Data[currentTile].Start); @@ -152,8 +157,8 @@ void main() } else if (light.Type == 2) { //Directional light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); } - totalLighting.Diffuse += light_result.Diffuse; - totalLighting.Specular += light_result.Specular; + totalLighting.Diffuse += vec4(light_result.Diffuse.rgb * ao, light_result.Diffuse.a); + totalLighting.Specular += vec4(light_result.Specular.rgb * ao, light_result.Specular.a); } vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); diff --git a/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl b/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl index e862d926..cf358b96 100644 --- a/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl +++ b/resources/Shaders/ForwardPlusSplatMapRGB.frag.glsl @@ -1,5 +1,7 @@ #version 430 +#define MIN_AMBIENT_LIGHT 0.3 + uniform mat4 M; uniform mat4 V; uniform mat4 P; @@ -23,19 +25,20 @@ uniform vec2 SpecularUVRepeat3; uniform vec2 GlowUVRepeat1; uniform vec2 GlowUVRepeat2; uniform vec2 GlowUVRepeat3; -layout (binding = 0) uniform sampler2D SplatMapTexture; -layout (binding = 1) uniform sampler2D DiffuseTexture1; -layout (binding = 2) uniform sampler2D DiffuseTexture2; -layout (binding = 3) uniform sampler2D DiffuseTexture3; -layout (binding = 4) uniform sampler2D NormalMapTexture1; -layout (binding = 5) uniform sampler2D NormalMapTexture2; -layout (binding = 6) uniform sampler2D NormalMapTexture3; -layout (binding = 7) uniform sampler2D SpecularMapTexture1; -layout (binding = 8) uniform sampler2D SpecularMapTexture2; -layout (binding = 9) uniform sampler2D SpecularMapTexture3; -layout (binding = 10) uniform sampler2D GlowMapTexture1; -layout (binding = 11) uniform sampler2D GlowMapTexture2; -layout (binding = 12) uniform sampler2D GlowMapTexture3; +layout (binding = 0) uniform sampler2D AOTexture; +layout (binding = 1) uniform sampler2D SplatMapTexture; +layout (binding = 2) uniform sampler2D DiffuseTexture1; +layout (binding = 3) uniform sampler2D DiffuseTexture2; +layout (binding = 4) uniform sampler2D DiffuseTexture3; +layout (binding = 5) uniform sampler2D NormalMapTexture1; +layout (binding = 6) uniform sampler2D NormalMapTexture2; +layout (binding = 7) uniform sampler2D NormalMapTexture3; +layout (binding = 8) uniform sampler2D SpecularMapTexture1; +layout (binding = 9) uniform sampler2D SpecularMapTexture2; +layout (binding = 10) uniform sampler2D SpecularMapTexture3; +layout (binding = 11) uniform sampler2D GlowMapTexture1; +layout (binding = 12) uniform sampler2D GlowMapTexture2; +layout (binding = 13) uniform sampler2D GlowMapTexture3; #define TILE_SIZE 16 @@ -174,6 +177,9 @@ vec4 CalcBlendedNormal(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, void main() { + float ao = texelFetch(AOTexture, ivec2(gl_FragCoord.xy), 0).r; + ao = (clamp(1.0 - (1.0 - ao), 0.0, 1.0) + MIN_AMBIENT_LIGHT) / (1.0 + MIN_AMBIENT_LIGHT); + vec4 splatTexel = texture2D(SplatMapTexture, Input.TextureCoordinate); vec4 diffuseTexel = CalcBlendedTexel(splatTexel, DiffuseTexture1, DiffuseTexture2, DiffuseTexture3, @@ -195,7 +201,7 @@ void main() tilePos.y = int(gl_FragCoord.y/TILE_SIZE); LightResult totalLighting; - totalLighting.Diffuse = vec4(AmbientColor.rgb, 1.0); + totalLighting.Diffuse = vec4(AmbientColor.rgb * ao, 1.0); int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); int start = int(LightGrids.Data[currentTile].Start); @@ -213,8 +219,8 @@ void main() } else if (light.Type == 2) { //Directional light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); } - totalLighting.Diffuse += light_result.Diffuse; - totalLighting.Specular += light_result.Specular; + totalLighting.Diffuse += vec4(light_result.Diffuse.rgb * ao, light_result.Diffuse.a); + totalLighting.Specular += vec4(light_result.Specular.rgb * ao, light_result.Specular.a); } vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); diff --git a/resources/Shaders/SSAO.frag.glsl b/resources/Shaders/SSAO.frag.glsl new file mode 100644 index 00000000..68c830f8 --- /dev/null +++ b/resources/Shaders/SSAO.frag.glsl @@ -0,0 +1,114 @@ +#version 430 + +//Number of samples per pixel +uniform int uNumOfSamples; +//#define NUM_SAMPLES (11) + +//Number of turns around the cirle +uniform int uNumOfTurns; +//#define NUM_TURNS (7) + +layout (binding = 0) uniform sampler2D ViewSpaceZ; + +uniform vec4 uProjInfo; + +uniform float uProjScale; +//#define ProjScale 500 + +uniform float uRadius; +//#define Radius 1.0f + +uniform float uBias; +//#define Bias 0.012f + +uniform float uContrast; +//#define IntensityDivR6 1 + +uniform float uIntensityScale; + +out float AO; + +vec3 getVSPosition(ivec2 ScreenSpaceCoord) { + float z = texelFetch(ViewSpaceZ, ScreenSpaceCoord, 0).r; + //Get the xy view space coordinates and add the z value from ViewSpaceZ buffer. + return vec3((uProjInfo[0] + (ScreenSpaceCoord.x * uProjInfo[1])) * z, (uProjInfo[2] + (ScreenSpaceCoord.y * uProjInfo[3])) * z, z); +} + +vec3 getVSFaceNormal(vec3 ViewSpacePosition) { + // Get tangets vector for the plane and ViewSpacePositin... don't ask how this functions works. It's pure magic. + // They do this and it just works... I would guess that they approximate the function of a plane from pixels close to the pixel were on now. + return normalize(cross(dFdx(ViewSpacePosition), dFdy(ViewSpacePosition))); +} + + +vec3 getSampleViewSpacePos(ivec2 ScreenSpaceCoord, int SampleIndex, float RotationAngle, float ScreenSpaceSampleRadius){ + // Pure Magic... + float alpha = float(SampleIndex) * (1.0 / uNumOfSamples); + + // Angle to where to sample + float angle = alpha * (uNumOfTurns * 6.28) + RotationAngle; + + //Lenght to were to sample + ScreenSpaceSampleRadius = ScreenSpaceSampleRadius * alpha; + + vec2 screenSpaceSampleOffsetVecor = vec2(cos(angle), sin(angle)); + + // Get texel coordinate on where to sample by going screenSpaceSampleOffsetVecor direction in ScreenSpaceSampleRadius units from ScreenSpaceCoord (the point being shaded); + ivec2 screenSpaceSampleTexel = ivec2(ScreenSpaceSampleRadius * screenSpaceSampleOffsetVecor) + ScreenSpaceCoord; + + return getVSPosition(screenSpaceSampleTexel); +} + + + +float sampleAO(ivec2 ScreenSpaceCoord, vec3 Origin, vec3 OriginNormal, float ScreenSpaceSampleRadius, int SampleIndex, float RotationAngle, float Radius) { + float radius2 = Radius * Radius; + vec3 sampleViewSpacePosition = getSampleViewSpacePos(ScreenSpaceCoord, SampleIndex, RotationAngle, ScreenSpaceSampleRadius); + + vec3 sampleVector = Origin - sampleViewSpacePosition; + + // vv = sampleVectorLenght ^ 2 + float vv = dot(sampleVector, sampleVector); + // vn = angle between sampleVector and Normal + float vn = dot(sampleVector, OriginNormal); + + const float epsilon = 0.0001f; + + // vv < radius2 if the vector is shorter then the radius; + // vn - bias, offset the angle to reduse self occlusion. + // epsilon is here to make divison by 0 impossible. + return float(vv < radius2) * max((vn - uBias) / (epsilon + vv), 0.0); + //float f = max(radius2 - vv, 0.0); + //return f * f * f * max((vn - uBias) / (epsilon + vv), 0.0); +} + + +void main() { + ivec2 originScreenCoord = ivec2(gl_FragCoord.xy); + + vec3 origin = getVSPosition(originScreenCoord); + + float radius; + if(origin.z < uRadius){ + radius = origin.z; + } else { + radius = uRadius; + } + + + vec3 originNormal = getVSFaceNormal(origin); + + float screenSpaceSampleRadius = -uProjScale * radius / origin.z; + + float rotationAngleOffset = 30 * originScreenCoord.x ^ originScreenCoord.y + 10 * originScreenCoord.x * originScreenCoord.y; + + float sum = 0.0; + for (int i = 0; i < uNumOfSamples; i++) { + sum += sampleAO(originScreenCoord, origin, originNormal, screenSpaceSampleRadius, i, rotationAngleOffset, radius); + } + + //float A = max(0.0, 1.0 - sum * (2.0f / uNumOfSamples)); + float A = 1.0 - sum * (2.0f * uIntensityScale / float(uNumOfSamples)); + AO = clamp(pow(A, uContrast), 0.0f, 1.0f); + //AO = vec4(originNormal, 1.0f); +} diff --git a/resources/Shaders/SSAO.vert.glsl b/resources/Shaders/SSAO.vert.glsl new file mode 100644 index 00000000..a019c5ef --- /dev/null +++ b/resources/Shaders/SSAO.vert.glsl @@ -0,0 +1,8 @@ +#version 430 + +layout (location = 0) in vec3 Position; + +void main() +{ + gl_Position = vec4(Position, 1.0); +} \ No newline at end of file diff --git a/resources/Shaders/SSAOViewSpaceZ.frag.glsl b/resources/Shaders/SSAOViewSpaceZ.frag.glsl new file mode 100644 index 00000000..dbcfd899 --- /dev/null +++ b/resources/Shaders/SSAOViewSpaceZ.frag.glsl @@ -0,0 +1,14 @@ +#version 430 + +layout (binding = 0) uniform sampler2D DepthBuffer; +uniform vec3 ClipInfo; + +out float depthLinear; +//Just for Debug, should be depthLinear +//out vec4 fragmentColor; +void main() { + float depthSample = texelFetch(DepthBuffer, ivec2(gl_FragCoord.xy), 0).r; + depthLinear = ClipInfo[0] / (ClipInfo[1] * depthSample + ClipInfo[2]); + //float depthLinear = (NearClip) / ( -depthSample + 1.0f); + //fragmentColor = vec4(depthLinear, depthLinear, depthLinear, 1.0f); +} \ No newline at end of file diff --git a/resources/Shaders/Sprite.frag.glsl b/resources/Shaders/Sprite.frag.glsl index 9ce2bbdf..754be6ac 100644 --- a/resources/Shaders/Sprite.frag.glsl +++ b/resources/Shaders/Sprite.frag.glsl @@ -7,8 +7,8 @@ uniform mat4 M; uniform mat4 V; uniform mat4 P; -layout (binding = 0) uniform sampler2D DiffuseTexture; -layout (binding = 1) uniform sampler2D GlowMapTexture; +layout (binding = 1) uniform sampler2D DiffuseTexture; +layout (binding = 2) uniform sampler2D GlowMapTexture; in VertexData{ diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 99566404..68d99d92 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -207,7 +207,7 @@ bool RayVsModel(const Ray& ray, glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - float dist = INFINITY; + float dist = outDistance; float u; float v; if (RayVsTriangle(ray, v0, v1, v2, dist, u, v)) { diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index afd09022..fcc3665f 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -3,24 +3,71 @@ #include "Core/AABB.h" #include "Rendering/Model.h" -void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) +void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPhysics, double dt) { - if (!entity.HasComponent("Physics")) { + if (!entity.HasComponent("Collidable")) { return; } - ComponentWrapper& cPhysics = entity["Physics"]; - boost::optional boundingBox = Collision::EntityAbsoluteAABB(entity); if (!boundingBox) { return; } ComponentWrapper& cTransform = entity["Transform"]; EntityAABB& boxA = *boundingBox; + bool everHitTheGround = false; + + glm::vec3 size = boxA.Size(); + float diameter = std::min(size.x, size.z); + glm::vec3 prevOrigin = (glm::vec3)cPhysics["PrevOrigin"]; + glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin; + float rayLength = glm::length(toCurrentPos) + 0.5f*diameter; + //If the entity has moved farther than the size of its box, we need to handle it specially. + bool traceCollision = rayLength > diameter; + //hack solution: If prevOrigin is less than -9000 in all dimensions, + //then it means it is not set, i.e. this is the first collision check for the entity. + if (traceCollision && glm::any(glm::greaterThan((glm::vec3)cPhysics["PrevOrigin"], glm::vec3(-9000.f)))) { + Ray ray(prevOrigin, toCurrentPos); + m_OctreeResult.clear(); + m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult); + for (auto& boxB : m_OctreeResult) { + if (boxA.Entity == boxB.Entity) { + continue; + } + bool hit; + float dist; + if (boxB.Entity.HasComponent("Model")) { + RawModel* model; + std::string res = (std::string)boxB.Entity["Model"]["Resource"]; + try { + model = ResourceManager::Load(res); + } catch (const std::exception&) { + continue; + } + float u, v; + hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v); + } else { + hit = Collision::RayVsAABB(ray, boxB, dist); + } + if (hit && dist < rayLength) { + //Set the entity to where it was colliding, minus the maximum box size. + //TODO: Perhaps this should be done slightly more properly. + glm::vec3 newOriginPos = ray.Origin() + (dist - 0.707107f*diameter) * ray.Direction(); + glm::vec3 resolve = newOriginPos - boxA.Origin(); + (glm::vec3&)cTransform["Position"] += resolve; + boxA = *Collision::EntityAbsoluteAABB(entity); + if (resolve.y > 0) { + everHitTheGround = true; + (bool)cPhysics["IsOnGround"] = true; + ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + } + break; + } + } + } // Collide against octree items m_OctreeResult.clear(); m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); - bool everHitTheGround = false; for (auto& boxB : m_OctreeResult) { glm::vec3 resolutionVector; if (boxA.Entity == boxB.Entity) { @@ -64,4 +111,6 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c if (!everHitTheGround) { (bool)cPhysics["IsOnGround"] = false; } + + (glm::vec3&)cPhysics["PrevOrigin"] = boxA.Origin(); } diff --git a/src/Engine/Core/ComponentPool.cpp b/src/Engine/Core/ComponentPool.cpp index 7b465fbc..059b2e38 100644 --- a/src/Engine/Core/ComponentPool.cpp +++ b/src/Engine/Core/ComponentPool.cpp @@ -1,7 +1,5 @@ #include "Core/ComponentPool.h" - - ComponentWrapper ComponentPoolForwardIterator::operator*() const { char* data = &(*m_MemoryPoolIterator); @@ -32,6 +30,34 @@ ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++() return *this; } +ComponentPool::ComponentPool(const ComponentPool& other) + : m_ComponentInfo(other.m_ComponentInfo) + , m_Pool(other.m_Pool) + , m_EntityToComponent() +{ + // Update EntityToComponent pointers + for (char& ptr : m_Pool) { + EntityID entity = *reinterpret_cast(&ptr); + m_EntityToComponent[entity] = &ptr; + } + + // Duplicate strings + for (auto& name : m_ComponentInfo.StringFields) { + for (auto& c : *this) { + std::string& val = c[name]; + ComponentWrapper::SolidifyStrings(c); + } + } +} + +ComponentPool::~ComponentPool() +{ + // Destroy component data + for (auto& c : *this) { + ComponentWrapper::Destroy(c.Info, c.Data); + } +} + //const ::ComponentInfo& ComponentPool::ComponentInfo() const //{ // return m_ComponentInfo; @@ -39,10 +65,19 @@ ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++() ComponentWrapper ComponentPool::Allocate(EntityID entity) { + // Allocate pool data char* data = m_Pool.Allocate(); + // Copy EntityID memcpy(data, &entity, sizeof(EntityID)); + m_EntityToComponent[entity] = data; - return ComponentWrapper(m_ComponentInfo, data); + ComponentWrapper component(m_ComponentInfo, data); + + // Copy defaults + memcpy(component.Data, m_ComponentInfo.Defaults.get(), m_ComponentInfo.Stride); + ComponentWrapper::SolidifyStrings(component); + + return component; } ComponentWrapper ComponentPool::GetByEntity(EntityID ent) @@ -57,6 +92,7 @@ bool ComponentPool::KnowsEntity(EntityID ent) void ComponentPool::Delete(ComponentWrapper& wrapper) { + ComponentWrapper::Destroy(wrapper.Info, wrapper.Data); m_EntityToComponent.erase(wrapper.EntityID); m_Pool.Free(wrapper.Data - sizeof(EntityID)); } diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index a1370dd2..592daedb 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -185,6 +185,9 @@ void EntityFilePreprocessor::parseComponentInfo() field.Offset = fieldOffset; field.Stride = stride; compInfo.FieldsInOrder.push_back(name); + if (field.Type == "string") { + compInfo.StringFields.push_back(name); + } fieldOffset += stride; } @@ -201,7 +204,7 @@ void EntityFilePreprocessor::parseDefaults() for (auto& ci : m_ComponentInfo) { // Allocate memory for default values - ci.second.Defaults = std::shared_ptr(new char[ci.second.Stride]); + ci.second.Defaults = boost::shared_array(new char[ci.second.Stride], std::bind(&ComponentWrapper::Destroy, ci.second, std::placeholders::_1)); memset(ci.second.Defaults.get(), 0, ci.second.Stride); std::string componentName = ci.first; diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 69c25f61..8788a92e 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -9,7 +9,20 @@ World::~World() } } -EntityID World::CreateEntity(EntityID parent /*= 0*/) +World::World(const World& other) + : m_EventBroker(other.m_EventBroker) + , m_CurrentEntityID(other.m_CurrentEntityID) + , m_EntityParents(other.m_EntityParents) + , m_EntityChildren(other.m_EntityChildren) + , m_EntityNames(other.m_EntityNames) +{ + // Deep copy component pools + for (auto& kv : other.m_ComponentPools) { + m_ComponentPools[kv.first] = new ComponentPool(*kv.second); + } +} + +EntityID World::CreateEntity(EntityID parent /*= EntityID_Invalid*/) { EntityID newEntity = generateEntityID(); if (newEntity == parent) { @@ -44,10 +57,8 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp ComponentPool* pool = m_ComponentPools.at(componentType); const ComponentInfo& ci = pool->ComponentInfo(); - // Allocate space for the component + // Allocate component with default values ComponentWrapper c = pool->Allocate(entity); - // Write default values - memcpy(c.Data, ci.Defaults.get(), ci.Stride); return c; } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 3406535a..a2f52adb 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -437,11 +437,12 @@ void Client::parsePlayerDamage(Packet& packet) { Events::PlayerDamage e; PlayerID victimID = packet.ReadPrimitive(); - if(serverClientMapsHasEntity(victimID)){ + PlayerID inflictorID = packet.ReadPrimitive(); + if(!serverClientMapsHasEntity(victimID) || !serverClientMapsHasEntity(inflictorID)){ return; } e.Inflictor = EntityWrapper(m_World, m_ServerIDToClientID.at(victimID)); - e.Victim = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive())); + e.Victim = EntityWrapper(m_World, m_ServerIDToClientID.at(inflictorID)); e.Damage = packet.ReadPrimitive(); // Don't rebroadcast our own player damage events or we'll have an infinite loop! if (e.Inflictor != m_LocalPlayer) { diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 082849c7..aa66433b 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -84,7 +84,6 @@ void Server::Update() if (isReadingData) { Network::Update(); } - } void Server::parseMessageType(Packet& packet) diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 1855a653..6bfb58eb 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -19,16 +19,20 @@ void DrawBloomPass::InitializeTextures() void DrawBloomPass::InitializeShaderPrograms() { m_GaussianProgram_horiz = ResourceManager::Load("##GaussianProgramHoriz"); - m_GaussianProgram_horiz->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_horiz.vert.glsl"))); - m_GaussianProgram_horiz->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl"))); - m_GaussianProgram_horiz->Compile(); - m_GaussianProgram_horiz->Link(); + if (m_GaussianProgram_horiz->GetHandle() == 0) { + m_GaussianProgram_horiz->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_horiz.vert.glsl"))); + m_GaussianProgram_horiz->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl"))); + m_GaussianProgram_horiz->Compile(); + m_GaussianProgram_horiz->Link(); + } - m_GaussianProgram_vert = ResourceManager::Load("##GaussianProgramVert"); - m_GaussianProgram_vert->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_vert.vert.glsl"))); - m_GaussianProgram_vert->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_vert.frag.glsl"))); - m_GaussianProgram_vert->Compile(); - m_GaussianProgram_vert->Link(); + m_GaussianProgram_vert = ResourceManager::Load("##GaussianProgramVert"); + if (m_GaussianProgram_vert->GetHandle() == 0) { + m_GaussianProgram_vert->AddShader(std::shared_ptr(new VertexShader("Shaders/Gaussian_vert.vert.glsl"))); + m_GaussianProgram_vert->AddShader(std::shared_ptr(new FragmentShader("Shaders/Gaussian_vert.frag.glsl"))); + m_GaussianProgram_vert->Compile(); + m_GaussianProgram_vert->Link(); + } } @@ -71,15 +75,12 @@ void DrawBloomPass::Draw(GLuint texture) //Horizontal pass, first use the given texture then save it to the horizontal framebuffer. m_GaussianFrameBuffer_horiz.Bind(); m_GaussianProgram_horiz->Bind(); - 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 @@ -92,7 +93,6 @@ void DrawBloomPass::Draw(GLuint texture) 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_horiz.Bind(); @@ -112,7 +112,6 @@ void DrawBloomPass::Draw(GLuint texture) m_GaussianProgram_vert->Bind(); 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 diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 1b99955a..c16caa24 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -27,6 +27,7 @@ void DrawFinalPass::InitializeFrameBuffers() glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); GLERROR("RenderBuffer generation"); + GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); //GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); @@ -173,26 +174,26 @@ void DrawFinalPass::InitializeShaderPrograms() GLERROR("Creating DepthFill program"); } -void DrawFinalPass::Draw(RenderScene& scene) +void DrawFinalPass::Draw(RenderScene& scene, GLuint SSAOTexture) { GLERROR("Pre"); - DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle()); if (scene.ClearDepth) { - glClear(GL_DEPTH_BUFFER_BIT); + //glClear(GL_DEPTH_BUFFER_BIT); + state->Disable(GL_DEPTH_TEST); + state->DepthMask(GL_FALSE); } //TODO: Do we need check for this or will it be per scene always? glClearStencil(0x00); glClear(GL_STENCIL_BUFFER_BIT); //Fill depth buffer - - + state->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene); + DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene, SSAOTexture); GLERROR("OpaqueObjects"); state->BlendFunc(GL_ONE, GL_ONE); - DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene); + DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene, SSAOTexture); GLERROR("TransparentObjects"); state->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); DrawSprites(scene.Jobs.SpriteJob, scene); @@ -208,11 +209,11 @@ void DrawFinalPass::Draw(RenderScene& scene) //Draw Opaque shielded objects state->StencilFunc(GL_NOTEQUAL, 1, 0xFF); state->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueShieldedObjects, scene); //might need changing + DrawModelRenderQueues(scene.Jobs.OpaqueShieldedObjects, scene, SSAOTexture); //might need changing GLERROR("Shielded Opaque object"); //Draw Transparen Shielded objects - DrawModelRenderQueues(scene.Jobs.TransparentShieldedObjects, scene); //might need changing + DrawModelRenderQueues(scene.Jobs.TransparentShieldedObjects, scene, SSAOTexture); //might need changing GLERROR("Shielded Transparent objects"); GLERROR("END"); @@ -243,14 +244,14 @@ void DrawFinalPass::Draw(RenderScene& scene) DrawShieldToStencilBuffer(scene.Jobs.ShieldObjects, scene); GLERROR("StencilPass"); - glClear(GL_DEPTH_BUFFER_BIT); + //glClear(GL_DEPTH_BUFFER_BIT); stateLowRes->Enable(GL_DEPTH_TEST); stateLowRes->StencilFunc(GL_LEQUAL, 1, 0xFF); stateLowRes->StencilMask(0x00); - DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene); + DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene, SSAOTexture); GLERROR("OpaqueObjects"); - DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene); + DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene, SSAOTexture); GLERROR("TransparentObjects"); glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); @@ -323,7 +324,7 @@ void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm: GLERROR("MipMap Texture initialization failed"); } -void DrawFinalPass::DrawModelRenderQueues(std::list>& jobs, RenderScene& scene) +void DrawFinalPass::DrawModelRenderQueues(std::list>& jobs, RenderScene& scene, GLuint SSAOTexture) { GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); GLERROR("forwardHandle"); @@ -346,6 +347,9 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, SSAOTexture); + for (auto &job : jobs) { auto explosionEffectJob = std::dynamic_pointer_cast(job); if (explosionEffectJob) { @@ -692,14 +696,14 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(spriteJob->FillColor)); glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), spriteJob->FillPercentage); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); if (spriteJob->DiffuseTexture != nullptr) { glBindTexture(GL_TEXTURE_2D, spriteJob->DiffuseTexture->m_Texture); } else { glBindTexture(GL_TEXTURE_2D, m_ErrorTexture->m_Texture); } - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE2); if (spriteJob->IncandescenceTexture != nullptr) { glBindTexture(GL_TEXTURE_2D, spriteJob->IncandescenceTexture->m_Texture); } else { @@ -809,7 +813,7 @@ void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptrDiffuseTexture.size() > 0 && job->DiffuseTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(job->DiffuseTexture[0]->UVRepeat)); @@ -819,7 +823,7 @@ void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptrNormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); @@ -829,7 +833,7 @@ void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptrSpecularTexture.size() > 0 && job->SpecularTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(job->SpecularTexture[0]->UVRepeat)); @@ -839,7 +843,7 @@ void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptrIncandescenceTexture.size() > 0 && job->IncandescenceTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(job->IncandescenceTexture[0]->UVRepeat)); @@ -852,7 +856,7 @@ void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, std::shared_ptrSplatMap->Texture->m_Texture); int texturePosition = GL_TEXTURE1; @@ -927,7 +931,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptrDiffuseTexture.size() > 0 && job->DiffuseTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(job->DiffuseTexture[0]->UVRepeat)); @@ -937,7 +941,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptrNormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); @@ -947,7 +951,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptrSpecularTexture.size() > 0 && job->SpecularTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(job->SpecularTexture[0]->UVRepeat)); @@ -957,7 +961,7 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptrIncandescenceTexture.size() > 0 && job->IncandescenceTexture[0]->Texture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[0]->Texture->m_Texture); glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(job->IncandescenceTexture[0]->UVRepeat)); @@ -970,10 +974,10 @@ void DrawFinalPass::BindModelTextures(GLuint shaderHandle, std::shared_ptrSplatMap->Texture->m_Texture); - int texturePosition = GL_TEXTURE1; + int texturePosition = GL_TEXTURE2; //Bind 5 diffuse textures std::string UniformName = "DiffuseUVRepeat"; diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 40509d0c..d1ed73dd 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -25,11 +25,20 @@ void PickingPass::InitializeTextures() void PickingPass::InitializeFrameBuffers() { - glGenRenderbuffers(1, &m_DepthBuffer); + /* glGenRenderbuffers(1, &m_DepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);*/ - m_PickingBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); + glGenTextures(1, &m_DepthBuffer); + + glBindTexture(GL_TEXTURE_2D, m_DepthBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, (int)(m_Renderer->GetViewportSize().Width), (int)(m_Renderer->GetViewportSize().Height), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0))); m_PickingBuffer.Generate(); } @@ -63,7 +72,9 @@ void PickingPass::Draw(RenderScene& scene) m_PickingProgram->Bind(); if (scene.ClearDepth) { - glClear(GL_DEPTH_BUFFER_BIT); + //glClear(GL_DEPTH_BUFFER_BIT); + state->Disable(GL_DEPTH_TEST); + state->DepthMask(GL_FALSE); } m_Camera = scene.Camera; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index b8665fce..0c668cad 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -108,7 +108,15 @@ void Renderer::Update(double dt) void Renderer::Draw(RenderFrame& frame) { - ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0SceneLowRes\0BloomLowRes\0Gaussian\0Picking"); + ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0SceneLowRes\0BloomLowRes\0Gaussian\0Picking\0Ambient Occlusion"); + + ImGui::SliderFloat("SSAO sample radius", &m_SSAO_Radius, 0.01f, 5.0f); + ImGui::SliderFloat("SSAO bias", &m_SSAO_Bias, 0.0f, 0.1f); + ImGui::SliderFloat("SSAO contrast", &m_SSAO_Contrast, 0.0f, 10.0f); + ImGui::SliderFloat("SSAO IntensityScale", &m_SSAO_IntensityScale, 0.0f, 10.0f); + ImGui::SliderInt("SSAO Number of Samples", &m_SSAO_NumOfSamples, 2, 100); + ImGui::SliderInt("SSAO Number of Turns", &m_SSAO_NumOfTurns, 0, 50); + m_SSAOPass->Setting(m_SSAO_Radius, m_SSAO_Bias, m_SSAO_Contrast, m_SSAO_IntensityScale, m_SSAO_NumOfSamples, m_SSAO_NumOfTurns); //clear buffer 0 glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -119,15 +127,21 @@ void Renderer::Draw(RenderFrame& frame) m_DrawFinalPass->ClearBuffer(); m_DrawBloomPass->ClearBuffer(); PerformanceTimer::StopTimer("Renderer-ClearBuffers"); - + for (auto scene : frame.RenderScenes) { + PerformanceTimer::StartTimer("Renderer-Depth"); + m_PickingPass->Draw(*scene); + GLERROR("Drawing pickingpass"); + PerformanceTimer::StopTimer("Renderer-Depth"); + } + PerformanceTimer::StartTimer("AO generation"); + m_SSAOPass->Draw(m_PickingPass->DepthBuffer(), frame.RenderScenes.front()->Camera); + GLuint ao = m_SSAOPass->SSAOTexture(); + PerformanceTimer::StopTimer("AO generation"); for (auto scene : frame.RenderScenes){ - PerformanceTimer::StartTimer("Renderer-Depth"); + PerformanceTimer::StartTimer("Renderer-Drawing PickingPass"); SortRenderJobsByDepth(*scene); GLERROR("SortByDepth"); - PerformanceTimer::StartTimerAndStopPrevious("Renderer-Drawing PickingPass"); - m_PickingPass->Draw(*scene); - GLERROR("Drawing pickingpass"); PerformanceTimer::StartTimerAndStopPrevious("Renderer-Generate Frustrums"); m_LightCullingPass->GenerateNewFrustum(*scene); GLERROR("Generate frustums"); @@ -137,8 +151,8 @@ void Renderer::Draw(RenderFrame& frame) PerformanceTimer::StartTimerAndStopPrevious("Renderer-Light Culling"); m_LightCullingPass->CullLights(*scene); GLERROR("LightCulling"); + m_DrawFinalPass->Draw(*scene, ao); PerformanceTimer::StartTimerAndStopPrevious("Renderer-Draw Geometry+Light"); - m_DrawFinalPass->Draw(*scene); GLERROR("Draw Geometry+Light"); //m_DrawScenePass->Draw(*scene); @@ -147,14 +161,17 @@ void Renderer::Draw(RenderFrame& frame) GLERROR("Draw Text"); PerformanceTimer::StopTimer("Renderer-Draw Text"); } + PerformanceTimer::StartTimer("Renderer-Draw Bloom"); m_DrawBloomPass->Draw(m_DrawFinalPass->BloomTexture()); PerformanceTimer::StopTimer("Renderer-Draw Bloom"); + if (m_DebugTextureToDraw == 0) { PerformanceTimer::StartTimer("Renderer-Color Correction Pass"); m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), m_DrawFinalPass->SceneTextureLowRes(), m_DrawFinalPass->BloomTextureLowRes(), frame.Gamma, frame.Exposure); PerformanceTimer::StopTimer("Renderer-Color Correction Pass"); } + PerformanceTimer::StartTimer("Renderer-Misc Debug Draws"); if (m_DebugTextureToDraw == 1) { m_DrawScreenQuadPass->Draw(m_DrawFinalPass->SceneTexture()); @@ -174,7 +191,10 @@ void Renderer::Draw(RenderFrame& frame) if (m_DebugTextureToDraw == 6) { m_DrawScreenQuadPass->Draw(m_PickingPass->PickingTexture()); } - PerformanceTimer::StopTimer("Renderer-Misc Debug Draws"); + if (m_DebugTextureToDraw == 7) { + m_DrawScreenQuadPass->Draw(m_SSAOPass->SSAOTexture()); + } + PerformanceTimer::StopTimer("Renderer-Misc Debug Draws"); PerformanceTimer::StartTimer("Renderer-ImGuiRenderPass"); m_ImGuiRenderPass->Draw(); @@ -223,4 +243,5 @@ void Renderer::InitializeRenderPasses() m_DrawScreenQuadPass = new DrawScreenQuadPass(this); m_DrawBloomPass = new DrawBloomPass(this); m_DrawColorCorrectionPass = new DrawColorCorrectionPass(this); + m_SSAOPass = new SSAOPass(this); } diff --git a/src/Engine/Rendering/SSAOPass.cpp b/src/Engine/Rendering/SSAOPass.cpp new file mode 100644 index 00000000..331e040f --- /dev/null +++ b/src/Engine/Rendering/SSAOPass.cpp @@ -0,0 +1,141 @@ +#include "Rendering/SSAOPass.h" + +SSAOPass::SSAOPass(IRenderer* renderer) +{ + m_Renderer = renderer; + + m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); + + InitializeBuffer(); + InitializeShaderProgram(); + Setting(0.1f, 0.012f, 1.0f, 1.0f, 13, 7); + + m_DrawBloomPass = new DrawBloomPass(renderer); +} + +void SSAOPass::InitializeShaderProgram() +{ + m_SSAOProgram = ResourceManager::Load("##SSAOProgram"); + m_SSAOProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); + m_SSAOProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAO.frag.glsl"))); + m_SSAOProgram->Compile(); + m_SSAOProgram->Link(); + + m_SSAOViewSpaceZProgram = ResourceManager::Load("##SSAOViewSpaceZProgram"); + m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/SSAO.vert.glsl"))); + m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/SSAOViewSpaceZ.frag.glsl"))); + m_SSAOViewSpaceZProgram->Compile(); + m_SSAOViewSpaceZProgram->Link(); +} + + +void SSAOPass::InitializeBuffer() +{ + GenerateTexture(&m_SSAOTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_R8, GL_RED, GL_FLOAT); + + m_SSAOFramBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SSAOTexture, GL_COLOR_ATTACHMENT0))); + m_SSAOFramBuffer.Generate(); + + GenerateTexture(&m_SSAOViewSpaceZTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_R32F, GL_RED, GL_FLOAT); + + m_SSAOViewSpaceZFramBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SSAOViewSpaceZTexture, GL_COLOR_ATTACHMENT0))); + m_SSAOViewSpaceZFramBuffer.Generate(); +} + +void SSAOPass::ClearBuffer() +{ + m_SSAOFramBuffer.Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_SSAOFramBuffer.Unbind(); + + m_SSAOViewSpaceZFramBuffer.Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_SSAOViewSpaceZFramBuffer.Unbind(); +} + +void SSAOPass::Setting(float radius, float bias, float contrast, float intensityScale, int numOfSamples, int NumOfTurns) { + m_Radius = radius; + m_Bias = bias; + m_Contrast = contrast; + m_IntensityScale = intensityScale; + m_NumOfSamples = numOfSamples; + m_NumOfTurns = NumOfTurns; +} + +void SSAOPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const +{ + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr); + GLERROR("Texture initialization failed"); +} + +void SSAOPass::Draw(GLuint depthBuffer, Camera* camera) +{ + SSAOPassState state; + GLuint viewSpaceZPShaderHandle = m_SSAOViewSpaceZProgram->GetHandle(); + GLuint SSAOShaderHandle = m_SSAOProgram->GetHandle(); + + m_SSAOViewSpaceZFramBuffer.Bind(); + m_SSAOViewSpaceZProgram->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, depthBuffer); + glm::vec3 clipInfo = glm::vec3( + (camera->NearClip() * camera->FarClip()), + (camera->NearClip() - camera->FarClip()), + (camera->FarClip()) + ); + /*glm::vec3 clipInfo = glm::vec3( + (camera->NearClip()), + (-1.0f), + (+1.0f) + );*/ + glUniform3fv(glGetUniformLocation(viewSpaceZPShaderHandle, "ClipInfo"), 1, glm::value_ptr(clipInfo)); + + 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); + + glm::vec4 projInfo = glm::vec4( + ((1.0 - camera->ProjectionMatrix()[0][2]) / camera->ProjectionMatrix()[0][0]), + (-2.0 / (m_Renderer->GetViewportSize().Width * camera->ProjectionMatrix()[0][0])), + ((1.0 + camera->ProjectionMatrix()[1][2]) / camera->ProjectionMatrix()[1][1]), + (-2.0 / (m_Renderer->GetViewportSize().Height * camera->ProjectionMatrix()[1][1])) + ); + + + m_SSAOFramBuffer.Bind(); + m_SSAOProgram->Bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_SSAOViewSpaceZTexture); + + // How many pixel there are in a 1m long object 1m away from the camera + glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uProjScale"), m_Renderer->GetViewportSize().Height / (-2.0f * glm::tan(camera->FOV() * 0.5f))); + + glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uRadius"), m_Radius); + glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uBias"), m_Bias); + glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uContrast"), m_Contrast); + glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uIntensityScale"), m_IntensityScale); + glUniform1i(glGetUniformLocation(SSAOShaderHandle, "uNumOfSamples"), m_NumOfSamples); + glUniform1i(glGetUniformLocation(SSAOShaderHandle, "uNumOfTurns"), m_NumOfTurns);; + + glUniform4fv(glGetUniformLocation(SSAOShaderHandle, "uProjInfo"), 1, glm::value_ptr(projInfo)); + 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_DrawBloomPass->ClearBuffer(); + m_DrawBloomPass->Draw(m_SSAOTexture); +} + +void ComputeAO(GLuint depthBuffer, Camera* camera) { + +} \ No newline at end of file diff --git a/src/Engine/Rendering/SSAOPassState.cpp b/src/Engine/Rendering/SSAOPassState.cpp new file mode 100644 index 00000000..7dd49841 --- /dev/null +++ b/src/Engine/Rendering/SSAOPassState.cpp @@ -0,0 +1,16 @@ +#include "Rendering/SSAOPassState.h" + + +SSAOPassState::SSAOPassState() +{ + //BindFramebuffer(0); + Disable(GL_BLEND); + Disable(GL_DEPTH_TEST); + Disable(GL_CULL_FACE); +} + +SSAOPassState::~SSAOPassState() +{ + +} + diff --git a/src/Engine/Rendering/ShaderProgram.cpp b/src/Engine/Rendering/ShaderProgram.cpp index 9c26c15c..ae536bc0 100644 --- a/src/Engine/Rendering/ShaderProgram.cpp +++ b/src/Engine/Rendering/ShaderProgram.cpp @@ -98,8 +98,7 @@ void ShaderProgram::AddShader(std::shared_ptr shader) void ShaderProgram::Compile() { - if (m_ShaderProgramHandle == 0) - { + if (m_ShaderProgramHandle == 0) { m_ShaderProgramHandle = glCreateProgram(); } diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 7f5089c4..94f23c67 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -24,7 +24,7 @@ void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cHea bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) { - if (!IsServer && m_NetworkEnabled) { + if (!IsServer && m_NetworkEnabled || !e.Victim.Valid()) { return false; } diff --git a/src/Tests/WorldTest.cpp b/src/Tests/WorldTest.cpp index 03008562..633e617a 100644 --- a/src/Tests/WorldTest.cpp +++ b/src/Tests/WorldTest.cpp @@ -69,3 +69,47 @@ BOOST_AUTO_TEST_CASE(WorldTestMultipleAllocations, * utf::tolerance(0.00001)) i++; } } + +BOOST_AUTO_TEST_CASE(WorldCopy, *utf::tolerance(0.00001)) +{ + World w1; + + // Create a test component + auto testComponent = ComponentWrapperFactory("Test", 2); + testComponent.AddProperty("TestInteger", 1337); + testComponent.AddProperty("TestDouble", 13.37); + testComponent.AddProperty("TestString", std::string("DefaultString")); + testComponent.AddProperty("TestVec3", glm::vec3(1.f, 2.f, 3.f)); + w1.RegisterComponent(testComponent); + + // Create a test entity + EntityID w1_e1 = w1.CreateEntity(); + auto w1_c1 = w1.AttachComponent(w1_e1, "Test"); + + // Create a child + EntityID w1_e2 = w1.CreateEntity(w1_e1); + auto w1_c2 = w1.AttachComponent(w1_e2, "Test"); + w1_c2["TestString"] = "NonDefaultString"; + + // Copy the world! + World w2 = w1; + + // Fetch the components + auto w2_c1 = w2.GetComponent(w1_e1, "Test"); + auto w2_c2 = w2.GetComponent(w1_e2, "Test"); + + // Check that built-in types are copied but don't reside in the same memory + BOOST_CHECK((int)w1_c1["TestInteger"] == (int)w2_c1["TestInteger"]); + BOOST_CHECK(&(int&)w1_c1["TestInteger"] != &(int&)w2_c1["TestInteger"]); + BOOST_CHECK((double)w1_c1["TestDouble"] == (double)w2_c1["TestDouble"]); + BOOST_CHECK(&(int&)w1_c1["TestDouble"] != &(int&)w2_c1["TestDouble"]); + BOOST_CHECK((int)w1_c2["TestInteger"] == (int)w2_c2["TestInteger"]); + BOOST_CHECK(&(int&)w1_c2["TestInteger"] != &(int&)w2_c2["TestInteger"]); + BOOST_CHECK((double)w1_c2["TestDouble"] == (double)w2_c2["TestDouble"]); + BOOST_CHECK(&(int&)w1_c2["TestDouble"] != &(int&)w2_c2["TestDouble"]); + // Check that specially handled strings are fine + BOOST_CHECK((std::string)w1_c1["TestString"] == (std::string)w2_c1["TestString"]); + BOOST_CHECK(&(std::string&)w1_c1["TestString"] != &(std::string&)w2_c1["TestString"]); + BOOST_CHECK((std::string)w1_c2["TestString"] == (std::string)w2_c2["TestString"]); + BOOST_CHECK(&(std::string&)w1_c2["TestString"] != &(std::string&)w2_c2["TestString"]); +}