//! Called by the engine when the vertex and/or pixel shader constants for an
//! material renderer should be set.
void COpenGLParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
{
	video::IVideoDriver* driver = services->getVideoDriver();

	// set transposed world matrix
	const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed();
	services->setVertexShaderConstant(tWorld.pointer(), 0, 4);

	// The  viewpoint is at (0., 0., 0.) in eye space.
	// Turning this into a vector [0 0 0 1] and multiply it by
	// the inverse of the view matrix, the resulting vector is the
	// object space location of the camera.

	f32 floats[4] = {0.0f,0.0f,0.0f,1.0f};
	core::matrix4 minv(driver->getTransform(video::ETS_VIEW));
	minv.makeInverse();
	minv.multiplyWith1x4Matrix(floats);
	services->setVertexShaderConstant(floats, 16, 1);

	// set transposed worldViewProj matrix
	core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
	worldViewProj *= driver->getTransform(video::ETS_VIEW);
	worldViewProj *= driver->getTransform(video::ETS_WORLD);
	core::matrix4 tr(worldViewProj.getTransposed());
	services->setVertexShaderConstant(tr.pointer(), 8, 4);

	// here we fetch the fixed function lights from the driver
	// and set them as constants

	u32 cnt = driver->getDynamicLightCount();

	for (u32 i=0; i<2; ++i)
	{
		video::SLight light;

		if (i<cnt)
			light = driver->getDynamicLight(i);
		else
		{
			light.DiffuseColor.set(0,0,0); // make light dark
			light.Radius = 1.0f;
		}

		light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation

		services->setVertexShaderConstant(
			reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);

		services->setVertexShaderConstant(
			reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
	}

	// set scale factor
	f32 factor = 0.02f; // default value
	if (CurrentScale != 0.0f)
		factor = CurrentScale;

	f32 c6[] = {factor, factor, factor, factor};
	services->setPixelShaderConstant(c6, 0, 1);
}
	//! Called by the engine when the vertex and/or pixel shader constants for an
	//! material renderer should be set.
	void COpenGLNormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, SINT32 userData)
	{
		IVideoDriver* driver = services->getVideoDriver();

		// set transposed world matrix
		//const Matrix4& tWorld = driver->getTransform(ETS_WORLD).getTransposed();
		Matrix4 tWorld = driver->getTransform(ETS_WORLD);
		services->setVertexShaderConstant(tWorld.pointer(), 0, 4);

		// set transposed worldViewProj matrix
		Matrix4 worldViewProj(driver->getTransform(ETS_PROJECTION));
		//worldViewProj *= driver->getTransform(ETS_VIEW);
		//worldViewProj *= driver->getTransform(ETS_WORLD);
		worldViewProj = driver->getTransform(ETS_VIEW)*worldViewProj;
		worldViewProj = driver->getTransform(ETS_WORLD)*worldViewProj;
		//Matrix4 tr(worldViewProj.getTransposed());
		Matrix4 tr(worldViewProj);
		services->setVertexShaderConstant(tr.pointer(), 8, 4);

		// here we fetch the fixed function lights from the driver
		// and set them as constants

		UINT32 cnt = driver->getDynamicLightCount();

		// Load the inverse world matrix.
		Matrix4 invWorldMat;
		driver->getTransform(ETS_WORLD).getInverse(invWorldMat);

		for (UINT32 i = 0; i<2; ++i)
		{
			SLight light;

			if (i<cnt)
				light = driver->getDynamicLight(i);
			else
			{
				//light.DiffuseColor.set(0, 0, 0); // make light dark
				light.DiffuseColor = ColourValue(0, 0, 0); // make light dark
				light.Radius = 1.0f;
			}

			light.DiffuseColor.a = 1.0f / (light.Radius*light.Radius); // set attenuation

			// Transform the light by the inverse world matrix to get it into object space.
			//invWorldMat.transformVect(light.Position);
			light.Position = invWorldMat.transformAffine(light.Position);
			

			services->setVertexShaderConstant(
				reinterpret_cast<const Real*>(&light.Position), 12 + (i * 2), 1);

			services->setVertexShaderConstant(
				reinterpret_cast<const Real*>(&light.DiffuseColor), 13 + (i * 2), 1);
		}
	}
	//! Called by the engine when the vertex and/or pixel shader constants
	//! for an material renderer should be set.
	void COGLES2NormalMapRenderer::OnSetConstants( IMaterialRendererServices* services, s32 userData )
	{
		video::IVideoDriver* driver = services->getVideoDriver();

		// set transposed worldViewProj matrix
		core::matrix4 worldViewProj( driver->getTransform( video::ETS_PROJECTION ) );
		worldViewProj *= driver->getTransform( video::ETS_VIEW );
		worldViewProj *= driver->getTransform( video::ETS_WORLD );
		setUniform( MVP_MATRIX, worldViewProj.pointer() );

		// here we fetch the fixed function lights from the driver
		// and set them as constants

		u32 cnt = driver->getDynamicLightCount();

		// Load the inverse world matrix.
		core::matrix4 invWorldMat;
		driver->getTransform( video::ETS_WORLD ).getInverse( invWorldMat );

		float lightPosition[4*MAX_LIGHTS];
		float lightColor[4*MAX_LIGHTS];

		for ( u32 i = 0; i < MAX_LIGHTS; ++i )
		{
			video::SLight light;

			if ( i < cnt )
				light = driver->getDynamicLight( i );
			else
			{
				light.DiffuseColor.set( 0, 0, 0 ); // make light dark
				light.Radius = 1.0f;
			}

			light.DiffuseColor.a = 1.0f / ( light.Radius * light.Radius ); // set attenuation

			// Transform the light by the inverse world matrix to get it into object space.
			invWorldMat.transformVect( light.Position );

			memcpy( lightPosition + i*4, &light.Position, sizeof( float )*4 );
			memcpy( lightColor + i*4, &light.DiffuseColor, sizeof( float )*4 );
		}
		setUniform( LIGHT_POSITION, lightPosition, MAX_LIGHTS );
		setUniform( LIGHT_COLOR, lightColor, MAX_LIGHTS );
	}
	//! Called by the engine when the vertex and/or pixel shader constants for an
	//! material renderer should be set.
	void CD3D9NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
	{
		video::IVideoDriver* driver = services->getVideoDriver();

		// set transposed world matrix
		const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed();
		services->setVertexShaderConstant(&tWorld.M[0], 0, 4);

		// set transposed worldViewProj matrix
		core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
		worldViewProj *= driver->getTransform(video::ETS_VIEW);
		worldViewProj *= driver->getTransform(video::ETS_WORLD);
		core::matrix4 tr(worldViewProj.getTransposed());
		services->setVertexShaderConstant(&tr.M[0], 8, 4);

		// here we've got to fetch the fixed function lights from the driver
		// and set them as constants

		int cnt = driver->getDynamicLightCount();
		
		for (int i=0; i<2; ++i)
		{
			video::SLight light; 

			if (i<cnt)
				light = driver->getDynamicLight(i);
			else
			{
				light.DiffuseColor.set(0,0,0); // make light dark
				light.Radius = 1.0f;
			}

			light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation

			services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
			services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
		}

		// this is not really necessary in d3d9 (used a def instruction), but to be sure:
		f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
		services->setVertexShaderConstant(c95, 95, 1);
	}
