예제 #1
0
void EffectHandler::update(const irr::u32 time, const bool screenSpaceOnly,irr::video::ITexture* outputTarget,irr::scene::ISceneNode* node,irr::core::array<scene::IMeshBuffer*>* buffers)
{
    if(outputTarget)
    {
        if(outputTarget->getSize()!= ScreenRTT->getSize())
        {
            setScreenRenderTargetResolution(outputTarget->getSize());
        }
    }
    if (shadowsUnsupported || smgr->getActiveCamera() == 0)
        return;

    if (!ShadowNodeArray.empty() && !LightList.empty())
    {
        driver->setRenderTarget(ScreenQuad.rt[0], true, true, AmbientColour);

        ICameraSceneNode* activeCam = smgr->getActiveCamera();
        activeCam->OnAnimate(device->getTimer()->getTime());
        activeCam->OnRegisterSceneNode();
        activeCam->render();

        const u32 ShadowNodeArraySize = ShadowNodeArray.size();
        const u32 LightListSize = LightList.size();
        for (u32 l = 0; l < LightListSize; ++l)
        {
            // Set max distance constant for depth shader.
            depthMC->FarLink = LightList[l].getFarValue();

            driver->setTransform(ETS_VIEW, LightList[l].getViewMatrix());
            driver->setTransform(ETS_PROJECTION, LightList[l].getProjectionMatrix());

            ITexture* currentShadowMapTexture = getShadowMapTexture(LightList[l].getShadowMapResolution());
            driver->setRenderTarget(currentShadowMapTexture, true, true, SColor(0xffffffff));

            for (u32 i = 0; i < ShadowNodeArraySize; ++i)
            {
                if (ShadowNodeArray[i].shadowMode == ESM_RECEIVE || ShadowNodeArray[i].shadowMode == ESM_EXCLUDE)
                    continue;

                const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();
                core::array<irr::s32> BufferMaterialList(CurrentMaterialCount);
                BufferMaterialList.set_used(0);

                for (u32 m = 0; m < CurrentMaterialCount; ++m)
                {
                    BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);
                    ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)
                            (BufferMaterialList[m] == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF ? DepthT : Depth);
                }

                ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
                ShadowNodeArray[i].node->render();

                const u32 BufferMaterialListSize = BufferMaterialList.size();
                for (u32 m = 0; m < BufferMaterialListSize; ++m)
                    ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
            }

            // Blur the shadow map texture if we're using VSM filtering.
            if (useVSM)
            {
                ITexture* currentSecondaryShadowMap = getShadowMapTexture(LightList[l].getShadowMapResolution(), true);

                driver->setRenderTarget(currentSecondaryShadowMap, true, true, SColor(0xffffffff));
                ScreenQuad.getMaterial().setTexture(0, currentShadowMapTexture);
                ScreenQuad.getMaterial().setTexture(0, currentShadowMapTexture);
                ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)VSMBlurH;
                ScreenQuad.getMaterial().TextureLayer[0].TextureWrapU=1;
                ScreenQuad.getMaterial().TextureLayer[0].BilinearFilter=0;
                //ScreenQuad.getMaterial().TextureLayer[1].BilinearFilter=false;

                ScreenQuad.render(driver);

                driver->setRenderTarget(currentShadowMapTexture, true, true, SColor(0xffffffff));
                ScreenQuad.getMaterial().setTexture(0, currentSecondaryShadowMap);
                ScreenQuad.getMaterial().setTexture(0, currentSecondaryShadowMap);
                ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)VSMBlurV;
                ScreenQuad.getMaterial().TextureLayer[0].BilinearFilter=0;
                //ScreenQuad.getMaterial().TextureLayer[1].BilinearFilter=false;

                ScreenQuad.render(driver);
            }

            driver->setRenderTarget(ScreenQuad.rt[1], true, true, SColor(0,0,0,0));

            driver->setTransform(ETS_VIEW, activeCam->getViewMatrix());
            driver->setTransform(ETS_PROJECTION, activeCam->getProjectionMatrix());

            shadowMC->LightColour = LightList[l].getLightColor();
            shadowMC->LightLink = LightList[l].getPosition();
            shadowMC->FarLink = LightList[l].getFarValue();
            shadowMC->ViewLink = LightList[l].getViewMatrix();
            shadowMC->ProjLink = LightList[l].getProjectionMatrix();
            shadowMC->MapRes = (f32)LightList[l].getShadowMapResolution();

            for (u32 i = 0; i < ShadowNodeArraySize; ++i)
            {
                if (ShadowNodeArray[i].shadowMode == ESM_CAST || ShadowNodeArray[i].shadowMode == ESM_EXCLUDE)
                    continue;

                const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();
                core::array<irr::s32> BufferMaterialList(CurrentMaterialCount);
                core::array<irr::video::ITexture*> BufferTextureList(CurrentMaterialCount);

                core::array<u8> clampModesUList(CurrentMaterialCount);
                core::array<u8> clampModesVList(CurrentMaterialCount);



                for (u32 m = 0; m < CurrentMaterialCount; ++m)
                {
                    BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);
                    BufferTextureList.push_back(ShadowNodeArray[i].node->getMaterial(m).getTexture(0));

                    if (screenSpaceOnly)
                    {
                        if(LightList[l].isSpot())
                            ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)ShadowSSS[ShadowNodeArray[i].filterType];
                        else
                            ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)ShadowSS[ShadowNodeArray[i].filterType];
                    }

                    else
                        ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)Shadow[ShadowNodeArray[i].filterType];
                    ShadowNodeArray[i].node->getMaterial(m).setTexture(0, currentShadowMapTexture);

                    clampModesUList.push_back(ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].TextureWrapU);
                    clampModesVList.push_back(ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].TextureWrapV);
                    //ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].TextureWrapU=video::ETC_CLAMP;
                    //ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].TextureWrapV=video::ETC_CLAMP;
                }

                //Render all project shadow maps
                if (!node)
                {
                    ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
                    ShadowNodeArray[i].node->render();
                }
                else
                {
                    //render projected shadows on specific buffers of a single shAdow map
                    if (ShadowNodeArray[i].node==node)
                    {
                        ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());

                        driver->setTransform(video::ETS_WORLD, node->getAbsoluteTransformation());
                        irr::core::array<scene::IMeshBuffer*>bufferlist=*buffers;

                        for (int buf=0; buf<bufferlist.size(); buf++)
                        {
                            driver->setMaterial(ShadowNodeArray[i].node->getMaterial(buf));
                            driver->drawMeshBuffer(bufferlist[buf]);
                        }
                    }
                }

                for (u32 m = 0; m < CurrentMaterialCount; ++m)
                {
                    ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
                    ShadowNodeArray[i].node->getMaterial(m).setTexture(0, BufferTextureList[m]);

                    ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].TextureWrapU=clampModesUList[m];
                    ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].TextureWrapV=clampModesVList[m];
                }
            }

            driver->setRenderTarget(ScreenQuad.rt[0], false, false, SColor(0,0,0,0));
            ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[1]);
            ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)Simple;
            ScreenQuad.getMaterial().ColorMask=0xffffffff;
            ScreenQuad.render(driver);
        }
        /*
                // Render all the excluded and casting-only nodes.
                for (u32 i = 0;i < ShadowNodeArraySize;++i)
                {
                    if (ShadowNodeArray[i].shadowMode != ESM_CAST && ShadowNodeArray[i].shadowMode != ESM_EXCLUDE)
                        continue;

                    const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();
                    core::array<irr::s32> BufferMaterialList(CurrentMaterialCount);
                    BufferMaterialList.set_used(0);

                    for (u32 m = 0;m < CurrentMaterialCount;++m)
                    {
                        BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);

                        switch (BufferMaterialList[m])
                        {
                        case EMT_TRANSPARENT_ALPHA_CHANNEL_REF:
                            ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWashTRef;
                            break;
                        case EMT_TRANSPARENT_ADD_COLOR:
                            ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWashTAdd;
                            break;
                        case EMT_TRANSPARENT_ALPHA_CHANNEL:
                            ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWashTAlpha;
                            break;
                        default:
                            ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWash;
                            break;
                        }
                    }

                    ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
                    ShadowNodeArray[i].node->render();

                    for (u32 m = 0;m < CurrentMaterialCount;++m)
                        ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
                }*/
    }
    else
    {
        driver->setRenderTarget(ScreenQuad.rt[0], true, true, SColor(0xffffffff));
    }
    if (!screenSpaceOnly)
    {
        driver->setRenderTarget(ScreenQuad.rt[1], true, true, SColor(0xffffffff));

        core::list<scene::ISceneNode*>::ConstIterator it = smgr->getRootSceneNode()->getChildren().begin();
        while (it!=smgr->getRootSceneNode()->getChildren().end())
        {
            scene::ISceneNode* node = *it;
            node->OnAnimate(time);
            node->render();
            it++;

        }
    }

    const u32 PostProcessingRoutinesSize = PostProcessingRoutines.size();

    if (!screenSpaceOnly)
    {
        driver->setRenderTarget(outputTarget, true, true, SColor(0x0));


        ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[1]);
        ScreenQuad.getMaterial().setTexture(1, ScreenQuad.rt[0]);

        ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)LightModulate;

        ScreenQuad.render(driver);
    }

    if (outputTarget)
    {

        driver->setRenderTarget(ScreenRTT , true, true, SColor(0,255,0,255));
        ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[0]);
        ScreenQuad.getMaterial().setTexture(1, ScreenQuad.rt[0]);
        ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)VSMBlurH;
        ScreenQuad.getMaterial().TextureLayer[0].TextureWrapU=1;
        ScreenQuad.getMaterial().TextureLayer[0].TextureWrapV=1;
        ScreenQuad.getMaterial().TextureLayer[0].BilinearFilter=true;
        ScreenQuad.getMaterial().TextureLayer[1].BilinearFilter=false;


        //ScreenQuad.getMaterial().setFlag(video::EMF_BILINEAR_FILTER,false);
        ScreenQuad.render(driver);

        driver->setRenderTarget(ScreenQuad.rt[0], true, true, SColor(0,255,0,255))  ;
        ScreenQuad.getMaterial().setTexture(0, ScreenRTT );
        ScreenQuad.getMaterial().setTexture(1, ScreenRTT );
        ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)VSMBlurV;
        ScreenQuad.getMaterial().TextureLayer[0].TextureWrapU=1;
        ScreenQuad.getMaterial().TextureLayer[0].TextureWrapV=1;
        ScreenQuad.getMaterial().TextureLayer[0].BilinearFilter=true;
        ScreenQuad.getMaterial().TextureLayer[1].BilinearFilter=false;

        ScreenQuad.render(driver);


        //ScreenQuad.getMaterial().setFlag(video::EMF_BILINEAR_FILTER,false);
        ScreenQuad.render(driver);

        driver->setRenderTarget(outputTarget, true, true, SColor(0,255,0,255))  ;
        ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[0] );
        ScreenQuad.getMaterial().setTexture(1, ScreenQuad.rt[0] );
        ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)VSMBlurH;
        ScreenQuad.getMaterial().TextureLayer[0].TextureWrapU=1;
        ScreenQuad.getMaterial().TextureLayer[0].TextureWrapV=1;
        ScreenQuad.getMaterial().TextureLayer[0].BilinearFilter=true;
        ScreenQuad.getMaterial().TextureLayer[1].BilinearFilter=true;

        ScreenQuad.render(driver);




    }

}
예제 #2
0
void effectHandler::update(irr::video::ITexture* outputTarget)
{
	if(shadowsUnsupported || smgr->getActiveCamera() == 0)
		return;
	
	if(!ShadowNodeArray.empty() && !LightList.empty())
	{
		driver->setRenderTarget(ScreenQuad.rt[0], true, true, AmbientColour);

		ICameraSceneNode* activeCam = smgr->getActiveCamera();
		activeCam->OnAnimate(device->getTimer()->getTime());
		activeCam->OnRegisterSceneNode();
		activeCam->render();

		const u32 LightListSize = LightList.size();
		for(u32 l = 0;l < LightListSize;++l)
		{
			// Set max distance constant for depth shader.
			depthMC->FarLink = LightList[l].getFarValue();

			driver->setTransform(ETS_VIEW, LightList[l].getViewMatrix());
			driver->setTransform(ETS_PROJECTION, LightList[l].getProjectionMatrix());
			
			driver->setRenderTarget(ShadowMapTex, true, true, SColor(0xffffffff));
			
			const u32 ShadowNodeArraySize = ShadowNodeArray.size();
			for(u32 i = 0;i < ShadowNodeArraySize;++i)
			{
				if(ShadowNodeArray[i].shadowMode == ESM_RECEIVE)
					continue;

				BufferMaterialList.set_used(0);

				const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();
				for(u32 m = 0;m < CurrentMaterialCount;++m)
				{
					BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);
					ShadowNodeArray[i].node->getMaterial(m).MaterialType =
						ShadowNodeArray[i].node->getMaterial(m).MaterialType == Effects[EET_MRWIGGLE]
						? (E_MATERIAL_TYPE)DepthWiggle : (E_MATERIAL_TYPE)Depth;
				}

				ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
				ShadowNodeArray[i].node->render();

				const u32 BufferMaterialListSize = BufferMaterialList.size();
				for(u32 m = 0;m < BufferMaterialListSize;++m)
					ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
			}
		
			driver->setTransform(ETS_VIEW, activeCam->getViewMatrix());
			driver->setTransform(ETS_PROJECTION, activeCam->getProjectionMatrix());

			shadowMC->LightColour = LightList[l].getLightColor();
			shadowMC->LightLink = LightList[l].getPosition();
			shadowMC->FarLink = LightList[l].getFarValue();
			shadowMC->ViewLink = LightList[l].getViewMatrix();
			shadowMC->ProjLink = LightList[l].getProjectionMatrix();
			
			driver->setRenderTarget(ScreenQuad.rt[1], true, true, SColor(0xffffffff));

			for(u32 i = 0;i < ShadowNodeArraySize;++i)
			{
				const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();

				BufferMaterialList.reallocate(CurrentMaterialCount);
				BufferTextureList.reallocate(CurrentMaterialCount);
				core::array<bool> BilinearBuffer(CurrentMaterialCount);
				BufferMaterialList.set_used(0);
				BufferTextureList.set_used(0);
				BilinearBuffer.set_used(0);
				
				for(u32 m = 0;m < CurrentMaterialCount;++m)
				{
					BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);
					BufferTextureList.push_back(ShadowNodeArray[i].node->getMaterial(m).getTexture(0));
					BilinearBuffer.push_back(ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].BilinearFilter);
				
					ShadowNodeArray[i].node->getMaterial(m).MaterialType = 
						(ShadowNodeArray[i].shadowMode == ESM_CAST) ? (E_MATERIAL_TYPE)WhiteWash
						: (E_MATERIAL_TYPE)Solid[ShadowNodeArray[i].filterType];

					ShadowNodeArray[i].node->getMaterial(m).setTexture(0, ShadowMapTex);
					ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].BilinearFilter = false;
				}

				ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
				ShadowNodeArray[i].node->render();

				for(u32 m = 0;m < CurrentMaterialCount;++m)
				{
					ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
					ShadowNodeArray[i].node->getMaterial(m).setTexture(0, BufferTextureList[m]);
					ShadowNodeArray[i].node->getMaterial(m).TextureLayer[0].BilinearFilter = BilinearBuffer[m];
				}
			}

			driver->setRenderTarget(ScreenQuad.rt[0], false, false, SColor(0x0));
			ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[1]);
			ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)Simple;
			
			ScreenQuad.render(driver);
		}
	}
	else
	{
		driver->setRenderTarget(ScreenQuad.rt[0], true, true, SColor(0xffffffff));
	}
	
	driver->setRenderTarget(ScreenQuad.rt[1], true, true, ClearColour);
	smgr->drawAll();

	const u32 PostProcessingRoutinesSize = PostProcessingRoutines.size();

	driver->setRenderTarget(PostProcessingRoutinesSize 
		? ScreenRTT : outputTarget, true, true, SColor(0x0));

	ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[1]);
	ScreenQuad.getMaterial().setTexture(1, ScreenQuad.rt[0]);

	ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)LightModulate;
	ScreenQuad.render(driver);
	
	if(PostProcessingRoutinesSize)
	{
		bool Alter = 0;
		ScreenQuad.getMaterial().setTexture(1, ScreenRTT);
		ScreenQuad.getMaterial().setTexture(2, DepthRTT);
		for(u32 i = 0;i < PostProcessingRoutinesSize;++i)
		{
			ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)PostProcessingRoutines[i];

			Alter = !Alter;
			ScreenQuad.getMaterial().setTexture(0, i == 0 ? ScreenRTT : ScreenQuad.rt[int(!Alter)]);
			driver->setRenderTarget(i >= PostProcessingRoutinesSize - 1 ?
				outputTarget : ScreenQuad.rt[int(Alter)], true, true, ClearColour);
			ScreenQuad.render(driver);
		}
	}

	// Perform depth pass after rendering, to ensure animations stay up to date.
	if(DepthPass)
	{
		driver->setRenderTarget(DepthRTT, true, true, SColor(0xffffffff));

		// Set max distance constant for depth shader.
		depthMC->FarLink = smgr->getActiveCamera()->getFarValue();

		for(u32 i = 0;i < DepthPassArray.size();++i)
		{
			BufferMaterialList.set_used(0);

			for(u32 g = 0;g < DepthPassArray[i]->getMaterialCount();++g)
				BufferMaterialList.push_back(DepthPassArray[i]->getMaterial(g).MaterialType);

			DepthPassArray[i]->setMaterialType((E_MATERIAL_TYPE)Depth);
			DepthPassArray[i]->OnAnimate(device->getTimer()->getTime());
			DepthPassArray[i]->render();

			for(u32 g = 0;g < DepthPassArray[i]->getMaterialCount();++g)
				DepthPassArray[i]->getMaterial(g).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[g];
		}
	}
}
예제 #3
0
void EffectHandler::update(irr::video::ITexture* outputTarget)
{
	if(shadowsUnsupported || smgr->getActiveCamera() == 0)
		return;
	
	if(!ShadowNodeArray.empty() && !LightList.empty())
	{
		driver->setRenderTarget(ScreenQuad.rt[0], true, true, AmbientColour);

		ICameraSceneNode* activeCam = smgr->getActiveCamera();
		activeCam->OnAnimate(device->getTimer()->getTime());
		activeCam->OnRegisterSceneNode();
		activeCam->render();

		const u32 ShadowNodeArraySize = ShadowNodeArray.size();
		const u32 LightListSize = LightList.size();
		for(u32 l = 0;l < LightListSize;++l)
		{
			// Set max distance constant for depth shader.
			depthMC->FarLink = LightList[l].getFarValue();

			driver->setTransform(ETS_VIEW, LightList[l].getViewMatrix());
			driver->setTransform(ETS_PROJECTION, LightList[l].getProjectionMatrix());
			
			ITexture* currentShadowMapTexture = getShadowMapTexture(LightList[l].getShadowMapResolution());
			driver->setRenderTarget(currentShadowMapTexture, true, true, SColor(0xffffffff));
			
			for(u32 i = 0;i < ShadowNodeArraySize;++i)
			{
				if(ShadowNodeArray[i].shadowMode == ESM_RECEIVE || ShadowNodeArray[i].shadowMode == ESM_EXCLUDE)
					continue;

				const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();
				core::array<irr::s32> BufferMaterialList(CurrentMaterialCount);
				BufferMaterialList.set_used(0);

				for(u32 m = 0;m < CurrentMaterialCount;++m)
				{
					BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);
					ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)
						(BufferMaterialList[m] == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF ? DepthT : Depth);
				}

				ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
				ShadowNodeArray[i].node->render();

				const u32 BufferMaterialListSize = BufferMaterialList.size();
				for(u32 m = 0;m < BufferMaterialListSize;++m)
					ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
			}

			// Blur the shadow map texture if we're using VSM filtering.
			if(useVSM)
			{
				ITexture* currentSecondaryShadowMap = getShadowMapTexture(LightList[l].getShadowMapResolution(), true);

				driver->setRenderTarget(currentSecondaryShadowMap, true, true, SColor(0xffffffff));
				ScreenQuad.getMaterial().setTexture(0, currentShadowMapTexture);
				ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)VSMBlurH;
				
				ScreenQuad.render(driver);

				driver->setRenderTarget(currentShadowMapTexture, true, true, SColor(0xffffffff));
				ScreenQuad.getMaterial().setTexture(0, currentSecondaryShadowMap);
				ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)VSMBlurV;
				
				ScreenQuad.render(driver);
			}

			driver->setRenderTarget(ScreenQuad.rt[1], true, true, SColor(0xffffffff));
		
			driver->setTransform(ETS_VIEW, activeCam->getViewMatrix());
			driver->setTransform(ETS_PROJECTION, activeCam->getProjectionMatrix());

			shadowMC->LightColour = LightList[l].getLightColor();
			shadowMC->LightLink = LightList[l].getPosition();
			shadowMC->FarLink = LightList[l].getFarValue();
			shadowMC->ViewLink = LightList[l].getViewMatrix();
			shadowMC->ProjLink = LightList[l].getProjectionMatrix();
			shadowMC->MapRes = (f32)LightList[l].getShadowMapResolution();

			for(u32 i = 0;i < ShadowNodeArraySize;++i)
			{
				if(ShadowNodeArray[i].shadowMode == ESM_CAST || ShadowNodeArray[i].shadowMode == ESM_EXCLUDE)
						continue;

				const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();
				core::array<irr::s32> BufferMaterialList(CurrentMaterialCount);
				core::array<irr::video::ITexture*> BufferTextureList(CurrentMaterialCount);
				
				for(u32 m = 0;m < CurrentMaterialCount;++m)
				{
					BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);
					BufferTextureList.push_back(ShadowNodeArray[i].node->getMaterial(m).getTexture(0));
				
					ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)Shadow[ShadowNodeArray[i].filterType];
					ShadowNodeArray[i].node->getMaterial(m).setTexture(0, currentShadowMapTexture);
				}

				ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
				ShadowNodeArray[i].node->render();

				for(u32 m = 0;m < CurrentMaterialCount;++m)
				{
					ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
					ShadowNodeArray[i].node->getMaterial(m).setTexture(0, BufferTextureList[m]);
				}
			}

			driver->setRenderTarget(ScreenQuad.rt[0], false, false, SColor(0x0));
			ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[1]);
			ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)Simple;
			
			ScreenQuad.render(driver);
		}

		// Render all the excluded and casting-only nodes.
		for(u32 i = 0;i < ShadowNodeArraySize;++i)
		{
			if(ShadowNodeArray[i].shadowMode != ESM_CAST && ShadowNodeArray[i].shadowMode != ESM_EXCLUDE)
					continue;

			const u32 CurrentMaterialCount = ShadowNodeArray[i].node->getMaterialCount();
			core::array<irr::s32> BufferMaterialList(CurrentMaterialCount);
			BufferMaterialList.set_used(0);
			
			for(u32 m = 0;m < CurrentMaterialCount;++m)
			{
				BufferMaterialList.push_back(ShadowNodeArray[i].node->getMaterial(m).MaterialType);
			
				switch(BufferMaterialList[m])
				{
					case EMT_TRANSPARENT_ALPHA_CHANNEL_REF:
						ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWashTRef;
						break;
					case EMT_TRANSPARENT_ADD_COLOR:
						ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWashTAdd;
						break;
					case EMT_TRANSPARENT_ALPHA_CHANNEL:
						ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWashTAlpha;
						break;
					default:
						ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)WhiteWash;
						break;
				}
			}

			ShadowNodeArray[i].node->OnAnimate(device->getTimer()->getTime());
			ShadowNodeArray[i].node->render();

			for(u32 m = 0;m < CurrentMaterialCount;++m)
				ShadowNodeArray[i].node->getMaterial(m).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[m];
		}
	}
	else
	{
		driver->setRenderTarget(ScreenQuad.rt[0], true, true, SColor(0xffffffff));
	}
	
	driver->setRenderTarget(ScreenQuad.rt[1], true, true, ClearColour);
	smgr->drawAll();

	const u32 PostProcessingRoutinesSize = PostProcessingRoutines.size();

	driver->setRenderTarget(PostProcessingRoutinesSize 
		? ScreenRTT : outputTarget, true, true, SColor(0x0));

	ScreenQuad.getMaterial().setTexture(0, ScreenQuad.rt[1]);
	ScreenQuad.getMaterial().setTexture(1, ScreenQuad.rt[0]);

	ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)LightModulate;
	ScreenQuad.render(driver);

	// Perform depth pass after rendering, to ensure animations stay up to date.
	if(DepthPass)
	{
		driver->setRenderTarget(DepthRTT, true, true, SColor(0xffffffff));

		// Set max distance constant for depth shader.
		depthMC->FarLink = smgr->getActiveCamera()->getFarValue();

		for(u32 i = 0;i < DepthPassArray.size();++i)
		{
			core::array<irr::s32> BufferMaterialList(DepthPassArray[i]->getMaterialCount());
			BufferMaterialList.set_used(0);

			for(u32 g = 0;g < DepthPassArray[i]->getMaterialCount();++g)
				BufferMaterialList.push_back(DepthPassArray[i]->getMaterial(g).MaterialType);

			DepthPassArray[i]->setMaterialType((E_MATERIAL_TYPE)Depth);
			DepthPassArray[i]->OnAnimate(device->getTimer()->getTime());
			DepthPassArray[i]->render();

			for(u32 g = 0;g < DepthPassArray[i]->getMaterialCount();++g)
				DepthPassArray[i]->getMaterial(g).MaterialType = (E_MATERIAL_TYPE)BufferMaterialList[g];
		}

		driver->setRenderTarget(0, false, false);
	}
	
	if(PostProcessingRoutinesSize)
	{
		bool Alter = false;
		ScreenQuad.getMaterial().setTexture(1, ScreenRTT);
		ScreenQuad.getMaterial().setTexture(2, DepthRTT);
		for(u32 i = 0;i < PostProcessingRoutinesSize;++i)
		{
			ScreenQuad.getMaterial().MaterialType = (E_MATERIAL_TYPE)PostProcessingRoutines[i].materialType;

			Alter = !Alter;
			ScreenQuad.getMaterial().setTexture(0, i == 0 ? ScreenRTT : ScreenQuad.rt[int(!Alter)]);
			driver->setRenderTarget(i >= PostProcessingRoutinesSize - 1 ?
				outputTarget : ScreenQuad.rt[int(Alter)], true, true, ClearColour);

			if(PostProcessingRoutines[i].renderCallback) PostProcessingRoutines[i].renderCallback->OnPreRender(this);
			ScreenQuad.render(driver);
			if(PostProcessingRoutines[i].renderCallback) PostProcessingRoutines[i].renderCallback->OnPostRender(this);
		}
	}
}