Пример #1
0
void InstanceFiller<GlowInstanceData>::add(GLMesh* mesh,
                                           const InstanceSettings& is,
                                           GlowInstanceData& instance)
{
    scene::ISceneNode* node = STK::tuple_get<0>(is);
    fillOriginOrientationScale<GlowInstanceData>(node, instance);
    STKMeshSceneNode *nd = dynamic_cast<STKMeshSceneNode*>(node);
    instance.Color = nd->getGlowColor().color;
}
Пример #2
0
/** Render the post-processed scene */
FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, bool isRace)
{
    FrameBuffer *in_fbo = &irr_driver->getFBO(FBO_COLORS);
    FrameBuffer *out_fbo = &irr_driver->getFBO(FBO_TMP1_WITH_DS);
    // Each effect uses these as named, and sets them up for the next effect.
    // This allows chaining effects where some may be disabled.

    // As the original color shouldn't be touched, the first effect can't be disabled.
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);

    if (isRace && UserConfigParams::m_dof)
    {
        PROFILER_PUSH_CPU_MARKER("- DoF", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_DOF));
        renderDoF(*out_fbo, in_fbo->getRTT()[0]);
        std::swap(in_fbo, out_fbo);
        PROFILER_POP_CPU_MARKER();
    }

    {
        PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_GODRAYS));
        bool hasgodrays = false;
        if (World::getWorld() != NULL)
            hasgodrays = World::getWorld()->getTrack()->hasGodRays();

        if (isRace && UserConfigParams::m_light_shaft && hasgodrays)
        {
            Track* track = World::getWorld()->getTrack();

            glEnable(GL_DEPTH_TEST);
            // Grab the sky
            out_fbo->Bind();
            glClear(GL_COLOR_BUFFER_BIT);
//            irr_driver->renderSkybox(camnode);

            // Set the sun's color
            const SColor col = track->getGodRaysColor();
            ColorizeProvider * const colcb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE);
            colcb->setColor(col.getRed() / 255.0f, col.getGreen() / 255.0f, col.getBlue() / 255.0f);

            // The sun interposer
            STKMeshSceneNode *sun = irr_driver->getSunInterposer();
            sun->setGlowColors(col);
            sun->setPosition(track->getGodRaysPosition());
            sun->updateAbsolutePosition();
            irr_driver->setPhase(GLOW_PASS);
            sun->render();
            glDisable(GL_DEPTH_TEST);

            // Fade to quarter
            irr_driver->getFBO(FBO_QUARTER1).Bind();
            glViewport(0, 0, UserConfigParams::m_width / 4, UserConfigParams::m_height / 4);
            renderGodFade(out_fbo->getRTT()[0], col);

            // Blur
            renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER1), irr_driver->getFBO(FBO_QUARTER2));

            // Calculate the sun's position in texcoords
            const core::vector3df pos = track->getGodRaysPosition();
            float ndc[4];
            core::matrix4 trans = camnode->getProjectionMatrix();
            trans *= camnode->getViewMatrix();

            trans.transformVect(ndc, pos);

            const float texh = m_vertices[0].v1.TCoords.Y - m_vertices[0].v0.TCoords.Y;
            const float texw = m_vertices[0].v3.TCoords.X - m_vertices[0].v0.TCoords.X;

            const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw;
            const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh;

            // Rays please
            irr_driver->getFBO(FBO_QUARTER2).Bind();
            renderGodRay(irr_driver->getRenderTargetTexture(RTT_QUARTER1), core::vector2df(sunx, suny));

            // Blur
            renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER2), irr_driver->getFBO(FBO_QUARTER1));

            // Blend
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE);
            glBlendEquation(GL_FUNC_ADD);

            in_fbo->Bind();
            renderPassThrough(irr_driver->getRenderTargetTexture(RTT_QUARTER2));
            glDisable(GL_BLEND);
        }
        PROFILER_POP_CPU_MARKER();
    }

    // Simulate camera defects from there

    {
        PROFILER_PUSH_CPU_MARKER("- Bloom", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_BLOOM));
        if (isRace && UserConfigParams::m_bloom)
        {
            glClear(GL_STENCIL_BUFFER_BIT);
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

            FrameBuffer::Blit(*in_fbo, irr_driver->getFBO(FBO_BLOOM_1024), GL_COLOR_BUFFER_BIT, GL_LINEAR);

            irr_driver->getFBO(FBO_BLOOM_512).Bind();
            renderBloom(irr_driver->getRenderTargetTexture(RTT_BLOOM_1024));

            // Downsample
            FrameBuffer::Blit(irr_driver->getFBO(FBO_BLOOM_512), irr_driver->getFBO(FBO_BLOOM_256), GL_COLOR_BUFFER_BIT, GL_LINEAR);
            FrameBuffer::Blit(irr_driver->getFBO(FBO_BLOOM_256), irr_driver->getFBO(FBO_BLOOM_128), GL_COLOR_BUFFER_BIT, GL_LINEAR);

            // Blur
            renderGaussian6Blur(irr_driver->getFBO(FBO_BLOOM_512), irr_driver->getFBO(FBO_TMP_512));

            renderGaussian6Blur(irr_driver->getFBO(FBO_BLOOM_256), irr_driver->getFBO(FBO_TMP_256));

            renderGaussian6Blur(irr_driver->getFBO(FBO_BLOOM_128), irr_driver->getFBO(FBO_TMP_128));

            // Additively blend on top of tmp1
            in_fbo->Bind();
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE);
            glBlendEquation(GL_FUNC_ADD);
            FullScreenShader::BloomBlendShader::getInstance()->SetTextureUnits(createVector<GLuint>(
                irr_driver->getRenderTargetTexture(RTT_BLOOM_128), irr_driver->getRenderTargetTexture(RTT_BLOOM_256), irr_driver->getRenderTargetTexture(RTT_BLOOM_512) ));
            DrawFullScreenEffect<FullScreenShader::BloomBlendShader>();

            glDisable(GL_BLEND);
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        } // end if bloom
        PROFILER_POP_CPU_MARKER();
    }

    //computeLogLuminance(in_rtt);
    {
        PROFILER_PUSH_CPU_MARKER("- Tonemap", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TONEMAP));
        toneMap(*out_fbo, in_fbo->getRTT()[0]);
        std::swap(in_fbo, out_fbo);
        PROFILER_POP_CPU_MARKER();
    }

    {
        PROFILER_PUSH_CPU_MARKER("- Motion blur", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_MOTIONBLUR));
        if (isRace && UserConfigParams::m_motionblur && World::getWorld() != NULL) // motion blur
        {
            renderMotionBlur(0, *in_fbo, *out_fbo);
            std::swap(in_fbo, out_fbo);
        }
        PROFILER_POP_CPU_MARKER();
    }

    // Workaround a bug with srgb fbo on sandy bridge windows
    if (irr_driver->needUBOWorkaround())
        return in_fbo;

    glEnable(GL_FRAMEBUFFER_SRGB);
    irr_driver->getFBO(FBO_MLAA_COLORS).Bind();
    renderPassThrough(in_fbo->getRTT()[0]);
    out_fbo = &irr_driver->getFBO(FBO_MLAA_COLORS);

    if (UserConfigParams::m_mlaa) // MLAA. Must be the last pp filter.
    {
        PROFILER_PUSH_CPU_MARKER("- MLAA", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_MLAA));
        applyMLAA();
        PROFILER_POP_CPU_MARKER();
    }
    glDisable(GL_FRAMEBUFFER_SRGB);

    return out_fbo;
}   // render
Пример #3
0
void IrrDriver::renderGlow(std::vector<GlowData>& glows)
{
    m_scene_manager->setCurrentRendertime(scene::ESNRP_SOLID);
    m_rtts->getFBO(FBO_TMP1_WITH_DS).Bind();
    glClearStencil(0);
    glClearColor(0, 0, 0, 0);
    glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    const u32 glowcount = (int)glows.size();

    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    glStencilFunc(GL_ALWAYS, 1, ~0);
    glEnable(GL_STENCIL_TEST);

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);
    glDisable(GL_BLEND);

    if (CVS->isARBBaseInstanceUsable())
        glBindVertexArray(VAOManager::getInstance()->getVAO(EVT_STANDARD));
    for (u32 i = 0; i < glowcount; i++)
    {
        const GlowData &dat = glows[i];
        scene::ISceneNode * cur = dat.node;

        STKMeshSceneNode *node = static_cast<STKMeshSceneNode *>(cur);
        node->setGlowColors(SColor(0, (unsigned) (dat.b * 255.f), (unsigned)(dat.g * 255.f), (unsigned)(dat.r * 255.f)));
        if (!CVS->supportsIndirectInstancingRendering())
            node->render();
    }

    if (CVS->supportsIndirectInstancingRendering())
    {
        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd);
        glUseProgram(MeshShader::InstancedColorizeShader::getInstance()->Program);

        glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeGlow));
        if (CVS->isAZDOEnabled())
        {
            if (GlowPassCmd::getInstance()->Size)
            {
                glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
                    (const void*)(GlowPassCmd::getInstance()->Offset * sizeof(DrawElementsIndirectCommand)),
                    (int)GlowPassCmd::getInstance()->Size,
                    sizeof(DrawElementsIndirectCommand));
            }
        }
        else
        {
            for (unsigned i = 0; i < ListInstancedGlow::getInstance()->size(); i++)
                glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((GlowPassCmd::getInstance()->Offset + i) * sizeof(DrawElementsIndirectCommand)));
        }
    }

    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_BLEND);

    // To half
    FrameBuffer::Blit(irr_driver->getFBO(FBO_TMP1_WITH_DS), irr_driver->getFBO(FBO_HALF1), GL_COLOR_BUFFER_BIT, GL_LINEAR);

    // To quarter
    FrameBuffer::Blit(irr_driver->getFBO(FBO_HALF1), irr_driver->getFBO(FBO_QUARTER1), GL_COLOR_BUFFER_BIT, GL_LINEAR);


    glEnable(GL_BLEND);
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glStencilFunc(GL_EQUAL, 0, ~0);
    glEnable(GL_STENCIL_TEST);
    m_rtts->getFBO(FBO_COLORS).Bind();
    m_post_processing->renderGlow(m_rtts->getRenderTarget(RTT_QUARTER1));
    glDisable(GL_STENCIL_TEST);
}
Пример #4
0
void TrackObjectPresentationMesh::init(const XMLNode* xml_node, scene::ISceneNode* parent, bool enabled)
{
    bool skeletal_animation = true; // for backwards compatibility, if unspecified assume there is
    if(xml_node)
        xml_node->get("skeletal-animation", &skeletal_animation);

    bool animated = skeletal_animation && (UserConfigParams::m_graphical_effects ||
             World::getWorld()->getIdent() == IDENT_CUTSCENE);
    bool displacing = false;
    if(xml_node)
        xml_node->get("displacing", &displacing);
    animated &= !displacing;

    m_mesh->grab();
    irr_driver->grabAllTextures(m_mesh);

    if (m_is_in_skybox)
    {
        // Tell the driver that this mesh is a part of the background
        scene::IMeshSceneNode * const node =
            irr_driver->getSceneManager()->addMeshSceneNode(m_mesh);
        node->grab();
        node->setParent(NULL);

        irr_driver->addBackgroundNode(node);

        m_node = node;
    }
    else if (animated)
    {
        scene::IAnimatedMeshSceneNode *node =
            irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_mesh, parent);
        m_node = node;

        m_frame_start = node->getStartFrame();
        if (xml_node)
            xml_node->get("frame-start", &m_frame_start);

        m_frame_end = node->getEndFrame();
        if (xml_node)
            xml_node->get("frame-end", &m_frame_end);
    }
    else
    {
        bool displacing = false;
        if (xml_node)
            xml_node->get("displacing", &displacing);

        m_node = irr_driver->addMesh(m_mesh, parent);

        STKMeshSceneNode* stkmesh = dynamic_cast<STKMeshSceneNode*>(m_node);
        if (displacing && stkmesh != NULL)
            stkmesh->setIsDisplacement(displacing);

        m_frame_start = 0;
        m_frame_end = 0;

        if (World::getWorld() != NULL && World::getWorld()->getTrack() != NULL && xml_node != NULL)
            World::getWorld()->getTrack()->handleAnimatedTextures(m_node, *xml_node);
    }
