[SOLVED] ManualObject and Shadow: cast & receive

Problems building or running the engine, queries about how to use features etc.
Post Reply
IPC
Gnoblar
Posts: 11
Joined: Mon Aug 06, 2012 8:46 pm

[SOLVED] ManualObject and Shadow: cast & receive

Post by IPC »

Hello

I have a problem with shadow and ManualObject.
I use ManualObject for my terrain.
I need my land cast and receive shadow.
How to enable cast & receive ?

My terrain (One ManualObject):

Code: Select all

                    ____
[SUN]-->           |    |____
                 |           |
               |             |
_____________|               |_____[SHADOW HERE]___________________
Bug same as http://www.ogre3d.org/forums/viewtopic. ... 89#p478689: Image

Solution FOUND: http://www.ogre3d.org/forums/viewtopic. ... 86#p478686

Bye
I-PC
Last edited by IPC on Sat Dec 08, 2012 4:01 pm, edited 5 times in total.
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80
Contact:

Re: ManualObject and Shadow: cast & receive

Post by duststorm »

It depends on what type of shadows you want.
A good reference is the source of the shadows sample.

For texture shadows you generally need to add a shadow caster and shadow receiver shader to your materials. And you need to setup the shadow textures.
Developer @ MakeHuman.org
IPC
Gnoblar
Posts: 11
Joined: Mon Aug 06, 2012 8:46 pm

Re: ManualObject and Shadow: cast & receive

Post by IPC »

Hello,

"It depends on what type of shadows you want."
>> Any type of shadow (STENCIL, TEXTURE, T_ADDITIVE, ...)

"A good reference is the source of the shadows sample."
>> The example is somewhat complicated ... Extract the minimum vital is a real headlock. Between Ogre/DepthShadowmap/ReceiverFP_HLSL, Ogre/DepthShadowmap/ReceiverFPPCF_HLSL, ...
What script is to take!? What should we add to the material?

Example of my current code:

Code: Select all

/*******************************************************************************
* General Scene
*/
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.0, 0.0, 0.0));

//mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_MODULATIVE);// display bug (1)
//mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);// display bug (1)
//mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE);// display bug (2)
//mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);// Stange effect (3)
//mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);// Not working
//mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);// Not working

// Light
Ogre::Light* mSunLight = mSceneMgr->createLight("pointLight");
mSunLight->setType(Ogre::Light::LT_POINT);
mSunLight->setPosition(Ogre::Vector3(150, 50, 250));
mSunLight->setCastShadows(true);


/*******************************************************************************
* Draw Terrain
*/
int iVertex = 0;
int x=0;
int y=0;
int z=0;
Ogre::ManualObject* mesh = m_sceneMgr->createManualObject();
mesh->begin("BasicMaterial");
/*
	NOTE: BasicMaterial has been made like this:

	Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create("BasicMaterial", "General", true);
	mat->setReceiveShadows(true);
	Ogre::Technique* tech = mat->getTechnique(0);
	Ogre::Pass* pass = tech->getPass(0);
	if( isAlpha )
		pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
	Ogre::TextureUnitState* tex = pass->createTextureUnitState();
	tex->setTextureName("texture.png");
	tex->setNumMipmaps(4);
	tex->setTextureAnisotropy(1);
	tex->setTextureFiltering(Ogre::FO_POINT, Ogre::FO_POINT, Ogre::FO_POINT);
*/

// Draw left
mesh->position(x, y,   z+1);	mesh->normal(-1,0,0);	mesh->textureCoord(Ogre::Vector2(1.0,1.0));
mesh->position(x, y+1, z+1);	mesh->normal(-1,0,0);	mesh->textureCoord(Ogre::Vector2(1.0,0.0));
mesh->position(x, y+1, z);		mesh->normal(-1,0,0);	mesh->textureCoord(Ogre::Vector2(0.0,0.0));
mesh->position(x, y,   z);		mesh->normal(-1,0,0);	mesh->textureCoord(Ogre::Vector2(0.0,1.0));
mesh->triangle(iVertex, iVertex+1, iVertex+2);
mesh->triangle(iVertex+2, iVertex+3, iVertex);
iVertex += 4;

// Draw right
mesh->position(x+1, y,   z);	mesh->normal(1,0,0); mesh->textureCoord(Ogre::Vector2(1.0,1.0));
mesh->position(x+1, y+1, z);	mesh->normal(1,0,0); mesh->textureCoord(Ogre::Vector2(1.0,0.0));
mesh->position(x+1, y+1, z+1);	mesh->normal(1,0,0); mesh->textureCoord(Ogre::Vector2(0.0,0.0));
mesh->position(x+1, y,   z+1);	mesh->normal(1,0,0); mesh->textureCoord(Ogre::Vector2(0.0,1.0));
mesh->triangle(iVertex, iVertex+1, iVertex+2);
mesh->triangle(iVertex+2, iVertex+3, iVertex);
iVertex += 4;
// ...

mesh->end();
mesh->setCastShadows(true);
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mesh);
Display Bug 1: http://immortal-pc.info/Rapport/Ogre/1.jpg
Display Bug 2: http://immortal-pc.info/Rapport/Ogre/2.jpg
Display Bug 3: http://immortal-pc.info/Rapport/Ogre/3.jpg
User avatar
saejox
Goblin
Posts: 260
Joined: Tue Oct 25, 2011 1:07 am
x 36

Re: ManualObject and Shadow: cast & receive

Post by saejox »

shadows are a strange subject.
lots of dos and donts.

ogre has a very good manual entry about shadows
http://www.ogre3d.org/docs/manual/manual_70.html
Nimet - Advanced Ogre3D Mesh/dotScene Viewer
asPEEK - Remote Angelscript debugger with html interface
ogreHTML - HTML5 user interfaces in Ogre
IPC
Gnoblar
Posts: 11
Joined: Mon Aug 06, 2012 8:46 pm

Re: ManualObject and Shadow: cast & receive

Post by IPC »

Hello

I have already read this manual... No help from this manual...

I have tryed to extract the minimum vital. But it doesn't work... No shadow at all... Why ?

And why I have my "Bug 1" with Stencil ?

Here my code:

Code: Select all

	m_sceneMgr->setShadowTextureCasterMaterial("Ogre/DepthShadowmap/Caster/Float");
	m_sceneMgr->setShadowTextureReceiverMaterial("Ogre/DepthShadowmap/Receiver/Float");
	m_sceneMgr->setShadowTextureSelfShadow(true);

Code: Select all

material BasicMaterial
{

	// This is the preferred technique which uses both vertex and
	// fragment programs, supports coloured lights
	technique
	{
		// Base ambient pass
		pass
		{
			// base colours, not needed for rendering, but as information
			// to lighting pass categorisation routine
			ambient 1 1 1
			diffuse 0 0 0
			specular 0 0 0 0
			// Really basic vertex program
			vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTextureUnified
			{
			}

		}
		// Now do the lighting pass
		// NB we don't do decal texture here because this is repeated per light
		pass lighting
		{
			// base colours, not needed for rendering, but as information
			// to lighting pass categorisation routine
			ambient 0 0 0

			// do this for each light
			iteration once_per_light


			scene_blend add

			// Vertex program reference
			vertex_program_ref Ogre/DepthShadowmap/ReceiverVP
			{
			}
			shadow_receiver_vertex_program_ref Ogre/DepthShadowmap/ReceiverVP
			{
			}

			// Fragment program
			fragment_program_ref Ogre/DepthShadowmap/ReceiverFP
			{
			}
			shadow_receiver_fragment_program_ref Ogre/DepthShadowmap/ReceiverFP
			{
			}

			// shadowmap texture will be bound by code

		}

		// Decal pass
		pass
		{
			// base colours, not needed for rendering, but as information
			// to lighting pass categorisation routine
			lighting off
			// Really basic vertex program
			vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTextureUnified
			{
				param_named ambient float4 1 1 1 1
			}
			scene_blend dest_colour zero


			texture_unit
			{
				texture terrain.png
				//scene_blend alpha_blend
			}

		}
	}
}
Last edited by IPC on Thu Aug 16, 2012 4:23 pm, edited 1 time in total.
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80
Contact:

