diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009 Antti Salonen
+Copyright (c) 2009, 2010 Antti Salonen
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
diff --git a/Media/Example.material b/Media/Example.material
deleted file mode 100644
--- a/Media/Example.material
+++ /dev/null
@@ -1,122 +0,0 @@
-
-material Examples/CloudyNoonSkyBox
-{
-	technique
-	{
-		pass
-		{
-			lighting off
-			depth_write off
-
-			texture_unit
-			{
-				cubic_texture cloudy_noon.jpg separateUV
-				tex_address_mode clamp
-			}
-		}
-	}
-}
-
-material Examples/StormySkyBox
-{
-	technique
-	{
-		pass
-		{
-			lighting off
-			depth_write off
-
-			texture_unit
-			{
-				cubic_texture stormy.jpg separateUV
-				tex_address_mode clamp
-			}
-		}
-	}
-}
-
-material Examples/EveningSkyBox
-{
-	technique
-	{
-		pass
-		{
-			lighting off
-			depth_write off
-
-			texture_unit
-			{
-				cubic_texture evening.jpg separateUV
-				tex_address_mode clamp
-			}
-		}
-	}
-}
-
-material Examples/CloudySky
-{
-	technique
-	{
-		pass
-		{
-			lighting off
-			depth_write off
-
-			texture_unit
-			{
-				texture clouds.jpg
-				scroll_anim 0.15 0
-			}
-		}
-	}
-}
-
-material Examples/Robot
-{
-        // Hardware skinning techniique
-        technique
-        {
-                pass
-                {
-/*
-                        vertex_program_ref Ogre/HardwareSkinningOneWeight
-                        {
-                                param_named_auto worldMatrix3x4Array world_matrix_array_3x4
-                                param_named_auto viewProjectionMatrix viewproj_matrix
-                                param_named_auto lightPos[0] light_position 0
-                                param_named_auto lightPos[1] light_position 1
-                                param_named_auto lightDiffuseColour[0] light_diffuse_colour 0
-                                param_named_auto lightDiffuseColour[1] light_diffuse_colour 1
-                                param_named_auto ambient ambient_light_colour
-
-                        }
-                        // alternate shadow caster program
-                        shadow_caster_vertex_program_ref Ogre/HardwareSkinningOneWeightShadowCaster
-                        {
-                                param_named_auto worldMatrix3x4Array world_matrix_array_3x4
-                                param_named_auto viewProjectionMatrix viewproj_matrix
-                                param_named_auto ambient ambient_light_colour
-
-                        }
-*/
-                        texture_unit
-                        {
-                                texture r2skin.jpg
-                        }
-                }
-        }
-
-        // Software blending technique
-        technique
-        {
-                pass
-                {
-
-                        texture_unit
-                        {
-                                texture r2skin.jpg
-                        }
-                }
-        }
-}
-
diff --git a/Media/Example_Basic.cg b/Media/Example_Basic.cg
new file mode 100644
--- /dev/null
+++ b/Media/Example_Basic.cg
@@ -0,0 +1,310 @@
+/*
+  Basic ambient lighting vertex program
+*/
+void ambientOneTexture_vp(float4 position : POSITION,
+						  float2 uv		  : TEXCOORD0,
+						  
+						  out float4 oPosition : POSITION,
+						  out float2 oUv	   : TEXCOORD0,
+						  out float4 colour    : COLOR,
+
+						  uniform float4x4 worldViewProj,
+						  uniform float4 ambient)
+{
+	oPosition = mul(worldViewProj, position);
+	oUv = uv;
+	colour = ambient;
+}
+
+/*
+  Single-weight-per-vertex hardware skinning, 2 lights
+  The trouble with vertex programs is they're not general purpose, but
+  fixed function hardware skinning is very poorly supported
+*/
+void hardwareSkinningOneWeight_vp(
+	float4 position : POSITION,
+	float3 normal   : NORMAL,
+	float2 uv       : TEXCOORD0,
+	float  blendIdx : BLENDINDICES,
+	
+
+	out float4 oPosition : POSITION,
+	out float2 oUv       : TEXCOORD0,
+	out float4 colour           : COLOR,
+	// Support up to 24 bones of float3x4
+	// vs_1_1 only supports 96 params so more than this is not feasible
+	uniform float3x4   worldMatrix3x4Array[24],
+	uniform float4x4 viewProjectionMatrix,
+	uniform float4   lightPos[2],
+	uniform float4   lightDiffuseColour[2],
+	uniform float4   ambient)
+{
+	// transform by indexed matrix
+	float4 blendPos = float4(mul(worldMatrix3x4Array[blendIdx], position).xyz, 1.0);
+	// view / projection
+	oPosition = mul(viewProjectionMatrix, blendPos);
+	// transform normal
+	float3 norm = mul((float3x3)worldMatrix3x4Array[blendIdx], normal);
+	// Lighting - support point and directional
+	float3 lightDir0 = 	normalize(
+		lightPos[0].xyz -  (blendPos.xyz * lightPos[0].w));
+	float3 lightDir1 = 	normalize(
+		lightPos[1].xyz -  (blendPos.xyz * lightPos[1].w));
+
+	oUv = uv;
+	colour = ambient + 
+		(saturate(dot(lightDir0, norm)) * lightDiffuseColour[0]) + 
+		(saturate(dot(lightDir1, norm)) * lightDiffuseColour[1]);
+	
+}	
+
+/*
+  Single-weight-per-vertex hardware skinning, shadow-caster pass
+*/
+void hardwareSkinningOneWeightCaster_vp(
+	float4 position : POSITION,
+	float3 normal   : NORMAL,
+	float  blendIdx : BLENDINDICES,
+	
+
+	out float4 oPosition : POSITION,
+	out float4 colour    : COLOR,
+	// Support up to 24 bones of float3x4
+	// vs_1_1 only supports 96 params so more than this is not feasible
+	uniform float3x4   worldMatrix3x4Array[24],
+	uniform float4x4 viewProjectionMatrix,
+	uniform float4   ambient)
+{
+	// transform by indexed matrix
+	float4 blendPos = float4(mul(worldMatrix3x4Array[blendIdx], position).xyz, 1.0);
+	// view / projection
+	oPosition = mul(viewProjectionMatrix, blendPos);
+	
+	colour = ambient;
+	
+}	
+
+/*
+  Two-weight-per-vertex hardware skinning, 2 lights
+  The trouble with vertex programs is they're not general purpose, but
+  fixed function hardware skinning is very poorly supported
+*/
+void hardwareSkinningTwoWeights_vp(
+	float4 position : POSITION,
+	float3 normal   : NORMAL,
+	float2 uv       : TEXCOORD0,
+	float4 blendIdx : BLENDINDICES,
+	float4 blendWgt : BLENDWEIGHT,
+	
+
+	out float4 oPosition : POSITION,
+	out float2 oUv       : TEXCOORD0,
+	out float4 colour           : COLOR,
+	// Support up to 24 bones of float3x4
+	// vs_1_1 only supports 96 params so more than this is not feasible
+	uniform float3x4   worldMatrix3x4Array[24],
+	uniform float4x4 viewProjectionMatrix,
+	uniform float4   lightPos[2],
+	uniform float4   lightDiffuseColour[2],
+	uniform float4   ambient)
+{
+	// transform by indexed matrix
+	float4 blendPos = float4(0,0,0,0);
+	int i;
+	for (i = 0; i < 2; ++i)
+	{
+		blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];
+	}
+	// view / projection
+	oPosition = mul(viewProjectionMatrix, blendPos);
+	// transform normal
+	float3 norm = float3(0,0,0);
+	for (i = 0; i < 2; ++i)
+	{
+		norm += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], normal) * 
+		blendWgt[i];
+	}
+	norm = normalize(norm);
+	// Lighting - support point and directional
+	float3 lightDir0 = 	normalize(
+		lightPos[0].xyz -  (blendPos.xyz * lightPos[0].w));
+	float3 lightDir1 = 	normalize(
+		lightPos[1].xyz -  (blendPos.xyz * lightPos[1].w));
+
+	
+	oUv = uv;
+	colour = float4(0.5, 0.5, 0.5, 1) + 
+		(saturate(dot(lightDir0, norm)) * lightDiffuseColour[0]) + 
+		(saturate(dot(lightDir1, norm)) * lightDiffuseColour[1]);
+	
+}
+
+/*
+  Two-weight-per-vertex hardware skinning, shadow caster pass
+*/
+void hardwareSkinningTwoWeightsCaster_vp(
+	float4 position : POSITION,
+	float3 normal   : NORMAL,
+	float2 uv       : TEXCOORD0,
+	float4 blendIdx : BLENDINDICES,
+	float4 blendWgt : BLENDWEIGHT,
+	
+
+	out float4 oPosition : POSITION,
+	out float4 colour           : COLOR,
+	// Support up to 24 bones of float3x4
+	// vs_1_1 only supports 96 params so more than this is not feasible
+	uniform float3x4   worldMatrix3x4Array[24],
+	uniform float4x4 viewProjectionMatrix,
+	uniform float4   ambient)
+{
+	// transform by indexed matrix
+	float4 blendPos = float4(0,0,0,0);
+	int i;
+	for (i = 0; i < 2; ++i)
+	{
+		blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];
+	}
+	// view / projection
+	oPosition = mul(viewProjectionMatrix, blendPos);
+	
+
+	colour = ambient;
+		
+	
+}
+
+
+/*
+  Four-weight-per-vertex hardware skinning, 2 lights
+  The trouble with vertex programs is they're not general purpose, but
+  fixed function hardware skinning is very poorly supported
+*/
+void hardwareSkinningFourWeights_vp(
+	float4 position : POSITION,
+	float3 normal   : NORMAL,
+	float2 uv       : TEXCOORD0,
+	float4 blendIdx : BLENDINDICES,
+	float4 blendWgt : BLENDWEIGHT,
+	
+
+	out float4 oPosition : POSITION,
+	out float2 oUv       : TEXCOORD0,
+	out float4 colour           : COLOR,
+	// Support up to 24 bones of float3x4
+	// vs_1_1 only supports 96 params so more than this is not feasible
+	uniform float3x4   worldMatrix3x4Array[24],
+	uniform float4x4 viewProjectionMatrix,
+	uniform float4   lightPos[2],
+	uniform float4   lightDiffuseColour[2],
+	uniform float4   ambient)
+{
+	// transform by indexed matrix
+	float4 blendPos = float4(0,0,0,0);
+	int i;
+	for (i = 0; i < 4; ++i)
+	{
+		blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];
+	}
+	// view / projection
+	oPosition = mul(viewProjectionMatrix, blendPos);
+	// transform normal
+	float3 norm = float3(0,0,0);
+	for (i = 0; i < 4; ++i)
+	{
+		norm += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], normal) * 
+		blendWgt[i];
+	}
+	norm = normalize(norm);
+	// Lighting - support point and directional
+	float3 lightDir0 = 	normalize(
+		lightPos[0].xyz -  (blendPos.xyz * lightPos[0].w));
+	float3 lightDir1 = 	normalize(
+		lightPos[1].xyz -  (blendPos.xyz * lightPos[1].w));
+
+	
+	oUv = uv;
+	colour = ambient + 
+		(saturate(dot(lightDir0, norm)) * lightDiffuseColour[0]) + 
+		(saturate(dot(lightDir1, norm)) * lightDiffuseColour[1]);
+	
+}
+
+void hardwareMorphAnimation(float3 pos1 : POSITION,
+			  float4 normal		: NORMAL,
+			  float2 uv		  : TEXCOORD0,
+			  float3 pos2	  : TEXCOORD1,
+						  
+			  out float4 oPosition : POSITION,
+			  out float2 oUv	   : TEXCOORD0,
+			  out float4 colour    : COLOR,
+
+			  uniform float4x4 worldViewProj, 
+			  uniform float4 anim_t)
+{
+	// interpolate
+	float4 interp = float4(pos1 + anim_t.x*(pos2 - pos1), 1.0f);
+	
+	oPosition = mul(worldViewProj, interp);
+	oUv = uv;
+	colour = float4(1,0,0,1);
+}
+
+void hardwarePoseAnimation(float3 pos : POSITION,
+			  float4 normal		: NORMAL,
+			  float2 uv		  : TEXCOORD0,
+			  float3 pose1	  : TEXCOORD1,
+			  float3 pose2	  : TEXCOORD2,
+						  
+			  out float4 oPosition : POSITION,
+			  out float2 oUv	   : TEXCOORD0,
+			  out float4 colour    : COLOR,
+
+			  uniform float4x4 worldViewProj, 
+			  uniform float4 anim_t)
+{
+	// interpolate
+	float4 interp = float4(pos + anim_t.x*pose1 + anim_t.y*pose2, 1.0f);
+	
+	oPosition = mul(worldViewProj, interp);
+	oUv = uv;
+	colour = float4(1,0,0,1);
+}
+
+
+void basicPassthroughTangent_v(float4 position : POSITION,
+						float3 tangent       : TANGENT,
+						  
+						  out float4 oPosition : POSITION,
+						  out float3 oTangent  : TEXCOORD0,
+
+						  uniform float4x4 worldViewProj)
+{
+	oPosition = mul(worldViewProj, position);
+	oTangent = tangent;
+}
+void basicPassthroughNormal_v(float4 position : POSITION,
+						float3 normal       : NORMAL,
+						  
+						  out float4 oPosition : POSITION,
+						  out float3 oNormal  : TEXCOORD0,
+
+						  uniform float4x4 worldViewProj)
+{
+	oPosition = mul(worldViewProj, position);
+	oNormal = normal;
+}
+// Basic fragment program to display UV
+float4 showuv_p (float2 uv : TEXCOORD0) : COLOR
+{
+	// wrap values using frac
+	return float4(frac(uv.x), frac(uv.y), 0, 1);
+}
+// Basic fragment program to display 3d uv
+float4 showuvdir3d_p (float3 uv : TEXCOORD0) : COLOR
+{
+	float3 n = normalize(uv);
+	return float4(n.x, n.y, n.z, 1);
+}
+
+
diff --git a/Media/Examples.material b/Media/Examples.material
new file mode 100644
--- /dev/null
+++ b/Media/Examples.material
@@ -0,0 +1,1762 @@
+material Examples/SphereMappedRustySteel
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture RustySteel.jpg
+			}
+
+			texture_unit
+			{
+				texture spheremap.png
+				colour_op_ex add src_texture src_current
+				colour_op_multipass_fallback one one
+				env_map spherical
+			}
+		}
+	}
+}
+
+material Examples/OgreLogo
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.8 0.8 0.8
+
+			texture_unit
+			{
+				texture ogrelogo.png
+			}
+		}
+	}
+}
+
+material Examples/BeachStones
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.1 0.1 0.1
+
+			texture_unit
+			{
+				texture BeachStones.jpg
+			}
+		}
+	}
+}
+
+material Examples/TrippySkyBox
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture nm.png separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/SpaceSkyBox
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture stevecube.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/SceneSkyBox1
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture cubemap_fr.jpg cubemap_bk.jpg cubemap_lf.jpg cubemap_rt.jpg cubemap_up.jpg cubemap_dn.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/SceneCubeMap1
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+
+			texture_unit
+			{
+				cubic_texture cubemap.jpg combinedUVW
+				tex_address_mode clamp
+				env_map cubic_reflection
+			}
+		}
+	}
+}
+
+material Examples/SceneSkyBox2
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture cubescene_fr.jpg cubescene_bk.jpg cubescene_lf.jpg cubescene_rt.jpg cubescene_up.jpg cubescene_dn.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/SceneCubeMap2
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+
+			texture_unit
+			{
+				cubic_texture cubescene.jpg combinedUVW
+				tex_address_mode clamp
+				env_map cubic_reflection
+			}
+		}
+	}
+}
+
+material Examples/CloudyNoonSkyBox
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture cloudy_noon.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/StormySkyBox
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture stormy.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/EarlyMorningSkyBox
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture early_morning.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+
+fragment_program Examples/MorningSkyBoxHDRfp cg
+{
+	source hdr.cg
+	entry_point morningskybox_fp
+	profiles ps_2_0 arbfp1
+
+}
+
+material Examples/MorningSkyBox
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture morning.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+
+	// HDR technique (fake)
+	technique
+	{
+		scheme HDR
+
+		pass
+		{
+			lighting off
+			depth_write off
+
+			vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
+			{
+				param_named_auto worldViewProj worldviewproj_matrix
+				param_named ambient float4 1 1 1 1
+			}
+			fragment_program_ref Examples/MorningSkyBoxHDRfp
+			{
+			}
+
+			texture_unit
+			{
+				cubic_texture morning.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+fragment_program Examples/MorningCubeMapHDRfp cg
+{
+	source hdr.cg
+	entry_point morningcubemap_fp
+	profiles ps_2_0 arbfp1
+
+}
+
+material Examples/MorningCubeMap
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+
+			texture_unit
+			{
+				cubic_texture morning.jpg combinedUVW
+				tex_address_mode clamp
+				env_map cubic_reflection
+			}
+		}
+	}
+	// HDR technique (fake)
+	technique
+	{
+		scheme HDR
+
+		pass
+		{
+			lighting off
+
+			fragment_program_ref Examples/MorningCubeMapHDRfp
+			{
+			}
+			texture_unit
+			{
+				cubic_texture morning.jpg combinedUVW
+				tex_address_mode clamp
+				env_map cubic_reflection
+			}
+		}
+	}
+}
+
+material Examples/EveningSkyBox
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				cubic_texture evening.jpg separateUV
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/DynamicCubeMap
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				// will be filled in at runtime
+				cubic_texture dyncubemap combinedUVW
+				tex_address_mode clamp
+				env_map cubic_reflection
+			}
+		}
+	}
+}
+
+material Examples/CloudySky
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				texture clouds.jpg
+				scroll_anim 0.15 0
+			}
+		}
+	}
+}
+
+material Examples/RustySteel
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture RustySteel.jpg
+			}
+		}
+	}
+}
+
+material Examples/Chrome
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture Chrome.jpg
+				env_map spherical
+			}
+		}
+	}
+}
+
+material Examples/SpaceSkyPlane
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			depth_write off
+
+			texture_unit
+			{
+				texture spacesky.jpg
+			}
+		}
+	}
+}
+
+material Examples/OgreDance
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			scene_blend alpha_blend
+			cull_hardware none
+			cull_software none
+
+			texture_unit
+			{
+				anim_texture ogredance.png 8 2
+				filtering none
+			}
+		}
+	}
+}
+
+material Examples/OgreParade : Examples/OgreDance
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				scroll 0.5 0
+				scale 0.5 0.5
+				scroll_anim 0 0.5
+			}
+		}
+	}
+}
+
+material Examples/OgreSpin : Examples/OgreDance
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture ogredance_1.png
+				rotate_anim 0.25
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/OgreWobble : Examples/OgreDance
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture ogredance_6.png
+				wave_xform scale_x sine 1 1.2 0 0.35
+				wave_xform scale_y sine 1 1 0.5 0.25
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material Examples/BumpyMetal
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.75 0.75 0.75
+
+			texture_unit
+			{
+				texture BumpyMetal.jpg
+			}
+		}
+	}
+}
+
+material Examples/WaterStream
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.1 0.1 0.1
+			scene_blend add
+			depth_write off
+			cull_software none
+			cull_hardware none
+
+			texture_unit
+			{
+				texture Water01.jpg
+				scroll_anim 0.125 0
+			}
+
+			texture_unit
+			{
+				texture Water01.jpg
+				wave_xform scroll_y sine 0 0.1 0 0.25
+			}
+		}
+	}
+}
+
+material Examples/Flare
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			scene_blend add
+			depth_write off
+			diffuse vertexcolour
+
+			texture_unit
+			{
+				texture flare.png
+			}
+		}
+	}
+}
+material Examples/Flare2
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			scene_blend add
+			depth_write off
+			diffuse vertexcolour
+
+			texture_unit
+			{
+				texture flaretrail.png
+			}
+		}
+	}
+}
+material Examples/Flare3
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			scene_blend alpha_blend
+			depth_write off
+			diffuse vertexcolour
+
+			texture_unit
+			{
+				texture flare_alpha.dds
+			}
+		}
+	}
+}
+material Examples/FlarePointSprite
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			scene_blend add
+			depth_write off
+			diffuse vertexcolour
+
+			point_sprites on
+			point_size 2
+			point_size_attenuation on
+
+			texture_unit
+			{
+				texture flare.png
+			}
+		}
+	}
+}
+
+material Examples/Droplet
+{
+	technique
+	{
+		pass
+		{
+			emissive 0.3 0.3 0.3
+			scene_blend colour_blend
+			depth_write off
+			diffuse vertexcolour
+
+			texture_unit
+			{
+				texture basic_droplet.png
+			}
+		}
+	}
+}
+material Examples/Hilite/Yellow
+{
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture dkyellow.png
+			}
+		}
+	}
+}
+material Examples/Rocky
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.2 0.2 0.2
+
+			texture_unit
+			{
+				texture egyptrockyfull.jpg
+			}
+		}
+	}
+}
+material Examples/10PointBlock
+{
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture 10points.png
+			}
+		}
+	}
+}
+material Material__25
+{
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture texmap2.jpg
+			}
+		}
+	}
+}
+material "2 - Default"
+{
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture MtlPlat2.jpg
+			}
+		}
+	}
+}
+material "Material #8"
+{
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture BODY.jpg
+			}
+		}
+	}
+}
+material "Material #3"
+{
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture HEAD4.jpg
+			}
+		}
+	}
+}
+material "Material #9"
+{
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture LEGS.jpg
+			}
+		}
+	}
+}
+
+material Examples/Fish
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture steelhead.png
+			}
+		}
+	}
+}
+material Examples/Ninja
+{
+	technique
+	{
+		pass
+		{
+		
+			texture_unit
+			{
+				texture nskingr.jpg
+			}
+		}
+	}
+}
+
+material Examples/Robot
+{
+	// Hardware skinning techniique
+	technique
+	{
+		pass
+		{
+			vertex_program_ref Ogre/HardwareSkinningOneWeight
+			{
+				param_named_auto worldMatrix3x4Array world_matrix_array_3x4
+				param_named_auto viewProjectionMatrix viewproj_matrix
+				param_named_auto lightPos[0] light_position 0
+				param_named_auto lightPos[1] light_position 1
+				param_named_auto lightDiffuseColour[0] light_diffuse_colour 0
+				param_named_auto lightDiffuseColour[1] light_diffuse_colour 1
+				param_named_auto ambient ambient_light_colour
+			
+			}
+			// alternate shadow caster program
+			shadow_caster_vertex_program_ref Ogre/HardwareSkinningOneWeightShadowCaster
+			{
+				param_named_auto worldMatrix3x4Array world_matrix_array_3x4
+				param_named_auto viewProjectionMatrix viewproj_matrix
+				param_named_auto ambient ambient_light_colour
+			
+			}
+
+			texture_unit
+			{
+				texture r2skin.jpg
+			}
+		}
+	}
+
+	// Software blending technique
+	technique
+	{
+		pass
+		{
+
+			texture_unit
+			{
+				texture r2skin.jpg
+			}
+		}
+	}
+}
+
+material Examples/GrassFloor
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture grass_1024.jpg
+			}
+		}
+	}
+}
+
+vertex_program Examples/GrassWaverVp cg
+{
+	source Grass.cg
+	entry_point grass_vp
+	profiles vs_1_1 arbvp1
+    
+    default_params
+    {    
+        param_named_auto worldViewProj worldviewproj_matrix
+        
+        param_named_auto camObjPos camera_position_object_space
+        
+        param_named_auto ambient ambient_light_colour
+        param_named_auto objSpaceLight light_position_object_space 0
+        param_named_auto lightColour light_diffuse_colour 0
+        
+        param_named_auto offset custom 999
+    }
+  }
+  
+vertex_program Examples/GrassWaverTexVp cg
+  {
+	source Grass.cg
+	entry_point grassTex_vp
+	profiles vs_1_1 arbvp1
+    
+    default_params
+      {
+        param_named_auto worldViewProj worldviewproj_matrix        
+        param_named_auto offset custom 999
+    }
+}
+vertex_program Examples/GrassWaverAmbientVp cg
+          {
+	source Grass.cg
+	entry_point grassAmbient_vp
+	profiles vs_1_1 arbvp1
+    
+    default_params
+  			{
+  				param_named_auto worldViewProj worldviewproj_matrix
+  				param_named_auto ambient ambient_light_colour
+        param_named_auto offset custom 999
+    }
+}
+fragment_program Examples/GrassWaverAmbientFp cg
+{
+	source Grass.cg
+	entry_point grassAmbient_fp
+	profiles ps_2_0 arbfp1
+    default_params
+    {
+    }
+}
+fragment_program Examples/GrassWaverFp cg
+{
+	source Grass.cg
+	entry_point grass_fp
+	profiles ps_2_0 arbfp1
+    default_params
+    {
+    }
+}
+
+vertex_program Examples/GrassWaverCasterVp cg
+{
+	source Grass.cg
+	entry_point grasscaster_vp
+	profiles vs_1_1 arbvp1
+    
+    default_params
+    {    
+        param_named_auto worldViewProj worldviewproj_matrix
+        param_named_auto offset custom 999
+		param_named_auto texelOffsets texel_offsets
+    }
+}
+fragment_program Examples/GrassWaverCasterFp cg
+{
+	source Grass.cg
+	entry_point grasscaster_fp
+	profiles ps_2_0 arbfp1
+    default_params
+    {
+    }
+}
+
+vertex_program Examples/GrassWaverReceiverVp cg
+{
+	source Grass.cg
+	entry_point grassreceiver_vp
+	profiles vs_1_1 arbvp1
+    
+    default_params
+    {
+        param_named_auto world world_matrix
+		param_named_auto worldViewProj worldviewproj_matrix
+		param_named_auto texViewProj texture_viewproj_matrix
+        
+        param_named_auto camObjPos camera_position_object_space
+        
+  				param_named_auto objSpaceLight light_position_object_space 0
+  				param_named_auto lightColour light_diffuse_colour 0
+        
+  				param_named_auto offset custom 999
+  			}
+}
+
+
+fragment_program Examples/GrassWaverReceiverFp cg
+{
+	source Grass.cg
+	entry_point grassreceiver_fp
+	profiles ps_2_0 arbfp1
+   
+	default_params
+    {
+        //param_named inverseShadowmapSize float 0.0009765625
+		param_named fixedDepthBias float 0.0005
+		param_named gradientClamp float 0.0098
+		param_named gradientScaleBias float 0
+    }
+}
+
+
+material Examples/GrassBladesShadowCaster
+{
+	// Vertex program waving grass
+    technique
+    {
+        pass
+        {
+			vertex_program_ref Examples/GrassWaverCasterVp
+			{
+			}
+			fragment_program_ref Examples/GrassWaverCasterFp
+			{
+			}
+            
+  			alpha_rejection greater 150 
+            
+  			scene_blend alpha_blend
+            
+  		    cull_hardware none
+              cull_software none
+            
+              texture_unit
+              {
+				tex_address_mode clamp
+                  texture gras_02.png 
+              }
+          }
+        
+      }
+}
+
+material Examples/GrassBladesShadowReceiver
+{
+	// Vertex program waving grass
+    technique
+    {
+        pass 
+		{
+			scene_blend add
+  
+			alpha_rejection greater 150       
+            
+		    cull_hardware none
+            cull_software none 
+            
+			vertex_program_ref Examples/GrassWaverReceiverVp
+			{
+			}
+			fragment_program_ref Examples/GrassWaverReceiverFp
+			{
+			}
+            
+            texture_unit ShadowMap
+            {
+                 tex_address_mode border
+                 tex_border_colour 1.0 1.0 1.0 0.0                
+                 content_type shadow
+                 filtering linear linear none		
+                 tex_coord_set 0
+            }
+           
+           texture_unit
+           {
+				tex_address_mode clamp				
+                tex_coord_set 1
+                texture gras_02.png
+           }
+        }
+        
+    }
+}
+
+material Examples/GrassBladesAdditiveFloatTransparentBest
+{
+    
+    transparency_casts_shadows on
+    receive_shadows on
+     
+	// This is the preferred technique which uses both vertex and
+	// fragment programs, supports coloured lights
+    technique
+    {
+        shadow_caster_material Examples/GrassBladesShadowCaster
+        shadow_receiver_material Examples/GrassBladesShadowReceiver
+
+		// 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 
+            
+			alpha_rejection greater 150 
+            
+			scene_blend alpha_blend  
+            
+		    cull_hardware none
+            cull_software none
+            
+			// Really basic vertex program		
+			vertex_program_ref Examples/GrassWaverAmbientVp
+			{
+			}
+            
+			fragment_program_ref Examples/GrassWaverAmbientFp
+			{
+			}
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+			
+		}
+        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_ref Examples/GrassWaverAmbientVp
+			{
+			}
+            
+			fragment_program_ref Examples/GrassWaverAmbientFp
+			{
+			}
+            
+            
+			alpha_rejection greater 150 
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit ShadowMap
+            {
+                 tex_address_mode border
+                 tex_border_colour 1.0 1.0 1.0 0.0                
+                 content_type shadow
+                 filtering linear linear none		
+                 tex_coord_set 0
+            }
+           
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+        }
+		// Decal pass
+		pass
+		{
+			// base colours, not needed for rendering, but as information
+			// to lighting pass categorisation routine
+			lighting off
+            
+			alpha_rejection greater 150 
+            
+			//scene_blend alpha_blend            
+			scene_blend dest_colour zero
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+            
+			vertex_program_ref Examples/GrassWaverVp
+			{
+			}
+            
+            
+        }
+    }
+}
+
+material Examples/GrassBladesAdditiveFloatTransparent
+{
+    
+    transparency_casts_shadows on
+    receive_shadows on
+     
+	// This is the preferred technique which uses both vertex and
+	// fragment programs, supports coloured lights
+  	technique
+      {
+        shadow_caster_material Examples/GrassBladesShadowCaster
+        shadow_receiver_material Examples/GrassBladesShadowReceiver
+
+		// 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 
+            
+  			alpha_rejection greater 150 
+            
+  			scene_blend alpha_blend
+            
+		    cull_hardware none
+            cull_software none
+            
+			// Really basic vertex program		
+			vertex_program_ref Examples/GrassWaverAmbientVp
+			{
+			}
+            
+			fragment_program_ref Examples/GrassWaverAmbientFp
+			{
+			}
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+			
+		}
+        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_ref Examples/GrassWaverAmbientVp
+			{
+			}
+            
+			fragment_program_ref Examples/GrassWaverAmbientFp
+			{
+			}
+            
+            
+			alpha_rejection greater 150 
+            
+  		    cull_hardware none
+              cull_software none
+            
+            texture_unit ShadowMap
+            {
+                 tex_address_mode border
+                 tex_border_colour 1.0 1.0 1.0 0.0                
+                 content_type shadow
+                 filtering linear linear none		
+                 tex_coord_set 0
+            }
+           
+            
+              texture_unit
+              {
+				tex_address_mode clamp
+                  texture gras_02.png 
+              }
+          }
+		// Decal pass
+		pass
+		{
+			// base colours, not needed for rendering, but as information
+			// to lighting pass categorisation routine
+			lighting off
+            
+			alpha_rejection greater 150 
+            
+			//scene_blend alpha_blend            
+			scene_blend dest_colour zero
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+      }
+            
+			vertex_program_ref Examples/GrassWaverTexVp
+			{
+			}
+            
+            
+        }
+    }
+}
+
+material Examples/GrassBladesAdditiveFloat
+{
+    transparency_casts_shadows on
+    receive_shadows on
+     
+	// This is the preferred technique which uses both vertex and
+	// fragment programs, supports coloured lights
+    technique
+    {
+        shadow_caster_material Ogre/DepthShadowmap/Caster/Float
+        shadow_receiver_material Ogre/DepthShadowmap/Receiver/Float
+
+		// 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
+			{
+  }
+  
+		}
+        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_ref Examples/GrassWaverAmbientVp
+			{
+			}
+            
+			fragment_program_ref Examples/GrassWaverAmbientFp
+			{
+			}
+            
+            
+			alpha_rejection greater 150 
+			scene_blend alpha_blend
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+        }
+		// Decal pass
+		pass
+		{
+			// base colours, not needed for rendering, but as information
+			// to lighting pass categorisation routine
+			lighting off
+            
+			alpha_rejection greater 150 
+			scene_blend alpha_blend
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+            
+			vertex_program_ref Examples/GrassWaverAmbientVp
+			{
+			}
+            
+			fragment_program_ref Examples/GrassWaverAmbientFp
+			{
+			}
+            
+        }
+    }
+    
+}
+
+material Examples/GrassBladesAdditive
+{
+    transparency_casts_shadows on
+    receive_shadows on
+	// Vertex program waving grass    
+    technique
+    {
+        pass
+        {
+			vertex_program_ref Examples/GrassWaverAmbientVp
+			{
+			}            
+            
+			alpha_rejection greater 150 
+			scene_blend alpha_blend
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+        }
+    }
+}
+
+material Examples/GrassBlades
+{
+    transparency_casts_shadows on
+    receive_shadows on
+	// Vertex program waving grass    
+    technique
+    {
+        pass
+        {
+			vertex_program_ref Examples/GrassWaverVp
+			{
+			} 
+			fragment_program_ref Examples/GrassWaverFp
+			{
+			}
+            
+			alpha_rejection greater 150 
+			scene_blend alpha_blend
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+        }
+    }
+    // fallback
+    technique
+    {
+        pass
+        {
+			alpha_rejection greater 150 
+			scene_blend alpha_blend
+            
+		    cull_hardware none
+            cull_software none
+            
+            texture_unit
+            {
+				tex_address_mode clamp
+                texture gras_02.png 
+            }
+        }
+    }
+}
+
+
+material Examples/Rockwall
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture rockwall.tga
+			}
+		}
+	}
+}
+
+material Examples/Aureola
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			scene_blend alpha_blend
+			depth_write off			
+			diffuse vertexcolour
+			cull_hardware none
+
+			texture_unit
+			{
+				texture aureola.png PF_BYTE_LA
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+// Test hardware morph animation
+material Examples/HardwareMorphAnimation
+{
+	technique
+	{
+		pass
+		{
+			
+			vertex_program_ref Ogre/HardwareMorphAnimation
+			{
+				// all default
+			}
+
+			texture_unit
+			{
+				tex_coord_set 0
+				colour_op_ex source1 src_current src_current
+			}
+			// need to define these texture units otherwise GL won't use the uv sets			
+			texture_unit
+			{
+				tex_coord_set 1
+				// also need to set blending to ignore texture which is GL warning texture
+				colour_op_ex source1 src_current src_current
+			}
+			texture_unit
+			{
+				tex_coord_set 2
+				colour_op_ex source1 src_current src_current
+			}
+		
+		}
+	}
+}
+
+// Test hardware pose animation
+material Examples/HardwarePoseAnimation
+{
+	technique
+	{
+		pass
+		{
+			
+			vertex_program_ref Ogre/HardwarePoseAnimation
+			{
+				// all default
+			}
+			texture_unit
+			{
+				tex_coord_set 0
+				colour_op_ex source1 src_current src_current
+			}
+			// need to define these texture units otherwise GL won't use the uv sets			
+			texture_unit
+			{
+				tex_coord_set 1
+				// also need to set blending to ignore texture which is GL warning texture
+				colour_op_ex source1 src_current src_current
+			}
+			texture_unit
+			{
+				tex_coord_set 2
+				colour_op_ex source1 src_current src_current
+			}
+
+		
+		}
+	}
+}
+
+material RustyBarrel
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.5 0.5 0.5 1.0
+			diffuse 1.0 1.0 1.0 1.0
+			specular 0.0 0.0 0.0 1.0 12.5
+			emissive 0.0 0.0 0.0 1.0
+			texture_unit
+			{
+				texture RustyBarrel.png
+				filtering trilinear
+			}
+		}
+	}
+}
+
+material WoodPallet
+{
+	receive_shadows on
+	technique
+	{
+		pass
+		{
+			ambient 0.5 0.5 0.5 1.0
+			diffuse 1.0 1.0 1.0 1.0
+			specular 0.0 0.0 0.0 1.0 12.5
+
+			texture_unit
+			{
+				texture WoodPallet.png
+				filtering trilinear
+			}
+		}
+	}
+}
+
+material Examples/LightRibbonTrail
+{
+	technique
+	{
+		pass
+		{
+			lighting off
+			scene_blend add
+			depth_write off
+			diffuse vertexcolour
+
+			texture_unit
+			{
+				texture ribbonband.png 1d
+				tex_address_mode clamp
+				filtering none
+			}
+		}
+	}
+}
+
+material Examples/TudorHouse
+{
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture fw12b.jpg
+				tex_address_mode clamp
+			}
+		}
+	}
+}
+
+material jaiqua
+{
+	// Hardware skinning techniique
+	technique
+	{
+		pass
+		{
+			vertex_program_ref Ogre/HardwareSkinningTwoWeights
+			{
+			
+			}
+			// alternate shadow caster program
+			shadow_caster_vertex_program_ref Ogre/HardwareSkinningTwoWeightsShadowCaster
+			{
+				param_named_auto worldMatrix3x4Array world_matrix_array_3x4
+				param_named_auto viewProjectionMatrix viewproj_matrix
+				param_named_auto ambient ambient_light_colour
+			
+			}
+
+			texture_unit
+			{
+				texture blue_jaiqua.jpg
+				tex_address_mode clamp
+			}
+		}
+	}
+
+	// Software blending technique
+	technique
+	{
+		pass
+		{
+			texture_unit
+			{
+				texture blue_jaiqua.jpg
+				tex_address_mode clamp
+			}
+		}
+	}
+	
+}
+
+
+material Examples/Plane/IntegratedShadows
+{
+	technique
+	{
+		pass
+		{
+			// Single-pass shadowing
+			texture_unit
+			{
+				texture MtlPlat2.jpg
+			}
+			texture_unit
+			{
+				// standard modulation blend
+				content_type shadow
+				tex_address_mode clamp
+			}
+		}
+	}
+	
+}
+
+
+fragment_program Examples/ShowUV_p cg
+{
+	source Example_Basic.cg
+	entry_point showuv_p
+	profiles ps_2_0 arbfp1
+}
+fragment_program Examples/ShowUVdir3D cg
+{
+	source Example_Basic.cg
+	entry_point showuvdir3d_p
+	profiles ps_2_0 arbfp1
+}
+vertex_program Examples/ShowTangents_v cg
+{
+	source Example_Basic.cg
+	entry_point basicPassthroughTangent_v
+	profiles vs_2_0 arbvp1
+	default_params
+	{
+		param_named_auto worldViewProj worldviewproj_matrix
+	}
+}
+vertex_program Examples/ShowNormals_v cg
+{
+	source Example_Basic.cg
+	entry_point basicPassthroughNormal_v
+	profiles vs_2_0 arbvp1
+	default_params
+	{
+		param_named_auto worldViewProj worldviewproj_matrix
+	}
+}
+
+material Examples/ShowUV
+{
+	technique
+	{
+		pass
+		{
+			vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
+			{
+			}
+			fragment_program_ref Examples/ShowUV_p
+			{
+			}
+
+			
+		}
+	}
+}
+material Examples/ShowTangents
+{
+	technique
+	{
+		pass
+		{
+			vertex_program_ref Examples/ShowTangents_v
+			{
+			}
+			fragment_program_ref Examples/ShowUVdir3D
+			{
+			}
+
+			
+		}
+	}
+}
+material Examples/ShowNormals
+{
+	technique
+	{
+		pass
+		{
+			vertex_program_ref Examples/ShowNormals_v
+			{
+			}
+			fragment_program_ref Examples/ShowUVdir3D
+			{
+			}
+
+			
+		}
+	}
+}
+
+
diff --git a/Media/Grass.cg b/Media/Grass.cg
new file mode 100644
--- /dev/null
+++ b/Media/Grass.cg
@@ -0,0 +1,275 @@
+////////////////////////////// MOVING GRASS
+// Vertex program to wave some grass about
+// Assumes UV texture coords of v==0 indicates the top of the grass
+void grass_vp(float4 position : POSITION,
+			  float3 normal   : NORMAL,
+			  float2 uv		  : TEXCOORD0,
+			  out float4 oPosition : POSITION,
+			  out float2 oUv	   : TEXCOORD0,
+			  out float4 oColour    : COLOR,
+
+			  uniform float4x4 worldViewProj,
+			  uniform float4 camObjPos,
+			  uniform float4 ambient,
+			  uniform float4 objSpaceLight,
+			  uniform float4 lightColour,
+			  uniform float4 offset)
+{
+	float4 mypos = position;
+	//offset = float4(0.5, 0, 0, 0);
+	float4 factor = float4(1,1,1,1) - uv.yyyy;
+	mypos = mypos + offset * factor;
+	oPosition = mul(worldViewProj, mypos);
+
+	oUv = uv;
+    // Color    
+	// get vertex light direction (support directional and point)
+	float3 light = normalize(objSpaceLight.xyz -  (mypos.xyz * objSpaceLight.w));
+	// grass is just 2D quads, so if light passes underneath we need to invert the normal
+	// abs() will have the same effect
+    float diffuseFactor = abs(dot(normal.xyz, light));
+	oColour = ambient + diffuseFactor * lightColour;    
+    
+}
+
+void grass_fp( float2 uv	         : TEXCOORD0,
+               float4 colour         : COLOR,  
+               
+               out float4 oColour    : COLOR,
+              
+              uniform sampler2D diffuseMap
+              )
+{	
+    float4 texColor = tex2D(diffuseMap, uv.xy);
+    oColour = float4(texColor.rgb * colour.rgb, texColor.a); 
+}
+
+
+void grassTex_vp(
+              float4 position : POSITION,
+			  float4 normal   : NORMAL,
+			  float2 uv		  : TEXCOORD0,
+              
+			  out float4 oPosition : POSITION,
+			  out float2 oUv	   : TEXCOORD0,
+			  //out float4 oNormal   : NORMAL,
+
+			  uniform float4x4 worldViewProj,
+              
+			  uniform float4 ambient,
+			  uniform float4 objSpaceLight,
+			  uniform float4 lightColour,
+              
+			  uniform float4 offset)
+{	    
+     // Position
+	float4 mypos = position;
+	float4 factor = float4(1,1,1,1) - uv.yyyy;
+	mypos = mypos + offset * factor;
+	oPosition = mul(worldViewProj, mypos);
+    // Texture Coord
+	oUv.xy = uv.xy;      
+}
+
+/// grass_vp ambient
+void grassAmbient_vp(
+              float4 position : POSITION,
+			  float4 normal   : NORMAL,
+			  float2 uv		  : TEXCOORD0,
+              
+			  out float4 oPosition : POSITION,
+			  out float2 oUv	   : TEXCOORD0,
+			  out float4 oColour    : COLOR,
+			  //out float4 oNormal   : NORMAL,
+
+              //uniform float4 camObjPos,
+			  uniform float4x4 worldViewProj,              
+			  uniform float4 ambient,
+			  uniform float4 offset)
+{	
+     // Position
+	float4 mypos = position;
+	float4 factor = float4(1,1,1,1) - uv.yyyy;
+	mypos = mypos + offset * factor;
+  	oPosition = mul(worldViewProj, mypos);
+    // Texture Coord
+	oUv.xy = uv.xy;      
+    /*
+    // Normal
+    // Make vec from vertex to camera
+    float4 EyeVec = camObjPos - mypos;
+    // Dot the v to eye and the normal to see if they point
+    //  in the same direction or opposite
+    float aligned = dot(normal, EyeVec); // -1..1
+    // If aligned is negative, we need to flip the normal
+    if (aligned < 0)  
+        normal = -normal;  
+    //oNormal = normal; 
+    */
+    // Color    
+	oColour = ambient; 
+}
+
+
+void grassAmbient_fp( float2 uv	         : TEXCOORD0,
+               float4 colour         : COLOR,  
+               
+               out float4 oColour    : COLOR,
+              
+              uniform sampler2D diffuseMap
+              )
+{	
+    float4 texColor = tex2D(diffuseMap, uv.xy);
+    oColour = float4(colour.rgb, texColor.a); 
+}
+
+//////////////////////// GRASS SHADOW CASTER
+// Shadow caster vertex program.
+void grasscaster_vp(float4 position : POSITION,
+			        float2 uv	    : TEXCOORD0,
+              
+    			  out float4 oPosition  : POSITION,
+    			  out float2 oUv	    : TEXCOORD0,
+                  out float2 oDepth	    : TEXCOORD1,
+
+    			  uniform float4x4 worldViewProj,
+    			  uniform float4 offset,
+                  uniform float4 texelOffsets)
+{
+	float4 mypos = position;
+	float4 factor = float4(1,1,1,1) - uv.yyyy;
+	mypos = mypos + offset * factor;
+	oPosition = mul(worldViewProj, mypos);
+
+	// fix pixel / texel alignment
+	oPosition.xy += texelOffsets.zw * oPosition.w;
+    
+	oDepth.x = oPosition.z;
+	oDepth.y = oPosition.w;
+  
+  	oUv = uv;
+    
+}
+
+
+void grasscaster_fp(float2 uv	        : TEXCOORD0,
+                    float2 depth		: TEXCOORD1,
+                         
+                    out float4 result : COLOR,
+              
+                    uniform sampler2D diffuseMap
+                    )
+{	
+	float alpha = tex2D(diffuseMap, uv).a;
+	if (alpha > 0.001)
+    {
+       result = float4(1.0f, 1.0f, 1.0f, 0.0f);
+    }
+    else
+    {
+        float finalDepth = depth.x / depth.y;
+        // just smear across all components 
+        // therefore this one needs high individual channel precision
+        result = float4(finalDepth.xxx, 1.0f);
+    }
+}
+
+
+//////////////////////// GRASS SHADOW RECEIVER
+void grassreceiver_vp(
+                      float4 position : POSITION,
+        			  float4 normal   : NORMAL,
+        			  float2 uv		  : TEXCOORD0,
+              
+			  out float4 oPosition    : POSITION,
+			  out float4 oShadowUV    : TEXCOORD0,
+			  out float3 oUv	      : TEXCOORD1,
+			  out float4 oColour      : COLOR,
+        	  //out float4 oNormal      : NORMAL,
+
+              uniform float4x4        world,
+			  uniform float4x4        worldViewProj,
+              uniform float4x4        texViewProj,
+              
+              uniform float4 camObjPos,
+              
+			  uniform float4 objSpaceLight,
+			  uniform float4 lightColour,
+              
+			  uniform float4 offset)
+{	    
+	float4 mypos = position;
+	float4 factor = float4(1,1,1,1) - uv.yyyy;
+	mypos = mypos + offset * factor;
+	oPosition = mul(worldViewProj, mypos);
+	oUv.xy = uv.xy;    
+    // Transform position to world space
+	float4 worldPos = mul(world, mypos);    
+	// calculate shadow map coords
+	oShadowUV = mul(texViewProj, worldPos);  
+       
+    // Make vec from vertex to camera
+    float4 EyeVec = camObjPos - mypos;
+    // Dot the v to eye and the normal to see if they point
+    // in the same direction or opposite
+    float alignedEye = dot(normal, EyeVec); // -1..1
+    // If aligned is negative, we need to flip the normal
+    if (alignedEye < 0)  
+        normal = -normal;        
+    //oNormal = normal;
+    
+  	// get vertex light direction (support directional and point)
+	float3 lightVec = normalize(objSpaceLight.xyz -  (mypos.xyz * objSpaceLight.w));
+    // Dot the v to light and the normal to see if they point
+    // in the same direction or opposite
+    float alignedLight = dot(normal.xyz, lightVec); // -1..1
+    // If aligned is negative, shadowing/lighting is not possible.
+    oUv.z = (alignedLight < 0)? 0 : 1 ;
+         
+    float diffuseFactor = max(alignedLight, 0);
+	//oColour = diffuseFactor * lightColour;    
+	oColour = lightColour;    
+}
+  	
+  	
+void grassreceiver_fp( 
+                         float4 shadowUV    : TEXCOORD0
+                       , float3 uv	        : TEXCOORD1
+                       , float4 vertexLight : COLOR     
+                      
+                       , out float4 oColour : COLOR
+              
+                       , uniform sampler2D shadowMap : register(s0)
+                       , uniform sampler2D diffuseMap : register(s1)
+                      
+                      //, uniform float inverseShadowmapSize
+                      , uniform float fixedDepthBias
+                      , uniform float gradientClamp
+                      , uniform float gradientScaleBias
+              )
+{		
+    if (shadowUV.z > 0)
+    {
+       float4 diffuse = tex2D(diffuseMap, uv.xy);
+       if (diffuse.a > 0.001)
+       {
+            oColour = float4(0.0f, 0.0f, 0.0f, 0.0f);
+  }
+       else
+       {
+            // point on shadowmap (no gradient as cg1.4 compiler is unable to handle that complexity)
+            shadowUV = shadowUV / shadowUV.w;
+            float4 shadowDepths = tex2D(shadowMap, shadowUV.xy);        
+            
+            float gradientFactor = gradientClamp * gradientScaleBias;
+            float depthAdjust = gradientFactor + fixedDepthBias * shadowDepths.x;
+            float centerdepth = shadowDepths.x + depthAdjust;
+  
+            oColour = (centerdepth > shadowUV.z) ? float4(vertexLight.rgb, diffuse.a) : float4(0, 0, 0, diffuse.a);
+       }
+    }
+    else
+    {
+        oColour = float4(0.0f, 0.0f, 0.0f, 0.0f);
+    }
+}
diff --git a/Media/GreenSkin.jpg b/Media/GreenSkin.jpg
new file mode 100644
Binary files /dev/null and b/Media/GreenSkin.jpg differ
diff --git a/Media/HornetUV_Cylinder.tga b/Media/HornetUV_Cylinder.tga
deleted file mode 100644
Binary files a/Media/HornetUV_Cylinder.tga and /dev/null differ
diff --git a/Media/IMG_0436.JPG b/Media/IMG_0436.JPG
deleted file mode 100644
Binary files a/Media/IMG_0436.JPG and /dev/null differ
diff --git a/Media/MtlPlat2.jpg b/Media/MtlPlat2.jpg
new file mode 100644
Binary files /dev/null and b/Media/MtlPlat2.jpg differ
diff --git a/Media/Ogre.material b/Media/Ogre.material
new file mode 100644
--- /dev/null
+++ b/Media/Ogre.material
@@ -0,0 +1,66 @@
+material Ogre/Earring
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.7 0.7 0
+			diffuse 0.7 0.7 0
+
+			texture_unit
+			{
+				texture spheremap.png
+				colour_op_ex add src_texture src_current
+				colour_op_multipass_fallback one one
+				env_map spherical
+			}
+		}
+	}
+}
+
+material Ogre/Skin
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.3 0.8 0.3
+
+			texture_unit
+			{
+				texture GreenSkin.jpg
+				tex_address_mode mirror
+			}
+		}
+	}
+}
+
+material Ogre/Tusks
+{
+	technique
+	{
+		pass
+		{
+			ambient 0.7 0.7 0.6
+
+			texture_unit
+			{
+				texture tusk.jpg
+				scale 0.2 0.2
+			}
+		}
+	}
+}
+
+material Ogre/Eyes
+{
+	technique
+	{
+		pass
+		{
+			ambient 1 0.4 0.4
+			diffuse 1 0.7 0
+			emissive 0.3 0.1 0
+		}
+	}
+}
diff --git a/Media/TailWings.JPG b/Media/TailWings.JPG
deleted file mode 100644
Binary files a/Media/TailWings.JPG and /dev/null differ
diff --git a/Media/WingFlap.jpg b/Media/WingFlap.jpg
deleted file mode 100644
Binary files a/Media/WingFlap.jpg and /dev/null differ
diff --git a/Media/WingFlapBump.jpg b/Media/WingFlapBump.jpg
deleted file mode 100644
Binary files a/Media/WingFlapBump.jpg and /dev/null differ
diff --git a/Media/Wings.jpg b/Media/Wings.jpg
deleted file mode 100644
Binary files a/Media/Wings.jpg and /dev/null differ
diff --git a/Media/WingsBump.jpg b/Media/WingsBump.jpg
deleted file mode 100644
Binary files a/Media/WingsBump.jpg and /dev/null differ
diff --git a/Media/blackhawk.material b/Media/blackhawk.material
deleted file mode 100644
--- a/Media/blackhawk.material
+++ /dev/null
@@ -1,37 +0,0 @@
-material Windows
-{
-	receive_shadows on
-	technique
-	{
-		pass
-		{
-			ambient 0.500000 0.500000 0.500000 0.168000
-			diffuse 0.640000 0.640000 0.711253 0.168000
-			specular 0.490442 0.490442 0.490442 0.168000 4.000000
-			emissive 0.000000 0.000000 0.000000 0.168000
-			scene_blend alpha_blend
-			depth_write off
-		}
-	}
-}
-material HelicopterBody
-{
-	receive_shadows on
-	technique
-	{
-		pass
-		{
-			// ambient 0.300000 0.300000 0.000000 1.000000
-			// diffuse 0.786168 0.795673 0.786204 1.000000
-			// specular 0.630000 0.630000 0.630000 1.000000 12.500000
-			// emissive 0.000000 0.000000 0.000000 1.000000
-			texture_unit
-			{
-				texture lava.tga
-				// tex_address_mode wrap
-				// filtering trilinear
-				// colour_op alpha_blend
-			}
-		}
-	}
-}
diff --git a/Media/clouds.jpg b/Media/clouds.jpg
deleted file mode 100644
Binary files a/Media/clouds.jpg and /dev/null differ
diff --git a/Media/hdr.cg b/Media/hdr.cg
new file mode 100644
--- /dev/null
+++ b/Media/hdr.cg
@@ -0,0 +1,25 @@
+void morningskybox_fp (
+	float2 uv : TEXCOORD0,
+	out float4 colour : COLOR,
+
+	uniform sampler2D tex : register(s0) )
+{
+	colour = tex2D(tex, uv);
+
+	// blow out the light a bit
+	colour *= 1.7;
+}
+void morningcubemap_fp (
+	float3 uv : TEXCOORD0,
+	out float4 colour : COLOR,
+
+	uniform samplerCUBE tex : register(s0) )
+{
+	colour = texCUBE(tex, uv);
+
+	// blow out the light a bit
+	colour *= 1.7;
+}
+
+
+
diff --git a/Media/knot.mesh b/Media/knot.mesh
new file mode 100644
Binary files /dev/null and b/Media/knot.mesh differ
diff --git a/Media/lagoon.tga b/Media/lagoon.tga
deleted file mode 100644
Binary files a/Media/lagoon.tga and /dev/null differ
diff --git a/Media/lava.tga b/Media/lava.tga
deleted file mode 100644
Binary files a/Media/lava.tga and /dev/null differ
diff --git a/Media/mix.tga b/Media/mix.tga
deleted file mode 100644
Binary files a/Media/mix.tga and /dev/null differ
diff --git a/Media/ogrehead.mesh b/Media/ogrehead.mesh
new file mode 100644
Binary files /dev/null and b/Media/ogrehead.mesh differ
diff --git a/Media/r2skin.jpg b/Media/r2skin.jpg
new file mode 100644
Binary files /dev/null and b/Media/r2skin.jpg differ
diff --git a/Media/robot.mesh b/Media/robot.mesh
new file mode 100644
Binary files /dev/null and b/Media/robot.mesh differ
diff --git a/Media/robot.skeleton b/Media/robot.skeleton
new file mode 100644
Binary files /dev/null and b/Media/robot.skeleton differ
diff --git a/Media/spheremap.png b/Media/spheremap.png
new file mode 100644
Binary files /dev/null and b/Media/spheremap.png differ
diff --git a/Media/terrain.cfg b/Media/terrain.cfg
deleted file mode 100644
--- a/Media/terrain.cfg
+++ /dev/null
@@ -1,71 +0,0 @@
-# The main world texture (if you wish the terrain manager to create a material for you)
-WorldTexture=terrain_texture.jpg
-
-# The detail texture (if you wish the terrain manager to create a material for you)
-DetailTexture=terrain_detail.jpg
-
-#number of times the detail texture will tile in a terrain tile
-DetailTile=3
-
-# Heightmap source
-PageSource=Heightmap
-
-# Heightmap-source specific settings
-Heightmap.image=terrain.png
-
-# If you use RAW, fill in the below too
-# RAW-specific setting - size (horizontal/vertical)
-#Heightmap.raw.size=513
-# RAW-specific setting - bytes per pixel (1 = 8bit, 2=16bit)
-#Heightmap.raw.bpp=2
-
-# How large is a page of tiles (in vertices)? Must be (2^n)+1
-PageSize=513
-
-# How large is each tile? Must be (2^n)+1 and be smaller than PageSize
-TileSize=65
-
-# The maximum error allowed when determining which LOD to use
-MaxPixelError=3
-
-# The size of a terrain page, in world units
-PageWorldX=1500
-PageWorldZ=1500
-# Maximum height of the terrain 
-MaxHeight=100
-
-# Upper LOD limit
-MaxMipMapLevel=5
-
-#VertexNormals=yes
-#VertexColors=yes
-#UseTriStrips=yes
-
-# Use vertex program to morph LODs, if available
-VertexProgramMorph=yes
-
-# The proportional distance range at which the LOD morph starts to take effect
-# This is as a proportion of the distance between the current LODs effective range,
-# and the effective range of the next lower LOD
-LODMorphStart=0.2
-
-# This following section is for if you want to provide your own terrain shading routine
-# Note that since you define your textures within the material this makes the 
-# WorldTexture and DetailTexture settings redundant
-
-# The name of the vertex program parameter you wish to bind the morph LOD factor to
-# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely
-# to the same position as the next lower LOD
-# USE THIS IF YOU USE HIGH-LEVEL VERTEX PROGRAMS WITH LOD MORPHING
-#MorphLODFactorParamName=morphFactor
-
-# The index of the vertex program parameter you wish to bind the morph LOD factor to
-# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely
-# to the same position as the next lower LOD
-# USE THIS IF YOU USE ASSEMBLER VERTEX PROGRAMS WITH LOD MORPHING
-#MorphLODFactorParamIndex=4
-
-# The name of the material you will define to shade the terrain
-#CustomMaterialName=TestTerrainMaterial
-
-
diff --git a/Media/terrain.png b/Media/terrain.png
deleted file mode 100644
Binary files a/Media/terrain.png and /dev/null differ
diff --git a/Media/terrain_detail.jpg b/Media/terrain_detail.jpg
deleted file mode 100644
Binary files a/Media/terrain_detail.jpg and /dev/null differ
diff --git a/Media/terrain_texture.jpg b/Media/terrain_texture.jpg
deleted file mode 100644
Binary files a/Media/terrain_texture.jpg and /dev/null differ
diff --git a/Media/tusk.jpg b/Media/tusk.jpg
new file mode 100644
Binary files /dev/null and b/Media/tusk.jpg differ
diff --git a/README b/README
--- a/README
+++ b/README
@@ -6,35 +6,17 @@
 
 Usage:
 