//#ifdef DEBUG
//    std::string debug_name = model_name+" (track-object)";
//    m_node->setName(debug_name.c_str());
//#endif

    if(!enabled)
        m_node->setVisible(false);

    m_node->setPosition(m_init_xyz);
    m_node->setRotation(m_init_hpr);
    m_node->setScale(m_init_scale);
}
// ----------------------------------------------------------------------------
void TrackObjectPresentationMesh::init(const XMLNode* xml_node,
                                       scene::ISceneNode* parent, bool enabled)
{
    // for backwards compatibility, if unspecified assume there is
    bool skeletal_animation = true;
    if(xml_node)
        xml_node->get("skeletal-animation", &skeletal_animation);

    bool animated = skeletal_animation && (UserConfigParams::m_graphical_effects ||
             World::getWorld()->getIdent() == IDENT_CUTSCENE);
    bool displacing = false;
    std::string interaction;
    if (xml_node)
    {
        xml_node->get("displacing", &displacing);
        xml_node->get("interaction", &interaction);
    }
    animated &= !displacing;

    m_mesh->grab();
    irr_driver->grabAllTextures(m_mesh);

    if (interaction == "physicsonly")
    {
        std::string type;
        xml_node->get("type", &type);
        if (type == "animation" || xml_node->hasChildNamed("curve"))
        {
            // Animated
            //m_node = irr_driver->getSceneManager()->addEmptySceneNode();
            m_node = irr_driver->addMesh(m_mesh, m_model_file, parent, m_render_info);
            enabled = false;
            m_force_always_hidden = true;
            m_frame_start = 0;
            m_frame_end = 0;
        }
        else
        {
            // Static
            m_node = irr_driver->addMesh(m_mesh, m_model_file, parent, m_render_info);
            enabled = false;
            m_force_always_hidden = true;
            m_frame_start = 0;
            m_frame_end = 0;

            if (World::getWorld() && World::getWorld()->getTrack() && xml_node)
                World::getWorld()->getTrack()->addPhysicsOnlyNode(m_node);
        }
    }
    else if (m_is_in_skybox)
    {
        // Tell the driver that this mesh is a part of the background
        scene::IMeshSceneNode * const node =
            irr_driver->getSceneManager()->addMeshSceneNode(m_mesh);
        node->grab();
        node->setParent(NULL);

        irr_driver->addBackgroundNode(node);

        m_node = node;
    }
    else if (animated)
    {
        scene::IAnimatedMeshSceneNode *node =
            irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_mesh,
                                        m_model_file, parent, m_render_info);
        m_node = node;

        m_frame_start = node->getStartFrame();
        if (xml_node)
            xml_node->get("frame-start", &m_frame_start);

        m_frame_end = node->getEndFrame();
        if (xml_node)
            xml_node->get("frame-end", &m_frame_end);

        if (World::getWorld() && World::getWorld()->getTrack() && xml_node)
            World::getWorld()->getTrack()
            ->handleAnimatedTextures(m_node, *xml_node);
    }
    else
    {
        bool displacing = false;
        if (xml_node)
            xml_node->get("displacing", &displacing);

        m_node = irr_driver->addMesh(m_mesh, m_model_file, parent, m_render_info);

        STKMeshSceneNode* stkmesh = dynamic_cast<STKMeshSceneNode*>(m_node);
        if (displacing && stkmesh != NULL)
            stkmesh->setIsDisplacement(displacing);

        m_frame_start = 0;
        m_frame_end = 0;

        if (World::getWorld() && World::getWorld()->getTrack() && xml_node)
            World::getWorld()->getTrack()
                             ->handleAnimatedTextures(m_node, *xml_node);
    }

    if(!enabled)
        m_node->setVisible(false);

    m_node->setPosition(m_init_xyz);
    m_node->setRotation(m_init_hpr);
    m_node->setScale(m_init_scale);
}   // init
Пример #6
0
/** Render the post-processed scene */
void PostProcessing::render()
{
    if (!irr_driver->isGLSL()) return;

    IVideoDriver * const drv = irr_driver->getVideoDriver();
    drv->setTransform(ETS_WORLD, core::IdentityMatrix);
    drv->setTransform(ETS_VIEW, core::IdentityMatrix);
    drv->setTransform(ETS_PROJECTION, core::IdentityMatrix);

    MotionBlurProvider * const mocb = (MotionBlurProvider *) irr_driver->
                                                           getCallback(ES_MOTIONBLUR);
    GaussianBlurProvider * const gacb = (GaussianBlurProvider *) irr_driver->
                                                                 getCallback(ES_GAUSSIAN3H);

    const u32 cams = Camera::getNumCameras();
    for(u32 cam = 0; cam < cams; cam++)
    {
        scene::ICameraSceneNode * const camnode =
            Camera::getCamera(cam)->getCameraSceneNode();
        mocb->setCurrentCamera(cam);
        ITexture *in = irr_driver->getRTT(RTT_COLOR);
        ITexture *out = irr_driver->getRTT(RTT_TMP1);
	// Each effect uses these as named, and sets them up for the next effect.
	// This allows chaining effects where some may be disabled.

	// As the original color shouldn't be touched, the first effect can't be disabled.

        PROFILER_PUSH_CPU_MARKER("- Bloom", 0xFF, 0x00, 0x00);
        if (1) // bloom
        {
			// Blit the base to tmp1
			drv->setRenderTarget(out, true, false);
			renderPassThrough(in);

            const bool globalbloom = World::getWorld()->getTrack()->getBloom();

            if (globalbloom)
            {
				drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);
				renderBloom(in);
            }


            if (globalbloom)
            {
                // Clear the alpha to a suitable value, stencil
                glClearColor(0, 0, 0, 0.1f);
                glColorMask(0, 0, 0, 1);

                glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

                glClearColor(0, 0, 0, 0);
                glColorMask(1, 1, 1, 1);

                // To half
                drv->setRenderTarget(irr_driver->getRTT(RTT_HALF1), true, false);
				renderPassThrough(irr_driver->getRTT(RTT_TMP3));


                // To quarter
				drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), true, false);
				renderPassThrough(irr_driver->getRTT(RTT_HALF1));
                
                // To eighth
				drv->setRenderTarget(irr_driver->getRTT(RTT_EIGHTH1), true, false);
				renderPassThrough(irr_driver->getRTT(RTT_QUARTER1));

                // Blur it for distribution.
				renderGaussian6Blur(irr_driver->getRTT(RTT_EIGHTH1), irr_driver->getRTT(RTT_EIGHTH2), 8.f / UserConfigParams::m_width, 8.f / UserConfigParams::m_height);

                // Additively blend on top of tmp1
				drv->setRenderTarget(out, false, false);
				renderBloomBlend(irr_driver->getRTT(RTT_EIGHTH1));
            } // end if bloom

            in = irr_driver->getRTT(RTT_TMP1);
            out = irr_driver->getRTT(RTT_TMP2);
        }
        PROFILER_POP_CPU_MARKER();

        PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00);
        if (m_sunpixels > 30)//World::getWorld()->getTrack()->hasGodRays() && ) // god rays
        {
            // Grab the sky
            drv->setRenderTarget(out, true, false);
//            irr_driver->getSceneManager()->drawAll(ESNRP_SKY_BOX);
            irr_driver->renderSkybox();

            // Set the sun's color
            const SColor col = World::getWorld()->getTrack()->getSunColor();
            ColorizeProvider * const colcb = (ColorizeProvider *) irr_driver->getCallback(ES_COLORIZE);
                colcb->setColor(col.getRed() / 255.0f, col.getGreen() / 255.0f, col.getBlue() / 255.0f);

            // The sun interposer
            STKMeshSceneNode *sun = irr_driver->getSunInterposer();
/*            sun->getMaterial(0).ColorMask = ECP_ALL;
            irr_driver->getSceneManager()->setCurrentRendertime(ESNRP_SOLID);*/
            irr_driver->getSceneManager()->drawAll(ESNRP_CAMERA);
            irr_driver->setPhase(GLOW_PASS);
            sun->render();

            //sun->getMaterial(0).ColorMask = ECP_NONE;

            // Fade to quarter

            drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), false, false);
            renderGodFade(getTextureGLuint(out), col);


            // Blur
			renderGaussian3Blur(irr_driver->getRTT(RTT_QUARTER1),
                                irr_driver->getRTT(RTT_QUARTER2),
                                4.f / UserConfigParams::m_width,
                                4.f / UserConfigParams::m_height);



            // Calculate the sun's position in texcoords
            const core::vector3df pos = sun->getPosition();
            float ndc[4];
            core::matrix4 trans = camnode->getProjectionMatrix();
            trans *= camnode->getViewMatrix();

            trans.transformVect(ndc, pos);

            const float texh = m_vertices[cam].v1.TCoords.Y - m_vertices[cam].v0.TCoords.Y;
            const float texw = m_vertices[cam].v3.TCoords.X - m_vertices[cam].v0.TCoords.X;

            const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw;
            const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh;

