Example #1
0
void Scene::renderPass(unsigned int passId)
{
    assert( passId>=0 && passId<getNumPasses() );
    switch( passId )
    {
    case 0:
        if( _panorama ) _panorama->render();
        break;
    case 1:
        _stage->setPostRenderCallback( postRenderCallback, this );
        _stage->render();
        _stage->setPostRenderCallback( NULL, NULL );

        if( _timeSpeedMultiplier > 1 )
        {
            std::wstring text = wstrformat( Gameplay::iLanguage->getUnicodeString(376), int( _timeSpeedMultiplier ) );
            Vector3f screenSize = Gameplay::iEngine->getScreenSize();
            gui::Rect textRect( 0, 0, int( screenSize[0] ) ,32 );
            Gameplay::iGui->renderUnicodeText( textRect, "instruction", Vector4f( 0,0,0,0.75f ), gui::atCenter, gui::atCenter, true, text.c_str() );
            textRect.left -= 1, textRect.right -= 1, textRect.top -= 1, textRect.bottom -= 1;
            Gameplay::iGui->renderUnicodeText( textRect, "instruction", Vector4f( 1,1,0.25,1 ), gui::atCenter, gui::atCenter, true, text.c_str() );
        }
        break;
    }
}
Example #2
0
unsigned int Scene::getPassClearFlag(unsigned int passId)
{
    assert( passId>=0 && passId<getNumPasses() );
    switch( passId )
    {
    case 0:
        return engine::cmClearColor | engine::cmClearDepth | engine::cmClearStencil;
    case 1:
        return engine::cmClearDepth;
    }
    return 0;
}
Example #3
0
float Scene::getPassFarClip(unsigned int passId)
{
    assert( passId>=0 && passId<getNumPasses() );
    switch( passId )
    {
    case 0:
        return _panoramaFarClip;
    case 1:
        return _stageFarClip;
    }
    return 1000.0f;
}
Example #4
0
void ProcessedShaderMaterial::dumpMaterialInfo()
{
   for ( U32 i = 0; i < getNumPasses(); i++ )
   {
      const ShaderRenderPassData *passData = _getRPD( i );

      if ( passData == NULL )
         continue;

      const GFXShader      *shader = passData->shader;

      if ( shader == NULL )
         Con::printf( "  [%i] [NULL shader]", i );
      else
         Con::printf( "  [%i] %s", i, shader->describeSelf().c_str() );
   }
}
Action::ResultE DepthPeelingStage::renderEnter(Action *action)
{
    RenderAction *a = dynamic_cast<RenderAction *>(action);

    a->disableDefaultPartition();

    Int32 iVPWidth  = a->getActivePartition()->getViewportWidth ();
    Int32 iVPHeight = a->getActivePartition()->getViewportHeight();

    //Initial stage (fill depth buffer)
    this->beginPartitionGroup(a);
    {
        setupRenderScene(a, iVPWidth, iVPHeight, IS_INITIAL, DONTCARE);

        //Peel & Blend Stage
        Int32 numLayers = (getNumPasses() - 1) * 2;

        for (Int32 i=0; i < numLayers; ++i)
        {
            if (i % 2 == 0)
            {
                setupRenderScene(a, iVPWidth, iVPHeight, !IS_INITIAL, IS_PONG);
                setupPostProcess(a, !IS_FINAL, IS_PONG);
            }
            else
            {
                setupRenderScene(a, iVPWidth, iVPHeight, !IS_INITIAL, IS_PING);
                setupPostProcess(a, !IS_FINAL, IS_PING);
            }
        }
        //Final stage: draw quad to default framebuffer
        setupPostProcess(a, IS_FINAL, DONTCARE);
    }
    this->endPartitionGroup(a);

    return Action::Skip;
}
void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
	if (pass == -1)
	{
		for (S32 i = 1; i < getNumPasses(); i++)
		{ //skip foot shadows
			prerender();
			beginRenderPass(i);
			renderAvatars(single_avatar, i);
			endRenderPass(i);
		}

		return;
	}

	if (mDrawFace.empty() && !single_avatar)
	{
		return;
	}

	LLVOAvatar *avatarp;

	if (single_avatar)
	{
		avatarp = single_avatar;
	}
	else
	{
		const LLFace *facep = mDrawFace[0];
		if (!facep->getDrawable())
		{
			return;
		}
		avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
	}

    if (avatarp->isDead() || avatarp->mDrawable.isNull())
	{
		return;
	}

	if (!single_avatar && !avatarp->isFullyLoaded())
	{
		if (pass == 0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
		{
			// debug code to draw a sphere in place of avatar
			gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
			gGL.setColorMask(true, true);
			LLVector3 pos = avatarp->getPositionAgent();
			gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f);

			gGL.pushMatrix();
			gGL.translatef((F32)(pos.mV[VX]), (F32)(pos.mV[VY]), (F32)(pos.mV[VZ]));
			gGL.scalef(0.15f, 0.15f, 0.3f);

			gSphere.renderGGL();

			gGL.popMatrix();
			gGL.setColorMask(true, false);
		}
		// don't render please
		return;
	}

	BOOL impostor = avatarp->isImpostor() && !single_avatar;

	if (impostor && pass != 0)
	{ //don't draw anything but the impostor for impostored avatars
		return;
	}
	
	if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender)
	{ //don't draw foot shadows under water
		return;
	}

	if (pass == 0)
	{
		if (!LLPipeline::sReflectionRender)
		{
			LLVOAvatar::sNumVisibleAvatars++;
		}

		if (impostor)
		{
			if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender &&
				avatarp->mImpostor.isComplete()) 
			{
				if (normal_channel > -1)
				{
					avatarp->mImpostor.bindTexture(2, normal_channel);
				}
				if (specular_channel > -1)
				{
					avatarp->mImpostor.bindTexture(1, specular_channel);
				}
			}
			avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel);
		}
		return;
	}

	if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview,  3=morph view
	{
		gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
	}
	
	if (pass == 1)
	{
		// render rigid meshes (eyeballs) first
		avatarp->renderRigid();
		return;
	}
	
	if (pass == 3)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedSimple(avatarp);
		}
		else
		{
			renderRiggedSimple(avatarp);
		}
		return;
	}

	if (pass == 4)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedBump(avatarp);
		}
		else
		{
			renderRiggedFullbright(avatarp);
		}

		return;
	}

	if (pass == 5)
	{
		renderRiggedShinySimple(avatarp);
		return;
	}

	if (pass == 6)
	{
		renderRiggedFullbrightShiny(avatarp);
		return;
	}

	if (pass >= 7 && pass < 9)
	{
		LLGLEnable blend(GL_BLEND);

		gGL.setColorMask(true, true);
		gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
					  LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
					  LLRender::BF_ZERO,
					  LLRender::BF_ONE_MINUS_SOURCE_ALPHA);

		if (pass == 7)
		{
			renderRiggedAlpha(avatarp);
			return;
		}

		if (pass == 8)
		{
			renderRiggedFullbrightAlpha(avatarp);
			return;
		}
	}

	if (pass == 9)
	{
		LLGLEnable blend(GL_BLEND);
		LLGLDisable test(GL_ALPHA_TEST);
		gGL.flush();

		LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
		glPolygonOffset(-1.0f, -1.0f);
		gGL.setSceneBlendType(LLRender::BT_ADD);

		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
		gGL.setColorMask(false, true);

		renderRiggedGlow(avatarp);
		gGL.setColorMask(true, false);
		gGL.setSceneBlendType(LLRender::BT_ALPHA);
		return;
	}

	if (sShaderLevel > 0)
	{
		gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
	}
    
	if (sShaderLevel >= SHADER_LEVEL_CLOTH)
	{
		LLMatrix4 rot_mat;
		LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
		LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
		rot_mat *= cfr;
		
		LLVector4 wind;
		wind.setVec(avatarp->mWindVec);
		wind.mV[VW] = 0;
		wind = wind * rot_mat;
		wind.mV[VW] = avatarp->mWindVec.mV[VW];

		sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_WIND, wind.mV);
		F32 phase = -1.f * (avatarp->mRipplePhase);

		F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
		LLVector4 sin_params(freq, freq, freq, phase);
		sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_SINWAVE, sin_params.mV);

		LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
		gravity = gravity * rot_mat;
		sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_GRAVITY, gravity.mV);
	}

	if (!single_avatar || avatarp == single_avatar)
	{
		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
	}
}
void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
	LLFastTimer t(FTM_RENDER_AVATARS);

	if (pass == -1)
	{
		for (S32 i = 1; i < getNumPasses(); i++)
		{ //skip foot shadows
			prerender();
			beginRenderPass(i);
			renderAvatars(single_avatar, i);
			endRenderPass(i);
		}

		return;
	}

	if (mDrawFace.empty() && !single_avatar)
	{
		return;
	}

	LLVOAvatar *avatarp;

	if (single_avatar)
	{
		avatarp = single_avatar;
	}
	else
	{
		const LLFace *facep = mDrawFace[0];
		if (!facep->getDrawable())
		{
			return;
		}
		avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
	}

    if (avatarp->isDead() || avatarp->mDrawable.isNull())
	{
		return;
	}

	if (!single_avatar && !avatarp->isFullyLoaded() )
	{
		if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
		{
			// debug code to draw a sphere in place of avatar
			gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
			gGL.setColorMask(true, true);
			LLVector3 pos = avatarp->getPositionAgent();
			gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f);
			
			gGL.pushMatrix();	 
			gGL.translatef((F32)(pos.mV[VX]),	 
						   (F32)(pos.mV[VY]),	 
							(F32)(pos.mV[VZ]));	 
			 gGL.scalef(0.15f, 0.15f, 0.3f);

			 gSphere.renderGGL();

			 gGL.popMatrix();
			 gGL.setColorMask(true, false);
		}
		// don't render please
		return;
	}

	BOOL impostor = avatarp->isImpostor() && !single_avatar;

	if (impostor && pass != 0)
	{ //don't draw anything but the impostor for impostored avatars
		return;
	}
	
	if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender)
	{ //don't draw foot shadows under water
		return;
	}

	if (pass == 0)
	{
		if (!LLPipeline::sReflectionRender)
		{
			LLVOAvatar::sNumVisibleAvatars++;
		}

		if (impostor)
		{
			if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete()) 
			{
				if (normal_channel > -1)
				{
					avatarp->mImpostor.bindTexture(2, normal_channel);
				}
				if (specular_channel > -1)
				{
					avatarp->mImpostor.bindTexture(1, specular_channel);
				}
			}
			avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel);
		}
		//else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred)
		//{
		//	avatarp->renderFootShadows();	
		//}
		return;
	}

	llassert(LLPipeline::sImpostorRender || !avatarp->isVisuallyMuted());

	/*if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview,  3=morph view
	{
		gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
	}*/
	
	if (pass == 1)
	{
		// render rigid meshes (eyeballs) first
		avatarp->renderRigid();
		return;
	}

	if (pass == 3)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedSimple(avatarp);
		}
		else
		{
			renderRiggedSimple(avatarp);
			if (LLPipeline::sRenderDeferred)
			{ //render "simple" materials
				renderRigged(avatarp, RIGGED_MATERIAL);
				renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK);
				renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
				renderRigged(avatarp, RIGGED_NORMMAP);
				renderRigged(avatarp, RIGGED_NORMMAP_MASK);
				renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);	
				renderRigged(avatarp, RIGGED_SPECMAP);
				renderRigged(avatarp, RIGGED_SPECMAP_MASK);
				renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
				renderRigged(avatarp, RIGGED_NORMSPEC);
				renderRigged(avatarp, RIGGED_NORMSPEC_MASK);
				renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE);
			}
		}
		return;
	}

	if (pass == 4)
	{
		if (is_deferred_render)
		{
			renderDeferredRiggedBump(avatarp);
		}
		else
		{
			renderRiggedFullbright(avatarp);
		}

		return;
	}

	if (is_deferred_render && pass >= 5 && pass <= 21)
	{
		S32 p = pass-5;
		if (p != 1 &&
			p != 5 &&
			p != 9 &&
			p != 13)
		{
			renderDeferredRiggedMaterial(avatarp, p);
		}
		return;
	}
	if (pass == 5)
	{
		renderRiggedShinySimple(avatarp);
		return;
	}

	if (pass == 6)
	{
		renderRiggedFullbrightShiny(avatarp);
		return;
	}

	if (pass >= 7 && pass < 13)
	{
		if (pass == 7)
		{
			renderRiggedAlpha(avatarp);
			if (LLPipeline::sRenderDeferred && !is_post_deferred_render)
			{ //render transparent materials under water
				LLGLEnable blend(GL_BLEND);
				gGL.setColorMask(true, true);
				gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
								LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
								LLRender::BF_ZERO,
								LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
				renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
				renderRigged(avatarp, RIGGED_SPECMAP_BLEND);
				renderRigged(avatarp, RIGGED_NORMMAP_BLEND);
				renderRigged(avatarp, RIGGED_NORMSPEC_BLEND);
				gGL.setSceneBlendType(LLRender::BT_ALPHA);
				gGL.setColorMask(true, false);
			}
			return;
		}

		if (pass == 8)
		{
			renderRiggedFullbrightAlpha(avatarp);
			return;
		}
		if (LLPipeline::sRenderDeferred && is_post_deferred_render)
		{
			S32 p = 0;
			switch (pass)
			{
			case 9: p = 1; break;
			case 10: p = 5; break;
			case 11: p = 9; break;
			case 12: p = 13; break;
			}
			{
				LLGLEnable blend(GL_BLEND);
				renderDeferredRiggedMaterial(avatarp, p);
			}
			return;
		}
		else if (pass == 9)
		{
			renderRiggedGlow(avatarp);
			return;
		}
	}

	if (pass == 13)
	{
		renderRiggedGlow(avatarp);

		return;
	}
	
	if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
	{
		LLMatrix4 rot_mat;
		LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
		LLMatrix4 cfr(OGL_TO_CFR_ROTATION.getF32ptr());
		rot_mat *= cfr;
		
		LLVector4 wind;
		wind.setVec(avatarp->mWindVec);
		wind.mV[VW] = 0;
		wind = wind * rot_mat;
		wind.mV[VW] = avatarp->mWindVec.mV[VW];

		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV);
		F32 phase = -1.f * (avatarp->mRipplePhase);

		F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
		LLVector4 sin_params(freq, freq, freq, phase);
		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV);

		LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
		gravity = gravity * rot_mat;
		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV);
	}

	if( !single_avatar || (avatarp == single_avatar) )
	{
		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
	}
}
Example #8
0
PostShaderStageDataTransitPtr 
    PostShaderStage::setupStageData(Int32 iPixelWidth,
                                    Int32 iPixelHeight)
{
    PostShaderStageDataTransitPtr returnValue = 
        PostShaderStageData::createLocal();

    if(returnValue == NULL)
        return returnValue;

    OSG::Thread::setCurrentLocalFlags();

    // Scene Target
    FrameBufferObjectUnrecPtr pSceneFBO = FrameBufferObject::createLocal();
        
    //Depth texture
                            _pSceneDepthTex    = TextureObjChunk::createLocal();
    TextureEnvChunkUnrecPtr  pSceneDepthTexEnv = TextureEnvChunk::createLocal();
    ImageUnrecPtr            pDepthImg         = Image          ::createLocal();

    pDepthImg->set(Image::OSG_L_PF, 
                   iPixelWidth, 
                   iPixelHeight,
                   1,
                   1,
                   1,
                   0.0,
                   NULL,
                   Image::OSG_UINT8_IMAGEDATA,
                   false);

    _pSceneDepthTex  ->setImage         (pDepthImg         ); 
    _pSceneDepthTex  ->setMinFilter     (GL_LINEAR         );
    _pSceneDepthTex  ->setMagFilter     (GL_LINEAR         );
    _pSceneDepthTex  ->setWrapS         (GL_CLAMP_TO_EDGE  );
    _pSceneDepthTex  ->setWrapT         (GL_CLAMP_TO_EDGE  );
    _pSceneDepthTex  ->setInternalFormat(GL_DEPTH_COMPONENT);
    _pSceneDepthTex  ->setExternalFormat(GL_DEPTH_COMPONENT);

    pSceneDepthTexEnv->setEnvMode       (GL_REPLACE        );
    
    TextureBufferUnrecPtr pDepthBuffer = TextureBuffer::createLocal();
    //pDepthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24   );
    
    pDepthBuffer->setTexture(_pSceneDepthTex);

        
    //Color Buffer
                            _pSceneTex     = TextureObjChunk::createLocal();
    TextureEnvChunkUnrecPtr  pSceneTexEnv  = TextureEnvChunk::createLocal();
    ImageUnrecPtr            pImg          = Image          ::createLocal();
    
    pImg->set(Image::OSG_RGB_PF, 
              iPixelWidth, 
              iPixelHeight,
              1,
              1,
              1,
              0.0,
              0,
              Image::OSG_UINT8_IMAGEDATA,
              false);
    
    _pSceneTex  ->setImage         (pImg                  ); 
    _pSceneTex  ->setMinFilter     (GL_LINEAR             );
    _pSceneTex  ->setMagFilter     (GL_LINEAR             );
    _pSceneTex  ->setWrapS         (GL_CLAMP_TO_EDGE      );
    _pSceneTex  ->setWrapT         (GL_CLAMP_TO_EDGE      );
    _pSceneTex  ->setInternalFormat(getColorBufferFormat());

    pSceneTexEnv->setEnvMode       (GL_REPLACE            );
    
    TextureBufferUnrecPtr pSceneTexBuffer   = TextureBuffer::createLocal();
    
    pSceneTexBuffer->setTexture(_pSceneTex);
    

    
    pSceneFBO->setSize(iPixelWidth, iPixelHeight);
    
    pSceneFBO->setColorAttachment(pSceneTexBuffer, 0);
    pSceneFBO->setDepthAttachment(pDepthBuffer      );
    
    pSceneFBO->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);
    
    setRenderTarget(pSceneFBO);
    
    // general mat chunk

    //Init all of the render passes
    _vPostProcessPasses.clear();

    UInt32 NumPasses = getNumPasses();

    for(UInt32 i =0; i != NumPasses ; ++i)
    {
        _vPostProcessPasses.push_back(
            RenderPassData::create( getVertexShaders(i),
                                    getFragmentShaders(i),
                                    (i == NumPasses-1),
                                    i,
                                    iPixelWidth,
                                    iPixelHeight,
                                    returnValue.get(),
                                    getPassSizes(i),
                                   _pSceneTex,
                                   _pSceneDepthTex,
                                   _vPostProcessPasses,
                                    pSceneFBO));
    }
    
    OSG::Thread::resetCurrentLocalFlags();

    Thread::getCurrentChangeList()->commitChanges();

    return returnValue;
}
DepthFirstStateAction::ResultE
DepthFirstStateAction::traverseEnterLeave(void)
{
    ResultE              result          = NewActionTypes::Continue;
    Int32                nodePass;        // pass over current node
    UInt32               multiPasses;     // requested passes over current node
    NodePtr              pNode;
    StateRefCountStoreIt itStateRefCount;

    while((_nodeStack.empty() == false) && !(result & NewActionTypes::Quit))
    {
        pNode           = _nodeStack.back().getNode         ();
        nodePass        = _nodeStack.back().getPassCount    ();
        itStateRefCount = _nodeStack.back().getStateRefCount();

        if(itStateRefCount != _itActiveState)
        {
#ifdef OSG_NEWACTION_STATISTICS
            getStatistics()->getElem(statStateRestores)->inc();
#endif /* OSG_NEWACTION_STATISTICS */

            setState(itStateRefCount);

            // gained refs: active
            incRefCount(itStateRefCount);

            // lost refs: active
            decRefCount(_itActiveState);

            _itActiveState = itStateRefCount;
        }

        getChildrenList().setParentNode(pNode);

        if(nodePass > 0)
        {
            // positive pass -> enter node
            
#ifdef OSG_NEWACTION_STATISTICS
            getStatistics()->getElem(statNodesEnter)->inc();
#endif /* OSG_NEWACTION_STATISTICS */
            
            _stateClonedFlag = false;

            result      = enterNode   (pNode, static_cast<UInt32>(nodePass - 1));
            multiPasses = getNumPasses(                                        );

            // only initial pass (nodePass == 1) can request multiPass.
            if((nodePass == 1) && (multiPasses > 1))
            {
                // remove current node from stack
                _nodeStack.pop_back();
                
                for(; multiPasses > 1; -- multiPasses)
                {
                    // gained refs: addtional passs
                    incRefCount(_itActiveState);
                    
                    _nodeStack.push_back(
                        NodeStackEntry(pNode, _itActiveState, multiPasses));
                }
                
                // readd current node - with negative pass -> leave
                _nodeStack.push_back(
                    NodeStackEntry(pNode, _itActiveState, -nodePass));
            }
            else
            {
                // change current node passCount to negative -> leave
                _nodeStack.back().setPassCount(-nodePass);
            }
            
            pushChildren(pNode, result);
        }
        else
        {
            // negative pass -> leave node

#ifdef OSG_NEWACTION_STATISTICS
            getStatistics()->getElem(statNodesLeave)->inc();
#endif /* OSG_NEWACTION_STATISTICS */
            
            _stateClonedFlag = true;

            result = leaveNode(pNode, static_cast<UInt32>(-nodePass - 1));

            _nodeStack.pop_back();

            // lost refs: current node
            decRefCount(_itActiveState);
        }
    }

    return result;
}
DepthFirstStateAction::ResultE
DepthFirstStateAction::traverseEnter(void)
{
    ResultE              result          = NewActionTypes::Continue;
    NodePtr              pNode;
    Int32                nodePass;        // pass over current node
    UInt32               multiPasses;     // requested passes over current node
    StateRefCountStoreIt itStateRefCount; // state for current node

    while((_nodeStack.empty() == false) && !(result & NewActionTypes::Quit))
    {
        pNode           = _nodeStack.back().getNode         ();
        nodePass        = _nodeStack.back().getPassCount    ();
        itStateRefCount = _nodeStack.back().getStateRefCount();

#ifdef OSG_NEWACTION_STATISTICS
        getStatistics()->getElem(statNodesEnter)->inc();
#endif /* OSG_NEWACTION_STATISTICS */

        if(itStateRefCount != _itActiveState)
        {
#ifdef OSG_NEWACTION_STATISTICS
            getStatistics()->getElem(statStateRestores)->inc();
#endif /* OSG_NEWACTION_STATISTICS */

            setState(itStateRefCount);

            // gained refs: active
            incRefCount(itStateRefCount);

            // lost refs: active
            decRefCount(_itActiveState);

            _itActiveState = itStateRefCount;
        }

        _stateClonedFlag = false;

        getChildrenList().setParentNode(pNode);

        result      = enterNode   (pNode, static_cast<UInt32>(nodePass - 1));
        multiPasses = getNumPasses(                                        );

        _nodeStack.pop_back();

        // only initial pass (nodePass == 1) can request multiPasses
        if((nodePass == 1) && (multiPasses > 1))
        {
            for(; multiPasses > 1; --multiPasses)
            {
                // gained refs: additional pass
                incRefCount(_itActiveState);
                
                _nodeStack.push_back(
                    NodeStackEntry(pNode, _itActiveState, multiPasses));
            }
        }
        
        pushChildren(pNode, result);

        // lost refs: current node
        decRefCount(_itActiveState);
    }

    return result;
}