Ejemplo n.º 1
0
/** 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);
}
Ejemplo n.º 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);
}