Exemple #1
0
void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
{
    static_cast<scene::CSceneManager *>(m_scene_manager)->OnAnimate(os::Timer::getTime());
    camnode->render();
    irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
    irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
    irr_driver->genProjViewMatrix();

    m_current_screen_size = core::vector2df(float(width), float(height));

    const float oldfar = camnode->getFarValue();
    const float oldnear = camnode->getNearValue();
    float FarValues[] =
    {
        6.,
        21.,
        55.,
        150.,
    };
    float NearValues[] =
    {
        oldnear,
        5.,
        20.,
        50.,
    };


    float tmp[16 * 9 + 2];
    memcpy(tmp, irr_driver->getViewMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[16], irr_driver->getProjMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[32], irr_driver->getInvViewMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));

    const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix();
    for (unsigned i = 0; i < 4; i++)
    {
        if (!m_shadow_camnodes[i])
            m_shadow_camnodes[i] = (scene::ICameraSceneNode *) m_suncam->clone();
    }
    sun_ortho_matrix.clear();

    if (World::getWorld() && World::getWorld()->getTrack())
    {
        btVector3 btmin, btmax;
        if (World::getWorld()->getTrack()->getPtrTriangleMesh())
        {
            World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape().getAabb(btTransform::getIdentity(), btmin, btmax);
        }
        const Vec3 vmin = btmin , vmax = btmax;

        // Build the 3 ortho projection (for the 3 shadow resolution levels)
        for (unsigned i = 0; i < 4; i++)
        {
            camnode->setFarValue(FarValues[i]);
            camnode->setNearValue(NearValues[i]);
            camnode->render();
            const scene::SViewFrustum *frustrum = camnode->getViewFrustum();
            float tmp[24] = {
                frustrum->getFarLeftDown().X,
                frustrum->getFarLeftDown().Y,
                frustrum->getFarLeftDown().Z,
                frustrum->getFarLeftUp().X,
                frustrum->getFarLeftUp().Y,
                frustrum->getFarLeftUp().Z,
                frustrum->getFarRightDown().X,
                frustrum->getFarRightDown().Y,
                frustrum->getFarRightDown().Z,
                frustrum->getFarRightUp().X,
                frustrum->getFarRightUp().Y,
                frustrum->getFarRightUp().Z,
                frustrum->getNearLeftDown().X,
                frustrum->getNearLeftDown().Y,
                frustrum->getNearLeftDown().Z,
                frustrum->getNearLeftUp().X,
                frustrum->getNearLeftUp().Y,
                frustrum->getNearLeftUp().Z,
                frustrum->getNearRightDown().X,
                frustrum->getNearRightDown().Y,
                frustrum->getNearRightDown().Z,
                frustrum->getNearRightUp().X,
                frustrum->getNearRightUp().Y,
                frustrum->getNearRightUp().Z,
            };
            memcpy(m_shadows_cam[i], tmp, 24 * sizeof(float));
            const core::aabbox3df smallcambox = camnode->
                getViewFrustum()->getBoundingBox();
            core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
                core::vector3df(0, 30, 0));

            // Set up a nice ortho projection that contains our camera frustum
            core::aabbox3df box = smallcambox;
            box = box.intersect(trackbox);


            std::vector<vector3df> vectors;
            vectors.push_back(frustrum->getFarLeftDown());
            vectors.push_back(frustrum->getFarLeftUp());
            vectors.push_back(frustrum->getFarRightDown());
            vectors.push_back(frustrum->getFarRightUp());
            vectors.push_back(frustrum->getNearLeftDown());
            vectors.push_back(frustrum->getNearLeftUp());
            vectors.push_back(frustrum->getNearRightDown());
            vectors.push_back(frustrum->getNearRightUp());

/*            SunCamViewMatrix.transformBoxEx(trackbox);
            SunCamViewMatrix.transformBoxEx(box);

            core::vector3df extent = box.getExtent();
            const float w = fabsf(extent.X);
            const float h = fabsf(extent.Y);
            float z = box.MaxEdge.Z;

            // Snap to texels
            const float units_per_w = w / 1024;
            const float units_per_h = h / 1024;*/

            m_shadow_camnodes[i]->setProjectionMatrix(getTighestFitOrthoProj(SunCamViewMatrix, vectors) , true);
            m_shadow_camnodes[i]->render();

            sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
        }

        {
            core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
                core::vector3df(0, 30, 0));
            if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
                trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
                // Cover the case where SunCamViewMatrix is null
                SunCamViewMatrix.getScale() != core::vector3df(0., 0., 0.))
            {
                SunCamViewMatrix.transformBoxEx(trackbox);
                core::matrix4 tmp_matrix;
                tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X,
                    trackbox.MaxEdge.Y, trackbox.MinEdge.Y,
                    30, trackbox.MaxEdge.Z);
                m_suncam->setProjectionMatrix(tmp_matrix, true);
                m_suncam->render();
            }
            rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW);
        }
        rh_extend = core::vector3df(128, 64, 128);
        core::vector3df campos = camnode->getAbsolutePosition();
        core::vector3df translation(8 * floor(campos.X / 8), 8 * floor(campos.Y / 8), 8 * floor(campos.Z / 8));
        rh_matrix.setTranslation(translation);


        assert(sun_ortho_matrix.size() == 4);
        camnode->setNearValue(oldnear);
        camnode->setFarValue(oldfar);
        camnode->render();

        size_t size = irr_driver->getShadowViewProj().size();
        for (unsigned i = 0; i < size; i++)
            memcpy(&tmp[16 * i + 80], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
    }

    tmp[144] = float(width);
    tmp[145] = float(height);
    glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float), tmp);
}
Exemple #2
0
void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
{
    if (irr_driver->supportsSDSM())
        UpdateSplitAndLightcoordRangeFromComputeShaders(width, height);
    static_cast<scene::CSceneManager *>(m_scene_manager)->OnAnimate(os::Timer::getTime());
    camnode->render();
    irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
    irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
    irr_driver->genProjViewMatrix();

    m_current_screen_size = core::vector2df(float(width), float(height));

    const float oldfar = camnode->getFarValue();
    const float oldnear = camnode->getNearValue();
    float FarValues[] =
    {
        shadowSplit[1],
        shadowSplit[2],
        shadowSplit[3],
        shadowSplit[4],
    };
    float NearValues[] =
    {
        shadowSplit[0],
        shadowSplit[1],
        shadowSplit[2],
        shadowSplit[3]
    };


    float tmp[16 * 9 + 2];
    memcpy(tmp, irr_driver->getViewMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[16], irr_driver->getProjMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[32], irr_driver->getInvViewMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));

    m_suncam->render();
    const core::vector3df &camdir = (camnode->getTarget() - camnode->getAbsolutePosition()).normalize();
    const core::vector3df &sundir = (m_suncam->getTarget() - m_suncam->getAbsolutePosition()).normalize();
    const core::vector3df &up = camdir.crossProduct(sundir).normalize();
    if (up.getLength())
        m_suncam->setUpVector(up);
    m_suncam->render();

    for (unsigned i = 0; i < 4; i++)
    {
        if (m_shadow_camnodes[i])
            delete m_shadow_camnodes[i];
        m_shadow_camnodes[i] = (scene::ICameraSceneNode *) m_suncam->clone();
    }
    const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix();

    sun_ortho_matrix.clear();

    if (World::getWorld() && World::getWorld()->getTrack())
    {
        btVector3 btmin, btmax;
        if (World::getWorld()->getTrack()->getPtrTriangleMesh())
        {
            World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape().getAabb(btTransform::getIdentity(), btmin, btmax);
        }
        const Vec3 vmin = btmin , vmax = btmax;

        // Build the 3 ortho projection (for the 3 shadow resolution levels)
        for (unsigned i = 0; i < 4; i++)
        {
            if (!irr_driver->supportsSDSM())
            {
                camnode->setFarValue(FarValues[i]);
                camnode->setNearValue(NearValues[i]);
                camnode->render();
            }
            const scene::SViewFrustum *frustrum = camnode->getViewFrustum();
            float tmp[24] = {
                frustrum->getFarLeftDown().X,
                frustrum->getFarLeftDown().Y,
                frustrum->getFarLeftDown().Z,
                frustrum->getFarLeftUp().X,
                frustrum->getFarLeftUp().Y,
                frustrum->getFarLeftUp().Z,
                frustrum->getFarRightDown().X,
                frustrum->getFarRightDown().Y,
                frustrum->getFarRightDown().Z,
                frustrum->getFarRightUp().X,
                frustrum->getFarRightUp().Y,
                frustrum->getFarRightUp().Z,
                frustrum->getNearLeftDown().X,
                frustrum->getNearLeftDown().Y,
                frustrum->getNearLeftDown().Z,
                frustrum->getNearLeftUp().X,
                frustrum->getNearLeftUp().Y,
                frustrum->getNearLeftUp().Z,
                frustrum->getNearRightDown().X,
                frustrum->getNearRightDown().Y,
                frustrum->getNearRightDown().Z,
                frustrum->getNearRightUp().X,
                frustrum->getNearRightUp().Y,
                frustrum->getNearRightUp().Z,
            };
            memcpy(m_shadows_cam[i], tmp, 24 * sizeof(float));
            const core::aabbox3df smallcambox = camnode->
                getViewFrustum()->getBoundingBox();
            core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
                core::vector3df(0, 30, 0));

            // Set up a nice ortho projection that contains our camera frustum
            core::aabbox3df box = smallcambox;
            box = box.intersect(trackbox);

            std::vector<vector3df> vectors;
            vectors.push_back(frustrum->getFarLeftDown());
            vectors.push_back(frustrum->getFarLeftUp());
            vectors.push_back(frustrum->getFarRightDown());
            vectors.push_back(frustrum->getFarRightUp());
            vectors.push_back(frustrum->getNearLeftDown());
            vectors.push_back(frustrum->getNearLeftUp());
            vectors.push_back(frustrum->getNearRightDown());
            vectors.push_back(frustrum->getNearRightUp());

            core::matrix4 tmp_matrix;

            if (irr_driver->supportsSDSM()){
                float left = float(CBB[currentCBB][i].xmin / 4 - 2);
                float right = float(CBB[currentCBB][i].xmax / 4 + 2);
                float up = float(CBB[currentCBB][i].ymin / 4 - 2);
                float down = float(CBB[currentCBB][i].ymax / 4 + 2);

                // Prevent Matrix without extend
                if (left != right && up != down)
                {
                    tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
                        down, up,
                        float(CBB[currentCBB][i].zmin / 4 - 100),
                        float(CBB[currentCBB][i].zmax / 4 + 2));
                    m_shadow_scales[i] = std::make_pair(right - left, down - up);
                }
            }
            else
                tmp_matrix = getTighestFitOrthoProj(SunCamViewMatrix, vectors, m_shadow_scales[i]);

            m_shadow_camnodes[i]->setProjectionMatrix(tmp_matrix , true);
            m_shadow_camnodes[i]->render();

            sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
        }

        if (!m_rsm_matrix_initialized)
        {
            core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
                core::vector3df(0, 30, 0));
            if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
                trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
                // Cover the case where SunCamViewMatrix is null
                SunCamViewMatrix.getScale() != core::vector3df(0., 0., 0.))
            {
                SunCamViewMatrix.transformBoxEx(trackbox);
                core::matrix4 tmp_matrix;
                tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X,
                    trackbox.MaxEdge.Y, trackbox.MinEdge.Y,
                    30, trackbox.MaxEdge.Z);
                m_suncam->setProjectionMatrix(tmp_matrix, true);
                m_suncam->render();
            }
            rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW);
            m_rsm_matrix_initialized = true;
            m_rsm_map_available = false;
        }
        rh_extend = core::vector3df(128, 64, 128);
        core::vector3df campos = camnode->getAbsolutePosition();
        core::vector3df translation(8 * floor(campos.X / 8), 8 * floor(campos.Y / 8), 8 * floor(campos.Z / 8));
        rh_matrix.setTranslation(translation);


        assert(sun_ortho_matrix.size() == 4);
        camnode->setNearValue(oldnear);
        camnode->setFarValue(oldfar);
        camnode->render();

        size_t size = irr_driver->getShadowViewProj().size();
        for (unsigned i = 0; i < size; i++)
            memcpy(&tmp[16 * i + 80], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
    }

    tmp[144] = float(width);
    tmp[145] = float(height);
    glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float), tmp);
}
/** Generate View, Projection, Inverse View, Inverse Projection, ViewProjection and InverseProjection matrixes
and matrixes and cameras for the four shadow cascade and RSM.
*   \param camnode point of view used
*   \param width of the rendering viewport
*   \param height of the rendering viewport
*/
void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
{
    if (CVS->isSDSMEnabled())
        UpdateSplitAndLightcoordRangeFromComputeShaders(width, height);
    static_cast<scene::CSceneManager *>(m_scene_manager)->OnAnimate(os::Timer::getTime());
    camnode->render();
    irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
    irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
    irr_driver->genProjViewMatrix();

    m_current_screen_size = core::vector2df(float(width), float(height));

    const float oldfar = camnode->getFarValue();
    const float oldnear = camnode->getNearValue();
    float FarValues[] =
    {
        shadowSplit[1],
        shadowSplit[2],
        shadowSplit[3],
        shadowSplit[4],
    };
    float NearValues[] =
    {
        shadowSplit[0],
        shadowSplit[1],
        shadowSplit[2],
        shadowSplit[3]
    };

    float tmp[16 * 9 + 2];
    memcpy(tmp, irr_driver->getViewMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[16], irr_driver->getProjMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[32], irr_driver->getInvViewMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float));
    memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));

    m_suncam->render();
    for (unsigned i = 0; i < 4; i++)
    {
        if (m_shadow_camnodes[i])
            delete m_shadow_camnodes[i];
        m_shadow_camnodes[i] = (scene::ICameraSceneNode *) m_suncam->clone();
    }
    sun_ortho_matrix.clear();
    const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix();

    if (World::getWorld() && World::getWorld()->getTrack())
    {
        // Compute track extent
        btVector3 btmin, btmax;
        if (World::getWorld()->getTrack()->getPtrTriangleMesh())
        {
            World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape().getAabb(btTransform::getIdentity(), btmin, btmax);
        }
        const Vec3 vmin = btmin, vmax = btmax;
        core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
            core::vector3df(0, 30, 0));

        // Shadow Matrixes and cameras
        for (unsigned i = 0; i < 4; i++)
        {
            core::matrix4 tmp_matrix;

            camnode->setFarValue(FarValues[i]);
            camnode->setNearValue(NearValues[i]);
            camnode->render();
            const scene::SViewFrustum *frustrum = camnode->getViewFrustum();
            float tmp[24] = {
                frustrum->getFarLeftDown().X,
                frustrum->getFarLeftDown().Y,
                frustrum->getFarLeftDown().Z,
                frustrum->getFarLeftUp().X,
                frustrum->getFarLeftUp().Y,
                frustrum->getFarLeftUp().Z,
                frustrum->getFarRightDown().X,
                frustrum->getFarRightDown().Y,
                frustrum->getFarRightDown().Z,
                frustrum->getFarRightUp().X,
                frustrum->getFarRightUp().Y,
                frustrum->getFarRightUp().Z,
                frustrum->getNearLeftDown().X,
                frustrum->getNearLeftDown().Y,
                frustrum->getNearLeftDown().Z,
                frustrum->getNearLeftUp().X,
                frustrum->getNearLeftUp().Y,
                frustrum->getNearLeftUp().Z,
                frustrum->getNearRightDown().X,
                frustrum->getNearRightDown().Y,
                frustrum->getNearRightDown().Z,
                frustrum->getNearRightUp().X,
                frustrum->getNearRightUp().Y,
                frustrum->getNearRightUp().Z,
            };
            memcpy(m_shadows_cam[i], tmp, 24 * sizeof(float));

            std::vector<vector3df> vectors = getFrustrumVertex(*frustrum);
            tmp_matrix = getTighestFitOrthoProj(SunCamViewMatrix, vectors, m_shadow_scales[i]);


            m_shadow_camnodes[i]->setProjectionMatrix(tmp_matrix, true);
            m_shadow_camnodes[i]->render();

            sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
        }

        // Rsm Matrix and camera
        if (!m_rsm_matrix_initialized)
        {
            if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
                trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
                // Cover the case where SunCamViewMatrix is null
                SunCamViewMatrix.getScale() != core::vector3df(0., 0., 0.))
            {
                SunCamViewMatrix.transformBoxEx(trackbox);
                core::matrix4 tmp_matrix;
                tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X,
                    trackbox.MaxEdge.Y, trackbox.MinEdge.Y,
                    30, trackbox.MaxEdge.Z);
                m_suncam->setProjectionMatrix(tmp_matrix, true);
                m_suncam->render();
            }
            rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW);
            m_rsm_matrix_initialized = true;
            m_rsm_map_available = false;
        }
        rh_extend = core::vector3df(128, 64, 128);
        core::vector3df campos = camnode->getAbsolutePosition();
        core::vector3df translation(8 * floor(campos.X / 8), 8 * floor(campos.Y / 8), 8 * floor(campos.Z / 8));
        rh_matrix.setTranslation(translation);


        assert(sun_ortho_matrix.size() == 4);
        // reset normal camera
        camnode->setNearValue(oldnear);
        camnode->setFarValue(oldfar);
        camnode->render();

        size_t size = irr_driver->getShadowViewProj().size();
        for (unsigned i = 0; i < size; i++)
            memcpy(&tmp[16 * i + 80], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
    }

    tmp[144] = float(width);
    tmp[145] = float(height);
    glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
    if (CVS->isSDSMEnabled())
    {
        glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 5) * sizeof(float), tmp);
        glBufferSubData(GL_UNIFORM_BUFFER, (16 * 9) * sizeof(float), 2 * sizeof(float), &tmp[144]);
    }
    else
        glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float), tmp);
}
Exemple #4
0
void IrrDriver::renderShadows(//ShadowImportanceProvider * const sicb,
                              scene::ICameraSceneNode * const camnode,
                              //video::SOverrideMaterial &overridemat,
                              Camera * const camera)
{
    m_scene_manager->setCurrentRendertime(scene::ESNRP_SOLID);

    const Vec3 *vmin, *vmax;
    World::getWorld()->getTrack()->getAABB(&vmin, &vmax);

    const float oldfar = camnode->getFarValue();
    const float oldnear = camnode->getNearValue();
    float FarValues[] =
    {
        20.,
        50.,
        100.,
        oldfar,
    };
    float NearValues[] =
    {
        oldnear,
        20.,
        50.,
        100.,
    };

    const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix();
    sun_ortho_matrix.clear();

    // Build the 3 ortho projection (for the 3 shadow resolution levels)
    for (unsigned i = 0; i < 4; i++)
    {
        camnode->setFarValue(FarValues[i]);
        camnode->setNearValue(NearValues[i]);
        camnode->render();
        const core::aabbox3df smallcambox = camnode->
            getViewFrustum()->getBoundingBox();
        core::aabbox3df trackbox(vmin->toIrrVector(), vmax->toIrrVector() -
            core::vector3df(0, 30, 0));


        // Set up a nice ortho projection that contains our camera frustum
        core::aabbox3df box = smallcambox;
        box = box.intersect(trackbox);


        SunCamViewMatrix.transformBoxEx(trackbox);
        SunCamViewMatrix.transformBoxEx(box);

        core::vector3df extent = trackbox.getExtent();
        const float w = fabsf(extent.X);
        const float h = fabsf(extent.Y);
        float z = box.MaxEdge.Z;

        // Snap to texels
        const float units_per_w = w / 1024;
        const float units_per_h = h / 1024;

        float left = box.MinEdge.X;
        float right = box.MaxEdge.X;
        float up = box.MaxEdge.Y;
        float down = box.MinEdge.Y;

        left -= fmodf(left, units_per_w);
        right -= fmodf(right, units_per_w);
        up -= fmodf(up, units_per_h);
        down -= fmodf(down, units_per_h);
        z -= fmodf(z, 0.5f);

        // FIXME: quick and dirt (and wrong) workaround to avoid division by zero
        if (left == right) right += 0.1f;
        if (up == down) down += 0.1f;
        if (z == 30) z += 0.1f;

        core::matrix4 tmp_matrix;

        tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
            up, down,
            30, z);
        m_suncam->setProjectionMatrix(tmp_matrix, true);
        m_scene_manager->setActiveCamera(m_suncam);
        m_suncam->render();

        sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
    }
    assert(sun_ortho_matrix.size() == 4);

    irr_driver->setPhase(SHADOW_PASS);
    glDisable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_FRONT);
    glBindFramebuffer(GL_FRAMEBUFFER, m_rtts->getShadowFBO());
    glViewport(0, 0, 1024, 1024);
    glClear(GL_DEPTH_BUFFER_BIT);
    glDrawBuffer(GL_NONE);
    m_scene_manager->drawAll(scene::ESNRP_SOLID);
    glCullFace(GL_BACK);

    camnode->setNearValue(oldnear);
    camnode->setFarValue(oldfar);
    camnode->render();
    camera->activate();
    m_scene_manager->drawAll(scene::ESNRP_CAMERA);


    //sun_ortho_matrix *= m_suncam->getViewMatrix();