//            ((GodRayProvider *) irr_driver->getCallback(ES_GODRAY))->
//                setSunPosition(sunx, suny);

            // Rays please
            drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER2), true, false);
            renderGodRay(getTextureGLuint(irr_driver->getRTT(RTT_QUARTER1)), core::vector2df(sunx, suny));

            // Blur
            renderGaussian3Blur(irr_driver->getRTT(RTT_QUARTER2),
                irr_driver->getRTT(RTT_QUARTER1),
                4.f / UserConfigParams::m_width,
                4.f / UserConfigParams::m_height);

            // Blend
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE);
            glBlendEquation(GL_FUNC_ADD);

            drv->setRenderTarget(in, false, false);
            renderPassThrough(irr_driver->getRTT(RTT_QUARTER2));
        }
        PROFILER_POP_CPU_MARKER();

        if (UserConfigParams::m_motionblur && m_any_boost) // motion blur
        {
            PROFILER_PUSH_CPU_MARKER("- Motion blur", 0xFF, 0x00, 0x00);
            renderMotionBlur(cam, in, out);
            ITexture *tmp = in;
            in = out;
            out = tmp;
            PROFILER_POP_CPU_MARKER();
        }

        if (irr_driver->getDisplacingNodes().size()) // Displacement
        {
            PROFILER_PUSH_CPU_MARKER("- Displacement", 0xFF, 0x00, 0x00);
			drv->setRenderTarget(out, true, false);
			renderPPDisplace(in);

            ITexture *tmp = in;
            in = out;
            out = tmp;
            PROFILER_POP_CPU_MARKER();
        }