Re: ManualObject and Shadow: cast & receive

Post by duststorm »

That's not enough. You need to setup a shadow camera for your lights and specify which splitpoints have to be used for the cascaded shadows technique. Have a look at the shadow sample how it is done.
Developer @ MakeHuman.org
IPC
Gnoblar
Posts: 11
Joined: Mon Aug 06, 2012 8:46 pm

Re: ManualObject and Shadow: cast & receive

Post by IPC »

Hello,

I have tryed to mod the example: Shadow.
No shadow... Why ? Shadow are buggy (1)

Here my code: ( can be compiled )

Code: Select all

/*
-----------------------------------------------------------------------------
This source file is part of OGRE
	(Object-oriented Graphics Rendering Engine)
For the latest info, see ogre3d.org

Copyright (c) 2000-2009 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

You may use this sample code for anything you like, it is not covered by the
same license as the rest of the engine.
-----------------------------------------------------------------------------
*/

/**
	\file
		Shadows.cpp
	\brief
		Shows a few ways to use Ogre's shadowing techniques
*/

#include <SdkSample.h>
#include <stdio.h>

using namespace Ogre;
using namespace OgreBites;



// New depth shadowmapping
String CUSTOM_ROCKWALL_MATERIAL("Ogre/DepthShadowmap/Receiver/RockWall");
String CUSTOM_CASTER_MATERIAL("Ogre/DepthShadowmap/Caster/Float");
String CUSTOM_RECEIVER_MATERIAL("Ogre/DepthShadowmap/Receiver/Float");
String CUSTOM_ATHENE_MATERIAL("Ogre/DepthShadowmap/Receiver/Athene");

String BASIC_ROCKWALL_MATERIAL("Examples/Rockwall");
String BASIC_ATHENE_MATERIAL("Examples/Athene/NormalMapped");

enum { CHUNK_SIZE=11 };

void drawBlocks( SceneManager* sceneMgr )
{
	Ogre::Vector3 realPos(87,-40,16);

	bool m_blocks[CHUNK_SIZE][CHUNK_SIZE][CHUNK_SIZE];
	for( uint32_t y=0, x=0, z=0; y<CHUNK_SIZE; y++ )
	{
		for( x=0; x<CHUNK_SIZE; x++ )
		{
			for( z=0; z<CHUNK_SIZE; z++ )
			{
				m_blocks[y][x][z] = 0;
			}
		}
	}

	for( uint32_t x=0, z=0; x<CHUNK_SIZE; x++ )
	{
		for( z=0; z<CHUNK_SIZE; z++ )
		{
			m_blocks[0][x][z] = 1;
			//m_blocks[1][x][z] = 0;
		}
	}

	m_blocks[3][CHUNK_SIZE/2][CHUNK_SIZE/2] = 1;

	Ogre::ManualObject* m_mesh = sceneMgr->createManualObject();

	//m_mesh->setCastShadows(true);

	m_mesh->begin("terrain", Ogre::RenderOperation::OT_TRIANGLE_LIST);

	int iVertex = 0;
	for( uint32_t y=0, x, z; y<CHUNK_SIZE; y++ )
	{
		for( x=0; x<CHUNK_SIZE; x++ )
		{
			for( z=0; z<CHUNK_SIZE; z++ )
			{
				if( m_blocks[y][x][z] == 0 )
					continue;

				// Draw left ?
				if( (x > 0 && m_blocks[y][x-1][z] == 0) || (x == 0) ){
					m_mesh->position(realPos.x+x, realPos.y+y,   realPos.z+z+1);	m_mesh->normal(-1,0,0);	m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x, realPos.y+y+1, realPos.z+z+1);	m_mesh->normal(-1,0,0);	m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x, realPos.y+y+1, realPos.z+z);		m_mesh->normal(-1,0,0);	m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x, realPos.y+y,   realPos.z+z);		m_mesh->normal(-1,0,0);	m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,1.0/16.0));
					m_mesh->triangle(iVertex, iVertex+1, iVertex+2);
					m_mesh->triangle(iVertex+2, iVertex+3, iVertex);
					iVertex += 4;
				}
				// Draw right ?
				if( (x+1 < CHUNK_SIZE && m_blocks[y][x+1][z] == 0) || (x+1 >= CHUNK_SIZE) ){
					m_mesh->position(realPos.x+x+1, realPos.y+y,   realPos.z+z);	m_mesh->normal(1,0,0); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y+1, realPos.z+z);	m_mesh->normal(1,0,0); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y+1, realPos.z+z+1);	m_mesh->normal(1,0,0); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y,   realPos.z+z+1);	m_mesh->normal(1,0,0); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,1.0/16.0));
					m_mesh->triangle(iVertex, iVertex+1, iVertex+2);
					m_mesh->triangle(iVertex+2, iVertex+3, iVertex);
					iVertex += 4;
				}

				// Draw bottom ?
				if( (y > 0 && m_blocks[y-1][x][z] == 0) || (y == 0) ){
					m_mesh->position(realPos.x+x,   realPos.y+y, realPos.z+z);		m_mesh->normal(0,-1,0); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y, realPos.z+z);		m_mesh->normal(0,-1,0); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y, realPos.z+z+1);	m_mesh->normal(0,-1,0); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x,   realPos.y+y, realPos.z+z+1);	m_mesh->normal(0,-1,0); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,0.0));
					m_mesh->triangle(iVertex, iVertex+1, iVertex+2);
					m_mesh->triangle(iVertex+2, iVertex+3, iVertex);
					iVertex += 4;
				}

				// Draw top ?
				if( (y+1 < CHUNK_SIZE && m_blocks[y+1][x][z] == 0) || (y+1 >= CHUNK_SIZE) ){
					m_mesh->position(realPos.x+x,   realPos.y+y+1, realPos.z+z+1);	m_mesh->normal(0,1,0); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y+1, realPos.z+z+1);	m_mesh->normal(0,1,0); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y+1, realPos.z+z);	m_mesh->normal(0,1,0); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x,   realPos.y+y+1, realPos.z+z);	m_mesh->normal(0,1,0); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,0.0));
					m_mesh->triangle(iVertex, iVertex+1, iVertex+2);
					m_mesh->triangle(iVertex+2, iVertex+3, iVertex);
					iVertex += 4;
				}

				// Draw back side ?
				if( (z > 0 && m_blocks[y][x][z-1] == 0) || (z == 0) ){
					m_mesh->position(realPos.x+x,   realPos.y+y+1, realPos.z+z);	m_mesh->normal(0,0,-1); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y+1, realPos.z+z);	m_mesh->normal(0,0,-1); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y,   realPos.z+z);	m_mesh->normal(0,0,-1); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x,   realPos.y+y,   realPos.z+z);	m_mesh->normal(0,0,-1); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,1.0/16.0));
					m_mesh->triangle(iVertex, iVertex+1, iVertex+2);
					m_mesh->triangle(iVertex+2, iVertex+3, iVertex);
					iVertex += 4;
				}

				// Draw front ?
				if( (z+1 < CHUNK_SIZE && m_blocks[y][x][z+1] == 0) || (z+1 >= CHUNK_SIZE) ){
					m_mesh->position(realPos.x+x,   realPos.y+y,   realPos.z+z+1);	m_mesh->normal(0,0,1); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y,   realPos.z+z+1);	m_mesh->normal(0,0,1); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,1.0/16.0));
					m_mesh->position(realPos.x+x+1, realPos.y+y+1, realPos.z+z+1);	m_mesh->normal(0,0,1); m_mesh->textureCoord(Ogre::Vector2(3.0/16.0 ,0.0));
					m_mesh->position(realPos.x+x,   realPos.y+y+1, realPos.z+z+1);	m_mesh->normal(0,0,1); m_mesh->textureCoord(Ogre::Vector2(2.0/16.0 ,0.0));
					m_mesh->triangle(iVertex, iVertex+1, iVertex+2);
					m_mesh->triangle(iVertex+2, iVertex+3, iVertex);
					iVertex += 4;
				}
			}
		}
	}
	m_mesh->end();
	m_mesh->setVisible(true);
	SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode();
	node->attachObject(m_mesh);
}