/*    ((SunLightProvider *) m_shaders->m_callbacks[ES_SUNLIGHT])->setShadowMatrix(ortho);
    sicb->setShadowMatrix(ortho);

    overridemat.Enabled = 0;

    // Render the importance map
    m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_COLLAPSE), true, true);

    m_shadow_importance->render();

    CollapseProvider * const colcb = (CollapseProvider *)
                                            m_shaders->
                                            m_callbacks[ES_COLLAPSE];
    ScreenQuad sq(m_video_driver);
    sq.setMaterialType(m_shaders->getShader(ES_COLLAPSE));
    sq.setTexture(m_rtts->getRTT(RTT_COLLAPSE));
    sq.getMaterial().setFlag(EMF_BILINEAR_FILTER, false);

    const TypeRTT oldh = tick ? RTT_COLLAPSEH : RTT_COLLAPSEH2;
    const TypeRTT oldv = tick ? RTT_COLLAPSEV : RTT_COLLAPSEV2;
    const TypeRTT curh = tick ? RTT_COLLAPSEH2 : RTT_COLLAPSEH;
    const TypeRTT curv = tick ? RTT_COLLAPSEV2 : RTT_COLLAPSEV;

    colcb->setResolution(1, m_rtts->getRTT(RTT_WARPV)->getSize().Height);
    sq.setTexture(m_rtts->getRTT(oldh), 1);
    sq.render(m_rtts->getRTT(RTT_WARPH));

    colcb->setResolution(m_rtts->getRTT(RTT_WARPV)->getSize().Height, 1);
    sq.setTexture(m_rtts->getRTT(oldv), 1);
    sq.render(m_rtts->getRTT(RTT_WARPV));

    sq.setTexture(0, 1);
    ((GaussianBlurProvider *) m_shaders->m_callbacks[ES_GAUSSIAN3H])->setResolution(
                m_rtts->getRTT(RTT_WARPV)->getSize().Height,
                m_rtts->getRTT(RTT_WARPV)->getSize().Height);

    sq.setMaterialType(m_shaders->getShader(ES_GAUSSIAN6H));
    sq.setTexture(m_rtts->getRTT(RTT_WARPH));
    sq.render(m_rtts->getRTT(curh));

    sq.setMaterialType(m_shaders->getShader(ES_GAUSSIAN6V));
    sq.setTexture(m_rtts->getRTT(RTT_WARPV));
    sq.render(m_rtts->getRTT(curv));*/

    // Convert importance maps to warp maps
    //
    // It should be noted that while they do repeated work
    // calculating the min, max, and total, it's several hundred us
    // faster to do that than to do it once in a separate shader
    // (shader switch overhead, measured).
    /*colcb->setResolution(m_rtts->getRTT(RTT_WARPV)->getSize().Height,
                            m_rtts->getRTT(RTT_WARPV)->getSize().Height);

    sq.setMaterialType(m_shaders->getShader(ES_SHADOW_WARPH));
    sq.setTexture(m_rtts->getRTT(curh));
    sq.render(m_rtts->getRTT(RTT_WARPH));

    sq.setMaterialType(m_shaders->getShader(ES_SHADOW_WARPV));
    sq.setTexture(m_rtts->getRTT(curv));
    sq.render(m_rtts->getRTT(RTT_WARPV));*/

    // Actual shadow map