//! Called by the engine when the vertex and/or pixel shader constants for an
//! material renderer should be set.
void COpenGLNormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
{
	video::IVideoDriver* driver = services->getVideoDriver();

	// set transposed world matrix
	const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed();
	services->setVertexShaderConstant(tWorld.pointer(), 0, 4);

	// set transposed worldViewProj matrix
	core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
	worldViewProj *= driver->getTransform(video::ETS_VIEW);
	worldViewProj *= driver->getTransform(video::ETS_WORLD);
	core::matrix4 tr(worldViewProj.getTransposed());
	services->setVertexShaderConstant(tr.pointer(), 8, 4);

	// here we fetch the fixed function lights from the driver
	// and set them as constants

	u32 cnt = driver->getDynamicLightCount();

	for (u32 i=0; i<2; ++i)
	{
		video::SLight light;

		if (i<cnt)
			light = driver->getDynamicLight(i);
		else
		{
			light.DiffuseColor.set(0,0,0); // make light dark
			light.Radius = 1.0f;
		}

		light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation

		services->setVertexShaderConstant(
			reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);

		services->setVertexShaderConstant(
			reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
	}
}
//! Called by the engine when the vertex and/or pixel shader constants for an
//! material renderer should be set.
void COpenGLParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
{
	video::IVideoDriver* driver = services->getVideoDriver();

	// set transposed world matrix
	const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed();
	services->setVertexShaderConstant(tWorld.pointer(), 0, 4);

	// set transposed worldViewProj matrix
	core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
	worldViewProj *= driver->getTransform(video::ETS_VIEW);
	worldViewProj *= driver->getTransform(video::ETS_WORLD);
	core::matrix4 tr(worldViewProj.getTransposed());
	services->setVertexShaderConstant(tr.pointer(), 8, 4);

	// here we fetch the fixed function lights from the driver
	// and set them as constants

	u32 cnt = driver->getDynamicLightCount();

	// Load the inverse world matrix.
	core::matrix4 invWorldMat;
	driver->getTransform(video::ETS_WORLD).getInverse(invWorldMat);

	for (u32 i=0; i<2; ++i)
	{
		video::SLight light;

		if (i<cnt)
			light = driver->getDynamicLight(i);
		else
		{
			light.DiffuseColor.set(0,0,0); // make light dark
			light.Radius = 1.0f;
		}

		light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation

		// Transform the light by the inverse world matrix to get it into object space.
		invWorldMat.transformVect(light.Position);
		
		services->setVertexShaderConstant(
			reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);

		services->setVertexShaderConstant(
			reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
	}

	// Obtain the view position by transforming 0,0,0 by the inverse view matrix
	// and then multiply this by the inverse world matrix.
	core::vector3df viewPos(0.0f, 0.0f, 0.0f);
	core::matrix4 inverseView;
	driver->getTransform(video::ETS_VIEW).getInverse(inverseView);
	inverseView.transformVect(viewPos);
	invWorldMat.transformVect(viewPos);
	services->setVertexShaderConstant(reinterpret_cast<const f32*>(&viewPos.X), 16, 1);

	// set scale factor
	f32 factor = 0.02f; // default value
	if (CurrentScale != 0.0f)
		factor = CurrentScale;

	f32 c6[] = {factor, factor, factor, factor};
	services->setPixelShaderConstant(c6, 0, 1);
}
	//! Called by the engine when the vertex and/or pixel shader constants for an
	//! material renderer should be set.
	void COGLES2ParallaxMapRenderer::OnSetConstants( IMaterialRendererServices* services, s32 userData )
	{
		video::IVideoDriver* driver = services->getVideoDriver();

		// set transposed worldViewProj matrix
		core::matrix4 worldViewProj( driver->getTransform( video::ETS_PROJECTION ) );
		worldViewProj *= driver->getTransform( video::ETS_VIEW );
		worldViewProj *= driver->getTransform( video::ETS_WORLD );

		setUniform( MVP_MATRIX, worldViewProj.pointer() );


		// here we fetch the fixed function lights from the driver
		// and set them as constants

		u32 cnt = driver->getDynamicLightCount();

		// Load the inverse world matrix.
		core::matrix4 invWorldMat;
		driver->getTransform( video::ETS_WORLD ).getInverse( invWorldMat );

		float lightPosition[4*MAX_LIGHTS];
		float lightColor[4*MAX_LIGHTS];

		for ( u32 i = 0; i < 2; ++i )
		{
			video::SLight light;

			if ( i < cnt )
				light = driver->getDynamicLight( i );
			else
			{
				light.DiffuseColor.set( 0, 0, 0 ); // make light dark
				light.Radius = 1.0f;
			}

			light.DiffuseColor.a = 1.0f / ( light.Radius * light.Radius ); // set attenuation

			// Transform the light by the inverse world matrix to get it into object space.
			invWorldMat.transformVect( light.Position );

			memcpy( lightPosition + i*4, &light.Position, sizeof( float )*4 );
			memcpy( lightColor + i*4, &light.DiffuseColor, sizeof( float )*4 );
		}

		setUniform( LIGHT_POSITION, lightPosition, MAX_LIGHTS );
		setUniform( LIGHT_COLOR, lightColor, MAX_LIGHTS );

		// Obtain the view position by transforming 0,0,0 by the inverse view matrix
		// and then multiply this by the inverse world matrix.
		core::vector3df viewPos( 0.0f, 0.0f, 0.0f );
		core::matrix4 inverseView;
		driver->getTransform( video::ETS_VIEW ).getInverse( inverseView );
		inverseView.transformVect( viewPos );
		invWorldMat.transformVect( viewPos );
		setUniform( EYE_POSITION, &viewPos.X );

		// set scale factor
		f32 factor = 0.02f; // default value
		if ( CurrentScale != 0.0f )
			factor = CurrentScale;

		setUniform( HEIGHT_SCALE, &factor );
	}