#include "Rendering/LightCullingPass.h" LightCullingPass::LightCullingPass(IRenderer* renderer) { m_Renderer = renderer; SetSSBOSizes(); InitializeSSBOs(); InitializeShaderPrograms(); //GenerateNewFrustum(TODO); } LightCullingPass::~LightCullingPass() { } void LightCullingPass::GenerateNewFrustum(RenderScene& scene) { if (scene.Jobs.PointLight.size() == 0) return; GLERROR("CalculateFrustum Error: Pre"); m_CalculateFrustumProgram->Bind(); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); glDispatchCompute((int)(m_Renderer->GetViewportSize().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->GetViewportSize().Height/(TILE_SIZE*TILE_SIZE) + 1), 1); GLERROR("CalculateFrustum Error: End"); } void LightCullingPass::OnResolutionChange() { SetSSBOSizes(); } void LightCullingPass::SetSSBOSizes() { m_NumberOfTiles = (int)(m_Renderer->GetViewportSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewportSize().Height/TILE_SIZE); m_Frustums = new Frustum[m_NumberOfTiles]; m_LightGrid = new LightGrid[m_NumberOfTiles]; m_LightIndex = new float[m_NumberOfTiles*MAX_LIGHTS_PER_TILE]; for (int i = 0; i < m_NumberOfTiles*MAX_LIGHTS_PER_TILE; i++) { m_LightIndex[i] = -1; } } void LightCullingPass::CullLights(RenderScene& scene) { GLERROR("CullLights Error: Pre"); m_LightOffset = 0; glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); if (m_LightSources.size() > 0) { glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightSource) * m_LightSources.size(), &(m_LightSources[0]), GL_DYNAMIC_COPY); } else { GLfloat zero = 0.f; glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &zero , GL_DYNAMIC_COPY); } glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); m_LightCullProgram->Bind(); glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(scene.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(glm::ceil(m_Renderer->GetViewportSize().Width/ TILE_SIZE), glm::ceil(m_Renderer->GetViewportSize().Height / TILE_SIZE), 1); GLERROR("CullLights Error: End"); } void LightCullingPass::FillLightList(RenderScene& scene) { m_LightSources.clear(); for(auto &job : scene.Jobs.PointLight) { auto pointLightjob = std::dynamic_pointer_cast(job); if (pointLightjob) { LightSource p; p.Color = pointLightjob->Color; p.Falloff = pointLightjob->Falloff; p.Intensity = pointLightjob->Intensity; p.Position = glm::vec4(glm::vec3(pointLightjob->Position), 1.f); p.Radius = pointLightjob->Radius; //p.Padding = 123.f; p.Type = LightSource::Point; m_LightSources.push_back(p); } } for(auto &job : scene.Jobs.DirectionalLight) { auto directionalLightJob = std::dynamic_pointer_cast(job); if(directionalLightJob) { LightSource p; p.Direction = directionalLightJob->Direction; p.Color = directionalLightJob->Color; p.Intensity = directionalLightJob->Intensity; p.Type = LightSource::Directional; m_LightSources.push_back(p); } } } void LightCullingPass::OnWindowResize() { SetSSBOSizes(); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Frustum)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY); GLERROR("m_FrustumSSBO"); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightSource) * 200, nullptr, GL_DYNAMIC_COPY); GLERROR("m_LightSSBO"); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightGrid)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY); GLERROR("m_LightGridSSBO"); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); GLERROR("m_LightOffsetSSBO"); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float)*m_NumberOfTiles*MAX_LIGHTS_PER_TILE, m_LightIndex, GL_DYNAMIC_COPY); GLERROR("m_LightIndexSSBO"); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); } void LightCullingPass::InitializeSSBOs() { glGenBuffers(1, &m_FrustumSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Frustum)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY); 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(LightSource) * 200, nullptr, GL_DYNAMIC_COPY); 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(LightGrid)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY); 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); 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(float)*m_NumberOfTiles*MAX_LIGHTS_PER_TILE, m_LightIndex, GL_DYNAMIC_COPY); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); GLERROR("m_LightIndexSSBO"); } void LightCullingPass::InitializeShaderPrograms() { 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(); }