Example #1
0
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);
    }
}