-1. Install non-Haskell dependencies (OGRE: http://www.ogre3d.org/,
-SDL: http://www.libsdl.org/).
+1. Install non-Haskell dependencies (OGRE: http://www.ogre3d.org/).
 2. Install Haskell dependencies (hogre (see 
-http://github.com/anttisalonen/hogre), SDL, stm) either using
-cabal, by downloading and installing the packages manually.
+http://github.com/anttisalonen/hogre)) either using
+cabal or by downloading and installing the packages manually.
+   Note: you need cgen, a Haskell binding generator, for hogre. cgen can be
+   found at git://github.com/anttisalonen/cgen.git or at Hackage.
 3. Unpack hogre-examples
 4. cabal configure [--user] && cabal build
-5. Define the directory where the OGRE plugins are installed in plugins.cfg.
-The default is /usr/lib/OGRE.
-6. dist/build/example_0[123]/example_0[123]
-
-You need to run all the examples in the directory where the directory Media
-is located (root directory of the package), otherwise the content will not 
-be found.
-
-Example descriptions:
-
-example_01 creates a simple scene with a moving entity.
-It roughly corresponds to OGRE basic tutorial #2 but without input.
-If nothing is rendered, try deleting the ogre.cfg file.
-
-example_02 demonstrates use of SDL for input and window creation.
-Use arrow keys and page up/down to move, mouse with right mouse button down
-to look around and 'q' or escape to exit.
-
-example_03 demonstrates ray scene queries and loading a world configuration 
-from a file.
-It roughly corresponds to OGRE intermediate tutorial #2.
-Use arrow keys and page up/down to move, mouse with right mouse button down
-to look around and 'q' or escape to exit. With the left mouse button you can
-create some robots on the landscape.
+5. Define the directory where the OGRE plugins are installed by modifying
+   plugins.cfg. The default is /usr/lib/OGRE.
+6. Run an example: dist/build/example_01/example_01
+   The examples must be run in the root directory of the package in order
+   to find the media files.
 
diff --git a/hogre-examples.cabal b/hogre-examples.cabal
--- a/hogre-examples.cabal
+++ b/hogre-examples.cabal
@@ -1,11 +1,11 @@
 Name:           hogre-examples
-Version:        0.0.3
+Version:        0.1.0
 Cabal-Version:  >= 1.6
-License:        OtherLicense
+License:        MIT
 License-File:   LICENSE
 Author:         Antti Salonen<ajsalonen at gmail dot com>
 Maintainer:     Antti Salonen<ajsalonen at gmail dot com>
-Copyright:      Antti Salonen 2009
+Copyright:      Antti Salonen 2010
 Stability:      Unstable
 Homepage:       http://github.com/anttisalonen/hogre-examples
 Category:       Graphics
@@ -13,54 +13,41 @@
 Description:    Examples for using Hogre, Haskell bindings to OGRE
                 (Object-Oriented Graphics Rendering Engine)
                 (<http://www.ogre3d.org/>).
-                example_01 creates a simple scene with a moving entity.
-                example_02 demonstrates use of SDL for input and window
-                creation.
-                example_03 demonstrates ray scene queries and loading
-                a world configuration from a file.
 Build-type:     Simple
-extra-source-files: src/Common.hs,
-                resources.cfg, plugins.cfg, README,
-                Media/blackhawk.material,
-                Media/clouds.jpg,
-                Media/Example.material,
-                Media/HornetUV_Cylinder.tga,
-                Media/IMG_0436.JPG,
-                Media/lagoon.tga,
-                Media/lava.tga,
-                Media/mix.tga,
-                Media/TailWings.JPG,
-                Media/terrain.cfg,
-                Media/terrain_detail.jpg,
-                Media/terrain.png,
-                Media/terrain_texture.jpg,
-                Media/WingFlapBump.jpg,
-                Media/WingFlap.jpg,
-                Media/WingsBump.jpg,
-                Media/Wings.jpg
 
+data-files:     Media/Example_Basic.cg
+                Media/Examples.material
+                Media/Grass.cg
+                Media/GreenSkin.jpg
+                Media/hdr.cg
+                Media/knot.mesh
+                Media/MtlPlat2.jpg
+                Media/ogrehead.mesh
+                Media/Ogre.material
+                Media/r2skin.jpg
+                Media/robot.mesh
+                Media/robot.skeleton
+                Media/spheremap.png
+                Media/tusk.jpg
+                plugins.cfg
+                README
+
+extra-source-files: src/Common.hs
+
 source-repository head
   type:      git
   location:  git://github.com/anttisalonen/hogre-examples.git
 
 Executable example_01
-  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.0.1
+  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.1.0
   Main-is:         Example_01.hs
   Hs-Source-Dirs:  src
   Ghc-options:     -Wall
   extra-libraries: OgreMain
 
 Executable example_02
-  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.0.1, SDL>=0.4.0
+  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.1.0
   Main-is:         Example_02.hs
-  Hs-Source-Dirs:  src
-  Ghc-options:     -Wall
-  extra-libraries: OgreMain
-
-Executable example_03
-  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.0.1, SDL>=0.4.0,
-                   stm>=2.1.1.2
-  Main-is:         Example_03.hs
   Hs-Source-Dirs:  src
   Ghc-options:     -Wall
   extra-libraries: OgreMain
diff --git a/resources.cfg b/resources.cfg
deleted file mode 100644
--- a/resources.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-# Resource locations to be added to the default path
-[General]
-FileSystem=./Media
diff --git a/src/Common.hs b/src/Common.hs
--- a/src/Common.hs
+++ b/src/Common.hs
@@ -1,114 +1,85 @@
-module Common(runWithSDL, FrameCallback(..), EventCallback(..))
+module Common
 where
 
-import Control.Concurrent
-import Control.Concurrent.STM
-
-import qualified Graphics.UI.SDL as SDL
+import System.Exit
+import Control.Monad
 
-import Graphics.Ogre.Ogre
+import Graphics.Ogre.HOgre
+import Graphics.Ogre.Types
 
-data FrameCallback a = FrameCallback { framecallback :: (a -> IO a) }
-data EventCallback a = EventCallback { eventcallback :: (a -> [SDL.Event] -> IO a) }
+-- based on basic tutorial 6 from Ogre Wiki.
+-- http://www.ogre3d.org/tikiwiki/Basic+Tutorial+6&structure=Tutorials
+generalSetup :: (Root -> IO a) -> IO a
+generalSetup fun =
+  -- construct Ogre::Root
+  root_with "plugins.cfg" "ogre.cfg" "Ogre.log" $ \root -> do
 
-pollAllSDLEvents :: IO [SDL.Event]
-pollAllSDLEvents = go []
-    where go l = do
-                   e <- SDL.pollEvent
-                   if e == SDL.NoEvent 
-                     then return l 
-                     else do
-                       es <- pollAllSDLEvents
-                       return (e:es)
+    -- setup resources
+    root_addResourceLocation root "Media" "FileSystem" "Group" True
 
-type Action = (Bool,        -- right mouse button pressed
-    (Float, Float),         -- rotation (yaw, pitch)
-    (Float, Float, Float),  -- translation (x, y, z)
-    Bool)                   -- quit flag
+    -- configure
+    -- show the configuration dialog and initialise the system
+    restored <- root_restoreConfig root
+    when (not restored) $ do
+      configured <- root_showConfigDialog root
+      when (not configured) $ exitWith (ExitFailure 1)
+    window <- root_initialise root True "Render Window" ""
 
-eventToAction :: Action -> SDL.Event -> Action
-eventToAction (bt, ro, t, _) SDL.Quit = (bt, ro, t, True)
-eventToAction (bt, ro, t, _) (SDL.KeyDown (SDL.Keysym SDL.SDLK_ESCAPE _ _)) = (bt, ro, t, True)
-eventToAction (bt, ro, t, _) (SDL.KeyDown (SDL.Keysym SDL.SDLK_q      _ _)) = (bt, ro, t, True)
-eventToAction (bt, ro, t@(x_, y_, z_), q) (SDL.KeyDown (SDL.Keysym k _ _)) = case k of
-  SDL.SDLK_UP       -> (bt, ro, (x_, y_, z_ - 1.0), q)
-  SDL.SDLK_DOWN     -> (bt, ro, (x_, y_, z_ + 1.0), q)
-  SDL.SDLK_RIGHT    -> (bt, ro, (x_ + 1.0, y_, z_), q)
-  SDL.SDLK_LEFT     -> (bt, ro, (x_ - 1.0, y_, z_), q)
-  SDL.SDLK_PAGEDOWN -> (bt, ro, (x_, y_ - 1.0, z_), q)
-  SDL.SDLK_PAGEUP   -> (bt, ro, (x_, y_ + 1.0, z_), q)
-  _ -> (bt, ro, t, q)
-eventToAction (bt, ro, t@(x_, y_, z_), q) (SDL.KeyUp   (SDL.Keysym k _ _)) = case k of
-  SDL.SDLK_UP        -> (bt, ro, (x_, y_, z_ + 1.0), q)
-  SDL.SDLK_DOWN      -> (bt, ro, (x_, y_, z_ - 1.0), q)
-  SDL.SDLK_RIGHT     -> (bt, ro, (x_ - 1.0, y_, z_), q)
-  SDL.SDLK_LEFT      -> (bt, ro, (x_ + 1.0, y_, z_), q)
-  SDL.SDLK_PAGEDOWN  -> (bt, ro, (x_, y_ + 1.0, z_), q)
-  SDL.SDLK_PAGEUP    -> (bt, ro, (x_, y_ - 1.0, z_), q)
-  _ -> (bt, ro, t, q)
-eventToAction (False, ro, t, q)        (SDL.MouseMotion _ _ _ _) = (False, ro, t, q)
-eventToAction (True, (ya, pit), t, q) (SDL.MouseMotion _ _ abs_x abs_y) = (True, (ya - (0.005 * fromIntegral abs_x), pit - (0.005 * fromIntegral abs_y)), t, q)
-eventToAction (_,  ro, t, q) (SDL.MouseButtonUp   _ _ SDL.ButtonRight) = (False, ro, t, q)
-eventToAction (_,  ro, t, q) (SDL.MouseButtonDown _ _ SDL.ButtonRight) = (True, ro, t, q)
-eventToAction (bt, ro, t, q) _ = (bt, ro, t, q)
+    -- set default mipmap level (some APIs ignore this)
+    root_getTextureManager root >>= \tmgr -> textureManager_setDefaultNumMipmaps tmgr 5
 
-resetRotation :: Action -> Action
-resetRotation (bt, _, t, q) = (bt, (0, 0), t, q)
+    -- initialise all resource groups
+    resourceGroupManager_getSingletonPtr >>= resourceGroupManager_initialiseAllResourceGroups
 
-doAction :: (Float, Float) -> (Float, Float, Float) -> IO ()
-doAction (ya, pit) (x_, y_, z_) = do
-  rotateCamera (YPR ya 0 0)  World
-  rotateCamera (YPR 0 pit 0) Local
-  translateCamera (Vector3 x_ y_ z_)
+    -- create the scene manager, here a generic one
+    smgr <- root_createSceneManager1 root "DefaultSceneManager" "Scene Manager"
 
-shutdown :: IO ()
-shutdown = do
-    putStrLn "Shutting down..."
-    cleanupOgre
+    -- create and position the camera
+    cam <- sceneManager_createCamera smgr "PlayerCam"
+    frustum_setNearClipDistance (toFrustum cam) 5
 
-runWithSDL :: IO () -> (a, EventCallback a, FrameCallback a) -> IO ()
-runWithSDL initGame action = SDL.withInit [SDL.InitEverything] $ runThreadedNonblocking initGame action 20 20 >> return ()
+    -- create one viewport, entire window
+    vp <- renderTarget_addViewport (toRenderTarget window) cam 0 0 0 1 1
+    colourValue_with 0 0 0 1 $ viewport_setBackgroundColour vp
 
-nullAction :: Action
-nullAction = (False, (0, 0), (0, 0, 0), False)
+    -- Alter the camera aspect ratio to match the viewport
+    vpw <- viewport_getActualWidth vp
+    vph <- viewport_getActualHeight vp
+    frustum_setAspectRatio (toFrustum cam) (fromIntegral vpw / fromIntegral vph)
 
-runThreadedNonblocking :: IO () -> (a, EventCallback a, FrameCallback a) -> Int -> Int -> IO ()
-runThreadedNonblocking initGame (ival, ecb, fcb) renderinterval handleinterval = do
-   initGame
-   let ri = renderinterval * 1000
-   let si = handleinterval * 1000
-   box <- atomically $ newTMVar ival
-   rtid <- forkIO (renderLoop box fcb ri)
-   inputLoop si box ecb [rtid] nullAction
+    fun root
 
-renderLoop :: TMVar a -> FrameCallback a -> Int -> IO ()
-renderLoop box action ri = do
-   renderOgre
-   val <- atomically $ takeTMVar box
-   nval <- (framecallback action) val
-   atomically $ putTMVar box nval
-   threadDelay ri
-   renderLoop box action ri
+render :: RenderWindow -> Root -> a -> (Root -> Float -> a -> IO (a, Bool)) -> IO a
+render window root value fun = do
+    timer <- root_getTimer root
+    time <- timer_getMicroseconds timer
+    render' time window root value fun
 
-fullCleanup :: [ThreadId] -> IO () -> IO ()
-fullCleanup tids cf = mapM_ killThread tids >> cf
+render' :: Int -> RenderWindow -> Root -> a -> (Root -> Float -> a -> IO (a, Bool)) -> IO a
+render' time window root value fun = 
+  do windowEventUtilities_messagePump
+     closed <- renderWindow_isClosed window
+     if closed
+       then return value
+       else do
+         success <- root_renderOneFrame1 root
+         timer <- root_getTimer root
+         time' <- timer_getMicroseconds timer
+         let delta = (fromIntegral (time' - time)) / 1000000
+         (value', cont) <- fun root delta value
+         if success && cont
+           then render' time' window root value' fun
+           else return value'
 
-inputLoop :: Int -> TMVar a -> EventCallback a -> [ThreadId] -> Action -> IO ()
-inputLoop si box action tids ac = do
-  i <- input ac box action
-  case i of
-    Nothing  -> fullCleanup tids shutdown
-    Just nac -> threadDelay si >> inputLoop si box action tids (resetRotation nac)
+nullHandler :: Root -> Float -> () -> IO ((), Bool)
+nullHandler _ _ _ = return ((), True)
 
-input :: Action -> TMVar a -> EventCallback a -> IO (Maybe Action)
-input ac box action = do
-  events <- pollAllSDLEvents
-  -- when (not (null events)) (print events >> (getCameraPosition >>= print))
-  let nac@(_, ro, t, q) = foldl eventToAction ac events
-  if q then return Nothing else do 
-               val <- atomically $ takeTMVar box
-               nval <- (eventcallback action) val events
-               atomically $ putTMVar box nval
-               doAction ro t
-               return (Just nac)
+addEntity :: SceneManager -> String -> IO (Entity, SceneNode)
+addEntity smgr mesh = do
+  ent <- sceneManager_createEntity2 smgr mesh
+  rootNode <- sceneManager_getRootSceneNode smgr
+  node <- sceneManager_createSceneNode1 smgr
+  node_addChild (toNode rootNode) (toNode node)
+  sceneNode_attachObject node (toMovableObject ent)
+  return (ent, node)
 
diff --git a/src/Example_01.hs b/src/Example_01.hs
--- a/src/Example_01.hs
+++ b/src/Example_01.hs
@@ -1,48 +1,30 @@
 module Main
 where
 
-import Graphics.Ogre.Ogre
-import Control.Exception
-import Control.Concurrent (threadDelay)
+import Graphics.Ogre.HOgre
 
-renderLoop :: Float -> IO ()
-renderLoop f = do
-    renderOgre
-    setEntityPosition "obj1" (ogreloc f)
-    setLightPosition "light2" (Vector3 30 20 50)
-    threadDelay 10000
-    renderLoop (f + 0.008)
+import Common
 
-ogreloc :: Float -> Vector3
-ogreloc f = Vector3 (30 + 20 * sin f) (8 + 2 * sin (0.2 * f)) (50 + 20 * cos f)
+-- based on basic tutorial 6 from Ogre Wiki.
+-- http://www.ogre3d.org/tikiwiki/Basic+Tutorial+6&structure=Tutorials
+main :: IO ()
+main = generalSetup $ \root -> do
 
-plloc :: Float -> Vector3
-plloc f = Vector3 (30 + 40 * sin (4.0 * f)) 20 (50 + 40 * cos (4.0 * f))
+  smgr <- root_getSceneManager root "Scene Manager"
+  cam <- sceneManager_getCamera smgr "PlayerCam"
 
-main :: IO ()
-main = do
-    let set = OgreSettings "resources.cfg" True "Hogre Example 01" (Color 0.2 0.2 0.2) StencilAdditive [Generic]
-    let cam = Camera (Vector3 30.0 8.0 50.0) 0 (Vector3 135.0 40.0 50.0)
-    let yelcol = Color 1.0 1.0 0.0
-    let dircol = Color 0.25 0.25 0
-    let whitecol = Color 1 1 1
-    let spotrange = (0.0, degToRad 80.0)
-    let l1 = Light "light1" yelcol yelcol (SpotLight (Vector3  30 50.0 50) (Vector3  0.0  (-1.0)   0.0) spotrange)
-    let l2 = Light "light2" whitecol whitecol (PointLight (plloc 0))
-    let l3 = Light "light3" dircol dircol (DirectionalLight (Vector3 0 0 1))
-    let plane = Plane unitY 0.0 70.0 100.0 20 20 5.0 5.0 unitZ "DarkBlue"
-    let pl = Entity "ground" (Vector3 35.0 0.0 50.0) plane False (Vector3 1.0 1.0 1.0)
-    let lig = [l1, l2, l3]
-    let ents = [pl]
-    let sce = OgreScene cam ents lig
-    initOgre set
-    addScene sce
-    addEntity (Entity "obj1" (ogreloc 0) (StdMesh "robot.mesh" (YPR 0 0 0)) True (Vector3 0.20 0.20 0.20))
-    handle shutdown (renderLoop 0)
+  camera_setPosition1 cam 0 0 80
+  camera_lookAt cam 0 0 (-300)
 
-shutdown :: IOException -> IO ()
-shutdown e = do
-    print e
-    putStrLn "Shutting down..."
-    cleanupOgre
+  _ <- addEntity smgr "ogrehead.mesh"
+
+  -- set ambient light
+  colourValue_with 0.5 0.5 0.5 1.0 (sceneManager_setAmbientLight smgr)
+
+  -- create a light
+  l <- sceneManager_createLight1 smgr "MainLight"
+  light_setPosition1 l 20 80 50
+
+  window <- root_getAutoCreatedWindow root
+  render window root () nullHandler
 
diff --git a/src/Example_02.hs b/src/Example_02.hs
--- a/src/Example_02.hs
+++ b/src/Example_02.hs
@@ -1,39 +1,81 @@
-{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, FunctionalDependencies #-}
 module Main
 where
 
-import qualified Graphics.UI.SDL as SDL
+import Control.Monad
 
-import Graphics.Ogre.Ogre
-import Common
+import Graphics.Ogre.HOgre
+import Graphics.Ogre.Types
 
-initGame :: IO ()
-initGame = do
-    let set = OgreSettings "resources.cfg" False "Hogre Example 02" (Color 0.2 0.2 0.2) StencilModulative [Generic]
-    let cam = Camera (Vector3 100.0 10.0 40) 0 (Vector3 101 10 40)
-    let lightdiffuse = Color 0.9 0.9 0.9
-    let lightspecular = Color 0.8 0.8 0.8
-    let spotrange = (0.0, degToRad 80.0)
-    let l1 = Light "light1" lightdiffuse lightspecular (SpotLight (Vector3  0 15.0 0) (Vector3   1.0  (-1.0)   1.0) spotrange)
-    let l2 = Light "light2" lightdiffuse lightspecular (SpotLight (Vector3 70 15.0 0) (Vector3 (-1.0) (-1.0)   1.0) spotrange)
-    let l3 = Light "light3" lightdiffuse lightspecular (SpotLight (Vector3  0 15.0 100) (Vector3   1.0  (-1.0) (-1.0)) spotrange)
-    let l4 = Light "light4" lightdiffuse lightspecular (SpotLight (Vector3 70 15.0 100) (Vector3 (-1.0) (-1.0) (-1.0)) spotrange)
-    let plane = Plane unitY 0.0 70.0 100.0 20 20 5.0 5.0 unitZ "HelicopterBody"
-    let pl = Entity "ground" (Vector3 35.0 0.0 50.0) plane False (Vector3 1.0 1.0 1.0)
-    let robotmesh = "robot.mesh"
-    let robotscale = Vector3 0.36 0.24 0.3
-    let robot1 = Entity "robot1" (Vector3 35.0 3.0 4.2) (StdMesh robotmesh (YPR  halfPI  0.0 0.0)) True robotscale
-    let robot2 = Entity "robot2" (Vector3 35.0 3.0 84.5)  (StdMesh robotmesh (YPR  halfPI  0.0 0.0)) True robotscale
-    let lig = [l1, l2, l3, l4]
-    let ents = [pl, robot1, robot2]
-    let sce = OgreScene cam ents lig
-    let (wid, hei) = (1024, 768)
-    _ <- SDL.setVideoMode wid hei 16 [SDL.OpenGL, SDL.HWAccel]
-    SDL.wasInit [SDL.InitEverything] >>= print
-    initOgre set
-    addScene sce
-    addEntity (Entity "obj1" (Vector3 5.0 20.0 10.0) (StdMesh robotmesh (YPR 0.0 0.0 0.0)) True (Vector3 0.2 0.2 0.2))
+import Common
 
+-- based on intermediate tutorial 1 from Ogre Wiki.
+-- http://www.ogre3d.org/tikiwiki/Intermediate+Tutorial+1&structure=Tutorials
 main :: IO ()
-main = runWithSDL initGame ((), EventCallback (\_ _ -> return ()), FrameCallback (\_ -> return ()))
+main = do 
+  _ <- generalSetup $ \root -> do
+
+    smgr <- root_getSceneManager root "Scene Manager"
+    cam <- sceneManager_getCamera smgr "PlayerCam"
+
+    -- set ambient light
+    colourValue_with 1 1 1 1 $ sceneManager_setAmbientLight smgr
+
+    (robotEntity, robotNode) <- addEntity smgr "robot.mesh"
+    let (initx, initz) = initPos
+    node_translate2 (toNode robotNode) initx 0 initz TS_WORLD
+
+    anim <- entity_getAnimationState robotEntity "Walk"
+    animationState_setLoop anim True
+    animationState_setEnabled anim True
+
+    addKnot smgr 0 (-10) 25
+    addKnot smgr 550 (-10) 50
+    addKnot smgr (-100) (-10) (-200)
+
+    camera_setPosition1 cam 90 280 535
+    -- camera_lookAt cam 0 0 30
+    radian_with1 (-0.52359) $ camera_pitch cam
+    radian_with1 (-0.26179) $ camera_yaw cam 
+
+    window <- root_getAutoCreatedWindow root
+    render window root (initState robotEntity robotNode) handler
+
+  return ()
+
+type OgreState = (Entity, SceneNode, (Float, Float), [(Float, Float)])
+
+initPos :: (Float, Float)
+initPos = (0, 25)
+
+initState :: Entity -> SceneNode -> OgreState
+initState e n = (e, n, initPos, cycle [(550, 50), (-100, -200), (0, 25)])
+
+handler :: Root -> Float -> OgreState -> IO (OgreState, Bool)
+handler _ delta (ent, node, (locx, locz), wl) = do
+  let (wx, wz) = head wl
+  dist <- 
+    vector3_with4 locx 0 locz $ \locv ->
+       vector3_with4 wx 0 wz $ vector3_distance locv
+  let wl' = if dist <= 30
+              then tail wl
+              else wl
+      (tgtx, tgtz) = head wl'
+      ang = atan2 (locz - tgtz) (locx - tgtx)
+      locx' = locx - 35 * delta * cos ang
+      locz' = locz - 35 * delta * sin ang
+  when (dist > 150) $
+    vector3_with4 tgtx 0 tgtz $ \v1 -> 
+      vector3_with4 1 0 0 $ \v -> 
+       sceneNode_lookAt node v1 TS_WORLD v
+  node_setPosition (toNode node) locx' 0 locz'
+  anim <- entity_getAnimationState ent "Walk"
+  animationState_addTime anim delta
+  print (dist, tgtx, tgtz)
+  return ((ent, node, (locx', locz'), wl'), True)
+
+addKnot :: SceneManager -> Float -> Float -> Float -> IO ()
+addKnot smgr v1 v2 v3 = do
+  (_, knot) <- addEntity smgr "knot.mesh"
+  node_translate2 (toNode knot) v1 v2 v3 TS_WORLD
+  node_setScale (toNode knot) 0.1 0.1 0.1
 
diff --git a/src/Example_03.hs b/src/Example_03.hs
deleted file mode 100644
--- a/src/Example_03.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, FunctionalDependencies #-}
-module Main
-where
-
-import Control.Monad (when)
-
-import qualified Graphics.UI.SDL as SDL
-
-import Graphics.Ogre.Ogre
-import Common
-
-robotTemplate :: String -> Vector3 -> Entity
-robotTemplate swname pos = Entity swname pos (StdMesh "robot.mesh" (YPR  halfPI  0.0 0.0)) True (Vector3 0.2 0.2 0.2)
-
-initGame :: IO ()
-initGame = do
-    let set = OgreSettings "resources.cfg" False "Hogre Example 03" (Color 0.9 0.9 0.9) StencilModulative [ExteriorClose]
-    let cam = Camera (Vector3 242.0 120.0 580) 0 (Vector3 241 120 580)
-    let (wid, hei) = (1024, 768)
-    let sce = OgreScene cam [] []
-    _ <- SDL.setVideoMode wid hei 16 [SDL.OpenGL, SDL.HWAccel]
-    SDL.wasInit [SDL.InitEverything] >>= print
-    initOgre set
-    addScene sce
-    setSkyDome (Just ("Examples/CloudySky", 5))
-    setWorldGeometry "terrain.cfg"
-
-main :: IO ()
-main = runWithSDL initGame (0, EventCallback query, FrameCallback (\v -> return v))
-
-getLMB :: IO (Maybe (Int, Int))
-getLMB = do
-  (xpos, ypos, btns) <- SDL.getMouseState
-  return $ case SDL.ButtonLeft `elem` btns of
-    True  -> Just (xpos, ypos)
-    False -> Nothing
-
-getLMBPressed :: [SDL.Event] -> Maybe (Int, Int)
-getLMBPressed []     = Nothing
-getLMBPressed (e:es) = case e of
-                         (SDL.MouseButtonDown xp yp SDL.ButtonLeft) -> Just ((fromIntegral xp), (fromIntegral yp))
-                         _                                          -> getLMBPressed es
-
-query :: Int -> [SDL.Event] -> IO Int
-query counter events = do
-  cameraAboveGround
-  putObject counter events
-
-cameraAboveGround :: IO ()
-cameraAboveGround = do
-  (Vector3 camx camy camz) <- getCameraPosition
-  mres <- raySceneQuerySimple (Vector3 camx 5000 camz) negUnitY
-  case mres of
-    Nothing  -> return ()
-    Just res -> when ((y res) + 10 > camy) $ setCameraPosition (Vector3 camx ((y res) + 10) camz)
-
-putObject :: Int -> [SDL.Event] -> IO Int
-putObject counter events = do
-  let mp = getLMBPressed events
-  case mp of
-    Nothing           -> return counter
-    Just (xpos, ypos) -> do
-      scr <- SDL.getVideoSurface
-      let wid = SDL.surfaceGetWidth scr
-      let hei = SDL.surfaceGetHeight scr
-      print (xpos, ypos, wid, hei)
-      let wabs = (fromIntegral xpos) / (fromIntegral wid)
-      let habs = (fromIntegral ypos) / (fromIntegral hei)
-      pres <- raySceneQueryMouseSimple wabs habs
-      case pres of
-        Nothing                       -> return counter
-        Just (Vector3 resx resy resz) -> do
-          let swname = "robot" ++ (show counter)
-          let pos = Vector3 resx (resy + 10) resz
-          addEntity (robotTemplate swname pos)
-          print swname
-          return (counter + 1)
-
