diff --git a/include/Engine/Rendering/DrawScenePass.h b/include/Engine/Rendering/DrawScenePass.h new file mode 100644 index 00000000..782c5a49 --- /dev/null +++ b/include/Engine/Rendering/DrawScenePass.h @@ -0,0 +1,36 @@ +#ifndef DrawScenePass_h__ +#define DrawScenePass_h__ + +#include "IRenderer.h" +#include "DrawScenePassState.h" +#include "FrameBuffer.h" +#include "ShaderProgram.h" +#include "Util/UnorderedMapVec2.h" +#include "Texture.h" + +class DrawScenePass +{ +public: + DrawScenePass(IRenderer* renderer); + ~DrawScenePass() { } + void InitializeTextures(); + void InitializeFrameBuffers(); + void InitializeShaderPrograms(); + + void Draw(RenderQueueCollection& rq); + + //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; + + ShaderProgram* m_BasicForwardProgram; + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawScenePassState.h b/include/Engine/Rendering/DrawScenePassState.h new file mode 100644 index 00000000..7ce74006 --- /dev/null +++ b/include/Engine/Rendering/DrawScenePassState.h @@ -0,0 +1,15 @@ +#ifndef DrawScenePassState_h__ +#define DrawScenePassState_h__ + +#include "Rendering/RenderState.h" + +class DrawScenePassState : public RenderState +{ +public: + DrawScenePassState(); + ~DrawScenePassState(); +private: + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h new file mode 100644 index 00000000..e1bc42db --- /dev/null +++ b/include/Engine/Rendering/PickingPass.h @@ -0,0 +1,49 @@ +#ifndef PickingPass_h__ +#define PickingPass_h__ + +#include "IRenderer.h" +#include "PickingPassState.h" +#include "FrameBuffer.h" +#include "ShaderProgram.h" +#include "Util/UnorderedMapVec2.h" +#include "../Core/EventBroker.h" +#include "EPicking.h" + +class PickingPass +{ +public: + PickingPass(IRenderer* renderer, EventBroker* eb); + ~PickingPass(); + void InitializeTextures(); + void InitializeFrameBuffers(); + void InitializeShaderPrograms(); + + void Draw(RenderQueueCollection& rq); + + + //Getters + const ShaderProgram& PickingProgram() const { return *m_PickingProgram; } + const std::unordered_map& PickingColorsToEntity() const { return m_PickingColorsToEntity; } + GLuint PickingTexture() const { return m_PickingTexture; } + GLuint DepthBuffer() const { return m_DepthBuffer; } + const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; } + + +private: + void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; + + EventBroker* m_EventBroker; + + const IRenderer* m_Renderer; + + ShaderProgram* m_PickingProgram; + + std::unordered_map m_PickingColorsToEntity; + + GLuint m_PickingTexture; + GLuint m_DepthBuffer; + + FrameBuffer m_PickingBuffer; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/PickingPassState.h b/include/Engine/Rendering/PickingPassState.h new file mode 100644 index 00000000..4f6bfe40 --- /dev/null +++ b/include/Engine/Rendering/PickingPassState.h @@ -0,0 +1,15 @@ +#ifndef PickingPassState_h__ +#define PickingPassState_h__ + +#include "Rendering/RenderState.h" + +class PickingPassState : public RenderState +{ +public: + PickingPassState(GLuint frameBuffer); + ~PickingPassState(); + +private: +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/RenderState.h b/include/Engine/Rendering/RenderState.h new file mode 100644 index 00000000..e7ba2f80 --- /dev/null +++ b/include/Engine/Rendering/RenderState.h @@ -0,0 +1,23 @@ +#ifndef RenderState_h__ +#define RenderState_h__ + +#include "../Common.h" +#include "../OpenGL.h" +#include "../GLM.h" + +class RenderState +{ +public: + RenderState(); + ~RenderState(); + bool Enable(GLenum GLEnable); + bool CullFace(GLenum GlFaceToCull); + bool ClearColor(glm::vec4 color); + bool Clear(GLbitfield mask); + bool BindBuffer(GLint buffer); +private: + std::vector m_Enables; + float m_preClearColor[4]; + int m_preBuffer; +}; +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 76de0818..886c98ca 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -10,6 +10,21 @@ #include "Util/UnorderedMapVec2.h" #include "FrameBuffer.h" #include "../Core/World.h" +#include "PickingPass.h" +#include "DrawScenePass.h" + + +#define TILE_SIZE 16 +#define NUM_LIGHTS 3 + + +enum lightType +{ + Point, + Spot, + Directional, + Area +}; #include "../Core/EventBroker.h" #include "EPicking.h" @@ -21,44 +36,87 @@ public: : m_EventBroker(eventBroker) { } - virtual void Initialize() override; - virtual void Update(double dt) override; - virtual void Draw(RenderQueueCollection& rq) override; + virtual void Initialize() override; + virtual void Update(double dt) override; + virtual void Draw(RenderQueueCollection& rq) override; private: - //----------------------Variables----------------------// + //----------------------Variables----------------------// EventBroker* m_EventBroker; - Texture* m_ErrorTexture; - Texture* m_WhiteTexture; - float m_CameraMoveSpeed; - FrameBuffer m_PickingBuffer; - GLuint m_PickingTexture; - GLuint m_DepthBuffer; + Texture* m_ErrorTexture; + Texture* m_WhiteTexture; + float m_CameraMoveSpeed; Model* m_ScreenQuad; Model* m_UnitQuad; Model* m_UnitSphere; - std::unordered_map m_PickingColorsToEntity; + DrawScenePass* m_DrawScenePass; + PickingPass* m_PickingPass; - //----------------------Functions----------------------// - void InitializeWindow(); - void InitializeShaders(); + //----------------------Functions----------------------// + void InitializeWindow(); + void InitializeShaders(); void InitializeTextures(); - void InitializeFrameBuffers(); + void InitializeSSBOs(); + void InitializeRenderPasses(); //TODO: Renderer: Get InputUpdate out of renderer - void InputUpdate(double dt); - void PickingPass(RenderQueueCollection& rq); + void InputUpdate(double dt); + //void PickingPass(RenderQueueCollection& rq); void DrawScreenQuad(GLuint textureToDraw); - void DrawScene(RenderQueueCollection& rq); + //----------------------Forward+-----------------------// + void CalculateFrustum(); + void CullLights(); + //Frustum + struct Plane { + glm::vec3 Normal; + float d; + }; + struct Frustum { + Plane Planes[4]; + }; + Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution + + //Lights + void TEMPCreateLights(); + //TODO: Renderer: Add Directionllights, spotlights and area lights to this as type. + 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; + }; + PointLight m_PointLights[NUM_LIGHTS]; + + struct LightGrid { + int Amount; + int Start; + glm::vec2 Padding; + }; + LightGrid m_LightGrid[80*45]; + + int m_LightOffset = 0; + + int m_LightIndex[80*45*200]; + + //-------------------------SSBO------------------------// + GLuint m_FrustumSSBO = 0; + GLuint m_LightSSBO = 1; + GLuint m_LightGridSSBO = 2; + GLuint m_LightOffsetSSBO = 3; + GLuint m_LightIndexSSBO = 4; void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); //--------------------ShaderPrograms-------------------// - ShaderProgram m_BasicForwardProgram; - ShaderProgram m_PickingProgram; - ShaderProgram m_DrawScreenQuadProgram; + ShaderProgram* m_BasicForwardProgram; + ShaderProgram* m_DrawScreenQuadProgram; + ShaderProgram* m_CalculateFrustumProgram; + ShaderProgram* m_LightCullProgram; + }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/ShaderProgram.h b/include/Engine/Rendering/ShaderProgram.h index 1b87650e..ad01c029 100644 --- a/include/Engine/Rendering/ShaderProgram.h +++ b/include/Engine/Rendering/ShaderProgram.h @@ -1,6 +1,9 @@ +#ifndef ShaderProgram_h__ +#define ShaderProgram_h__ #include "../Common.h" #include "../OpenGL.h" +#include "../Core/ResourceManager.h" #include class Shader @@ -60,11 +63,13 @@ public: : ShaderType(fileName) { } }; -class ShaderProgram +class ShaderProgram : public Resource { -public: - ShaderProgram() + friend class ResourceManager; +private: + ShaderProgram(std::string) : m_ShaderProgramHandle(0) { } +public: ~ShaderProgram(); void AddShader(std::shared_ptr shader); @@ -79,3 +84,5 @@ private: GLuint m_ShaderProgramHandle; std::vector> m_Shaders; }; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/Util/GLError.h b/include/Engine/Rendering/Util/GLError.h index 8202f433..754623d1 100644 --- a/include/Engine/Rendering/Util/GLError.h +++ b/include/Engine/Rendering/Util/GLError.h @@ -9,7 +9,7 @@ inline bool _GLERROR(const char* info, const char* file, const char* func, unsig GLenum error = glGetError(); if (error != GL_NO_ERROR) { - _LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s %i %s", info, error, gluErrorString(error)); + _LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s, %i, %s", info, error, gluErrorString(error)); return true; } diff --git a/resources/Shaders/GridFrustum.comp.glsl b/resources/Shaders/GridFrustum.comp.glsl new file mode 100644 index 00000000..27559370 --- /dev/null +++ b/resources/Shaders/GridFrustum.comp.glsl @@ -0,0 +1,73 @@ +#version 430 + +#define TILE_SIZE 16 +#define NUM_TILES 3600 + +uniform mat4 P; +uniform vec2 ScreenDimensions; + +struct Plane { + vec3 Normal; + float d; +}; +struct Frustum { + Plane Planes[4]; +}; + +layout (std430, binding = 0) buffer FrustumBuffer +{ + Frustum Data[3600]; +} Frustums; + +vec4 ConvertToView(vec4 ScreenCoords) +{ + vec2 normalizedScreenCoords = ScreenCoords.xy / ScreenDimensions; + vec4 clipSpace = vec4( vec2(normalizedScreenCoords.x, normalizedScreenCoords.y) * 2.0 - 1.0, ScreenCoords.z, ScreenCoords.w); + vec4 view = inverse(P) * clipSpace; + view = view / view.w; + return view; +} + +Plane ComputePlane( vec3 p0, vec3 p1, vec3 p2 ) +{ + Plane plane; + + vec3 v0 = p1 - p0; + vec3 v2 = p2 - p0; + + plane.Normal = normalize( cross( v0, v2 ) ); + plane.d = dot( vec3(plane.Normal), p0 ); // Always 0 probably + return plane; +} + +layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main () +{ + if(gl_GlobalInvocationID.x * TILE_SIZE < ScreenDimensions.x && gl_GlobalInvocationID.y * TILE_SIZE < ScreenDimensions.y) { + //Top-Left = 0 | Top-Right = 1 + //Bottom-Left = 2 | Bottom-Right = 3 + vec4 ScreenCoords[4]; + ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); // Z-axis might need to be 1 + ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0); + ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); + ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); + + vec3 ViewVectors[4]; + for(int i = 0; i < 4; i++) { + ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i])); + } + + vec3 EyePos = vec3(0,0,0); + + Frustum f; + f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); + f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]); + f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]); + f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]); + + + + + Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f; + } +} \ No newline at end of file diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl new file mode 100644 index 00000000..e9fa9a95 --- /dev/null +++ b/resources/Shaders/cullLights.comp.glsl @@ -0,0 +1,35 @@ +#version 430 + +//in uvec3 gl_NumWorkGroups; +//in uvec3 gl_WorkGroupID; +//in uvec3 gl_LocalInvocationID; +//in uvec3 gl_GlobalInvocationID; +//in uint gl_LocalInvocationIndex; + + + +#define NUM_LIGHTS 3 +#define MAX_LIGHTS_PER_TILE 200 +#define NUM_TILES 3600 + +struct Plane { + vec3 Normal; + float d; +}; +struct Frustum { + Plane Planes[4]; +}; + +layout (std430, binding = 0) buffer FrustumBuffer +{ + Frustum Data[3600]; +} Frustums; + + + +layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +void main () +{ + if(1 == 1) { + } +} \ No newline at end of file diff --git a/src/Engine/Rendering/DrawScenePass.cpp b/src/Engine/Rendering/DrawScenePass.cpp new file mode 100644 index 00000000..559a0f58 --- /dev/null +++ b/src/Engine/Rendering/DrawScenePass.cpp @@ -0,0 +1,66 @@ +#include "Rendering/DrawScenePass.h" + +DrawScenePass::DrawScenePass(IRenderer* renderer) +{ + m_Renderer = renderer; + InitializeTextures(); + InitializeShaderPrograms(); +} + +void DrawScenePass::InitializeTextures() +{ + m_WhiteTexture = ResourceManager::Load("Textures/Core/Blank.png"); +} + +void DrawScenePass::InitializeShaderPrograms() +{ + //Gör så att shaders är en resource, tex som texture classen. Konstruktorn måste vara privat. + m_BasicForwardProgram = ResourceManager::Load("#BasicForwardProgram"); + + m_BasicForwardProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/BasicForward.vert.glsl"))); + m_BasicForwardProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/BasicForward.frag.glsl"))); + m_BasicForwardProgram->Compile(); + m_BasicForwardProgram->Link(); + + +} + +void DrawScenePass::Draw(RenderQueueCollection& rq) +{ + //glBindFramebuffer(GL_FRAMEBUFFER, 0); + GLERROR("Renderer::Draw PickingPass"); + + DrawScenePassState state; + + + //TODO: Render: Add code for more jobs than modeljobs. + for (auto &job : rq.Forward) { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + GLuint ShaderHandle = m_BasicForwardProgram->GetHandle(); + + m_BasicForwardProgram->Bind(); + //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix())); + glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); + + //TODO: Renderer: bättre textur felhantering samt fler texturer stöd + if (modelJob->DiffuseTexture != nullptr) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); + } else { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + } + + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); + + continue; + } + } + GLERROR("DrawScene Error"); +} diff --git a/src/Engine/Rendering/DrawScenePassState.cpp b/src/Engine/Rendering/DrawScenePassState.cpp new file mode 100644 index 00000000..59654775 --- /dev/null +++ b/src/Engine/Rendering/DrawScenePassState.cpp @@ -0,0 +1,18 @@ +#include "Rendering/DrawScenePassState.h" + + +DrawScenePassState::DrawScenePassState() +{ + GLERROR("---"); + BindBuffer(0); + GLERROR("---"); + Enable(GL_DEPTH_TEST); + Enable(GL_CULL_FACE); + ClearColor(glm::vec4(255.f / 255, 163.f / 255, 176.f / 255, 0.f)); + Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +DrawScenePassState::~DrawScenePassState() +{ + +} diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index 1b53d868..b2b29626 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -48,13 +48,21 @@ void FrameBuffer::Generate() switch ((*it)->m_ResourceType) { case GL_TEXTURE_2D: glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0); + GLERROR("FrameBuffer generate: glFramebufferTexture2D"); + break; case GL_RENDERBUFFER: glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle); + GLERROR("FrameBuffer generate: glFramebufferRenderbuffer"); + if ( (*it)->m_Attachment != GL_COLOR_ATTACHMENT0 || + (*it)->m_Attachment != GL_DEPTH_ATTACHMENT || + (*it)->m_Attachment != GL_STENCIL_ATTACHMENT) + { + LOG_ERROR("RenderBuffer Attachment not valid."); + } break; } - GLERROR("FrameBuffer generate"); if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT) { attachments.push_back((*it)->m_Attachment); diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp new file mode 100644 index 00000000..7d4cb66f --- /dev/null +++ b/src/Engine/Rendering/PickingPass.cpp @@ -0,0 +1,118 @@ +#include "Rendering/PickingPass.h" + +PickingPass::PickingPass(IRenderer* renderer, EventBroker* eb) +{ + m_Renderer = renderer; + m_EventBroker = eb; + + InitializeTextures(); + InitializeFrameBuffers(); + InitializeShaderPrograms(); +} + +PickingPass::~PickingPass() +{ + +} + +void PickingPass::InitializeTextures() +{ + GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, + glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); +} + +void PickingPass::InitializeFrameBuffers() +{ + glGenRenderbuffers(1, &m_DepthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + + m_PickingBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); + m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0))); + m_PickingBuffer.Generate(); +} + +void PickingPass::InitializeShaderPrograms() +{ + m_PickingProgram = ResourceManager::Load("#PickingProgram"); + + m_PickingProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/Picking.vert.glsl"))); + m_PickingProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Picking.frag.glsl"))); + m_PickingProgram->Compile(); + m_PickingProgram->BindFragDataLocation(0, "TextureFragment"); + m_PickingProgram->Link(); +} + +void PickingPass::Draw(RenderQueueCollection& rq) +{ + m_PickingColorsToEntity.clear(); + PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle()); + + int r = 1; + int g = 0; + //TODO: Render: Add code for more jobs than modeljobs. + + GLuint ShaderHandle = m_PickingProgram->GetHandle(); + m_PickingProgram->Bind(); + + for (auto &job : rq.Forward) { + auto modelJob = std::dynamic_pointer_cast(job); + + if (modelJob) { + //--------------- + //TODO: Renderer: IMPORTANT: Fixa detta så det inte loopar igenom listan varje frame. + //--------------- + int pickColor[2] = { r, g }; + for (auto i : m_PickingColorsToEntity) { + if (modelJob->Entity == i.second) { + pickColor[0] = i.first.x; + pickColor[1] = i.first.y; + r -= 1; + } + } + m_PickingColorsToEntity[glm::vec2(pickColor[0], pickColor[1])] = modelJob->Entity; + + //Render picking stuff + //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix())); + 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); + glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, nullptr, modelJob->StartIndex); + r += 1; + if (r > 255) { + r = 0; + g += 1; + } + } + } + m_PickingBuffer.Unbind(); + GLERROR("PickingPass Error"); + + //Publish pick event every frame with the pick data that can be picked by the event + Events::Picking pickEvent = Events::Picking( + &m_PickingBuffer, + &m_DepthBuffer, + m_Renderer->Camera()->ProjectionMatrix(), + m_Renderer->Camera()->ViewMatrix(), + m_Renderer->Resolution(), + &m_PickingColorsToEntity); + + m_EventBroker->Publish(pickEvent); +} + +void PickingPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const +{ + //TODO: Renderer: Make this in a sparate class + 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);//TODO: Renderer: Fix the precision and Resolution + GLERROR("Texture initialization failed"); +} diff --git a/src/Engine/Rendering/PickingPassState.cpp b/src/Engine/Rendering/PickingPassState.cpp new file mode 100644 index 00000000..a52fa546 --- /dev/null +++ b/src/Engine/Rendering/PickingPassState.cpp @@ -0,0 +1,20 @@ +#include "Rendering/PickingPassState.h" + + +PickingPassState::PickingPassState(GLuint frameBuffer) +{ + GLERROR("---2"); + BindBuffer(frameBuffer); + GLERROR("---3"); + Enable(GL_DEPTH_TEST); + Enable(GL_CULL_FACE); + + glm::vec4 clearColor = glm::vec4(0.f); + ClearColor(clearColor); + Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +PickingPassState::~PickingPassState() +{ + +} diff --git a/src/Engine/Rendering/RenderState.cpp b/src/Engine/Rendering/RenderState.cpp new file mode 100644 index 00000000..87f4a30d --- /dev/null +++ b/src/Engine/Rendering/RenderState.cpp @@ -0,0 +1,111 @@ +#include "Rendering/RenderState.h" + +RenderState::RenderState() +{ + +} + +bool RenderState::Enable(GLenum GLEnable) +{ + if(glIsEnabled(GLEnable)) + { + LOG_WARNING("Trying to enable somthing that is already enabled."); + return false; + } + m_Enables.push_back(GLEnable); + glEnable(GLEnable); + if (GLERROR("RenderState::Enable")) + { + return false; + } + return true; +} + +bool RenderState::CullFace(GLenum GLCullFace) +{ + if(!glIsEnabled(GL_CULL_FACE)) + { + LOG_ERROR("Setting GL_CULL_FACE without enabling it."); + return false; + } + + GLint a; + glGetIntegerv(GL_CULL_FACE_MODE, &a); + if(a != GL_BACK) + { + //LOG_INFO("Setting Cullface to back, unessesary since this is already default."); + glCullFace(GLCullFace); + } + if (GLERROR("RenderState::CullFace")) + { + return false; + } + return true; +} + +bool RenderState::ClearColor(glm::vec4 color) +{ + glGetFloatv(GL_COLOR_CLEAR_VALUE, &m_preClearColor[0]); + glClearColor(color.r, color.g, color.b, color.a); + if (GLERROR("RenderState::ClearColor")) { + return false; + } + return true; +} + +bool RenderState::Clear(GLbitfield mask) +{ + glClear(mask); + if (GLERROR("RenderState::Clear")) { + return false; + } + return true; +} + +bool RenderState::BindBuffer(GLint buffer) +{ + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_preBuffer); + if (buffer == m_preBuffer) + { + return true; + } + glBindFramebuffer(GL_FRAMEBUFFER, buffer); + if (GLERROR("RenderState::BindBuffer")) + { + printf("BufferID: %i\npreBufferID: %i\n", buffer, m_preBuffer); + return false; + } + return true; +} + +RenderState::~RenderState() +{ + GLERROR("RenderState::~RenderState Pre"); + GLint n_buffer = -1; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &n_buffer); + + //Set cullface to default + if (glIsEnabled(GL_CULL_FACE)) { + glCullFace(GL_BACK); + } + GLERROR("RenderState::~RenderState glCullFace"); + + //Set color to default + glClearColor(m_preClearColor[0], m_preClearColor[1], m_preClearColor[2], m_preClearColor[3]); + GLERROR("RenderState::~RenderState glClearColor"); + + //Disable Enables + for (auto i : m_Enables) + { + glDisable(i); + } + GLERROR("RenderState::~RenderState glDisable"); + + if(m_preBuffer != 0) + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + m_Enables.clear(); + GLERROR("RenderState::~RenderState glBindFramebuffer"); +} + diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 6f4235d2..f4897223 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -9,12 +9,14 @@ void Renderer::Initialize() if (m_Camera == nullptr) { m_Camera = m_DefaultCamera; } + TEMPCreateLights(); + InitializeRenderPasses(); glfwSwapInterval(m_VSYNC); InitializeShaders(); InitializeTextures(); - InitializeFrameBuffers(); - + InitializeSSBOs(); + //CalculateFrustum(); m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); @@ -63,22 +65,23 @@ void Renderer::InitializeWindow() void Renderer::InitializeShaders() { - m_BasicForwardProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/BasicForward.vert.glsl"))); - m_BasicForwardProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/BasicForward.frag.glsl"))); - m_BasicForwardProgram.Compile(); - m_BasicForwardProgram.Link(); + m_BasicForwardProgram = ResourceManager::Load("#m_BasicForwardProgram"); - m_PickingProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/Picking.vert.glsl"))); - m_PickingProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/Picking.frag.glsl"))); - m_PickingProgram.Compile(); - m_PickingProgram.BindFragDataLocation(0, "TextureFragment"); - m_PickingProgram.Link(); + m_DrawScreenQuadProgram = ResourceManager::Load("#DrawScreenQuadProgram"); + m_DrawScreenQuadProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/DrawScreenQuad.vert.glsl"))); + m_DrawScreenQuadProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl"))); + m_DrawScreenQuadProgram->Compile(); + m_DrawScreenQuadProgram->Link(); - m_DrawScreenQuadProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/DrawScreenQuad.vert.glsl"))); - m_DrawScreenQuadProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl"))); - m_DrawScreenQuadProgram.Compile(); - m_DrawScreenQuadProgram.Link(); + //m_CalculateFrustumProgram = ResourceManager::Load("#CalculateFrustumProgram"); + //m_CalculateFrustumProgram.AddShader(std::shared_ptr(new ComputeShader("Shaders/GridFrustum.comp.glsl"))); + //m_CalculateFrustumProgram.Compile(); + //m_CalculateFrustumProgram.Link(); + //m_LightCullProgram = ResourceManager::Load("#LightCullProgram"); + //m_LightCullProgram.AddShader(std::shared_ptr(new ComputeShader("Shaders/cullLights.comp.glsl"))); + //m_LightCullProgram.Compile(); + //m_LightCullProgram.Link(); } void Renderer::InputUpdate(double dt) @@ -112,7 +115,6 @@ void Renderer::InputUpdate(double dt) m_CameraMoveSpeed = 0.5f; } - static double mousePosX, mousePosY; glfwGetCursorPos(m_Window, &mousePosX, &mousePosY); @@ -142,134 +144,19 @@ void Renderer::Update(double dt) { m_EventBroker->Process(); InputUpdate(dt); - } void Renderer::Draw(RenderQueueCollection& rq) { - //TODO: Renderer: Kanske borde vara längst upp i update. - PickingPass(rq); - DrawScreenQuad(m_PickingTexture); + m_PickingPass->Draw(rq); + //DrawScreenQuad(m_PickingPass->PickingTexture()); + //CullLights(); - DrawScene(rq); + m_DrawScenePass->Draw(rq); + GLERROR("Renderer::Draw m_DrawScenePass->Draw"); glfwSwapBuffers(m_Window); } -void Renderer::DrawScene(RenderQueueCollection& rq) -{ - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - //TODO: Render: Clean up draw code - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - //TODO: Render: Add code for more jobs than modeljobs. - for (auto &job : rq.Forward) { - auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - GLuint ShaderHandle = m_BasicForwardProgram.GetHandle(); - - m_BasicForwardProgram.Bind(); - //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); - glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); - - //TODO: Renderer: bättre textur felhantering samt fler texturer stöd - if (modelJob->DiffuseTexture != nullptr) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); - } else { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); - } - - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); - - continue; - } - } - GLERROR("DrawScene Error"); -} - -void Renderer::PickingPass(RenderQueueCollection& rq) -{ - m_PickingColorsToEntity.clear(); - m_PickingBuffer.Bind(); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - glClearColor(0.f, 0.f, 0.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - int r = 1; - int g = 0; - //TODO: Render: Add code for more jobs than modeljobs. - - - GLuint ShaderHandle = m_PickingProgram.GetHandle(); - m_PickingProgram.Bind(); - - for (auto &job : rq.Forward) { - auto modelJob = std::dynamic_pointer_cast(job); - - if (modelJob) { - //--------------- - //TODO: Renderer: IMPORTANT: Fixa detta så det inte loopar igenom listan varje frame. - //--------------- - int pickColor[2] = { r, g }; - for (auto i : m_PickingColorsToEntity) { - if(modelJob->Entity == i.second) { - pickColor[0] = i.first.x; - pickColor[1] = i.first.y; - r -= 1; - } - } - m_PickingColorsToEntity[glm::vec2(pickColor[0], pickColor[1])] = modelJob->Entity; - - - //Render picking stuff - //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); - 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); - glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); - r += 1; - if(r > 255) { - r = 0; - g += 1; - } - } - } - m_PickingBuffer.Unbind(); - GLERROR("PickingPass Error"); - - //Publish pick event every frame with the pick data that can be picked by the event - Events::Picking pickEvent = Events::Picking( - &m_PickingBuffer, - &m_DepthBuffer, - m_Camera->ProjectionMatrix(), - m_Camera->ViewMatrix(), - m_Resolution, - &m_PickingColorsToEntity); - - m_EventBroker->Publish(pickEvent); - -} - - void Renderer::DrawScreenQuad(GLuint textureToDraw) { glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -281,7 +168,7 @@ void Renderer::DrawScreenQuad(GLuint textureToDraw) glClear(GL_COLOR_BUFFER_BIT); - m_DrawScreenQuadProgram.Bind(); + m_DrawScreenQuadProgram->Bind(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureToDraw); @@ -291,24 +178,10 @@ void Renderer::DrawScreenQuad(GLuint textureToDraw) , GL_UNSIGNED_INT, 0, m_ScreenQuad->TextureGroups[0].StartIndex); } - void Renderer::InitializeTextures() { m_ErrorTexture=ResourceManager::Load("Textures/Core/ErrorTexture.png"); m_WhiteTexture=ResourceManager::Load("Textures/Core/Blank.png"); - /* - glGenTextures(1, &m_PickingTexture); - glBindTexture(GL_TEXTURE_2D, m_PickingTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, m_Resolution.Width, m_Resolution.Height, 0, GL_RG, GL_FLOAT, NULL);//TODO: Renderer: Fix the precision and Resolution - GLERROR("m_PickingTexture initialization failed"); - */ - - GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, - glm::vec2(m_Resolution.Width, m_Resolution.Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); } void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) @@ -323,15 +196,95 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin GLERROR("Texture initialization failed"); } - - -void Renderer::InitializeFrameBuffers()//TODO: Renderer: Get this to a better location, as its really big +void Renderer::InitializeSSBOs() { - glGenRenderbuffers(1, &m_DepthBuffer); - glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Resolution.Width, m_Resolution.Height); + printf("Size: %i\n", sizeof(m_Frustums)); + glGenBuffers(1, &m_FrustumSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + GLERROR("m_FrustumSSBO"); + + glGenBuffers(1, &m_LightSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + GLERROR("m_LightSSBO"); + + + glGenBuffers(1, &m_LightGridSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + GLERROR("m_LightGridSSBO"); + + + glGenBuffers(1, &m_LightOffsetSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + GLERROR("m_LightOffsetSSBO"); + + + glGenBuffers(1, &m_LightIndexSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + GLERROR("m_LightIndexSSBO"); + +} + +void Renderer::InitializeRenderPasses() +{ + m_DrawScenePass = new DrawScenePass(this); + m_PickingPass = new PickingPass(this, m_EventBroker); +} + +void Renderer::CalculateFrustum() +{ + GLERROR("CalculateFrustum Error-1"); + m_CalculateFrustumProgram->Bind(); - m_PickingBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); - m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0))); - m_PickingBuffer.Generate(); -} \ No newline at end of file + GLERROR("CalculateFrustum Error1"); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); + GLERROR("CalculateFrustum Error2"); + glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix())); + GLERROR("CalculateFrustum Error3"); + glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height); + GLERROR("CalculateFrustum Error4"); + glDispatchCompute(5, 3, 1); + GLERROR("CalculateFrustum Error5"); + +} + +void Renderer::TEMPCreateLights() +{ + for (int i = 0; i < NUM_LIGHTS; i++) { + m_PointLights[i].Position = glm::vec4(i, 0.f, 0.f, 0.f); + m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f); + } +} + +void Renderer::CullLights() +{ + m_LightCullProgram->Bind(); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); + glDispatchCompute(m_Resolution.Width / TILE_SIZE, m_Resolution.Height / TILE_SIZE, 1); + GLERROR("CullLights Error"); + +} + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 97697766..3ab5d204 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -6,6 +6,7 @@ Game::Game(int argc, char* argv[]) ResourceManager::RegisterType("Model"); ResourceManager::RegisterType("Texture"); ResourceManager::RegisterType("EntityXMLFile"); + ResourceManager::RegisterType("ShaderProgram"); m_Config = ResourceManager::Load("Config.ini"); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); @@ -77,8 +78,9 @@ void Game::Tick() m_Renderer->Update(dt); m_RenderQueueFactory->Update(m_World); + GLERROR("Game::Tick m_RenderQueueFactory->Update"); m_Renderer->Draw(m_RenderQueueFactory->RenderQueues()); - + GLERROR("Game::Tick m_Renderer->Draw"); m_EventBroker->Swap(); m_EventBroker->Clear();