/** This class 'wibbles' the light and billboard */
class LightWibbler : public ControllerValue<Real>
{
protected:
	Light* mLight;
	Billboard* mBillboard;
	ColourValue mColourRange;
	ColourValue mMinColour;
	Real mMinSize;
	Real mSizeRange;
	Real intensity;
public:
	LightWibbler(Light* light, Billboard* billboard, const ColourValue& minColour, const ColourValue& maxColour, Real minSize, Real maxSize)
	{
		mLight = light;
		mBillboard = billboard;
		mMinColour = minColour;
		mColourRange.r = maxColour.r - minColour.r;
		mColourRange.g = maxColour.g - minColour.g;
		mColourRange.b = maxColour.b - minColour.b;
		mMinSize = minSize;
		mSizeRange = maxSize - minSize;

	}

	virtual Real  getValue (void) const
	{
		return intensity;
	}

	virtual void  setValue (Real value)
	{
		intensity = value;

		ColourValue newColour;

		// Attenuate the brightness of the light
		newColour.r = mMinColour.r + (mColourRange.r * intensity);
		newColour.g = mMinColour.g + (mColourRange.g * intensity);
		newColour.b = mMinColour.b + (mColourRange.b * intensity);

		mLight->setDiffuseColour(newColour);
		mBillboard->setColour(newColour);
		// set billboard size
		Real newSize = mMinSize + (intensity * mSizeRange);
		mBillboard->setDimensions(newSize, newSize);

	}
};

Real timeDelay = 0;

class Sample_Shadows : public SdkSample, public Ogre::WindowEventListener, public Ogre::FrameListener, public OIS::KeyListener, public OIS::MouseListener
{
protected:
	Entity* mAthene;
	AnimationState* mAnimState;
	Entity* pPlaneEnt;
	vector<Entity*>::type pColumns;
	Light* mLight;
	Light* mSunLight;
	SceneNode* mLightNode;
	AnimationState* mLightAnimationState;
	ColourValue mMinLightColour;
	ColourValue mMaxLightColour;
	Real mMinFlareSize;
	Real mMaxFlareSize;
	Controller<Real>* mController;
	bool m_shutDown;

	enum ShadowProjection
	{
		UNIFORM,
		UNIFORM_FOCUSED,
		LISPSM,
		PLANE_OPTIMAL
	};

	enum ShadowMaterial
	{
		MAT_STANDARD,
		MAT_DEPTH_FLOAT,
		MAT_DEPTH_FLOAT_PCF
	};

	typedef enum {
		MOVE_FORWARD	= 0,//!< Déplacement vers l'avant
		MOVE_BACKWARD	= 1,//!< Déplacement vers l'arrière
		MOVE_LEFT		= 2,//!< Déplacement vers la gauche
		MOVE_RIGHT		= 3,//!< Déplacement vers la droite
		MOVE_JUMP		= 4,//!< Saut/monter
		MOVE_GO_DOWN	= 5,//!< Se baisse/descendre
		MOVE_SUN_UP		= 6,
		MOVE_SUN_LEFT	= 7,
		MOVE_SUN_RIGHT	= 8,
		MOVE_SUN_DOWN	= 9,
		__MOVE_SIZE__//!< Nombre de mouvement. Doit être le dernier element ! Sert pour l'allocation fixe.
	} t_move;//!< Permet de gérer le déplacement de la camera

	ShadowTechnique mCurrentShadowTechnique;
	ShadowProjection mCurrentProjection;
	ShadowMaterial mCurrentMaterial;

	GpuProgramParametersSharedPtr mCustomRockwallVparams;
	GpuProgramParametersSharedPtr mCustomRockwallFparams;
	GpuProgramParametersSharedPtr mCustomAtheneVparams;
	GpuProgramParametersSharedPtr mCustomAtheneFparams;

	ShadowCameraSetupPtr mCurrentShadowCameraSetup;
	/// Plane that defines plane-optimal shadow mapping basis
	MovablePlane* mPlane;
	// transient pointer to LiSPSM setup if present
	LiSPSMShadowCameraSetup* mLiSPSMSetup;
	OIS::InputManager* mInputManager;

	bool mIsOpenGL;
	bool						m_camMove[__MOVE_SIZE__];//!< Gère le déplacement de la camera. @see t_move


public:
	bool frameEnded(const FrameEvent& evt)
	{
		if (mAnimState)
				mAnimState->addTime(evt.timeSinceLastFrame);
		return SdkSample::frameEnded(evt);
	}

	bool frameRenderingQueued(const Ogre::FrameEvent& evt)
	{
		if( mWindow->isClosed() || m_shutDown )
			return false;

		// Need to capture/update each device
		mKeyboard->capture();
		mMouse->capture();

		/***************************************************************************
		* System de déplacement
		*/
		if( m_camMove[MOVE_FORWARD] || m_camMove[MOVE_BACKWARD] || m_camMove[MOVE_LEFT] || m_camMove[MOVE_RIGHT] || m_camMove[MOVE_JUMP] || m_camMove[MOVE_GO_DOWN] ){
			Ogre::Vector3 goingTo = Ogre::Vector3::ZERO;
			if( m_camMove[MOVE_FORWARD] ){
				goingTo += mCamera->getDirection();
			}else if( m_camMove[MOVE_BACKWARD] ){
				goingTo -= mCamera->getDirection();
			}
			if( m_camMove[MOVE_LEFT] ){
				goingTo -= mCamera->getRight();
			}else if( m_camMove[MOVE_RIGHT] ){
				goingTo += mCamera->getRight();
			}
			if( m_camMove[MOVE_JUMP] ){
				goingTo.y = 0.6;
			}else if( m_camMove[MOVE_GO_DOWN] ){
				goingTo.y = -0.6;
			}
			mCamera->move(evt.timeSinceLastFrame*550.0*goingTo);
			printf("%f %f %f\n",mCamera->getPosition().x,mCamera->getPosition().y,mCamera->getPosition().z);
		}

		return mTrayMgr->frameRenderingQueued(evt);
	}

