void DeferredLightingEffect::render(RenderArgs* args) { // perform deferred lighting, rendering to free fbo glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_COLOR_MATERIAL); glDepthMask(false); auto textureCache = DependencyManager::get<TextureCache>(); glBindFramebuffer(GL_FRAMEBUFFER, 0 ); QSize framebufferSize = textureCache->getFrameBufferSize(); // binding the first framebuffer auto freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFBO)); glClear(GL_COLOR_BUFFER_BIT); // glEnable(GL_FRAMEBUFFER_SRGB); // glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryColorTextureID()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryNormalTextureID()); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureCache->getPrimarySpecularTextureID()); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, textureCache->getPrimaryDepthTextureID()); // get the viewport side (left, right, both) int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; const int VIEWPORT_Y_INDEX = 1; const int VIEWPORT_WIDTH_INDEX = 2; const int VIEWPORT_HEIGHT_INDEX = 3; float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width(); float tMin = viewport[VIEWPORT_Y_INDEX] / (float)framebufferSize.height(); float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)framebufferSize.height(); bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap()); // Fetch the ViewMatrix; glm::mat4 invViewMat; _viewState->getViewTransform().getMatrix(invViewMat); ProgramObject* program = &_directionalLight; const LightLocations* locations = &_directionalLightLocations; bool shadowsEnabled = _viewState->getShadowsEnabled(); if (shadowsEnabled) { glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, textureCache->getShadowDepthTextureID()); program = &_directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; if (_viewState->getCascadeShadowsEnabled()) { program = &_directionalLightCascadedShadowMap; locations = &_directionalLightCascadedShadowMapLocations; if (useSkyboxCubemap) { program = &_directionalSkyboxLightCascadedShadowMap; locations = &_directionalSkyboxLightCascadedShadowMapLocations; } else if (_ambientLightMode > -1) { program = &_directionalAmbientSphereLightCascadedShadowMap; locations = &_directionalAmbientSphereLightCascadedShadowMapLocations; } program->bind(); program->setUniform(locations->shadowDistances, _viewState->getShadowDistances()); } else { if (useSkyboxCubemap) { program = &_directionalSkyboxLightShadowMap; locations = &_directionalSkyboxLightShadowMapLocations; } else if (_ambientLightMode > -1) { program = &_directionalAmbientSphereLightShadowMap; locations = &_directionalAmbientSphereLightShadowMapLocations; } program->bind(); } program->setUniformValue(locations->shadowScale, 1.0f / textureCache->getShadowFramebuffer()->getWidth()); } else { if (useSkyboxCubemap) { program = &_directionalSkyboxLight; locations = &_directionalSkyboxLightLocations; } else if (_ambientLightMode > -1) { program = &_directionalAmbientSphereLight; locations = &_directionalAmbientSphereLightLocations; } program->bind(); } { auto globalLight = _allocatedLights[_globalLights.front()]; if (locations->ambientSphere >= 0) { gpu::SphericalHarmonics sh = globalLight->getAmbientSphere(); if (useSkyboxCubemap && _skybox->getCubemap()->getIrradiance()) { sh = (*_skybox->getCubemap()->getIrradiance()); } for (int i =0; i <gpu::SphericalHarmonics::NUM_COEFFICIENTS; i++) { program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i)); } } if (useSkyboxCubemap) { glActiveTexture(GL_TEXTURE5); glBindTexture(GL_TEXTURE_CUBE_MAP, gpu::GLBackend::getTextureID(_skybox->getCubemap())); } if (locations->lightBufferUnit >= 0) { gpu::Batch batch; batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); gpu::GLBackend::renderBatch(batch); } if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) { gpu::Batch batch; batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); } float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); program->setUniformValue(locations->nearLocation, nearVal); float depthScale = (farVal - nearVal) / farVal; program->setUniformValue(locations->depthScale, depthScale); float nearScale = -1.0f / nearVal; float depthTexCoordScaleS = (right - left) * nearScale / sWidth; float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight; float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS; float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT; program->setUniformValue(locations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight); program->release(); if (useSkyboxCubemap) { glBindTexture(GL_TEXTURE_CUBE_MAP, 0); if (!shadowsEnabled) { glActiveTexture(GL_TEXTURE3); } } if (shadowsEnabled) { glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE3); } // additive blending glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_CULL_FACE); glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); glm::vec4 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f); glTexGenfv(GL_S, GL_OBJECT_PLANE, (const GLfloat*)&sCoefficients); glTexGenfv(GL_T, GL_OBJECT_PLANE, (const GLfloat*)&tCoefficients); // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; const glm::vec3& eyePoint = _viewState->getCurrentViewFrustum()->getPosition(); float nearRadius = glm::distance(eyePoint, _viewState->getCurrentViewFrustum()->getNearTopLeft()); auto geometryCache = DependencyManager::get<GeometryCache>(); if (!_pointLights.empty()) { _pointLight.bind(); _pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal); _pointLight.setUniformValue(_pointLightLocations.depthScale, depthScale); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); for (auto lightID : _pointLights) { auto light = _allocatedLights[lightID]; if (_pointLightLocations.lightBufferUnit >= 0) { gpu::Batch batch; batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer()); gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); glPushMatrix(); float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, -1.0f); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); renderFullscreenQuad(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } else { glTranslatef(light->getPosition().x, light->getPosition().y, light->getPosition().z); geometryCache->renderSphere(expandedRadius, 32, 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); } glPopMatrix(); } _pointLights.clear(); _pointLight.release(); } if (!_spotLights.empty()) { _spotLight.bind(); _spotLight.setUniformValue(_spotLightLocations.nearLocation, nearVal); _spotLight.setUniformValue(_spotLightLocations.depthScale, depthScale); _spotLight.setUniformValue(_spotLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); _spotLight.setUniformValue(_spotLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); for (auto lightID : _spotLights) { auto light = _allocatedLights[lightID]; if (_spotLightLocations.lightBufferUnit >= 0) { gpu::Batch batch; batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer()); gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); glPushMatrix(); float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); float edgeRadius = expandedRadius / glm::cos(light->getSpotAngle()); if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < edgeRadius + nearRadius) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, -1.0f); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); renderFullscreenQuad(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } else { glTranslatef(light->getPosition().x, light->getPosition().y, light->getPosition().z); glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light->getDirection()); glm::vec3 axis = glm::axis(spotRotation); glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); glTranslatef(0.0f, 0.0f, -light->getMaximumRadius() * (1.0f + SCALE_EXPANSION * 0.5f)); geometryCache->renderCone(expandedRadius * glm::tan(light->getSpotAngle()), expandedRadius, 32, 1); } glPopMatrix(); } _spotLights.clear(); _spotLight.release(); } glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); // glDisable(GL_FRAMEBUFFER_SRGB); // End of the Lighting pass }
GLuint TextureCache::getShadowDepthTextureID() { // ensure that the shadow framebuffer object is initialized before returning the depth texture id getShadowFramebuffer(); return gpu::GLBackend::getTextureID(_shadowTexture); }