void FBOViewport::render(DrawActionBase *action)
{
    if(getFrameBufferObject() != NULL)
    {
        DrawEnv oEnv;
        oEnv.setWindow(action->getWindow());

        getFrameBufferObject()->activate(&oEnv);

        Inherited::render(action);

        getFrameBufferObject()->deactivate(&oEnv);
    }
    else
    {
        Inherited::render(action);
    }
}
void OcclusionCullingTreeBuilder::drawTestResults(DrawEnv             &denv,
                                                  RenderPartitionBase *part)
{
    OCRenderTreeNode* pNode;
    while (!_testPendingNodes.empty())
    {
        pNode = _testPendingNodes.front();
        //DRAW DRAW DRAW
        if(pNode->hasFunctor() == true && !pNode->getIsRendered())
        {
            Window* win = denv.getWindow();
            GetQueryObjectuivT getquiv =
                reinterpret_cast<GetQueryObjectuivT>(
                    win->getFunction(_funcGetQueryObjectuivARB));
            GLuint available = 0;
            getquiv(_testSamples[pNode->getResultNum()], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
            if (!available)
            {
                //std::cout << "Waiting on " << pNode->getResultNum() << " buf size:" << _testPendingNodes.size() << std::endl;
                return;
            }
            GLuint sampleCount = 1;  //XXX: Set to what it should be from calc above.
            getquiv(_testSamples[pNode->getResultNum()], GL_QUERY_RESULT_ARB, &sampleCount);

            if(sampleCount > _visPixelThreshold)
            {
                drawNode(pNode, denv, part);
            }
            else
            {
                StatCollector *sc = _ract->getStatCollector();
                if(sc != NULL)
                    sc->getElem(statNOccInvisible)->inc();

                DrawableStatsAttachment *st =
                    DrawableStatsAttachment::get(pNode->getNode()->getCore());

                st->validate();

                if(sc != NULL)
                    sc->getElem(statNOccTriangles)->
                        add(st->getTriangles());

                if(_ract->getOcclusionCullingDebug() && pNode->getNode())
                {
                    pNode->getNode()->setTravMask(
                        pNode->getNode()->getTravMask() |
                        _ract->getOcclusionCulledDebugMask()
                        );
                }
            }
        }
        //std::cout << "Popped: " << pNode->getResultNum() << " buf size now: " << _testPendingNodes.size() - 1 <<  std::endl;
        _testPendingNodes.pop();
    }
}
Exemple #3
0
void StagedViewport::stretchTargetToFrameBuffer(RenderActionBase *action, FrameBufferObject *target)
{

    Window  *pWin = action->getWindow();

    if((pWin->getDrawMode() & Window::PartitionDrawMask) ==
        Window::SequentialPartitionDraw)
    {
        DrawEnv  oEnv;

        oEnv.setWindow(action->getWindow());

        //oEnv.setTileFullSize(getCamera()->tileGetFullSize());
        //oEnv.setTileRegion  (getCamera()->tileGetRegion  ());

        // THINKABOUTME KS:
        //oEnv.setDrawerId  (action->getDrawerId  ());
        //oEnv.setDrawableId(action->getDrawableId());

        glClearColor(0.0, 1.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);

        FrameBufferAttachment* fba = target->getColorAttachments(0);
        TextureObjChunk* texObj = dynamic_cast<TextureBuffer*>(fba)->getTexture();
        if( texObj )
        {
            texObj->activate(&oEnv,0);
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

            glMatrixMode(GL_PROJECTION);
            glPushMatrix();
            glLoadIdentity();
            glOrtho(0, 1, 0, 1, -1, 1 );
            glMatrixMode(GL_MODELVIEW);
            glPushMatrix();
            glLoadIdentity();

            float u = 0.0f;
            float v = 0.0f;

            //            glColor3f(1,1,1);
            glBegin(GL_QUADS);
#if 0
            RTsize w,h;
            buffer->getSize(w,h);
            float view[4];
            view[0] = _optixViewport._viewport.x/(float)w;
            view[1] = _optixViewport._viewport.y/(float)h;
            view[2] = view[0] + _optixViewport._viewport.z/(float)w;
            view[3] = view[1] + _optixViewport._viewport.w/(float)h;

            glTexCoord2f(view[0], view[1]);
            glVertex2f(0.0f, 0.0f);

            glTexCoord2f(view[2], view[1]);
            glVertex2f(1.0f, 0.0f);

            glTexCoord2f(view[2], view[3]);
            glVertex2f(1.0f, 1.0f);

            glTexCoord2f(view[0], view[3]);
            glVertex2f(0.0f, 1.0f);
#else
            glTexCoord2f(u, v);
            glVertex2f(0.1f, 0.1f);
            glTexCoord2f(1.0f, v);
            glVertex2f(.9f, 0.1f);
            glTexCoord2f(1.0f - u, 1.0f - v);
            glVertex2f(.9f, .9f);
            glTexCoord2f(u, 1.0f - v);
            glVertex2f(0.1f, .9f);
#endif
            glEnd();

            glMatrixMode(GL_PROJECTION);
            glPopMatrix();
            glMatrixMode(GL_MODELVIEW);
            glPopMatrix();

            texObj->deactivate(&oEnv,0);
        }
    }
    else
    {
        // TODO: ???
        OSG_ASSERT(false);
    }

}
void OcclusionCullingTreeBuilder::drawNode(OCRenderTreeNode   *pNode,
                                           DrawEnv             &denv,
                                           RenderPartitionBase *part)
{
    leaveTesting(denv, part);

    UInt32 uiNextMatrix = pNode->getMatrixStore().first;

    if(uiNextMatrix != 0 && uiNextMatrix != _uiActiveMatrix)
    {
        glLoadMatrixf(pNode->getMatrixStore().second.getValues());

        _uiActiveMatrix = uiNextMatrix;

        _currMatrix.second = pNode->getMatrixStore().second;

        updateTopMatrix(denv);

        denv.setObjectToWorld(_accMatrix);

        ++part->_uiNumMatrixChanges;
    }

    //STATE ACTIVATION
    State         *pNewState         = pNode->getState();
    StateOverride *pNewStateOverride = pNode->getStateOverride();

    denv.setLightState(pNode->getLightState());

    denv.activateState(pNewState, pNewStateOverride);

    pNode->setIsRendered(true);

    if(_ract->getOcclusionCullingDebug() && pNode->getNode())
    {
        pNode->getNode()->setTravMask(
            pNode->getNode()->getTravMask() |
            _ract->getOcclusionVisibleDebugMask()
            );
    }

    //DRAW DRAW DRAW

    if(pNode->hasFunctor() == true)
    {
        if(part->_bCorrectNegScale)
        {
            const Matrix &m = _currMatrix.second;

            // test for a "flipped" matrix
            // glFrontFace can give conflicts with the polygon chunk ...

            if(m[0].cross(m[1]).dot(m[2]) < 0.0)
            {
                glFrontFace(GL_CW);
            }
            else
            {
                glFrontFace(GL_CCW);
            }
        }

        //BoxVolume volume = pNode->getVol();
        //drawVolume(volume);
        pNode->getFunctor()(&denv);
    }
}
void OcclusionCullingTreeBuilder::drawTestNode(OCRenderTreeNode    *pNode,
                                               DrawEnv             &denv,
                                               RenderPartitionBase *part)
{

    //std::cout << "Front: " << _currSample << " Back: " << _currSampleBack << std::endl;
    while(_testPendingNodes.size() == _numTestSamples - 1)
    {
        drawTestResults(denv, part);
        //std::cout << "NOW:  Front: " << _currSample << " Back: " << _currSampleBack << std::endl;
    }

    //DRAW DRAW DRAW
    Window* win = denv.getWindow();
    pNode->setIsRendered(false);


    if(_ract->getOcclusionCullingDebug() && pNode->getNode())
    {
        pNode->getNode()->setTravMask(
            pNode->getNode()->getTravMask() |
            _ract->getOcclusionTestedDebugMask()
            );
    }

    const BoxVolume &volume = pNode->getVolume();
    Pnt3f min,max;
    volume.getBounds(min, max);
    static GLfloat n[6][3] = {
    {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
    {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
    };
    static GLint faces[6][4] = {
    { 0, 1, 2, 3}, { 3, 2, 6, 7}, { 7, 6, 5, 4},
    { 4, 5, 1, 0}, { 5, 6, 2, 1}, { 7, 4, 0, 3}
    };

    GLfloat v[8][3];
    v[0][0] = v[1][0] = v[2][0] = v[3][0] = min[0];
    v[4][0] = v[5][0] = v[6][0] = v[7][0] = max[0];
    v[0][1] = v[1][1] = v[4][1] = v[5][1] = min[1];
    v[2][1] = v[3][1] = v[6][1] = v[7][1] = max[1];
    v[0][2] = v[3][2] = v[4][2] = v[7][2] = min[2];
    v[1][2] = v[2][2] = v[5][2] = v[6][2] = max[2];


    if(_currSample == _numTestSamples - 1)
    {
        _currSample = 0;
    }
    _currSample++;

    StatCollector *sc = _ract->getStatCollector();
    if(sc != NULL)
        sc->getElem(statNOccTests    )->inc();

    enterTesting(denv, part);
    BeginQueryT beginq = reinterpret_cast<BeginQueryT>(
        win->getFunction(_funcBeginQueryARB));
    //std::cout << "Push: " << _currSample << std::endl;
    pNode->setResultNum(_currSample);
    beginq(GL_SAMPLES_PASSED_ARB, _testSamples[_currSample]);
    glBegin(GL_QUADS);
    for(UInt32 i = 0; i<6; i++)
    {
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][0]][0]);
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][1]][0]);
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][2]][0]);
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][3]][0]);
    }
    glEnd();

    EndQueryT endq = reinterpret_cast<EndQueryT>(
        win->getFunction(_funcEndQueryARB));

    endq(GL_SAMPLES_PASSED_ARB);
    _testPendingNodes.push(pNode);
}
void OcclusionCullingTreeBuilder::testNode(OCRenderTreeNode   *pNode,
                                           DrawEnv             &denv,
                                           RenderPartitionBase *part,
                                           Real32              &scr_percent)
{
    while (pNode != NULL)
    {
    //MATRIX SETUP
        UInt32 uiNextMatrix = pNode->getMatrixStore().first;

        if(uiNextMatrix != 0 && uiNextMatrix != _uiActiveMatrix)
        {
            glLoadMatrixf(pNode->getMatrixStore().second.getValues());

            _uiActiveMatrix = uiNextMatrix;

            _currMatrix.second = pNode->getMatrixStore().second;

            updateTopMatrix(denv);

            denv.setObjectToWorld(_accMatrix);

            ++part->_uiNumMatrixChanges;
        }

        const BoxVolume &volume = pNode->getVolume();
        Pnt3f min,max;

        volume.getBounds(min, max);
        Pnt3f p[8];
        p[0].setValues(min[0],min[1],min[2]);
        p[1].setValues(max[0],min[1],min[2]);
        p[2].setValues(min[0],max[1],min[2]);
        p[3].setValues(min[0],min[1],max[2]);
        p[4].setValues(max[0],max[1],min[2]);
        p[5].setValues(max[0],min[1],max[2]);
        p[6].setValues(min[0],max[1],max[2]);
        p[7].setValues(max[0],max[1],max[2]);

        //std::cout << "OtoW:" << std::endl;
        //std::cout << denv.getObjectToWorld() << std::endl;
        //std::cout << "WtoC:" << std::endl;
        //std::cout << worldToCam << std::endl;
        for(UInt32 i = 0; i<8;i++)
        {
           // std::cout << p[i] << "=>";
            denv.getObjectToWorld().mult    (p[i], p[i]);
            _worldToScreen         .multFull(p[i], p[i]);
            //std::cout << p[i] << "  ";
        }
        min=p[0];
        max=p[0];
        for(UInt32 i = 0; i<8; i++)
        {
           for(UInt32 j=0; j<2; j++)
           {
              if(p[i][j] < min[j])
              {
                min[j] = p[i][j];
              }
              if(p[i][j] > max[j])
              {
                max[j] = p[i][j];
              }
           }
        }
        max[0] = osgClamp(-1.f, max[0], 1.f);
        max[1] = osgClamp(-1.f, max[1], 1.f);
        min[0] = osgClamp(-1.f, min[0], 1.f);
        min[1] = osgClamp(-1.f, min[1], 1.f);

        // cbb is the percent of the screen real estate this would cover
        Real32 cbb = (max[0] - min[0]) * (max[1] - min[1]) / 4.f;

        //std::cout << cur_node << ":" << pix << " ";
        //std::cout << pNode->getScalar() << std::endl;

//Make decision

        if(pNode->hasFunctor() == false) //Nothing to do
        {
            //renderNode
            drawNode(pNode, denv, part);
        }
        else
        {
            //make decision
            //if(0 > 1)
            if(cbb > scr_percent) // Rendering major occluders
            {
                drawNode(pNode, denv, part);
                //scr_percent+=cbb;
            }
            else
            {

                Real32 pcov;
                pcov = sqrt(scr_percent) - sqrt(cbb);
                pcov *= pcov;
                //std::cout << "cbb:" << cbb << " scr_percent:" << scr_percent <<" pcov:" << pcov << std::endl;
                //if(scr_percent - pcov > 0.001)
                if(pcov > _coveredProbThreshold || cbb < 0.001) // If within threshold or reall small
                {
                    //Get triangles
                    DrawableStatsAttachment *st =
                        DrawableStatsAttachment::get(pNode->getNode()->getCore());
                    st->validate();
                    UInt32 triangles = st->getTriangles();

                    if(cbb * _vpWidth * _vpHeight < _minFeatureSize) //small feature culling
                    {
                        StatCollector *sc = _ract->getStatCollector();
                        if(sc != NULL)
                            sc->getElem(statNOccTriangles)->
                                add(triangles);
                        if(_ract->getOcclusionCullingDebug() && pNode->getNode())
                        {
                            pNode->getNode()->setTravMask(
                                pNode->getNode()->getTravMask() |
                                _ract->getOcclusionCulledDebugMask()
                                );
                        }
                        pNode->setIsRendered(true);
                    }
                    else if( triangles <= _minTriangleCount )
                    {
                        drawNode(pNode, denv, part);
                    }
                    else if((_testPendingNodes.size() == _numTestSamples - 1)) // Make sure we have room to draw a test
                    {
                        drawTestResults(denv, part);
                        if(_testPendingNodes.size() == _numTestSamples - 1) // If we are waiting on a result, draw a node
                        {
                            drawNode(pNode, denv, part);
                        }
                        else
                        {
                            drawTestNode(pNode, denv, part); // Made room, go ahead and draw a test node
                        }
                    }
                    else
                    {
                        drawTestNode(pNode, denv, part); //Plenty of room in buffer to draw a test node
                    }
                }
                else
                {
                    drawNode(pNode, denv, part); // Probably not being covered up...draw the real node
                    //scr_percent+=cbb;
                }
            }
            scr_percent += ((1.0 - scr_percent) * cbb);
        }

//DRAW CHILDREN OR GO TO TOP AND DO IT AGAIN
        if(pNode->getFirstChild() != NULL)
        {
            OCRenderTreeNode *child =
                static_cast<OCRenderTreeNode *>(pNode->getFirstChild());

            testNode(child, denv, part, scr_percent);
        }

        pNode = static_cast<OCRenderTreeNode *>(pNode->getBrother());
    }
}
void OcclusionCullingTreeBuilder::draw(DrawEnv             &denv,
                                       RenderPartitionBase *part)
{
#if 1 //CHECK_ENV_ACTION
    //std::cout << "Frame Start" << std::endl;
    Window* win = denv.getWindow();

    if(_sortMode == ModeAdaptiveBucket)
    {
        // Merge all the buckets to a tree
        for(UInt32 i = 0; i < _numBuckets; ++i)
        {
            if(_buckets[i] != NULL)
            {
                _pRoot->addChild(_buckets[i]);
            }
        }
    }

    if(!win->hasExtension(_extOcclusionQuery))
    {
        // Don't have it, just draw the whole tree.
        SLOG << "Missing OCC GL extensions!!" << endLog;

        _uiActiveMatrix = 0;
        Inherited::drawNode(_pRoot, denv, part);

        return;
    }

//SETUP
// done in add, action should never change
//    _ract = dynamic_cast<RenderAction*>(denv.getAction());

    if(!_ract)
    {
        FFATAL(("OcclusionCullingTreeBuilder::draw: Action in denv is not a "
                "RenderAction!\n"));
        return;
    }

    _uiActiveMatrix = 0;
    Real32 screenCoveredPercentage = 0.f;
    if(_ract->getOcclusionCullingQueryBufferSize() != _numTestSamples || !_occInitialized)
    {
        _numTestSamples = _ract->getOcclusionCullingQueryBufferSize();
        //std::cout << "Buf size: " << _numTestSamples << std::endl;
        _testSamples.resize(_numTestSamples);
        //std::cout << "Performing OCC on " << _numNodes << " nodes." << std::endl;

        GenQueryT genquer = reinterpret_cast<GenQueryT>(
            win->getFunction(_funcGenQueriesARB));
        genquer(_numTestSamples, &(_testSamples.front()));
        _occInitialized = true;
    }

    if(!_isOccStateCreated)
    {
        _isOccStateCreated = true;

        // register an exit function to clean up the State object
        addPreFactoryExitFunction(&releaseTestingState);

        // Create an empty state to render test nodes.
        _testingStatePtr = State::create();

        DepthChunkUnrecPtr dc = DepthChunk::create();
        dc->setReadOnly(true);
        _testingStatePtr->addChunk(dc);

        ColorMaskChunkUnrecPtr cc = ColorMaskChunk::create();
        cc->setMaskR(false);
        cc->setMaskG(false);
        cc->setMaskB(false);
        cc->setMaskA(false);
        _testingStatePtr->addChunk(cc);

        PolygonChunkUnrecPtr pc = PolygonChunk::create();
        pc->setCullFace(GL_BACK);
        _testingStatePtr->addChunk(pc);

        commitChanges();
    }

    //glGenQueriesARB(_numNodes, queries);
    //std::cout << "Calculated Pixels" << std::endl;

    _vpWidth  = denv.getPixelWidth();
    _vpHeight = denv.getPixelHeight();

    _worldToScreen = denv.getVPWorldToScreen();

    _testingState = &*_testingStatePtr;


    _minFeatureSize = _ract->getOcclusionCullingMinimumFeatureSize();
    _visPixelThreshold = _ract->getOcclusionCullingVisibilityThreshold();
    _coveredProbThreshold = _ract->getOcclusionCullingCoveredThreshold();
    _minTriangleCount = _ract->getOcclusionCullingMinimumTriangleCount();
    _inTesting = false;

    _currSample = 0;
//DRAW / TEST / RE-DRAW ON BUFFER FULL
    testNode(_pRoot, denv, part, screenCoveredPercentage);

    StatCollector *sc = _ract->getStatCollector();
    if(sc != NULL)
        sc->getElem(statNOccNodes)->add(_numNodes);
    _numNodes=0;
    _uiActiveMatrix = 0;

    leaveTesting(denv, part);

//RESULTS / RE-DRAW
    while( !_testPendingNodes.empty() )
    {
        drawTestResults(denv, part);
    }

    //std::cout << "Calc Pixels" << std::endl;


    if(sc != NULL)
    {
        Real32 percentage =
            Real32(sc->getElem(statNOccInvisible)->get()) /
            Real32(sc->getElem(statNOccTests)->get());
        sc->getElem(statNOccSuccessTestPer)->set(percentage);
    }

    //std::cout << "Real pixels " << std::endl;
    //std::cout << std::endl;

   // screen_covered_percentage = 1.0;
   // drawNode(_pRoot, denv, part, screen_covered_percentage);
    _numNodes=0;
    _currSample = 0;
    //std::cout << "Frame End" << std::endl;
#endif
}
void SortLastWindow::clientRender(RenderActionBase *action)
{
    UInt32          p;
    UInt32          groupId = getMFServers()->size32();

    if(getMFServers()->size())
    {
        if(getClientWindow() != NULL)
        {
            setupNodes(groupId);
/*
            getClientWindow()->activate();
            getClientWindow()->frameInit();
*/
            action->setWindow(getClientWindow());

            if(getComposer() != NULL)
                getComposer()->startFrame();

            DrawEnv oEnv;
            
            oEnv.setWindow(action->getWindow());

            // render all viewports
            for(p = 0; p < getMFPort()->size() ; ++p)
            {
                Viewport *vp=getPort(p);

                oEnv.setViewportDimension(vp->calcPixelLeft   (),
                                          vp->calcPixelBottom (),
                                          vp->calcPixelRight  (),
                                          vp->calcPixelTop    (),
                                          vp->calcIsFullWindow());
                if(getComposer() != NULL)
                {
                    getComposer()->startViewport(vp);

                    action->setCamera    (vp->getCamera    ());
                    action->setBackground(vp->getBackground());
                    action->setViewarea  (vp                 );
                    action->setTravMask  (vp->getTravMask  ());

                    action->apply(vp->getRoot());

                    for(UInt16 i=0; i < vp->getMFForegrounds()->size(); i++)
                    {
                        if(dynamic_cast<StatisticsForeground *>(
                               vp->getForegrounds(i)) == NULL)
                        {
                            vp->getForegrounds(i)->draw(&oEnv);
                        }
                    }

                    getComposer()->composeViewport(vp);

                    for(UInt16 i=0; i < vp->getMFForegrounds()->size(); i++)
                    {
                        if(dynamic_cast<StatisticsForeground *>(
                               vp->getForegrounds(i)) != NULL)
                        {
                            vp->getForegrounds(i)->draw(&oEnv);
                        }
                    }

                }
                else
                {
                    vp->render(action);
                }
            }

            // compose whole window
            if(getComposer() != NULL)
                getComposer()->composeWindow();
        }
    }
}
/*! client rendering
 */