	Sample_Shadows()
		: mAnimState(0)
		, mLightNode(0)
		, mLightAnimationState(0)
		, mMinLightColour(0.2, 0.1, 0.0)
		, mMaxLightColour(0.5, 0.3, 0.1)
		, mMinFlareSize(40)
		, mMaxFlareSize(80)
		, mController(0)
		, mPlane(0)
	{
		for( uint8_t i=0; i<__MOVE_SIZE__; i++ )
			m_camMove[i] = false;
		m_shutDown = false;
		mInputManager = 0;
		mInfo["Title"] = "Shadows";
		mInfo["Description"] = "A demonstration of ogre's various shadowing techniques.";
		mInfo["Thumbnail"] = "thumb_shadows.png";
		mInfo["Category"] = "Lighting";

	}

	~Sample_Shadows()
	{
		//mDescWindow = 0;

		delete mPlane;
	}


	void go()
	{
		// Suppression de l'affichage de log
		(new Ogre::LogManager())->createLog("Ogre.log", true, false, false);
		Ogre::LogManager::getSingletonPtr()->setLogDetail(LL_LOW);
		// Création du noeud principale
		mRoot = new Ogre::Root("plugins.cfg", "ogre.cfg", "");

		if( !configure() )
			return ;

		Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
		OIS::ParamList pl;
		size_t windowHnd = 0;
		std::ostringstream windowHndStr;

		mWindow->getCustomAttribute("WINDOW", &windowHnd);
		windowHndStr << windowHnd;
		pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));

		mInputManager = OIS::InputManager::createInputSystem( pl );

		mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));
		mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));

		mKeyboard->setEventCallback(this);
		mMouse->setEventCallback(this);


		//Register as a Window listener
		Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
		mRoot->addFrameListener(this);

		// Set initial mouse clipping size
		windowResized(mWindow);

		__loadResources();

		_setup(mWindow, mKeyboard, mMouse, 0);

		mTrayMgr->hideCursor();

		//setupView();
		//setupContent();

		drawBlocks(mSceneMgr);


		mRoot->startRendering();

		cleanupContent();
	}

	/***************************************************************************//*!
	* @brief [EVENT] Redim de la window
	* @param[in] rw		Fenêtre de rendu
	* @return[NONE]
	* @warning Adjust mouse clipping area
	*/
	void windowResized( Ogre::RenderWindow* rw )
	{
		unsigned int width, height, depth;
		int left, top;
		rw->getMetrics(width, height, depth, left, top);

		const OIS::MouseState &ms = mMouse->getMouseState();
		ms.width = width;
		ms.height = height;
	}


	/***************************************************************************//*!
	* @brief [EVENT] Fermeture de la window
	* @param[in] rw		Fenêtre de rendu
	* @return[NONE]
	* @warning Unattach OIS before window shutdown (very important under Linux)
	*/
	void windowClosed( Ogre::RenderWindow* rw )
	{
		// Only close for window that created OIS (the main window)
		if( rw == mWindow && mInputManager ){
			mInputManager->destroyInputObject( mMouse );
			mInputManager->destroyInputObject( mKeyboard );

			OIS::InputManager::destroyInputSystem(mInputManager);
			mInputManager = 0;
		}
	}

	void __loadResources()
	{
		// Load resource paths from config file
		Ogre::ConfigFile cf;
		cf.load("resources.cfg");

		// Go through all sections & settings in the file
		Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

		Ogre::String secName, typeName, archName;
		while (seci.hasMoreElements())
		{
			secName = seci.peekNextKey();
			Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
			Ogre::ConfigFile::SettingsMultiMap::iterator i;
			for (i = settings->begin(); i != settings->end(); ++i)
			{
				typeName = i->first;
				archName = i->second;
				Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
			}
		}

		Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
		// Chargement des ressources
		Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	}