/*        m_material.MaterialType = irr_driver->getShader(ES_RAIN);
        drv->setMaterial(m_material);
        static_cast<irr::video::COpenGLDriver*>(drv)->setRenderStates3DMode();*/

        if (UserConfigParams::m_mlaa) // MLAA. Must be the last pp filter.
        {
            PROFILER_PUSH_CPU_MARKER("- MLAA", 0xFF, 0x00, 0x00);
            drv->setRenderTarget(out, false, false);

            glEnable(GL_STENCIL_TEST);
            glClearColor(0.0, 0.0, 0.0, 1.0);
            glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
            glStencilFunc(GL_ALWAYS, 1, ~0);
            glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

            // Pass 1: color edge detection
            m_material.setFlag(EMF_BILINEAR_FILTER, false);
            m_material.setFlag(EMF_TRILINEAR_FILTER, false);
            m_material.MaterialType = irr_driver->getShader(ES_MLAA_COLOR1);
            m_material.setTexture(0, in);

            drawQuad(cam, m_material);
            m_material.setFlag(EMF_BILINEAR_FILTER, true);
            m_material.setFlag(EMF_TRILINEAR_FILTER, true);

            glStencilFunc(GL_EQUAL, 1, ~0);
            glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

            // Pass 2: blend weights
            drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);

            m_material.MaterialType = irr_driver->getShader(ES_MLAA_BLEND2);
            m_material.setTexture(0, out);
            m_material.setTexture(1, m_areamap);
            m_material.TextureLayer[1].BilinearFilter = false;
            m_material.TextureLayer[1].TrilinearFilter = false;

            drawQuad(cam, m_material);

            m_material.TextureLayer[1].BilinearFilter = true;
            m_material.TextureLayer[1].TrilinearFilter = true;
            m_material.setTexture(1, 0);

            // Pass 3: gather
            drv->setRenderTarget(in, false, false);

            m_material.setFlag(EMF_BILINEAR_FILTER, false);
            m_material.setFlag(EMF_TRILINEAR_FILTER, false);
            m_material.MaterialType = irr_driver->getShader(ES_MLAA_NEIGH3);
            m_material.setTexture(0, irr_driver->getRTT(RTT_TMP3));
            m_material.setTexture(1, irr_driver->getRTT(RTT_COLOR));

            drawQuad(cam, m_material);

            m_material.setFlag(EMF_BILINEAR_FILTER, true);
            m_material.setFlag(EMF_TRILINEAR_FILTER, true);
            m_material.setTexture(1, 0);

            // Done.
            glDisable(GL_STENCIL_TEST);
            PROFILER_POP_CPU_MARKER();
        }

        // Final blit
		// TODO : Use glBlitFramebuffer
		drv->setRenderTarget(ERT_FRAME_BUFFER, false, false);
        if (irr_driver->getNormals())
			renderPassThrough(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH));
        else if (irr_driver->getSSAOViz())
			renderPassThrough(irr_driver->getRTT(RTT_SSAO));
        else
			renderColorLevel(in);
    }
}   // render