/*    overridemat.Material.MaterialType = m_shaders->getShader(ES_SHADOWPASS);
    overridemat.EnableFlags = video::EMF_MATERIAL_TYPE | video::EMF_TEXTURE1 |
                                video::EMF_TEXTURE2;
    overridemat.EnablePasses = scene::ESNRP_SOLID;
    overridemat.Material.setTexture(1, m_rtts->getRTT(RTT_WARPH));
    overridemat.Material.setTexture(2, m_rtts->getRTT(RTT_WARPV));
    overridemat.Material.TextureLayer[1].TextureWrapU =
    overridemat.Material.TextureLayer[1].TextureWrapV =
    overridemat.Material.TextureLayer[2].TextureWrapU =
    overridemat.Material.TextureLayer[2].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
    overridemat.Material.TextureLayer[1].BilinearFilter =
    overridemat.Material.TextureLayer[2].BilinearFilter = true;
    overridemat.Material.TextureLayer[1].TrilinearFilter =
    overridemat.Material.TextureLayer[2].TrilinearFilter = false;
    overridemat.Material.TextureLayer[1].AnisotropicFilter =
    overridemat.Material.TextureLayer[2].AnisotropicFilter = 0;
    overridemat.Material.Wireframe = 1;
    overridemat.Enabled = true;*/



//    overridemat.EnablePasses = 0;
//    overridemat.Enabled = false;
}