protected:

	// Override this to ensure FPU mode
	bool configure(void)
	{
		// Show the configuration dialog and initialise the system
		// You can skip this and use root.restoreConfig() to load configuration
		// settings if you were sure there are valid ones saved in ogre.cfg
		if( mRoot->restoreConfig() || mRoot->showConfigDialog() )
		{
/*
			// Custom option - to use PlaneOptimalShadowCameraSetup we must have
			// double-precision. Thus, set the D3D floating point mode if present,
			// no matter what was chosen
			ConfigOptionMap& optMap = mRoot->getRenderSystem()->getConfigOptions();
			ConfigOptionMap::iterator i = optMap.find("Floating-point mode");
			if (i != optMap.end())
			{
				if (i->second.currentValue != "Consistent")
				{
					i->second.currentValue = "Consistent";
					LogManager::getSingleton().logMessage("Demo_Shadows: overriding "
						"D3D floating point mode to 'Consistent' to ensure precision "
						"for plane-optimal camera setup option");

				}
			}
//*/
			// If returned true, user clicked OK so initialise
			// Here we choose to let the system create a default rendering window by passing 'true'
			mWindow = mRoot->initialise(true);
			return true;
		}
		return false;
	}

	// Just override the mandatory create scene method
	void setupContent(void)
	{
		// Need to detect D3D or GL for best depth shadowmapping
		mIsOpenGL = Root::getSingleton().getRenderSystem()->getName().find("GL") != String::npos;

		// do this first so we generate edge lists
		mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
		mCurrentShadowTechnique = SHADOWTYPE_STENCIL_ADDITIVE;

		// Set ambient light off
		mSceneMgr->setAmbientLight(ColourValue(0.0, 0.0, 0.0));

		// Fixed light, dim
		mSunLight = mSceneMgr->createLight("SunLight");
		mSunLight->setType(Light::LT_SPOTLIGHT);
		mSunLight->setPosition(1500,1750,1300);
		mSunLight->setSpotlightRange(Degree(30), Degree(50));
		Vector3 dir;
		dir = -mSunLight->getPosition();
		dir.normalise();
		mSunLight->setDirection(dir);
		mSunLight->setDiffuseColour(0.35, 0.35, 0.38);
		mSunLight->setSpecularColour(0.9, 0.9, 1);

		// Point light, movable, reddish
		mLight = mSceneMgr->createLight("Light2");
		mLight->setDiffuseColour(mMinLightColour);
		mLight->setSpecularColour(1, 1, 1);
		mLight->setAttenuation(8000,1,0.0005,0);

		// Create light node
		mLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("MovingLightNode");
		mLightNode->attachObject(mLight);
		// create billboard set
		BillboardSet* bbs = mSceneMgr->createBillboardSet("lightbbs", 1);
		bbs->setMaterialName("Examples/Flare");
		Billboard* bb = bbs->createBillboard(0,0,0,mMinLightColour);
		// attach
		mLightNode->attachObject(bbs);

		// create controller, after this is will get updated on its own
		ControllerFunctionRealPtr func = ControllerFunctionRealPtr(new WaveformControllerFunction(Ogre::WFT_SINE, 0.75, 0.5));
		ControllerManager& contMgr = ControllerManager::getSingleton();
		ControllerValueRealPtr val = ControllerValueRealPtr(new LightWibbler(mLight, bb, mMinLightColour, mMaxLightColour, mMinFlareSize, mMaxFlareSize));
		mController = contMgr.createController(contMgr.getFrameTimeSource(), val, func);

		//mLight->setPosition(Vector3(300,250,-300));
		mLightNode->setPosition(Vector3(300,1750,-700));


		// Create a track for the light
		Animation* anim = mSceneMgr->createAnimation("LightTrack", 20);
		// Spline it for nice curves
		anim->setInterpolationMode(Animation::IM_SPLINE);
		// Create a track to animate the camera's node
		NodeAnimationTrack* track = anim->createNodeTrack(0, mLightNode);
		// Setup keyframes
		TransformKeyFrame* key = track->createNodeKeyFrame(0); // A startposition
		key->setTranslate(Vector3(300,750,-700));
		key = track->createNodeKeyFrame(2);//B
		key->setTranslate(Vector3(150,800,-250));
		key = track->createNodeKeyFrame(4);//C
		key->setTranslate(Vector3(-150,850,-100));
		key = track->createNodeKeyFrame(6);//D
		key->setTranslate(Vector3(-400,700,-200));
		key = track->createNodeKeyFrame(8);//E
		key->setTranslate(Vector3(-200,700,-400));
		key = track->createNodeKeyFrame(10);//F
		key->setTranslate(Vector3(-100,850,-200));
		key = track->createNodeKeyFrame(12);//G
		key->setTranslate(Vector3(-100,575,180));
		key = track->createNodeKeyFrame(14);//H
		key->setTranslate(Vector3(0,750,300));
		key = track->createNodeKeyFrame(16);//I
		key->setTranslate(Vector3(100,850,100));
		key = track->createNodeKeyFrame(18);//J
		key->setTranslate(Vector3(250,800,0));
		key = track->createNodeKeyFrame(20);//K == A
		key->setTranslate(Vector3(300,750,-700));
		// Create a new animation state to track this
		mAnimState = mSceneMgr->createAnimationState("LightTrack");
		mAnimState->setEnabled(true);
		// Make light node look at origin, this is for when we
		// change the moving light to a spotlight
		mLightNode->setAutoTracking(true, mSceneMgr->getRootSceneNode());

		// Prepare athene mesh for normalmapping
		MeshPtr pAthene = MeshManager::getSingleton().load("athene.mesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
		unsigned short src, dest;
		if (!pAthene->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
		{
			pAthene->buildTangentVectors(VES_TANGENT, src, dest);
		}

		SceneNode* node;
		node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
		mAthene = mSceneMgr->createEntity( "athene", "athene.mesh" );
		mAthene->setMaterialName(BASIC_ATHENE_MATERIAL);
		node->attachObject( mAthene );
		node->translate(0,-27, 0);
		node->yaw(Degree(90));

		Entity* pEnt;
		// Columns
		for (int x = -2; x <= 2; ++x)
		{
			for (int z = -2; z <= 2; ++z)
			{
				if (x != 0 || z != 0)
				{
					StringUtil::StrStreamType str;
					str << "col" << x << "_" << z;
					node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
					pEnt = mSceneMgr->createEntity( str.str(), "column.mesh" );
					pEnt->setMaterialName(BASIC_ROCKWALL_MATERIAL);
					pColumns.push_back(pEnt);
					node->attachObject( pEnt );
					node->translate(x*300,0, z*300);

				}
			}

		}


		// Skybox
		mSceneMgr->setSkyBox(true, "Examples/StormySkyBox");

		// Floor plane (use POSM plane def)
		mPlane = new MovablePlane("*mPlane");
		mPlane->normal = Vector3::UNIT_Y;
		mPlane->d = 107;
		MeshManager::getSingleton().createPlane("Myplane",
			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, *mPlane,
			1500,1500,50,50,true,1,5,5,Vector3::UNIT_Z);
		pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
		pPlaneEnt->setMaterialName(BASIC_ROCKWALL_MATERIAL);
		pPlaneEnt->setCastShadows(false);
		mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

		if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_HWRENDER_TO_TEXTURE))
		{
			// In D3D, use a 1024x1024 shadow texture
			mSceneMgr->setShadowTextureSettings(1024, 2);
		}
		else
		{
			// Use 512x512 texture in GL since we can't go higher than the window res
			mSceneMgr->setShadowTextureSettings(512, 2);
		}

		mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
		//mSceneMgr->setShowDebugShadows(true);

		setupGUI();
		setDragLook(true);
	}

	virtual void setupView()
	{
		SdkSample::setupView();

		// incase infinite far distance is not supported
		mCamera->setFarClipDistance(100000);

		mCamera->setPosition(250, 20, 400);
		mCamera->lookAt(0, 10, 0);
	}

	virtual void cleanupContent()
	{
		ControllerManager::getSingleton().destroyController(mController);
	}

	/// Change basic shadow technique
	void changeShadowTechnique(ShadowTechnique newTech)
	{
		mSceneMgr->setShadowTechnique(newTech);

		// Below is for projection
		//configureShadowCameras(mCurrentShadowTechnique, newTech);

		configureLights(newTech);

		// Advanced modes - materials / compositors
		//configureCompositors(mCurrentShadowTechnique, newTech);
		//configureTextures(mCurrentShadowTechnique, newTech);
		//configureShadowCasterReceiverMaterials(mCurrentShadowTechnique, newTech);

		updateGUI(newTech);

		mCurrentShadowTechnique = newTech;
	}

	void configureLights(ShadowTechnique newTech)
	{
		Vector3 dir;
		switch (newTech)
		{
		case SHADOWTYPE_STENCIL_ADDITIVE:
			// Fixed light, dim
			mSunLight->setCastShadows(true);

			// Point light, movable, reddish
			mLight->setType(Light::LT_POINT);
			mLight->setCastShadows(true);
			mLight->setDiffuseColour(mMinLightColour);
			mLight->setSpecularColour(1, 1, 1);
			mLight->setAttenuation(8000,1,0.0005,0);

			break;
		case SHADOWTYPE_STENCIL_MODULATIVE:
			// Multiple lights cause obvious silhouette edges in modulative mode
			// So turn off shadows on the direct light
			// Fixed light, dim
			mSunLight->setCastShadows(false);

			// Point light, movable, reddish
			mLight->setType(Light::LT_POINT);
			mLight->setCastShadows(true);
			mLight->setDiffuseColour(mMinLightColour);
			mLight->setSpecularColour(1, 1, 1);
			mLight->setAttenuation(8000,1,0.0005,0);
			break;
		case SHADOWTYPE_TEXTURE_MODULATIVE:
		case SHADOWTYPE_TEXTURE_ADDITIVE:
			// Fixed light, dim
			mSunLight->setCastShadows(true);

			// Change moving light to spotlight
			// Point light, movable, reddish
			mLight->setType(Light::LT_SPOTLIGHT);
			mLight->setDirection(Vector3::NEGATIVE_UNIT_Z);
			mLight->setCastShadows(true);
			mLight->setDiffuseColour(mMinLightColour);
			mLight->setSpecularColour(1, 1, 1);
			mLight->setAttenuation(8000,1,0.0005,0);
			mLight->setSpotlightRange(Degree(80),Degree(90));


			break;
		default:
			break;
		};

	}

	SelectMenu* mTechniqueMenu;
	SelectMenu* mLightingMenu;
	SelectMenu* mProjectionMenu;
	SelectMenu* mMaterialMenu;

	Slider* mFixedBiasSlider;
	Slider* mSlopedBiasSlider;
	Slider* mClampSlider;

	void setupGUI()
	{
		mTechniqueMenu = mTrayMgr->createLongSelectMenu(
			TL_TOPLEFT, "TechniqueSelectMenu", "Technique", 300, 200, 5);
		mTechniqueMenu->addItem("Stencil");
		mTechniqueMenu->addItem("Texture");

		mLightingMenu = mTrayMgr->createLongSelectMenu(
			TL_TOPLEFT, "LightingSelectMenu", "Lighting", 300, 200, 5);
		mLightingMenu->addItem("Additive");
		mLightingMenu->addItem("Modulative");

		//These values are synchronized with ShadowProjection enum
		mProjectionMenu = mTrayMgr->createLongSelectMenu(
			TL_TOPLEFT, "ProjectionSelectMenu", "Projection", 300, 200, 5);
		mProjectionMenu->addItem("Uniform");
		mProjectionMenu->addItem("Uniform Focused");
		mProjectionMenu->addItem("LiSPSM");
		mProjectionMenu->addItem("Plane Optimal");

		mMaterialMenu = mTrayMgr->createLongSelectMenu(
			TL_TOPLEFT, "MaterialSelectMenu", "Material", 300, 200, 5);
		mMaterialMenu->addItem("Standard");
		mMaterialMenu->addItem("Depth Shadowmap");
		mMaterialMenu->addItem("Depth Shadowmap (PCF)");

		mFixedBiasSlider = mTrayMgr->createThickSlider(TL_NONE, "FixedBiasSlider", "Fixed Bias", 256, 80, 0, 0.02, 100);
		mFixedBiasSlider->setValue(0.0009, false);
		mFixedBiasSlider->hide();

		mSlopedBiasSlider = mTrayMgr->createThickSlider(TL_NONE, "SlopedBiasSlider", "Sloped Bias", 256, 80, 0, 0.2, 100);
		mSlopedBiasSlider->setValue(0.0008, false);
		mSlopedBiasSlider->hide();

		mClampSlider = mTrayMgr->createThickSlider(TL_NONE, "SlopeClampSlider", "Slope Clamp", 256, 80, 0, 2, 100);
		mClampSlider->setValue(0.2, false);
		mClampSlider->hide();

		updateGUI(mCurrentShadowTechnique);
		mTrayMgr->showCursor();
	}

	void updateGUI(ShadowTechnique newTech)
	{
		bool isTextureBased = (newTech & SHADOWDETAILTYPE_TEXTURE) != 0;

		if (isTextureBased)
		{
			mProjectionMenu->show();
			mTrayMgr->moveWidgetToTray(mProjectionMenu, TL_TOPLEFT);
			mMaterialMenu->show();
			mTrayMgr->moveWidgetToTray(mMaterialMenu, TL_TOPLEFT);
		}
		else
		{
			mProjectionMenu->hide();
			mTrayMgr->removeWidgetFromTray(mProjectionMenu);
			mMaterialMenu->hide();
			mTrayMgr->removeWidgetFromTray(mMaterialMenu);
		}
	}

	void itemSelected(SelectMenu* menu)
	{
		if (menu == mTechniqueMenu) handleShadowTypeChanged();
		else if (menu == mLightingMenu) handleShadowTypeChanged();
		else if (menu == mProjectionMenu) handleProjectionChanged();
		else if (menu == mMaterialMenu) handleMaterialChanged();
	}


	void handleShadowTypeChanged()
	{
		bool isStencil = mTechniqueMenu->getSelectionIndex() == 0;
		bool isAdditive = mLightingMenu->getSelectionIndex() == 0;
		ShadowTechnique newTech = mCurrentShadowTechnique;

		if (isStencil)
		{
			newTech = static_cast<ShadowTechnique>(
				(newTech & ~SHADOWDETAILTYPE_TEXTURE) | SHADOWDETAILTYPE_STENCIL);
			resetMaterials();
		}
		else
		{
			newTech = static_cast<ShadowTechnique>(
				(newTech & ~SHADOWDETAILTYPE_STENCIL) | SHADOWDETAILTYPE_TEXTURE);
		}

		if (isAdditive)
		{
			newTech = static_cast<ShadowTechnique>(
				(newTech & ~SHADOWDETAILTYPE_MODULATIVE) | SHADOWDETAILTYPE_ADDITIVE);
		}
		else
		{
			newTech = static_cast<ShadowTechnique>(
				(newTech & ~SHADOWDETAILTYPE_ADDITIVE) | SHADOWDETAILTYPE_MODULATIVE);
		}

		changeShadowTechnique(newTech);
	}

	void handleProjectionChanged()
	{
		ShadowProjection proj = (ShadowProjection)mProjectionMenu->getSelectionIndex();

		if (proj != mCurrentProjection)
		{
			switch(proj)
			{
			case UNIFORM:
				mCurrentShadowCameraSetup =
					ShadowCameraSetupPtr(new DefaultShadowCameraSetup());
				break;
			case UNIFORM_FOCUSED:
				mCurrentShadowCameraSetup =
					ShadowCameraSetupPtr(new FocusedShadowCameraSetup());
				break;
			case LISPSM:
				{
					mLiSPSMSetup = new LiSPSMShadowCameraSetup();
					//mLiSPSMSetup->setUseAggressiveFocusRegion(false);
					mCurrentShadowCameraSetup = ShadowCameraSetupPtr(mLiSPSMSetup);
				}
				break;
			case PLANE_OPTIMAL:
				mCurrentShadowCameraSetup =
					ShadowCameraSetupPtr(new PlaneOptimalShadowCameraSetup(mPlane));
				break;

			};
			mCurrentProjection = proj;

			mSceneMgr->setShadowCameraSetup(mCurrentShadowCameraSetup);

			//updateTipForCombo(cbo);
			if (!mCustomRockwallVparams.isNull() && !mCustomRockwallFparams.isNull())
			{
				// set
				setDefaultDepthShadowParams();
			}

		}
	}

	void updateDepthShadowParams()
	{
		mCustomRockwallFparams->setNamedConstant("fixedDepthBias",
			mFixedBiasSlider->getValue());
		mCustomRockwallFparams->setNamedConstant("gradientScaleBias",
			mSlopedBiasSlider->getValue());
		mCustomRockwallFparams->setNamedConstant("gradientClamp",
			mClampSlider->getValue());

		mCustomAtheneFparams->setNamedConstant("fixedDepthBias",
			mFixedBiasSlider->getValue());
		mCustomAtheneFparams->setNamedConstant("gradientScaleBias",
			mSlopedBiasSlider->getValue());
		mCustomAtheneFparams->setNamedConstant("gradientClamp",
			mClampSlider->getValue());
	}

	void setDefaultDepthShadowParams()
	{
		switch(mCurrentProjection)
		{
		case UNIFORM:
		case UNIFORM_FOCUSED:
		case PLANE_OPTIMAL:
			mFixedBiasSlider->setValue(0.0f, false);
			mSlopedBiasSlider->setValue(0.0f, false);
			break;
		case LISPSM:
			mFixedBiasSlider->setValue(0.009f, false);
			mSlopedBiasSlider->setValue(0.04f, false);
			break;
		};

		updateDepthShadowParams();

	}

	void sliderMoved(Slider* slider)
	{
		(void)slider;
		if (!mCustomRockwallVparams.isNull() && !mCustomRockwallFparams.isNull())
		{
			updateDepthShadowParams();
		}
	}

	void rebindDebugShadowOverlays()
	{
		/*MaterialPtr debugMat =
			MaterialManager::getSingleton().getByName("Ogre/DebugShadowMap0");
		TexturePtr shadowTex = mSceneMgr->getShadowTexture(0);
		debugMat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(shadowTex->getName());

		debugMat =
			MaterialManager::getSingleton().getByName("Ogre/DebugShadowMap1");
		shadowTex = mSceneMgr->getShadowTexture(1);
		debugMat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(shadowTex->getName());*/
	}

	void resetMaterials()
	{
		// Sort out base materials
		pPlaneEnt->setMaterialName(BASIC_ROCKWALL_MATERIAL);
		mAthene->setMaterialName(BASIC_ATHENE_MATERIAL);
		for (vector<Entity*>::type::iterator i = pColumns.begin();
			i != pColumns.end(); ++i)
		{
			(*i)->setMaterialName(BASIC_ROCKWALL_MATERIAL);
		}

		mCustomRockwallVparams.setNull();
		mCustomRockwallFparams.setNull();
		mCustomAtheneVparams.setNull();
		mCustomAtheneFparams.setNull();

	}

	void handleMaterialChanged()
	{
		bool showSliders = false;
		ShadowMaterial mat = (ShadowMaterial)mMaterialMenu->getSelectionIndex();
		MaterialPtr themat;
		if (mat != mCurrentMaterial)
		{
			switch(mat)
			{
			case MAT_STANDARD:
				mSceneMgr->setShadowTexturePixelFormat(PF_X8R8G8B8);
				mSceneMgr->setShadowTextureCasterMaterial(StringUtil::BLANK);
				mSceneMgr->setShadowTextureReceiverMaterial(StringUtil::BLANK);
				mSceneMgr->setShadowTextureSelfShadow(false);

				resetMaterials();

				break;
			case MAT_DEPTH_FLOAT:
				if (mIsOpenGL)
				{
					// GL performs much better if you pick half-float format
					mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT16_R);
				}
				else
				{
					// D3D is the opposite - if you ask for PF_FLOAT16_R you
					// get an integer format instead! You can ask for PF_FLOAT16_GR
					// but the precision doesn't work well
					mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
				}
				mSceneMgr->setShadowTextureCasterMaterial(CUSTOM_CASTER_MATERIAL);
				mSceneMgr->setShadowTextureReceiverMaterial(CUSTOM_RECEIVER_MATERIAL);
				mSceneMgr->setShadowTextureSelfShadow(true);
				// Sort out base materials
				pPlaneEnt->setMaterialName(CUSTOM_ROCKWALL_MATERIAL);
				mAthene->setMaterialName(CUSTOM_ATHENE_MATERIAL);
				for (vector<Entity*>::type::iterator i = pColumns.begin();
					i != pColumns.end(); ++i)
				{
					(*i)->setMaterialName(CUSTOM_ROCKWALL_MATERIAL);
				}

				themat = MaterialManager::getSingleton().getByName(CUSTOM_ROCKWALL_MATERIAL);
				mCustomRockwallVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
				mCustomRockwallFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
				themat = MaterialManager::getSingleton().getByName(CUSTOM_ATHENE_MATERIAL);
				mCustomAtheneVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
				mCustomAtheneFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
				showSliders = true;


				// set the current params
				setDefaultDepthShadowParams();
				break;
			case MAT_DEPTH_FLOAT_PCF:
				if (mIsOpenGL)
				{
					// GL performs much better if you pick half-float format
					mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT16_R);
				}
				else
				{
					// D3D is the opposite - if you ask for PF_FLOAT16_R you
					// get an integer format instead! You can ask for PF_FLOAT16_GR
					// but the precision doesn't work well
					mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
				}
				mSceneMgr->setShadowTextureCasterMaterial(CUSTOM_CASTER_MATERIAL);
				mSceneMgr->setShadowTextureReceiverMaterial(CUSTOM_RECEIVER_MATERIAL + "/PCF");
				mSceneMgr->setShadowTextureSelfShadow(true);
				// Sort out base materials
				pPlaneEnt->setMaterialName(CUSTOM_ROCKWALL_MATERIAL + "/PCF");
				mAthene->setMaterialName(CUSTOM_ATHENE_MATERIAL + "/PCF");
				for (vector<Entity*>::type::iterator i = pColumns.begin();
					i != pColumns.end(); ++i)
				{
					(*i)->setMaterialName(CUSTOM_ROCKWALL_MATERIAL + "/PCF");
				}

				themat = MaterialManager::getSingleton().getByName(CUSTOM_ROCKWALL_MATERIAL + "/PCF");
				mCustomRockwallVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
				mCustomRockwallFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
				themat = MaterialManager::getSingleton().getByName(CUSTOM_ATHENE_MATERIAL + "/PCF");
				mCustomAtheneVparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverVertexProgramParameters();
				mCustomAtheneFparams = themat->getTechnique(0)->getPass(1)->getShadowReceiverFragmentProgramParameters();
				showSliders = true;

				// set the current params
				setDefaultDepthShadowParams();
				break;
			};
			mCurrentMaterial = mat;

			if (showSliders)
			{
				mFixedBiasSlider->show();
				mTrayMgr->moveWidgetToTray(mFixedBiasSlider, TL_TOPRIGHT);
				mSlopedBiasSlider->show();
				mTrayMgr->moveWidgetToTray(mSlopedBiasSlider, TL_TOPRIGHT);
				mClampSlider->show();
				mTrayMgr->moveWidgetToTray(mClampSlider, TL_TOPRIGHT);
			}
			else
			{
				mFixedBiasSlider->hide();
				mTrayMgr->removeWidgetFromTray(mFixedBiasSlider);
				mSlopedBiasSlider->hide();
				mTrayMgr->removeWidgetFromTray(mSlopedBiasSlider);
				mClampSlider->hide();
				mTrayMgr->removeWidgetFromTray(mClampSlider);
			}
			//updateTipForCombo(cbo);
			//rebindDebugShadowOverlays();
		}
	}

	bool keyPressed(const OIS::KeyEvent& evt) {
		if( evt.key == OIS::KC_ESCAPE )
			m_shutDown = true;
		/***************************************************************************
		* Touches de déplacement
		*/
		if( evt.key == OIS::KC_Z ){
			m_camMove[MOVE_FORWARD] = true;
		}else if( evt.key == OIS::KC_S ){
			m_camMove[MOVE_BACKWARD] = true;
		}
		if( evt.key == OIS::KC_D ){
			m_camMove[MOVE_RIGHT] = true;
		}else if( evt.key == OIS::KC_Q ){
			m_camMove[MOVE_LEFT] = true;
		}

		if( evt.key == OIS::KC_SPACE ){
			m_camMove[MOVE_JUMP] = true;
		}else if( evt.key == OIS::KC_LSHIFT ){
			m_camMove[MOVE_GO_DOWN] = true;
		}
		return true;
	}
	bool keyReleased(const OIS::KeyEvent& evt) {
		/***************************************************************************
		* Touches de déplacement
		*/
		if( evt.key == OIS::KC_Z )
			m_camMove[MOVE_FORWARD] = false;
		if( evt.key == OIS::KC_S )
			m_camMove[MOVE_BACKWARD] = false;
		if( evt.key == OIS::KC_D )
			m_camMove[MOVE_RIGHT] = false;
		if( evt.key == OIS::KC_Q )
			m_camMove[MOVE_LEFT] = false;
		if( evt.key == OIS::KC_SPACE )
			m_camMove[MOVE_JUMP] = false;
		if( evt.key == OIS::KC_LSHIFT )
			m_camMove[MOVE_GO_DOWN] = false;
		return true;
	}
	bool mouseMoved(const OIS::MouseEvent& evt) {
		mCamera->yaw(Ogre::Degree(-evt.state.X.rel * 0.15f));
		mCamera->pitch(Ogre::Degree(-evt.state.Y.rel * 0.15f));
		return true;
	}
	bool mousePressed(const OIS::MouseEvent& evt, OIS::MouseButtonID id) { return mTrayMgr->injectMouseDown(evt,id); }
	bool mouseReleased(const OIS::MouseEvent& evt, OIS::MouseButtonID id) { return mTrayMgr->injectMouseUp(evt,id); }
};