void SortLastWindow::clientRender(DrawActionBase *action)
{
    UInt32          p;
    UInt32          groupId = getServers().size();
    UInt32          l,b,r,t;
    UInt32          front,back;
    SortLastWindow *clusterWindow(this);

    if(getServers().size())
    {
        Connection *srcConnection=
            getNetwork()->getConnection(groupId);
        
        if(getClientWindow() != NULL)
        {
            setupNodes(groupId);
/*
            getClientWindow()->activate();
            getClientWindow()->frameInit();
*/
            action->setWindow(getClientWindow());

            if(getComposer() != NULL)
                getComposer()->startFrame();

            DrawEnv oEnv;
            
            oEnv.setWindow(action->getWindow());

            // render all viewports
            for(p = 0; p < getPort().size() ; ++p)
            {
                Viewport *vp=getPort()[p];
                if(getComposer() != NULL)
                {
                    getComposer()->startViewport(vp);

                    action->setCamera    (vp->getCamera    ());
                    action->setBackground(vp->getBackground());
                    action->setViewport  (vp                 );
                    action->setTravMask  (vp->getTravMask  ());

                    action->apply(vp->getRoot());

                    for(UInt16 i=0; i < vp->getForegrounds().size(); i++)
                    {
                        if(dynamic_cast<StatisticsForeground *>(
                               vp->getForegrounds(i)) == NULL)
                        {
                            vp->getForegrounds(i)->draw(&oEnv, vp);
                        }
                    }

                    getComposer()->composeViewport(vp);

                    for(UInt16 i=0; i < vp->getForegrounds().size(); i++)
                    {
                        if(dynamic_cast<StatisticsForeground *>(
                               vp->getForegrounds(i)) != NULL)
                        {
                            vp->getForegrounds(i)->draw(&oEnv, vp);
                        }
                    }

                }
                else
                {
                    vp->render(action);
                }
            }

            // compose whole window
            if(getComposer() != NULL)
                getComposer()->composeWindow();
        }
    }
}