diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 886c98ca..59bf3d45 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -69,6 +69,7 @@ private: //----------------------Forward+-----------------------// void CalculateFrustum(); void CullLights(); + void DrawForwardPlus(RenderQueueCollection& rq); //Frustum struct Plane { glm::vec3 Normal; @@ -116,6 +117,7 @@ private: ShaderProgram* m_DrawScreenQuadProgram; ShaderProgram* m_CalculateFrustumProgram; ShaderProgram* m_LightCullProgram; + ShaderProgram* m_ForwardPlusProgram; }; diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl new file mode 100644 index 00000000..1f49102e --- /dev/null +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -0,0 +1,124 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec4 Color; + +uniform sampler2D texture0; + + +struct PointLight { + vec4 Position; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + float Padding; +}; + +layout (std430, binding = 1) buffer LightBuffer +{ + PointLight List[]; +} PointLights; + +struct LightGrid { + int Amount; + int Start; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + int LightIndex[]; +}; + + +in VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 DiffuseColor; +}Input; + +out vec4 fragmentColor; + +vec4 scene_ambient = vec4(0.6,0.6,0.6,1); + +struct LightResult { + vec4 Diffuse; + vec4 Specular; +}; + +float CalcAttenuation(float radius, float dist) { + return 1.0 - smoothstep(radius * 1.0, radius, dist); +} + +vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) { + vec4 R = normalize( reflect(-lightVec, normal)); + float RdotV = max( dot(R, viewVec), 0.0); + return lightColor * pow(RdotV, 90.0); +} + +vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) { + float power = max( dot(normal, lightVec), 0.0); + return lightColor * power; +} + +LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal) +{ + vec4 L = lightPos - position; + float dist = length(L); + L = normalize(L); + + float attenuation = CalcAttenuation(lightRadius, dist); + + LightResult result; + result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity; + result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity; + return result; +} + + +void main() +{ + vec4 texel = texture2D(texture0, Input.TextureCoordinate); + vec4 position = V * M * vec4(Input.Position, 1.0); + vec4 normal = V * vec4(Input.Normal, 0.0); + vec4 viewVec = normalize(-position); + + vec2 tilePos; + tilePos.x = int(gl_FragCoord.x/16); + tilePos.y = int(gl_FragCoord.y/16); + + LightResult totalLighting; + totalLighting.Diffuse = scene_ambient; + + //for(int i = 0; i < 3; i++) + for(int i = LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start; i < LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount; i++) + { + int l = LightIndex[i]; + + LightResult result = CalcPointLight(V * PointLights.List[l].Position, PointLights.List[l].Radius, PointLights.List[l].Color, PointLights.List[l].Intensity, viewVec, position, normal); + + totalLighting.Diffuse += result.Diffuse; + totalLighting.Specular += result.Specular; + } + + fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; + //fragmentColor = texel * Input.DiffuseColor * Color; + if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) + { + fragmentColor = vec4(0.5, 0, 0, 0); + } else { + //fragmentColor = vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start/3600, 0, 0, 1); + } + +} + + diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl new file mode 100644 index 00000000..20ab9051 --- /dev/null +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -0,0 +1,34 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec3 Tangent; +layout(location = 3) in vec3 BiTangent; +layout(location = 4) in vec2 TextureCoords; +layout(location = 5) in vec4 DiffuseVertexColor; +layout(location = 6) in vec4 SpecularVertexColor; +layout(location = 7) in vec4 BoneIndices1; +layout(location = 8) in vec4 BoneIndices2; +layout(location = 9) in vec4 BoneWeights1; +layout(location = 10) in vec4 BoneWeights2; + +out VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 DiffuseColor; +}Output; + +void main() +{ + gl_Position = P*V*M * vec4(Position, 1.0); + + Output.Position = Position; + Output.TextureCoordinate = TextureCoords; + Output.Normal = Normal; + Output.DiffuseColor = DiffuseVertexColor; +} \ No newline at end of file diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index e9fa9a95..ffa69d0e 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -1,16 +1,19 @@ #version 430 -//in uvec3 gl_NumWorkGroups; -//in uvec3 gl_WorkGroupID; -//in uvec3 gl_LocalInvocationID; -//in uvec3 gl_GlobalInvocationID; -//in uint gl_LocalInvocationIndex; +//in uvec3 gl_NumWorkGroups; //contains the number of workgroups that have been dispatched to a compute shader +//in uvec3 gl_WorkGroupID; //contains the index of the workgroup currently being operated on by a compute shader +//in uvec3 gl_LocalInvocationID; //contains the index of work item currently being operated on by a compute shader +//in uvec3 gl_GlobalInvocationID; //contains the global index of work item currently being operated on by a compute shader +//in uint gl_LocalInvocationIndex; //contains the local linear index of work item currently being operated on by a compute shader #define NUM_LIGHTS 3 -#define MAX_LIGHTS_PER_TILE 200 +#define MAX_LIGHTS_PER_TILE 1024 #define NUM_TILES 3600 +#define TILE_SIZE 16 + +uniform mat4 V; struct Plane { vec3 Normal; @@ -25,11 +28,124 @@ layout (std430, binding = 0) buffer FrustumBuffer Frustum Data[3600]; } Frustums; +struct PointLight { + vec4 Position; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + float Padding; +}; +layout (std430, binding = 1) buffer LightBuffer +{ + PointLight List[]; +} PointLights; + +struct LightGrid { + int Amount; + int Start; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 3) buffer LightOffsetBuffer +{ + int LightOffset[]; +}; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + int LightIndex[]; +}; + +shared int GroupLightCount; +shared int GroupLightIndexStartOffset; +shared int GroupLightIndex[MAX_LIGHTS_PER_TILE]; +shared Frustum GroupFrustum; +uint GroupIndex; + +bool SphereInsidePlane(vec3 center, float radius, Plane plane) +{ + return dot(plane.Normal, center) - plane.d < -radius; +} + +bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zNear, float zFar*/) +{ + bool result = true; + + //Check depth here + //if ( sphere.c.z - sphere.r > zNear || sphere.c.z + sphere.r < zFar ) + //{ + // result = false; + //} + + for (int i =0; i < 4 && result; i++) + { + if(SphereInsidePlane(center, radius, frustum.Planes[i])) + { + result = false; + } + } + return result; +} + +void AppendLight(uint li) +{ + uint index; + index = atomicAdd(GroupLightCount, 1); + if( index < MAX_LIGHTS_PER_TILE ) + { + GroupLightIndex[index] = int(li); + } +} layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main () { - if(1 == 1) { + GroupIndex = gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.y; + if(gl_LocalInvocationIndex == 0) + { + GroupLightCount = 0; + + GroupFrustum = Frustums.Data[GroupIndex]; + } + + memoryBarrierShared(); + barrier(); + + for(uint i = gl_LocalInvocationIndex; i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE) + { + PointLight light = PointLights.List[i]; + + //if pointlight + //Pos i view antagligen + if(SphereInsideFrustrum(vec3(V * light.Position), light.Radius, GroupFrustum)) + { + //TODO: Fix transparent and opaque list, and depth test. + AppendLight( i ); + } + + + //if conelight + + //if directional + + } + + memoryBarrierShared(); + barrier(); + + if(gl_LocalInvocationIndex == 0) + { + GroupLightIndexStartOffset = atomicAdd(LightOffset[0], GroupLightCount); + LightGrid g; + g.Start = GroupLightIndexStartOffset; + g.Amount = GroupLightCount; + LightGrids.Data[GroupIndex]; } } \ No newline at end of file diff --git a/src/Engine/Rendering/DrawScenePass.cpp b/src/Engine/Rendering/DrawScenePass.cpp index 559a0f58..34fc6d12 100644 --- a/src/Engine/Rendering/DrawScenePass.cpp +++ b/src/Engine/Rendering/DrawScenePass.cpp @@ -28,9 +28,10 @@ void DrawScenePass::InitializeShaderPrograms() void DrawScenePass::Draw(RenderQueueCollection& rq) { //glBindFramebuffer(GL_FRAMEBUFFER, 0); - GLERROR("Renderer::Draw PickingPass"); + GLERROR("DrawScenePass::Draw: Pre"); DrawScenePassState state; + m_BasicForwardProgram->Bind(); //TODO: Render: Add code for more jobs than modeljobs. @@ -39,7 +40,6 @@ void DrawScenePass::Draw(RenderQueueCollection& rq) 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())); @@ -62,5 +62,5 @@ void DrawScenePass::Draw(RenderQueueCollection& rq) continue; } } - GLERROR("DrawScene Error"); + GLERROR("DrawScenePass::Draw: End"); } diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index f4897223..13b4b892 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -16,7 +16,7 @@ void Renderer::Initialize() InitializeShaders(); InitializeTextures(); InitializeSSBOs(); - //CalculateFrustum(); + CalculateFrustum(); m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); @@ -73,15 +73,21 @@ void Renderer::InitializeShaders() 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_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(); + m_LightCullProgram = ResourceManager::Load("#LightCullProgram"); + m_LightCullProgram->AddShader(std::shared_ptr(new ComputeShader("Shaders/cullLights.comp.glsl"))); + m_LightCullProgram->Compile(); + m_LightCullProgram->Link(); + + m_ForwardPlusProgram = ResourceManager::Load("#ForwardPlusProgram"); + m_ForwardPlusProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ForwardPlusProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ForwardPlusProgram->Compile(); + m_ForwardPlusProgram->Link(); } void Renderer::InputUpdate(double dt) @@ -150,9 +156,10 @@ void Renderer::Draw(RenderQueueCollection& rq) { m_PickingPass->Draw(rq); //DrawScreenQuad(m_PickingPass->PickingTexture()); - //CullLights(); + CullLights(); - m_DrawScenePass->Draw(rq); + //m_DrawScenePass->Draw(rq); + DrawForwardPlus(rq); GLERROR("Renderer::Draw m_DrawScenePass->Draw"); glfwSwapBuffers(m_Window); } @@ -252,39 +259,86 @@ void Renderer::InitializeRenderPasses() void Renderer::CalculateFrustum() { - GLERROR("CalculateFrustum Error-1"); + GLERROR("CalculateFrustum Error: Pre"); + m_CalculateFrustumProgram->Bind(); - 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"); + GLERROR("CalculateFrustum Error: End"); } 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].Position = glm::vec4(5.f * (i-1), 0.f, 0.f, 1.f); m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f); + m_PointLights[i].Radius = 10.f; } } void Renderer::CullLights() { + GLERROR("CullLights Error: Pre"); + m_LightCullProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); 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"); + + GLERROR("CullLights Error: End"); } +void Renderer::DrawForwardPlus(RenderQueueCollection& rq) +{ + GLERROR("Renderer::DrawForwardPlus: Pre"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glClearColor(200.f / 255, 0.f / 255, 200.f / 255, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_ForwardPlusProgram->Bind(); + GLuint ShaderHandle = m_ForwardPlusProgram->GetHandle(); + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); + //TODO: Render: Add code for more jobs than modeljobs. + for (auto &job : rq.Forward) { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + + //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("Renderer::DrawForwardPlus: End"); +} +