int main()
{
	try {
		Sample_Shadows shadow;
		shadow.go();
	} catch( Ogre::Exception& e ) {
		printf("An exception has occured: %s\n", e.getFullDescription().c_str());
	}
	return 0;
}
Material:

Code: Select all

// Specific receiver material for rockwall
material terrain
{

	// This is the preferred technique which uses both vertex and
	// fragment programs, supports coloured lights
	technique
	{
		// Base ambient pass
		pass
		{
			// base colours, not needed for rendering, but as information
			// to lighting pass categorisation routine
			ambient 1 1 1
			diffuse 0 0 0
			specular 0 0 0 0
			// Really basic vertex program
			vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTextureUnified
			{
			}

		}
		// Now do the lighting pass
		// NB we don't do decal texture here because this is repeated per light
		pass lighting
		{
			// base colours, not needed for rendering, but as information
			// to lighting pass categorisation routine
			ambient 0 0 0

			// do this for each light
			iteration once_per_light


			scene_blend add

			// Vertex program reference
			vertex_program_ref Ogre/DepthShadowmap/ReceiverVP
			{
			}
			shadow_receiver_vertex_program_ref Ogre/DepthShadowmap/ReceiverVP
			{
			}

			// Fragment program
			fragment_program_ref Ogre/DepthShadowmap/ReceiverFP
			{
			}
			shadow_receiver_fragment_program_ref Ogre/DepthShadowmap/ReceiverFP
			{
			}

			// shadowmap texture will be bound by code

		}

		// Decal pass
		pass
		{
			// base colours, not needed for rendering, but as information
			// to lighting pass categorisation routine
			lighting off
			// Really basic vertex program
			vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTextureUnified
			{
				param_named ambient float4 1 1 1 1
			}
			scene_blend dest_colour zero


			texture_unit
			{
				texture terrain.png
				//scene_blend alpha_blend
			}

		}
	}
}
Compil command:

