Esempio n. 1
0
  int onDraw(int width, int height) {
    logic(width,height);

    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    lxCVector4 lightpos(0,0,0,1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

    m_rh.updateProjection(width,height);
    m_rh.setCameraGL();
    lxgContext_clearVertexState(&m_ctx);

    glBindTexture(GL_TEXTURE_2D,m_texture);
    glEnable(GL_TEXTURE_2D);
    
    lxgContext_checkedVertexDecl(&m_ctx, &m_vdecl);
    lxgContext_setVertexStream(&m_ctx, 0, &m_stream);
    lxgContext_checkedVertexFIXED(&m_ctx);
    lxgContext_checkedVertexAttribFIXED(&m_ctx, m_vattribs);
    lxgBuffer_bind(&m_ibo, LUXGL_BUFFER_INDEX);
    glDrawElements(GL_TRIANGLES, m_box.numIndicesTris(), GL_UNSIGNED_INT, NULL);

    glDisable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,0);

    return 0;
  }
Esempio n. 2
0
void config::

init_uniforms() {

   glm::vec3 lightpos(0.0,0.0,5.0);

   pipeline_.uniforms_.set("lightpos", lightpos);

   init_perspective();

   pipeline_.set_link("glyph","perspective_view");
   pipeline_.set_link("glyph","lightpos");
   pipeline_.set_link("streamline","perspective_view");
   pipeline_.set_link("bounding_box","perspective_view");
}
Esempio n. 3
0
void GSShadow::DrawScene()
{
  AmjuGL::SetClearColour(Colour(0, 0, 1, 1));

////  GSBase::Draw();

  float dt = TheTimer::Instance()->GetDt();

  // MV matrix is set up
  static float r = 0;
  r += 20.0f * dt;
  AmjuGL::RotateY(r);

  static float s = 0;
  s += dt;

  Vec3f lightpos(20, 20, 20); //5.0f * cos(s), 5.0f, 5.0f * sin(s));
  GetSG()->DrawShadows(lightpos);
}
Esempio n. 4
0
int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc, argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("--positionalLight", "Use a positional light.");
    arguments.getApplicationUsage()->addCommandLineOption("--directionalLight", "Use a direction light.");
    arguments.getApplicationUsage()->addCommandLineOption("--noUpdate", "Disable the updating the of light source.");

    arguments.getApplicationUsage()->addCommandLineOption("--castsShadowMask", "Override default castsShadowMask (default - 0x2)");
    arguments.getApplicationUsage()->addCommandLineOption("--receivesShadowMask", "Override default receivesShadowMask (default - 0x1)");

    arguments.getApplicationUsage()->addCommandLineOption("--base", "Add a base geometry to test shadows.");
    arguments.getApplicationUsage()->addCommandLineOption("--sv", "Select ShadowVolume implementation.");
    arguments.getApplicationUsage()->addCommandLineOption("--ssm", "Select SoftShadowMap implementation.");
    arguments.getApplicationUsage()->addCommandLineOption("--sm", "Select ShadowMap implementation.");

    arguments.getApplicationUsage()->addCommandLineOption("--pssm", "Select ParallelSplitShadowMap implementation.");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--mapcount", "ParallelSplitShadowMap texture count.");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--mapres", "ParallelSplitShadowMap texture resolution.");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--debug-color", "ParallelSplitShadowMap display debugging color (only the first 3 maps are color r=0,g=1,b=2.");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--minNearSplit", "ParallelSplitShadowMap shadow map near offset.");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--maxFarDist", "ParallelSplitShadowMap max far distance to shadow.");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--moveVCamFactor", "ParallelSplitShadowMap move the virtual frustum behind the real camera, (also back ground object can cast shadow).");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Factor", "ParallelSplitShadowMap set PolygonOffset factor.");//ADEGLI
    arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Unit", "ParallelSplitShadowMap set PolygonOffset unit.");//ADEGLI

    arguments.getApplicationUsage()->addCommandLineOption("--lispsm", "Select LightSpacePerspectiveShadowMap implementation.");
    arguments.getApplicationUsage()->addCommandLineOption("--msm", "Select MinimalShadowMap implementation.");
    arguments.getApplicationUsage()->addCommandLineOption("--ViewBounds", "MSM, LiSPSM optimize shadow for view frustum (weakest option)");
    arguments.getApplicationUsage()->addCommandLineOption("--CullBounds", "MSM, LiSPSM optimize shadow for bounds of culled objects in view frustum (better option).");
    arguments.getApplicationUsage()->addCommandLineOption("--DrawBounds", "MSM, LiSPSM optimize shadow for bounds of predrawn pixels in view frustum (best & default).");
    arguments.getApplicationUsage()->addCommandLineOption("--mapres", "MSM, LiSPSM & texture resolution.");
    arguments.getApplicationUsage()->addCommandLineOption("--maxFarDist", "MSM, LiSPSM max far distance to shadow.");
    arguments.getApplicationUsage()->addCommandLineOption("--moveVCamFactor", "MSM, LiSPSM move the virtual frustum behind the real camera, (also back ground object can cast shadow).");
    arguments.getApplicationUsage()->addCommandLineOption("--minLightMargin", "MSM, LiSPSM the same as --moveVCamFactor.");

    arguments.getApplicationUsage()->addCommandLineOption("-1", "Use test model one.");
    arguments.getApplicationUsage()->addCommandLineOption("-2", "Use test model two.");
    arguments.getApplicationUsage()->addCommandLineOption("-3", "Use test model three (default).");
    arguments.getApplicationUsage()->addCommandLineOption("-4", "Use test model four - island scene.");
    arguments.getApplicationUsage()->addCommandLineOption("--two-sided", "Use two-sided stencil extension for shadow volumes.");
    arguments.getApplicationUsage()->addCommandLineOption("--two-pass", "Use two-pass stencil for shadow volumes.");
    arguments.getApplicationUsage()->addCommandLineOption("--near-far-mode","COMPUTE_NEAR_USING_PRIMITIVES, COMPUTE_NEAR_FAR_USING_PRIMITIVES, COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES, DO_NOT_COMPUTE_NEAR_FAR");
    arguments.getApplicationUsage()->addCommandLineOption("--max-shadow-distance","<float> Maximum distance that the shadow map should extend from the eye point.");

    // construct the viewer.
    osgViewer::Viewer viewer(arguments);

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    double zNear=1.0, zMid=10.0, zFar=1000.0;
    if (arguments.read("--depth-partition",zNear, zMid, zFar))
    {
        // set up depth partitioning
        osg::ref_ptr<osgViewer::DepthPartitionSettings> dps = new osgViewer::DepthPartitionSettings;
        dps->_mode = osgViewer::DepthPartitionSettings::FIXED_RANGE;
        dps->_zNear = zNear;
        dps->_zMid = zMid;
        dps->_zFar = zFar;
        viewer.setUpDepthPartition(dps.get());
    }

    if (arguments.read("--dp"))
    {
        // set up depth partitioning
        viewer.setUpDepthPartition();
    }

    float fov = 0.0;
    while (arguments.read("--fov",fov)) {}

    osg::Vec4 lightpos(0.0,0.0,1,0.0);
    bool spotlight = false;
    while (arguments.read("--positionalLight")) { lightpos.set(0.5,0.5,1.5,1.0); }
    while (arguments.read("--directionalLight")) { lightpos.set(0.0,0.0,1,0.0); }
    while (arguments.read("--spotLight")) { lightpos.set(0.5,0.5,1.5,1.0); spotlight = true; }

    bool keepLightPos = false;
    osg::Vec3 spotLookat(0.0,0.0,0.0);
    while ( arguments.read("--light-pos", lightpos.x(), lightpos.y(), lightpos.z(), lightpos.w())) { keepLightPos = true; }
    while ( arguments.read("--light-pos", lightpos.x(), lightpos.y(), lightpos.z())) { lightpos.w()=1.0; keepLightPos = true; }
    while ( arguments.read("--light-dir", lightpos.x(), lightpos.y(), lightpos.z())) { lightpos.w()=0.0; keepLightPos = true; }
    while ( arguments.read("--spot-lookat", spotLookat.x(), spotLookat.y(), spotLookat.z())) { }


    while (arguments.read("--castsShadowMask", CastsShadowTraversalMask ));
    while (arguments.read("--receivesShadowMask", ReceivesShadowTraversalMask ));

    bool updateLightPosition = true;
    while (arguments.read("--noUpdate")) updateLightPosition = false;

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

        std::string pathfile;
        char keyForAnimationPath = '5';
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
            if (apm || !apm->valid())
            {
                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
                keyswitchManipulator->selectMatrixManipulator(num);
                ++keyForAnimationPath;
            }
        }

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add stats
    viewer.addEventHandler( new osgViewer::StatsHandler() );

    // add the record camera path handler
    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // add the threading handler
    viewer.addEventHandler( new osgViewer::ThreadingHandler() );

    osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;

    osgShadow::ShadowSettings* settings = shadowedScene->getShadowSettings();
    settings->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
    settings->setCastsShadowTraversalMask(CastsShadowTraversalMask);

    std::string nearFarMode("");
    if (arguments.read("--near-far-mode",nearFarMode))
    {
        if (nearFarMode=="COMPUTE_NEAR_USING_PRIMITIVES")                settings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_USING_PRIMITIVES);
        else if (nearFarMode=="COMPUTE_NEAR_FAR_USING_PRIMITIVES")       settings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
        else if (nearFarMode=="DO_NOT_COMPUTE_NEAR_FAR")                 settings->setComputeNearFarModeOverride(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
        else if (nearFarMode=="COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES") settings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);

        OSG_NOTICE<<"ComputeNearFarModeOverride set to ";
        switch(settings->getComputeNearFarModeOverride())
        {
            case(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES): OSG_NOTICE<<"COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES"; break;
            case(osg::CullSettings::COMPUTE_NEAR_USING_PRIMITIVES): OSG_NOTICE<<"COMPUTE_NEAR_USING_PRIMITIVES"; break;
            case(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES): OSG_NOTICE<<"COMPUTE_NEAR_FAR_USING_PRIMITIVES"; break;
            case(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR): OSG_NOTICE<<"DO_NOT_COMPUTE_NEAR_FAR"; break;
        }
        OSG_NOTICE<<std::endl;
    }

    double distance;
    if (arguments.read("--max-shadow-distance",distance))
    {
        settings->setMaximumShadowMapDistance(distance);
        OSG_NOTICE<<"MaximumShadowMapDistance set to "<<settings->getMaximumShadowMapDistance()<<std::endl;
    }


    osg::ref_ptr<osgShadow::MinimalShadowMap> msm = NULL;
    if (arguments.read("--no-shadows"))
    {
        OSG_NOTICE<<"Not using a ShadowTechnique"<<std::endl;
        shadowedScene->setShadowTechnique(0);
    }
    else if (arguments.read("--sv"))
    {
        // hint to tell viewer to request stencil buffer when setting up windows
        osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);

        osg::ref_ptr<osgShadow::ShadowVolume> sv = new osgShadow::ShadowVolume;
        sv->setDynamicShadowVolumes(updateLightPosition);
        while (arguments.read("--two-sided")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED);
        while (arguments.read("--two-pass")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_PASS);

        shadowedScene->setShadowTechnique(sv.get());
    }
    else if (arguments.read("--st"))
    {
        osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture;
        shadowedScene->setShadowTechnique(st.get());
    }
    else if (arguments.read("--stsm"))
    {
        osg::ref_ptr<osgShadow::StandardShadowMap> st = new osgShadow::StandardShadowMap;
        shadowedScene->setShadowTechnique(st.get());
    }
    else if (arguments.read("--pssm"))
    {
        int mapcount = 3;
        while (arguments.read("--mapcount", mapcount));
        osg::ref_ptr<osgShadow::ParallelSplitShadowMap> pssm = new osgShadow::ParallelSplitShadowMap(NULL,mapcount);

        int mapres = 1024;
        while (arguments.read("--mapres", mapres))
            pssm->setTextureResolution(mapres);

        while (arguments.read("--debug-color")) { pssm->setDebugColorOn(); }


        int minNearSplit=0;
        while (arguments.read("--minNearSplit", minNearSplit))
            if ( minNearSplit > 0 ) {
                pssm->setMinNearDistanceForSplits(minNearSplit);
                std::cout << "ParallelSplitShadowMap : setMinNearDistanceForSplits(" << minNearSplit <<")" << std::endl;
            }

        int maxfardist = 0;
        while (arguments.read("--maxFarDist", maxfardist))
            if ( maxfardist > 0 ) {
                pssm->setMaxFarDistance(maxfardist);
                std::cout << "ParallelSplitShadowMap : setMaxFarDistance(" << maxfardist<<")" << std::endl;
            }

        int moveVCamFactor = 0;
        while (arguments.read("--moveVCamFactor", moveVCamFactor))
            if ( maxfardist > 0 ) {
                pssm->setMoveVCamBehindRCamFactor(moveVCamFactor);
                std::cout << "ParallelSplitShadowMap : setMoveVCamBehindRCamFactor(" << moveVCamFactor<<")" << std::endl;
            }



        double polyoffsetfactor = pssm->getPolygonOffset().x();
        double polyoffsetunit   = pssm->getPolygonOffset().y();
        while (arguments.read("--PolyOffset-Factor", polyoffsetfactor));
        while (arguments.read("--PolyOffset-Unit", polyoffsetunit));
        pssm->setPolygonOffset(osg::Vec2(polyoffsetfactor,polyoffsetunit));

        shadowedScene->setShadowTechnique(pssm.get());
    }
    else if (arguments.read("--ssm"))
    {
        osg::ref_ptr<osgShadow::SoftShadowMap> sm = new osgShadow::SoftShadowMap;
        shadowedScene->setShadowTechnique(sm.get());
    }
    else if( arguments.read("--vdsm") )
    {
        while( arguments.read("--debugHUD") ) settings->setDebugDraw( true );
        if (arguments.read("--persp")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::PERSPECTIVE_SHADOW_MAP);
        if (arguments.read("--ortho")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::ORTHOGRAPHIC_SHADOW_MAP);

        unsigned int unit=1;
        if (arguments.read("--unit",unit)) settings->setBaseShadowTextureUnit(unit);

        double n=0.0;
        if (arguments.read("-n",n)) settings->setMinimumShadowMapNearFarRatio(n);

        unsigned int numShadowMaps;
        if (arguments.read("--num-sm",numShadowMaps)) settings->setNumShadowMapsPerLight(numShadowMaps);

        if (arguments.read("--parallel-split") || arguments.read("--ps") ) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::PARALLEL_SPLIT);
        if (arguments.read("--cascaded")) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::CASCADED);


        int mapres = 1024;
        while (arguments.read("--mapres", mapres))
            settings->setTextureSize(osg::Vec2s(mapres,mapres));

        osg::ref_ptr<osgShadow::ViewDependentShadowMap> vdsm = new osgShadow::ViewDependentShadowMap;
        shadowedScene->setShadowTechnique(vdsm.get());
    }
    else if ( arguments.read("--lispsm") )
    {
        if( arguments.read( "--ViewBounds" ) )
            msm = new osgShadow::LightSpacePerspectiveShadowMapVB;
        else if( arguments.read( "--CullBounds" ) )
            msm = new osgShadow::LightSpacePerspectiveShadowMapCB;
        else // if( arguments.read( "--DrawBounds" ) ) // default
            msm = new osgShadow::LightSpacePerspectiveShadowMapDB;
    }
    else if( arguments.read("--msm") )
    {
       if( arguments.read( "--ViewBounds" ) )
            msm = new osgShadow::MinimalShadowMap;
       else if( arguments.read( "--CullBounds" ) )
            msm = new osgShadow::MinimalCullBoundsShadowMap;
       else // if( arguments.read( "--DrawBounds" ) ) // default
            msm = new osgShadow::MinimalDrawBoundsShadowMap;
    }
    else /* if (arguments.read("--sm")) */
    {
        osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
        shadowedScene->setShadowTechnique(sm.get());

        int mapres = 1024;
        while (arguments.read("--mapres", mapres))
            sm->setTextureSize(osg::Vec2s(mapres,mapres));
    }

    if( msm )// Set common MSM & LISPSM arguments
    {
        shadowedScene->setShadowTechnique( msm.get() );
        while( arguments.read("--debugHUD") ) msm->setDebugDraw( true );

        float minLightMargin = 10.f;
        float maxFarPlane = 0;
        unsigned int texSize = 1024;
        unsigned int baseTexUnit = 0;
        unsigned int shadowTexUnit = 1;

        while ( arguments.read("--moveVCamFactor", minLightMargin ) );
        while ( arguments.read("--minLightMargin", minLightMargin ) );
        while ( arguments.read("--maxFarDist", maxFarPlane ) );
        while ( arguments.read("--mapres", texSize ));
        while ( arguments.read("--baseTextureUnit", baseTexUnit) );
        while ( arguments.read("--shadowTextureUnit", shadowTexUnit) );

        msm->setMinLightMargin( minLightMargin );
        msm->setMaxFarPlane( maxFarPlane );
        msm->setTextureSize( osg::Vec2s( texSize, texSize ) );
        msm->setShadowTextureCoordIndex( shadowTexUnit );
        msm->setShadowTextureUnit( shadowTexUnit );
        msm->setBaseTextureCoordIndex( baseTexUnit );
        msm->setBaseTextureUnit( baseTexUnit );
    }

    OSG_INFO<<"shadowedScene->getShadowTechnique()="<<shadowedScene->getShadowTechnique()<<std::endl;

    osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
    if (model.valid())
    {
        model->setNodeMask(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
    }
    else
    {
        model = createTestModel(arguments);
    }

    // get the bounds of the model.
    osg::ComputeBoundsVisitor cbbv;
    model->accept(cbbv);
    osg::BoundingBox bb = cbbv.getBoundingBox();

    if (lightpos.w()==1.0 && !keepLightPos)
    {
        lightpos.x() = bb.xMin()+(bb.xMax()-bb.xMin())*lightpos.x();
        lightpos.y() = bb.yMin()+(bb.yMax()-bb.yMin())*lightpos.y();
        lightpos.z() = bb.zMin()+(bb.zMax()-bb.zMin())*lightpos.z();
    }

    if ( arguments.read("--base"))
    {

        osg::Geode* geode = new osg::Geode;

        osg::Vec3 widthVec(bb.radius(), 0.0f, 0.0f);
        osg::Vec3 depthVec(0.0f, bb.radius(), 0.0f);
        osg::Vec3 centerBase( (bb.xMin()+bb.xMax())*0.5f, (bb.yMin()+bb.yMax())*0.5f, bb.zMin()-bb.radius()*0.1f );

        geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*1.5f-depthVec*1.5f,
                                                             widthVec*3.0f, depthVec*3.0f) );

        geode->setNodeMask(shadowedScene->getReceivesShadowTraversalMask());

        geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")));

        shadowedScene->addChild(geode);
    }

    osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
    ls->getLight()->setPosition(lightpos);

    if (spotlight)
    {
        osg::Vec3 center = spotLookat;
        osg::Vec3 lightdir = center - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z());
        lightdir.normalize();
        ls->getLight()->setDirection(lightdir);
        ls->getLight()->setSpotCutoff(25.0f);

        //set the LightSource, only for checking, there is only 1 light in the scene
        osgShadow::ShadowMap* shadowMap = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
        if( shadowMap ) shadowMap->setLight(ls.get());
    }

    if ( arguments.read("--coloured-light"))
    {
        ls->getLight()->setAmbient(osg::Vec4(1.0,0.0,0.0,1.0));
        ls->getLight()->setDiffuse(osg::Vec4(0.0,1.0,0.0,1.0));
    }
    else
    {
        ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
        ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
    }

    shadowedScene->addChild(model.get());
    shadowedScene->addChild(ls.get());

    viewer.setSceneData(shadowedScene.get());

    osg::ref_ptr< DumpShadowVolumesHandler > dumpShadowVolumes = new DumpShadowVolumesHandler;

    viewer.addEventHandler(new ChangeFOVHandler(viewer.getCamera()));
    viewer.addEventHandler( dumpShadowVolumes.get() );

    // create the windows and run the threads.
    viewer.realize();

    if (fov!=0.0)
    {
        double fovy, aspectRatio, zNear, zFar;
        viewer.getCamera()->getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);

        std::cout << "Setting FOV to " << fov << std::endl;
        viewer.getCamera()->getProjectionMatrix().makePerspective(fov, aspectRatio, zNear, zFar);
    }

    // it is done after viewer.realize() so that the windows are already initialized
    if ( arguments.read("--debugHUD"))
    {
        osgViewer::Viewer::Windows windows;
        viewer.getWindows(windows);

        if (windows.empty()) return 1;

        osgShadow::ShadowMap* sm = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
        if( sm ) {
            osg::ref_ptr<osg::Camera> hudCamera = sm->makeDebugHUD();

            // set up cameras to rendering on the first window available.
            hudCamera->setGraphicsContext(windows[0]);
            hudCamera->setViewport(0,0,windows[0]->getTraits()->width, windows[0]->getTraits()->height);

            viewer.addSlave(hudCamera.get(), false);
        }
    }

    osg::ref_ptr<LightAnimationHandler> lightAnimationHandler = updateLightPosition ? new LightAnimationHandler : 0;
    if (lightAnimationHandler) viewer.addEventHandler(lightAnimationHandler.get());


    // osgDB::writeNodeFile(*group,"test.osgt");

    while (!viewer.done())
    {
        {
            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );

            if( msm ) {

                // If scene decorated by CoordinateSystemNode try to find localToWorld
                // and set modellingSpaceToWorld matrix to optimize scene bounds computation

                osg::NodePath np = viewer.getCoordinateSystemNodePath();
                if( !np.empty() ) {
                    osg::CoordinateSystemNode * csn =
                        dynamic_cast<osg::CoordinateSystemNode *>( np.back() );

                    if( csn ) {
                        osg::Vec3d pos =
                            viewer.getCameraManipulator()->getMatrix().getTrans();

                        msm->setModellingSpaceToWorldTransform
                            ( csn->computeLocalCoordinateFrame( pos ) );
                    }
                }
            }
        }

        if (lightAnimationHandler.valid() && lightAnimationHandler ->getAnimating())
        {
            float t = viewer.getFrameStamp()->getSimulationTime();

            if (lightpos.w()==1.0)
            {
                lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius()*3.0f  ,1.0f);
            }
            else
            {
                lightpos.set(sinf(t),cosf(t),1.0f,0.0f);
            }
            ls->getLight()->setPosition(lightpos);

            osg::Vec3f lightDir(-lightpos.x(),-lightpos.y(),-lightpos.z());
            if(spotlight)
                lightDir =  osg::Vec3(bb.center().x()+sinf(t)*bb.radius()/2.0, bb.center().y() + cosf(t)*bb.radius()/2.0, bb.center().z())
                - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z()) ;
            lightDir.normalize();
            ls->getLight()->setDirection(lightDir);
        }

        if( dumpShadowVolumes->get() )
        {
            dumpShadowVolumes->set( false );

            static int dumpFileNo = 0;
            dumpFileNo ++;
            char filename[256];
            std::sprintf( filename, "shadowDump%d.osgt", dumpFileNo );

            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );

            if( msm ) msm->setDebugDump( filename );
        }

        viewer.frame();
    }

    return 0;
}
Esempio n. 5
0
bool WorldLoader::CreateTestWorld(Game *pGame)
{
	SceneManager * pSceneMgr = pGame->getRenderer()->getSceneManager();
 // PC: Note, ogre likes the shadow setup to happen first, because it affects the model loading?? weird.. check the manual
      // setup the shadow technique to use.. stencil does nice self-shadowing but its a bit slow.
      pSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
      //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
      //pSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
      //mSceneMgr->setShadowTextureSelfShadow(true);
      //pSceneMgr->setShadowTextureSize(1024);
      //mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
      /*
      LiSPSMShadowCameraSetup* lispsm = new LiSPSMShadowCameraSetup();
		lispsm->setOptimalAdjustFactor(0.3);
		mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(lispsm));
		mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
      */
	  srand(1027);
#ifdef _DEBUG
	  for(int i = 0; i < 20; i++)
#else
	  for(int i = 0; i < 2000; i++)
#endif
	  {
		CreateRandomRobot(pGame);
	  }
	  for(int i = 0; i < 4; i++)
	  {
		//CreateRandomBox(pGame);
	  }
		//CreateArena(pGame);
		//CreateCameraBox(pGame);
/*
		for(int i = 0; i < 40; i++)
	  {
		CreateRandomHouse(pGame);
	  }

		for(int i = 0; i < 40; i++)
	  {
		CreateRandomBarrel(pGame);
	  }
*/

#ifndef _TERRAIN_
      

      Plane plane(Vector3::UNIT_Y,0);
      MeshManager::getSingleton().createPlane("ground",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
         plane,150000,150000,20,20,true,1,500,500,Vector3::UNIT_Z);

      Entity *ent = pSceneMgr->createEntity("GroundEntity", "ground");
      SceneNode* planeNode = pSceneMgr->getRootSceneNode()->createChildSceneNode();
      planeNode->attachObject(ent);
      //ent->setMaterialName("Examples/GrassFloor");
		ent->setMaterialName("PAC/Floor");
	  //ent->setMaterialName("PAC/Floor");
      ent->setCastShadows(false);
     
#else
      pSceneMgr->setWorldGeometry("terrain.cfg");
#endif


	  Viewport * pView  = pGame->getRenderer()->getRenderWindow()->getViewport(0);
      pView->setBackgroundColour(ColourValue(0.3f,0.3f,0.3f,1.0f));

      //pSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
      //pSceneMgr->setSkyBox(true,"Examples/CloudyNoonSkyBox",50);
      



      // Set ambient light
      pSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

      // Create a light
      Light* l = pSceneMgr->createLight("MainLight");
      l->setType(Light::LightTypes::LT_DIRECTIONAL);
      Vector3 lightpos(20,140,50);
      Vector3 lightspot(0,0,0);
      Vector3 lightdir = lightspot - lightpos;
      l->setDirection(lightdir);
      l->setPosition(lightpos);

	return true;
};
Esempio n. 6
0
//*************************************************************************************************************
void Render(float alpha, float elapsedtime)
{
	static float time = 0;

	D3DXMATRIX		view, proj, vp;
	D3DXMATRIX		world;
	D3DXMATRIX		inv;

	D3DXVECTOR4		amblight(0.2f, 0.2f, 0.2f, 1);
	D3DXVECTOR4		intensity(0.8f, 0.8f, 0.8f, 1);
	D3DXVECTOR4		zero(0, 0, 0, 1);

	D3DXVECTOR3		lightpos(0, 0, -10);
	D3DXVECTOR3		eye(0, 0, -5.2f);
	D3DXVECTOR3		look(0, 0.5f, 0);
	D3DXVECTOR3		up(0, 1, 0);
	D3DXVECTOR3		p1, p2;
	D3DXVECTOR2		orient	= cameraangle.smooth(alpha);
	D3DXVECTOR2		light	= lightangle.smooth(alpha);

	time += elapsedtime;

	// setup light
	D3DXMatrixRotationYawPitchRoll(&view, light.x, light.y, 0);
	D3DXVec3TransformCoord(&lightpos, &lightpos, &view);

	// TODO: no need to calculate every frame
	for( int i = 0; i < NUM_OBJECTS; ++i )
	{
		FindSilhouette(objects[i], (D3DXVECTOR3&)lightpos);
		ExtrudeSilhouette(objects[i], (D3DXVECTOR3&)lightpos);
	}

	// setup camera
	D3DXMatrixRotationYawPitchRoll(&view, orient.x, orient.y, 0);
	D3DXVec3TransformCoord(&eye, &eye, &view);

	D3DXMatrixLookAtLH(&view, &eye, &look, &up);
	D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4, (float)screenwidth / (float)screenheight, 0.1f, 20);

	// put far plane to infinity
	proj._33 = 1;
	proj._43 = -0.1f;

	D3DXMatrixMultiply(&vp, &view, &proj);
	D3DXMatrixScaling(&world, 5, 0.1f, 5);

	// specular effect uniforms
	specular->SetMatrix("matViewProj", &vp);
	specular->SetVector("eyePos", (D3DXVECTOR4*)&eye);
	specular->SetVector("lightPos", (D3DXVECTOR4*)&lightpos);
	specular->SetVector("ambient", &zero); // it's a f**k-up
	specular->SetVector("lightColor", &intensity); // lazy to tonemap
	
	ambient->SetMatrix("matViewProj", &vp);
	ambient->SetVector("ambient", &amblight);

	if( SUCCEEDED(device->BeginScene()) )
	{
		device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0xff6694ed, 1.0f, 0);

		// STEP 1: z pass
		ambient->SetTechnique("ambientlight");
		ambient->SetMatrix("matViewProj", &vp);

		DrawScene(ambient);

		// STEP 2: draw shadow with depth fail method
		device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
		device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);

		device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
		device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
		device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
		device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
		device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR);
		device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);

		extrude->SetTechnique("extrude");
		extrude->SetMatrix("matViewProj", &vp);

		extrude->Begin(0, 0);
		extrude->BeginPass(0);
		{
			for( int i = 0; i < NUM_OBJECTS; ++i )
				DrawShadowVolume(objects[i]);

			device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
			device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

			for( int i = 0; i < NUM_OBJECTS; ++i )
				DrawShadowVolume(objects[i]);
		}
		extrude->EndPass();
		extrude->End();

		device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_ALPHA);

		// STEP 3: multipass lighting
		device->SetRenderState(D3DRS_ZENABLE, TRUE);
		device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
		device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
		device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
		device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

		device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
		device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER);
		device->SetRenderState(D3DRS_STENCILREF, 1);

		DrawScene(specular);

		device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
		device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
		device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

		if( drawsilhouette )
		{
			amblight = D3DXVECTOR4(1, 1, 0, 0.5f);

			// reuse whatever we can...
			extrude->SetVector("ambient", &amblight);
			extrude->Begin(0, 0);
			extrude->BeginPass(0);

			device->SetVertexDeclaration(shadowdecl);

			for( int i = 0; i < NUM_OBJECTS; ++i )
			{
				const ShadowCaster& caster = objects[i];
				D3DXVECTOR4* verts = (D3DXVECTOR4*)malloc(caster.silhouette.size() * 2 * sizeof(D3DXVECTOR4));

				for( size_t j = 0; j < caster.silhouette.size(); ++j )
				{
					const Edge& e = caster.silhouette[j];

					verts[j * 2 + 0] = D3DXVECTOR4(e.v1, 1);
					verts[j * 2 + 1] = D3DXVECTOR4(e.v2, 1);
				}

				extrude->SetMatrix("matWorld", &caster.world);
				extrude->CommitChanges();

				device->DrawPrimitiveUP(D3DPT_LINELIST, caster.silhouette.size(), verts, sizeof(D3DXVECTOR4));
				free(verts);
			}

			extrude->EndPass();
			extrude->End();
			extrude->SetVector("ambient", &zero);
		}

		if( drawvolume )
		{
			device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
			device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
			device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

			amblight = D3DXVECTOR4(1, 1, 0, 0.5f);

			extrude->SetVector("ambient", &amblight);
			extrude->Begin(0, 0);
			extrude->BeginPass(0);

			for( int i = 0; i < NUM_OBJECTS; ++i )
				DrawShadowVolume(objects[i]);

			extrude->EndPass();
			extrude->End();
			extrude->SetVector("ambient", &zero);

			device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
		}

		// render text
		device->SetFVF(D3DFVF_XYZRHW|D3DFVF_TEX1);
		device->SetRenderState(D3DRS_ZENABLE, FALSE);
		device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
		device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

		device->SetTexture(0, text);
		device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, textvertices, 6 * sizeof(float));

		device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
		device->SetRenderState(D3DRS_ZENABLE, TRUE);

		device->SetTexture(0, 0);
		device->EndScene();
	}

	device->Present(NULL, NULL, NULL, NULL);
}
Esempio n. 7
0
//*************************************************************************************************************
void Render(float alpha, float elapsedtime)
{
	D3DXMATRIX view, proj;
	D3DXMATRIX inv, vp, tmp;
	D3DXMATRIX lightview, lightproj, lightvp;

	D3DXVECTOR2 orient = cameraangle.smooth(alpha);
	D3DXVECTOR4 lightpos(0, 0, -5, 0);
	D3DXVECTOR3 look(0, 0.5f, 0), up(0, 1, 0);
	D3DXVECTOR3 eye(0, 0, -5.2f);
	D3DXVECTOR4 clipplanes(0, 0, 0, 0);
	D3DXVECTOR4 texelsize(1.0f / SHADOWMAP_SIZE, 1.0f / SHADOWMAP_SIZE, 0, 0);

	// setup camera
	D3DXMatrixRotationYawPitchRoll(&tmp, orient.x, orient.y, 0);
	D3DXVec3TransformCoord(&eye, &eye, &tmp);

	D3DXMatrixLookAtLH(&view, &eye, &look, &up);
	D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4, (float)screenwidth / (float)screenheight, 0.1f, 20);
	D3DXMatrixMultiply(&vp, &view, &proj);

	// setup light
	orient = lightangle.smooth(alpha);
	look = D3DXVECTOR3(0, 0, 0);

	D3DXMatrixRotationYawPitchRoll(&tmp, orient.x, orient.y, 0);
	D3DXVec4Transform(&lightpos, &lightpos, &tmp);

	D3DXMatrixLookAtLH(&lightview, (D3DXVECTOR3*)&lightpos, &look, &up);
	DXFitToBox(lightproj, clipplanes, lightview, scenebb);
	D3DXMatrixMultiply(&lightvp, &lightview, &lightproj);

	if( SUCCEEDED(device->BeginScene()) )
	{
		switch( shadowtech )
		{
		case 0:
			RenderWithPCF(vp, eye, lightview, lightproj, lightpos, clipplanes, D3DXVECTOR4(0, 0, 0, 0));
			break;

		case 1:
			RenderWithPCF(vp, eye, lightview, lightproj, lightpos, clipplanes, texelsize);
			break;

		case 2:
			RenderWithIrregularPCF(vp, eye, lightview, lightproj, lightpos, clipplanes, texelsize);
			break;

		case 3:
			RenderWithVariance(vp, eye, lightview, lightproj, lightpos, clipplanes);
			break;

		case 4:
			RenderWithConvolution(vp, eye, lightview, lightproj, lightpos, clipplanes);
			break;

		case 5:
			RenderWithExponential(vp, eye, lightview, lightproj, lightpos, clipplanes);
			break;

		case 6:
			RenderWithExponentialVariance(vp, eye, lightview, lightproj, lightpos, clipplanes);
			break;

		case 7:
			RenderWithPCSS(vp, eye, lightview, lightproj, lightpos, clipplanes, texelsize);
			break;

		default:
			device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0xff6694ed, 1.0f, 0);
			break;
		}

		// render text
		device->SetFVF(D3DFVF_XYZRHW|D3DFVF_TEX1);
		device->SetRenderState(D3DRS_ZENABLE, FALSE);
		device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
		device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

		device->SetTexture(0, text);
		device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, textvertices, 6 * sizeof(float));

		device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
		device->SetRenderState(D3DRS_ZENABLE, TRUE);

		device->EndScene();
	}

	device->Present(NULL, NULL, NULL, NULL);
}
Esempio n. 8
0
void Render(float alpha, float elapsedtime)
{
	static float time = 0;
	LPDIRECT3DSURFACE9 backbuffer = 0;

	D3DXMATRIX		view, proj, viewproj;
	D3DXMATRIX		world, inv;

	D3DXVECTOR4		texelsize;
	D3DXVECTOR4		lightpos(-600, 350, 1000, 1);
	D3DXVECTOR4		refllight;
	D3DXVECTOR3		eye(0, 0, -5.0f);
	D3DXVECTOR3		look(0, 1.2f, 0);
	D3DXVECTOR3		refleye, refllook;
	D3DXVECTOR3		up(0, 1, 0);
	D3DXVECTOR2		orient	= cameraangle.smooth(alpha);

	D3DXMatrixRotationYawPitchRoll(&view, orient.x, orient.y, 0);
	D3DXVec3TransformCoord(&eye, &eye, &view);
	
	eye.y += 1.2f;

	D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 2, (float)screenwidth / (float)screenheight, 0.1f, 30);

	time += elapsedtime;

	if( SUCCEEDED(device->BeginScene()) )
	{
		device->GetRenderTarget(0, &backbuffer);

		// STEP 1: render reflection texture
		device->SetRenderTarget(0, reflectsurf);
		device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0xff6694ed, 1.0f, 0);

		D3DXPLANE plane(0, 1, 0, 1);

		refleye = eye - 2 * D3DXPlaneDotCoord(&plane, &eye) * (D3DXVECTOR3&)plane;
		refllook = look - 2 * D3DXPlaneDotCoord(&plane, &look) * (D3DXVECTOR3&)plane;

		refllight = lightpos - 2 * D3DXPlaneDot(&plane, &lightpos) * (D3DXVECTOR4&)plane;
		refllight.w = 1;

		D3DXMatrixLookAtLH(&view, &refleye, &refllook, &up);
		D3DXMatrixMultiply(&viewproj, &view, &proj);

		D3DXMatrixInverse(&inv, 0, &viewproj);
		D3DXMatrixTranspose(&inv, &inv);
		D3DXPlaneTransform(&plane, &plane, &inv);

		device->SetClipPlane(0, &plane.a);

		RenderScene(viewproj, refleye, refllight, true);

		// STEP 2: render scene (later used for refraction)
		D3DXMatrixLookAtLH(&view, &eye, &look, &up);
		D3DXMatrixMultiply(&viewproj, &view, &proj);

		device->SetRenderTarget(0, refractsurf);
		device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0xff6694ed, 1.0f, 0);

		RenderScene(viewproj, eye, lightpos, false);

		// render water surface into alpha channel for masking
		device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);

		D3DXMatrixTranslation(&world, 0, -1, 0);

		device->SetTransform(D3DTS_WORLD, &world);
		device->SetTransform(D3DTS_VIEW, &view);
		device->SetTransform(D3DTS_PROJECTION, &proj);

		waterplane->DrawSubset(0, DXObject::Opaque);

		device->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0f);

		// STEP 3: light shafts
		quadvertices[6] = quadvertices[24] = quadvertices[30]	= (float)screenwidth - 0.5f;
		quadvertices[13] = quadvertices[19] = quadvertices[31]	= (float)screenheight - 0.5f;

		RenderLightShafts(view, proj, eye, lightpos);

		// STEP 4: gamma correct
		device->SetRenderTarget(0, sceneldrsurf);

		device->SetRenderState(D3DRS_ZENABLE, FALSE);
		device->SetVertexDeclaration(quaddecl);

		bloom->SetTechnique("gammacorrect");
		bloom->Begin(0, 0);
		bloom->BeginPass(0);
		{
			device->SetTexture(0, refraction);
			device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, quadvertices, 6 * sizeof(float));
		}
		bloom->EndPass();
		bloom->End();

		device->SetRenderState(D3DRS_ZENABLE, TRUE);

		// STEP 5: water surface
		device->SetRenderState(D3DRS_SRGBWRITEENABLE, TRUE);

		D3DXMatrixTranslation(&world, 0, -1, 0);
		D3DXMatrixIdentity(&inv);

		water->SetMatrix("matViewProj", &viewproj);
		water->SetMatrix("matWorld", &world);
		water->SetMatrix("matWorldInv", &inv);
		water->SetVector("eyePos", (D3DXVECTOR4*)&eye);
		water->SetVector("lightPos", &lightpos);
		water->SetVector("lightColor", &lightcolor);
		water->SetFloat("time", time);

		water->Begin(0, 0);
		water->BeginPass(0);
		{
			device->SetTexture(0, refraction);
			device->SetTexture(1, reflection);
			device->SetTexture(2, waves);

			waterplane->DrawSubset(0, DXObject::Opaque);
		}
		water->EndPass();
		water->End();

		device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);

		// STEP 6: downsample & blur
		quadvertices[6] = quadvertices[24] = quadvertices[30]	= (float)screenwidth * 0.5f - 0.5f;
		quadvertices[13] = quadvertices[19] = quadvertices[31]	= (float)screenheight * 0.5f - 0.5f;

		device->SetRenderTarget(0, bloomsurf1);
		device->SetRenderState(D3DRS_ZENABLE, FALSE);
		device->SetVertexDeclaration(quaddecl);

		texelsize.x = 1.0f / screenwidth;
		texelsize.y = 1.0f / screenheight;

		bloom->SetTechnique("downsample");
		bloom->SetVector("texelSize", &texelsize);

		bloom->Begin(0, 0);
		bloom->BeginPass(0);
		{
			device->SetTexture(0, sceneldr);
			device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, quadvertices, 6 * sizeof(float));
		}
		bloom->EndPass();
		bloom->End();

		device->SetRenderTarget(0, bloomsurf2);

		texelsize.x = 2.0f / screenwidth;
		texelsize.y = 2.0f / screenheight;

		bloom->SetTechnique("blur");
		bloom->SetVector("texelSize", &texelsize);

		bloom->Begin(0, 0);
		bloom->BeginPass(0);
		{
			device->SetTexture(0, bloomtex1);
			device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, quadvertices, 6 * sizeof(float));
		}
		bloom->EndPass();
		bloom->End();

		// STEP 7: add light shafts
		quadvertices[6] = quadvertices[24] = quadvertices[30]	= (float)screenwidth - 0.5f;
		quadvertices[13] = quadvertices[19] = quadvertices[31]	= (float)screenheight - 0.5f;

		device->SetRenderTarget(0, backbuffer);

		godray->SetTechnique("final");
		godray->Begin(0, 0);
		godray->BeginPass(0);
		{
			device->SetTexture(0, sceneldr);
			device->SetTexture(1, occluders);
			device->SetTexture(2, bloomtex2);

			device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, quadvertices, 6 * sizeof(float));
		}
		godray->EndPass();
		godray->End();

		backbuffer->Release();

		device->SetRenderState(D3DRS_ZENABLE, TRUE);
		device->EndScene();
	}

	device->Present(NULL, NULL, NULL, NULL);
}