void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, const LightingModelPointer& lightingModel, const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer, const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) { auto args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // Framebuffer copy operations cannot function as multipass stereo operations. batch.enableStereo(false); // perform deferred lighting, rendering to free fbo auto framebufferCache = DependencyManager::get<FramebufferCache>(); auto textureCache = DependencyManager::get<TextureCache>(); auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); // binding the first framebuffer auto lightingFBO = deferredFramebuffer->getLightingFramebuffer(); batch.setFramebuffer(lightingFBO); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); // Bind the G-Buffer surfaces batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, deferredFramebuffer->getDeferredColorTexture()); batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, deferredFramebuffer->getDeferredNormalTexture()); batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, deferredFramebuffer->getDeferredSpecularTexture()); batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, deferredFramebuffer->getPrimaryDepthTexture()); // FIXME: Different render modes should have different tasks if (args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && deferredLightingEffect->isAmbientOcclusionEnabled()) { batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, ambientOcclusionFramebuffer->getOcclusionTexture()); } else { // need to assign the white texture if ao is off batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, textureCache->getWhiteTexture()); } // The Deferred Frame Transform buffer batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, frameTransform->getFrameTransformBuffer()); // THe lighting model batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer()); // Subsurface scattering specific if (surfaceGeometryFramebuffer) { batch.setResourceTexture(DEFERRED_BUFFER_CURVATURE_UNIT, surfaceGeometryFramebuffer->getCurvatureTexture()); batch.setResourceTexture(DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT, surfaceGeometryFramebuffer->getLowCurvatureTexture()); } if (subsurfaceScatteringResource) { batch.setUniformBuffer(SCATTERING_PARAMETERS_BUFFER_SLOT, subsurfaceScatteringResource->getParametersBuffer()); batch.setResourceTexture(SCATTERING_LUT_UNIT, subsurfaceScatteringResource->getScatteringTable()); batch.setResourceTexture(SCATTERING_SPECULAR_UNIT, subsurfaceScatteringResource->getScatteringSpecular()); } // Global directional light and ambient pass assert(deferredLightingEffect->getLightStage().lights.size() > 0); const auto& globalShadow = deferredLightingEffect->getLightStage().lights[0]->shadow; // Bind the shadow buffer batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow.map); auto& program = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadow : deferredLightingEffect->_directionalLight; LightLocationsPtr locations = deferredLightingEffect->_shadowMapEnabled ? deferredLightingEffect->_directionalLightShadowLocations : deferredLightingEffect->_directionalLightLocations; const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()]; // Setup the global directional pass pipeline { if (deferredLightingEffect->_shadowMapEnabled) { if (keyLight->getAmbientMap()) { program = deferredLightingEffect->_directionalSkyboxLightShadow; locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations; } else { program = deferredLightingEffect->_directionalAmbientSphereLightShadow; locations = deferredLightingEffect->_directionalAmbientSphereLightShadowLocations; } } else { if (keyLight->getAmbientMap()) { program = deferredLightingEffect->_directionalAmbientSphereLight; locations = deferredLightingEffect->_directionalAmbientSphereLightLocations; //program = deferredLightingEffect->_directionalSkyboxLight; //locations = deferredLightingEffect->_directionalSkyboxLightLocations; } else { program = deferredLightingEffect->_directionalAmbientSphereLight; locations = deferredLightingEffect->_directionalAmbientSphereLightLocations; } } if (locations->shadowTransformBuffer >= 0) { batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow.getBuffer()); } batch.setPipeline(program); } // Adjust the texcoordTransform in the case we are rendeirng a sub region(mini mirror) auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), args->_viewport); batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); { // Setup the global lighting deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, SKYBOX_MAP_UNIT); } batch.draw(gpu::TRIANGLE_STRIP, 4); if (keyLight->getAmbientMap()) { batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr); } batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr); }); }
void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, const DeferredFrameTransformPointer& frameTransform, const DeferredFramebufferPointer& deferredFramebuffer, const LightingModelPointer& lightingModel, const LightStage::FramePointer& lightFrame, const LightStage::ShadowFramePointer& shadowFrame, const HazeStage::FramePointer& hazeFrame, const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer, const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) { auto args = renderContext->args; auto& batch = (*args->_batch); { // Framebuffer copy operations cannot function as multipass stereo operations. batch.enableStereo(false); auto textureCache = DependencyManager::get<TextureCache>(); auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>(); // binding the first framebuffer auto lightingFBO = deferredFramebuffer->getLightingFramebuffer(); batch.setFramebuffer(lightingFBO); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); // Bind the G-Buffer surfaces batch.setResourceTexture(ru::Texture::DeferredColor, deferredFramebuffer->getDeferredColorTexture()); batch.setResourceTexture(ru::Texture::DeferredNormal, deferredFramebuffer->getDeferredNormalTexture()); batch.setResourceTexture(ru::Texture::DeferredSpecular, deferredFramebuffer->getDeferredSpecularTexture()); batch.setResourceTexture(ru::Texture::DeferredDepth, deferredFramebuffer->getPrimaryDepthTexture()); // FIXME: Different render modes should have different tasks if (lightingModel->isAmbientOcclusionEnabled() && ambientOcclusionFramebuffer) { batch.setResourceTexture(ru::Texture::DeferredObscurance, ambientOcclusionFramebuffer->getOcclusionTexture()); } else { // need to assign the white texture if ao is off batch.setResourceTexture(ru::Texture::DeferredObscurance, textureCache->getWhiteTexture()); } // The Deferred Frame Transform buffer batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); // THe lighting model batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer()); batch.setResourceTexture(ru::Texture::AmbientFresnel, lightingModel->getAmbientFresnelLUT()); // Subsurface scattering specific if (surfaceGeometryFramebuffer) { batch.setResourceTexture(ru::Texture::DeferredLinearZEye, surfaceGeometryFramebuffer->getLinearDepthTexture()); batch.setResourceTexture(ru::Texture::DeferredCurvature, surfaceGeometryFramebuffer->getCurvatureTexture()); batch.setResourceTexture(ru::Texture::DeferredDiffusedCurvature, surfaceGeometryFramebuffer->getLowCurvatureTexture()); } if (subsurfaceScatteringResource) { batch.setUniformBuffer(ru::Buffer::SsscParams, subsurfaceScatteringResource->getParametersBuffer()); batch.setResourceTexture(ru::Texture::SsscLut, subsurfaceScatteringResource->getScatteringTable()); batch.setResourceTexture(ru::Texture::SsscSpecularBeckmann, subsurfaceScatteringResource->getScatteringSpecular()); } // Global directional light, maybe shadow and ambient pass auto lightStage = renderContext->_scene->getStage<LightStage>(); assert(lightStage); assert(lightStage->getNumLights() > 0); auto keyLight = lightStage->getCurrentKeyLight(*lightFrame); // Check if keylight casts shadows bool keyLightCastShadows{ false }; LightStage::ShadowPointer globalShadow; if (lightingModel->isShadowEnabled() && shadowFrame && !shadowFrame->_objects.empty()) { globalShadow = shadowFrame->_objects.front(); if (globalShadow) { keyLightCastShadows = true; } } // Global Ambient light graphics::LightPointer ambientLight; if (lightStage && lightFrame->_ambientLights.size()) { ambientLight = lightStage->getLight(lightFrame->_ambientLights.front()); } bool hasAmbientMap = (ambientLight != nullptr); // Setup the global directional pass pipeline auto program = deferredLightingEffect->_directionalSkyboxLight; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; { if (keyLightCastShadows) { // If the keylight has an ambient Map then use the Skybox version of the pass // otherwise use the ambient sphere version if (hasAmbientMap) { program = deferredLightingEffect->_directionalSkyboxLightShadow; locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations; } else { program = deferredLightingEffect->_directionalAmbientSphereLightShadow; locations = deferredLightingEffect->_directionalAmbientSphereLightShadowLocations; } } else { // If the keylight has an ambient Map then use the Skybox version of the pass // otherwise use the ambient sphere version if (hasAmbientMap) { program = deferredLightingEffect->_directionalSkyboxLight; locations = deferredLightingEffect->_directionalSkyboxLightLocations; } else { program = deferredLightingEffect->_directionalAmbientSphereLight; locations = deferredLightingEffect->_directionalAmbientSphereLightLocations; } } if (keyLightCastShadows && globalShadow) { batch.setResourceTexture(ru::Texture::Shadow, globalShadow->map); batch.setUniformBuffer(ru::Buffer::ShadowParams, globalShadow->getBuffer()); } batch.setPipeline(program); } // Setup the global lighting deferredLightingEffect->setupKeyLightBatch(args, batch, *lightFrame); // Haze const auto& hazeStage = args->_scene->getStage<HazeStage>(); if (hazeStage && hazeFrame->_hazes.size() > 0) { const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front()); if (hazePointer) { batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer()); } } batch.draw(gpu::TRIANGLE_STRIP, 4); deferredLightingEffect->unsetKeyLightBatch(batch); batch.setResourceTexture(ru::Texture::Shadow, nullptr); } }