Code: Select all

g++ -isystem /usr/include/OGRE -isystem /usr/include/OIS -Os -fdata-sections -ffunction-sections -pipe Shadows.cpp -s -Wl,--gc-sections -Wl,-O1 -lOgreMain -lOIS -lm && ./a.out
Note: My Block are very small, near athena
For texture: fc08.deviantart.net/fs70/f/2010/347/1/2/minecraft___terrain_pack_1_by_rebecca1208-d34sx9f.png
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80
Contact:

Re: ManualObject and Shadow: cast & receive

Post by duststorm »

I believe you need to build edgelists for your meshes when using stencil shadows. (since you seem to be using manualObject created objects)
Developer @ MakeHuman.org
IPC
Gnoblar
Posts: 11
Joined: Mon Aug 06, 2012 8:46 pm

Re: ManualObject and Shadow: cast & receive

Post by IPC »

Hello

I have found The solution ! ( Original: http://www.ogre3d.org/forums/viewtopic.php?f=22&t=69087 )
In fact, this is a bug of Ogre ( actualy 1.8.1 ).

For having shadow for a ManualObject:

Code: Select all

Ogre::ManualObject* mo = sceneMgr->createManualObject();

// Note: MyMaterial does not need special adaptation
mo->begin("MyMaterial", Ogre::RenderOperation::OT_TRIANGLE_LIST);

// Making Here a simple square
mo->position(0,5,0);
mo->position(0,5,100);
mo->position(100,5,100);
mo->position(100,5,0);

// You have 3 choices: index, triangle, quad. YOU NEED TO USE INDEXES !!!! IF NO INDEXES => NO SHADOW
mo->triangle(0,1,2);
mo->triangle(2,3,0);

mo->triangle(0,3,2);
mo->triangle(2,1,0);

mo->setVisible(true);
mo->setCastShadows(true);

// HERE THE BEST LINE !!!!!
// THIS LINE ENABLE CORRECT SHADOW FOR MANUALOBJECT
((Ogre::VertexData*)(mo->getEdgeList()->edgeGroups.at(0).vertexData))->prepareForShadowVolume();


mo->end();

sceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mo);
Bye
Immortal-PC
xEvilReeperx
Gnoblar
Posts: 3
Joined: Sat Jan 26, 2013 6:43 pm

