示例#1
0
void RenderDeferredLocals::run(const render::RenderContextPointer& renderContext,
    const DeferredFrameTransformPointer& frameTransform,
    const DeferredFramebufferPointer& deferredFramebuffer,
    const LightingModelPointer& lightingModel,
    const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, 
    const LightClustersPointer& lightClusters) {

    bool points = lightingModel->isPointLightEnabled();
    bool spots = lightingModel->isSpotLightEnabled();

    if (!points && !spots) {
        return;
    }
    auto args = renderContext->args;
    auto& batch = (*args->_batch);
    {
        // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport)
        auto viewport = args->_viewport;

        // The view frustum is the mono frustum base
        auto viewFrustum = args->getViewFrustum();

        // Eval the mono projection
        mat4 projMat;
        viewFrustum.evalProjectionMatrix(projMat);

        // The view transform
        Transform viewTransform;
        viewFrustum.evalViewTransform(viewTransform);


        auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();

        // Render in this viewport
        batch.setViewportTransform(viewport);
        batch.setStateScissorRect(viewport);

        auto& lightIndices = lightClusters->_visibleLightIndices;
        if (!lightIndices.empty() && lightIndices[0] > 0) {
            deferredLightingEffect->setupLocalLightsBatch(batch, lightClusters);

            // Local light pipeline
            batch.setPipeline(deferredLightingEffect->_localLight);

            batch.draw(gpu::TRIANGLE_STRIP, 4);

             // Draw outline as well ?
            if (lightingModel->isShowLightContourEnabled()) {
                batch.setPipeline(deferredLightingEffect->_localLightOutline);

                batch.draw(gpu::TRIANGLE_STRIP, 4);
            }
        }
    }
}
示例#2
0
void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
    const DeferredFrameTransformPointer& frameTransform,
    const DeferredFramebufferPointer& deferredFramebuffer,
    const LightingModelPointer& lightingModel) {

    bool points = lightingModel->isPointLightEnabled();
    bool spots = lightingModel->isSpotLightEnabled();

    if (!points && !spots) {
        return;
    }
    auto args = renderContext->args;
    gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {

        // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport)
        auto monoViewport = args->_viewport;

        // The view frustum is the mono frustum base
        auto viewFrustum = args->getViewFrustum();

        // Eval the mono projection
        mat4 monoProjMat;
        viewFrustum.evalProjectionMatrix(monoProjMat);

        // The mono view transform
        Transform monoViewTransform;
        viewFrustum.evalViewTransform(monoViewTransform);

        // THe mono view matrix coming from the mono view transform
        glm::mat4 monoViewMat;
        monoViewTransform.getMatrix(monoViewMat);

        auto geometryCache = DependencyManager::get<GeometryCache>();

        auto eyePoint = viewFrustum.getPosition();
        float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft());

        auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();

        // Render in this side's viewport
        batch.setViewportTransform(monoViewport);
        batch.setStateScissorRect(monoViewport);

        // enlarge the scales slightly to account for tesselation
        const float SCALE_EXPANSION = 0.05f;

        auto textureFrameTransform = gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(deferredFramebuffer->getFrameSize(), monoViewport);

        batch.setProjectionTransform(monoProjMat);
        batch.setViewTransform(monoViewTransform, true);

        // Splat Point lights
        if (points && !deferredLightingEffect->_pointLights.empty()) {
            // POint light pipeline
            batch.setPipeline(deferredLightingEffect->_pointLight);
            batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform));

            for (auto lightID : deferredLightingEffect->_pointLights) {
                auto& light = deferredLightingEffect->_allocatedLights[lightID];
                // IN DEBUG: light->setShowContour(true);
                batch.setUniformBuffer(deferredLightingEffect->_pointLightLocations->lightBufferUnit, light->getSchemaBuffer());

                float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
                glm::vec4 sphereParam(expandedRadius, 0.0f, 0.0f, 1.0f);

                // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,
                // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...
                if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) {
                    sphereParam.w = 0.0f;
                    batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam));
                    batch.draw(gpu::TRIANGLE_STRIP, 4);
                } else {
                    sphereParam.w = 1.0f;
                    batch._glUniform4fv(deferredLightingEffect->_pointLightLocations->sphereParam, 1, reinterpret_cast< const float* >(&sphereParam));
                    
                    Transform model;
                    model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z));
                    batch.setModelTransform(model.postScale(expandedRadius));
                    batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
                    geometryCache->renderSphere(batch);
                }
            }
        }

        // Splat spot lights
        if (spots && !deferredLightingEffect->_spotLights.empty()) {
            // Spot light pipeline
            batch.setPipeline(deferredLightingEffect->_spotLight);
            batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform));

            // Spot mesh
            auto mesh = deferredLightingEffect->getSpotLightMesh();
            batch.setIndexBuffer(mesh->getIndexBuffer());
            batch.setInputBuffer(0, mesh->getVertexBuffer());
            batch.setInputFormat(mesh->getVertexFormat());
            auto& conePart = mesh->getPartBuffer().get<model::Mesh::Part>(0);

            for (auto lightID : deferredLightingEffect->_spotLights) {
                auto light = deferredLightingEffect->_allocatedLights[lightID];
                // IN DEBUG: 
                // light->setShowContour(true);
                batch.setUniformBuffer(deferredLightingEffect->_spotLightLocations->lightBufferUnit, light->getSchemaBuffer());

                auto eyeLightPos = eyePoint - light->getPosition();
                auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection());

                const float TANGENT_LENGTH_SCALE = 0.666f;
                glm::vec4 coneParam(light->getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * light->getSpotAngle()), 1.0f);

                float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
                // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,
                // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...
                const float OVER_CONSERVATIVE_SCALE = 1.1f;
                if ((eyeHalfPlaneDistance > -nearRadius) &&
                    (glm::distance(eyePoint, glm::vec3(light->getPosition())) < (expandedRadius * OVER_CONSERVATIVE_SCALE) + nearRadius)) {
                    coneParam.w = 0.0f;
                    batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
                    batch.draw(gpu::TRIANGLE_STRIP, 4);
                } else {
                    coneParam.w = 1.0f;
                    batch._glUniform4fv(deferredLightingEffect->_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));

                    Transform model;
                    model.setTranslation(light->getPosition());
                    model.postRotate(light->getOrientation());
                    model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius));

                    batch.setModelTransform(model);

                    batch.drawIndexed(model::Mesh::topologyToPrimitive(conePart._topology), conePart._numIndices, conePart._startIndex);
                }
            }
        }
    });
}
示例#3
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);
    });
    
}
示例#4
0
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);
    }
}