Re: [SOLVED] ManualObject and Shadow: cast & receive

Post by xEvilReeperx »

Just for clarity for future people who might come across the same problem: make sure you have Ogre build the edge lists for each sub mesh. IPC's code assumes the ManualObject consists of only 1 sub mesh. It's obvious to me in hindsight but I thought I'd mention it in case anyone else glosses over the index value in edgeGroups like I did
IPC
Gnoblar
Posts: 11
Joined: Mon Aug 06, 2012 8:46 pm

Re: [SOLVED] ManualObject and Shadow: cast & receive

Post by IPC »

Hello,

for having all submesh:

Code: Select all

Ogre::EdgeData::EdgeGroupList::iterator itShadow, itEndShadow;
for( itShadow=m_mesh->getEdgeList()->edgeGroups.begin(), itEndShadow=m_mesh->getEdgeList()->edgeGroups.end(); itShadow!=itEndShadow; itShadow++ )
	const_cast<Ogre::VertexData*>((*itShadow).vertexData)->prepareForShadowVolume();
Romulus
Gnoblar
Posts: 1
Joined: Tue Mar 19, 2013 4:32 pm

Re: ManualObject and Shadow: cast & receive

Post by Romulus »

I guess you have to call

Code: Select all

((Ogre::VertexData*)(mo->getEdgeList()->edgeGroups.at(0).vertexData))->prepareForShadowVolume();
actually after

Code: Select all

mo->end();
at least I get an exception otherwise... Also this doesn't seem to work with SHADOWTYPE_STENCIL_ADDITIVE, but maybe my ManualObject accounts for that. Does anyone know if vertex redundancy may cause some trouble here?
IPC
Gnoblar
Posts: 11
Joined: Mon Aug 06, 2012 8:46 pm

Re: [SOLVED] ManualObject and Shadow: cast & receive

Post by IPC »

Hello !

Oups for

Code: Select all

mo->end();
New good code:

Code: Select all

    // Shadow type supported:
    //sceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_MODULATIVE);
    sceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);

    Ogre::ManualObject* mo = sceneMgr->createManualObject();

    // Note: MyMaterial does not need special adaptation
    mo->begin("MyMaterial", Ogre::RenderOperation::OT_TRIANGLE_LIST);

    // Making Here a simple square
    mo->position(0,5,0);
    mo->position(0,5,100);
    mo->position(100,5,100);
    mo->position(100,5,0);

    // You have 3 choices: index, triangle, quad. YOU NEED TO USE INDEXES !!!! IF NO INDEXES => NO SHADOW
    mo->triangle(0,1,2);
    mo->triangle(2,3,0);

    mo->triangle(0,3,2);
    mo->triangle(2,1,0);

    mo->setVisible(true);
    mo->setCastShadows(true);

    mo->end();//!< IMPORTANT !

    // HERE THE BEST LINE !!!!!
    // THIS LINE ENABLE CORRECT SHADOW FOR MANUALOBJECT
    // IF YOU HAVE 1 SUBMESH
    ((Ogre::VertexData*)(mo->getEdgeList()->edgeGroups.at(0).vertexData))->prepareForShadowVolume();

    // == OR ==
    // IF YOU HAVE MORE THAN 1 SUBMESH
    Ogre::EdgeData::EdgeGroupList::iterator itShadow, itEndShadow;
    for( itShadow=m_mesh->getEdgeList()->edgeGroups.begin(), itEndShadow=m_mesh->getEdgeList()->edgeGroups.end(); itShadow!=itEndShadow; itShadow++ )
        const_cast<Ogre::VertexData*>((*itShadow).vertexData)->prepareForShadowVolume();

    sceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mo);
This code will work for all shadow Ogre::SHADOWTYPE_STENCIL_*
Note I use Ogre::SHADOWTYPE_STENCIL_ADDITIVE and it works.
Post Reply