Representation of a dynamic light source in the scene.
Lights are added to the scene like any other object. They contain various parameters like type, position, attenuation (how light intensity fades with distance), color etc.

The defaults when a light is created is pure white diffuse light, with no attenuation (does not decrease with distance) and a range of 1000 world units.

Lights are created by using the SceneManager.CreateLight method. They can subsequently be added to a SceneNode if required to allow them to move relative to a node in the scene. A light attached to a SceneNode is assumed to have a base position of (0,0,0) and a direction of (0,0,1) before modification by the SceneNode's own orientation. If note attached to a SceneNode, the light's position and direction is as set using Position and Direction.

Remember also that dynamic lights rely on modifying the color of vertices based on the position of the light compared to an object's vertex normals. Dynamic lighting will only look good if the object being lit has a fair level of tesselation and the normals are properly set. This is particularly true for the spotlight which will only look right on highly tessellated models.

Inheritance: Axiom.Core.MovableObject, IComparable
Example #1
0
        public MultiLights(SceneManager pSceneManager, SceneNode pCamNode, MovingObject pPlayerShip, Int32 pNumberOfLights)
        {
            oldCamLightColor = CamLightColor = new ColorEx(0.13f, 0.1f, 0.05f);
            PlayerLightColor = ColorEx.White;
            camLights = new List<Light>(pNumberOfLights);

            innerLights = (Int32)Math.Round(pNumberOfLights / 3.0f, MidpointRounding.AwayFromZero);
            outerLights = pNumberOfLights - innerLights;

            // create the playership's light.
            playerLight = pSceneManager.CreateLight("playerSpotLight");
            playerLight.Type = LightType.Spotlight;
            playerLight.Diffuse = PlayerLightColor;
            playerLight.Specular = ColorEx.White;
            playerLight.SetSpotlightRange(0.0f, 120.0f);
            playerLight.Direction = Vector3.NegativeUnitZ;

            playerLightNode = pPlayerShip.Node.CreateChildSceneNode();
            playerLightNode.AttachObject(playerLight);
            playerLightNode.Position = new Vector3(0, 0, 0);
            playerLightNode.SetDirection(new Vector3(1, 0, 0), TransformSpace.Local);

            // create the camera spotlights around the camera's direction.
            camInnerLightNode = pCamNode.CreateChildSceneNode();
            camInnerLightNode.Position = new Vector3(0, 0, 0);
            camOuterLightNode = pCamNode.CreateChildSceneNode();
            camOuterLightNode.Position = new Vector3(0, 0, 0);

            for (var i = 0; i < innerLights; i++)
            {
                var light = pSceneManager.CreateLight("camInnerLight " + (i + 1));
                light.Type = LightType.Spotlight;
                light.Diffuse = CamLightColor;
                light.Specular = ColorEx.White;
                light.SetSpotlightRange(0.0f, 25.0f);
                light.Direction = Quaternion.FromAngleAxis(360.0 * i / innerLights * Constants.DegreesToRadians, Vector3.UnitZ) *
                    Quaternion.FromAngleAxis(10.0 * Constants.DegreesToRadians, Vector3.UnitX) *
                    Vector3.NegativeUnitZ;

                camLights.Add(light);
                camInnerLightNode.AttachObject(light);
            }
            for (var i = 0; i < outerLights; i++)
            {
                var light = pSceneManager.CreateLight("camOuterLight " + (i + 1));
                light.Type = LightType.Spotlight;
                light.Diffuse = CamLightColor;
                light.Specular = ColorEx.White;
                light.SetSpotlightRange(0.0f, 25.0f);
                light.Direction = Quaternion.FromAngleAxis(360.0 * i / outerLights * Constants.DegreesToRadians, Vector3.UnitZ) *
                    Quaternion.FromAngleAxis(20.0 * Constants.DegreesToRadians, Vector3.UnitX) *
                    Vector3.NegativeUnitZ;

                camLights.Add(light);
                camOuterLightNode.AttachObject(light);
            }
        }
Example #2
0
		public PerPixelLighting()
		{
			this.trackVertexColorType = TrackVertexColor.None;
			this.specularEnable = false;
			this.blankLight = new Light();
			this.blankLight.Diffuse = ColorEx.Black;
			this.blankLight.Specular = ColorEx.Black;
			this.blankLight.SetAttenuation( 0, 1, 0, 0 );
		}
Example #3
0
		public void OnLoad()
		{
			//ResourceGroupManager.Instance.AddResourceLocation("media", "Folder", true);

			_root.SceneManager = _sceneManager = _root.CreateSceneManager(SceneType.ExteriorClose);
			_sceneManager.ClearScene();

			_camera = _sceneManager.CreateCamera("MainCamera");

			_camera.Position = new Vector3(0, 0, 500);
			_camera.LookAt(new Vector3(0, 0, -300));
			_camera.Near = 5;
			_camera.AutoAspectRatio = true;
			_camera.FieldOfView = 0.70f;
			_viewport = _renderWindow.AddViewport(_camera, 0, 0, 1.0f, 1.0f, 100);
			_viewport.BackgroundColor = ColorEx.Black; ;

			_light = _sceneManager.CreateLight("light1");
			_light.Type = LightType.Directional;
			_light.Position = new Vector3(0, 150, 300);
			_light.Diffuse = ColorEx.Blue;
			_light.Specular = ColorEx.Blue;
			//_light.Direction = new Vector3(0, 0, -300);
			_sceneManager.AmbientLight = ColorEx.White;// new ColorEx(0.2f, 0.2f, 0.2f);

			ResourceGroupManager.Instance.InitializeAllResourceGroups();


			_inputReader = PlatformManager.Instance.CreateInputReader();
			_inputReader.Initialize(_renderWindow, true, true, false, false);

			_inputReader.UseKeyboardEvents = true;
			_inputReader.UseMouseEvents = false;

			//_renderItems.Add(new BasicCube());
			_renderItems.Add(new CubeBrowser());
			foreach (var i in _renderItems)
			{
				i.Initialise(_root);
			}
		}
Example #4
0
			public LightSpotlightFalloffValue( Light light )
				: base( AnimableType.Float )
			{
				this.light = light;
			}
Example #5
0
			public LightSpotlightOuterValue( Light light )
				: base( AnimableType.Float )
			{
				this.light = light;
			}
Example #6
0
			/// <summary>
			///		Prepare the listener for use with a set of parameters.
			/// </summary>
			/// <param name="lightInFrustum"></param>
			/// <param name="lightClipVolumes"></param>
			/// <param name="light"></param>
			/// <param name="camera"></param>
			/// <param name="shadowCasterList"></param>
			/// <param name="farDistSquared"></param>
			public void Prepare( bool lightInFrustum,
								 PlaneBoundedVolumeList lightClipVolumes,
								 Light light,
								 Camera camera,
								 List<ShadowCaster> shadowCasterList,
								 float farDistSquared )
			{
				this.casterList = shadowCasterList;
				this.isLightInFrustum = lightInFrustum;
				this.lightClipVolumeList = lightClipVolumes;
				this.camera = camera;
				this.light = light;
				this.farDistSquared = farDistSquared;
			}
        public override IEnumerator GetShadowVolumeRenderableEnumerator(ShadowTechnique technique, Light light, 
			HardwareIndexBuffer indexBuffer, bool extrudeVertices, float extrusionDistance, int flags)
        {
            return dummyList.GetEnumerator();
        }
Example #8
0
		protected override IList FindShadowCastersForLight( Light light, Camera camera )
		{
			// objectsForRendering was filled at ProcessVisibleLeaf which is called
			// during FindVisibleObjects

			IList casters = base.FindShadowCastersForLight( light, camera );

			for ( int i = 0; i < casters.Count; i++ )
			{
				if ( !this.objectsForRendering.ContainsKey( ( (MovableObject)casters[ i ] ).Name ) )
				{
					// this shadow caster is not visible, remove it
					casters.RemoveAt( i );
					i--;
				}
			}

			return casters;
		}
 public LightDiffuseColorValue(Light light)
     : base(AnimableType.ColorEx)
 {
     this.light = light;
     SetAsBaseValue(ColorEx.Black);
 }
Example #10
0
		/// <summary>
		///		Get the distance to extrude for a point/spot light.
		/// </summary>
		/// <param name="light"></param>
		/// <returns></returns>
		public abstract float GetPointExtrusionDistance( Light light );
        protected void GenerateScene()
        {
            ((Axiom.SceneManagers.Multiverse.SceneManager)sceneManager).SetWorldParams(terrainGenerator, new LODSpec());
            sceneManager.LoadWorldGeometry("");

            AmbientLightColor = new ColorEx(0.5f, 0.5f, 0.5f);

            // set up directional light
            directionalLight = sceneManager.CreateLight("MainLight");
            directionalLight.Type = LightType.Directional;
            directionalLight.SetAttenuation(1000 * OneMeter, 1, 0, 0);

            DirectionalDiffuseColor = ColorEx.White;
            DirectionalSpecularColor = ColorEx.White;

            PositionLight();

            // create and position the scene node used to display the loaded model
            modelNode = sceneManager.RootSceneNode.CreateChildSceneNode();
            modelNode.Position = modelBase;

            helperNode = sceneManager.RootSceneNode.CreateChildSceneNode();
            helperNode.Position = modelBase;

            Axiom.SceneManagers.Multiverse.TerrainManager.Instance.ShowOcean = false;
            // Set our DisplayTerrain property to the current value.
            // This will set the desired SceneManager properties.
            this.DisplayTerrain = displayTerrain;
            //particleNode = scene.RootSceneNode.CreateChildSceneNode();
            //particleNode.Position = new Vector3(0 * oneMeter, 50 * oneMeter, 0 * oneMeter);

            //ParticleSystem ps = ParticleSystemManager.Instance.CreateSystem("foo", "PEExamples/ringOfFire");
            //particleNode.AttachObject(ps);
            //particleNode.ScaleFactor = new Vector3(1000f, 1000f, 1000f);
            //ps.ShowBoundingBox = true;

            return;
        }
Example #12
0
		/// <summary>
		///		Generates the indexes required to render a shadow volume into the
		///		index buffer which is passed in, and updates shadow renderables to use it.
		/// </summary>
		/// <param name="edgeData">The edge information to use.</param>
		/// <param name="indexBuffer">The buffer into which to write data into; current
		///	contents are assumed to be discardable.</param>
		/// <param name="light">The light, mainly for type info as silhouette calculations
		/// should already have been done in <see cref="UpdateEdgeListLightFacing"/></param>
		/// <param name="shadowRenderables">A list of shadow renderables which has
		/// already been constructed but will need populating with details of
		/// the index ranges to be used.</param>
		/// <param name="flags">Additional controller flags, see <see cref="ShadowRenderableFlags"/>.</param>
		protected virtual void GenerateShadowVolume( EdgeData edgeData, HardwareIndexBuffer indexBuffer, Light light,
			ShadowRenderableList shadowRenderables, int flags )
		{
			// Edge groups should be 1:1 with shadow renderables
			Debug.Assert( edgeData.edgeGroups.Count == shadowRenderables.Count );

			LightType lightType = light.Type;

			bool extrudeToInfinity = ( flags & (int)ShadowRenderableFlags.ExtrudeToInfinity ) > 0;

			// Lock index buffer for writing
			IntPtr idxPtr = indexBuffer.Lock( BufferLocking.Discard );

			int indexStart = 0;

			unsafe
			{
				// TODO: Will currently cause an overflow for 32 bit indices, revisit
				short* pIdx = (short*)idxPtr.ToPointer();
				int count = 0;

				// Iterate over the groups and form renderables for each based on their
				// lightFacing
				for ( int groupCount = 0; groupCount < edgeData.edgeGroups.Count; groupCount++ )
				{
					EdgeData.EdgeGroup eg = (EdgeData.EdgeGroup)edgeData.edgeGroups[ groupCount ];
					ShadowRenderable si = (ShadowRenderable)shadowRenderables[ groupCount ];

					RenderOperation lightShadOp = null;

					// Initialize the index bounds for this shadow renderable
					RenderOperation shadOp = si.GetRenderOperationForUpdate();
					shadOp.indexData.indexCount = 0;
					shadOp.indexData.indexStart = indexStart;

					// original number of verts (without extruded copy)
					int originalVertexCount = eg.vertexData.vertexCount;
					bool firstDarkCapTri = true;
					int darkCapStart = 0;

					for ( int edgeCount = 0; edgeCount < eg.edges.Count; edgeCount++ )
					{
						EdgeData.Edge edge = (EdgeData.Edge)eg.edges[ edgeCount ];

						EdgeData.Triangle t1 = (EdgeData.Triangle)edgeData.triangles[ edge.triIndex[ 0 ] ];
						EdgeData.Triangle t2 =
							edge.isDegenerate ? (EdgeData.Triangle)edgeData.triangles[ edge.triIndex[ 0 ] ] : (EdgeData.Triangle)edgeData.triangles[ edge.triIndex[ 1 ] ];

						if ( t1.lightFacing && ( edge.isDegenerate || !t2.lightFacing ) )
						{
							/* Silhouette edge, first tri facing the light
															Also covers degenerate tris where only tri 1 is valid
															Remember verts run anticlockwise along the edge from
															tri 0 so to point shadow volume tris outward, light cap
															indexes have to be backwards

															We emit 2 tris if light is a point light, 1 if light
															is directional, because directional lights cause all
															points to converge to a single point at infinity.

															First side tri = near1, near0, far0
															Second tri = far0, far1, near1

															'far' indexes are 'near' index + originalVertexCount
															because 'far' verts are in the second half of the
															buffer
															*/
							pIdx[ count++ ] = (short)edge.vertIndex[ 1 ];
							pIdx[ count++ ] = (short)edge.vertIndex[ 0 ];
							pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
							shadOp.indexData.indexCount += 3;

							if ( !( lightType == LightType.Directional && extrudeToInfinity ) )
							{
								// additional tri to make quad
								pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
								pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
								pIdx[ count++ ] = (short)edge.vertIndex[ 1 ];
								shadOp.indexData.indexCount += 3;
							}

							// Do dark cap tri
							// Use McGuire et al method, a triangle fan covering all silhouette
							// edges and one point (taken from the initial tri)
							if ( ( flags & (int)ShadowRenderableFlags.IncludeDarkCap ) > 0 )
							{
								if ( firstDarkCapTri )
								{
									darkCapStart = edge.vertIndex[ 0 ] + originalVertexCount;
									firstDarkCapTri = false;
								}
								else
								{
									pIdx[ count++ ] = (short)darkCapStart;
									pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
									pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
									shadOp.indexData.indexCount += 3;
								}
							}
						}
						else if ( !t1.lightFacing && ( edge.isDegenerate || t2.lightFacing ) )
						{
							// Silhouette edge, second tri facing the light
							// Note edge indexes inverse of when t1 is light facing
							pIdx[ count++ ] = (short)edge.vertIndex[ 0 ];
							pIdx[ count++ ] = (short)edge.vertIndex[ 1 ];
							pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
							shadOp.indexData.indexCount += 3;

							if ( !( lightType == LightType.Directional && extrudeToInfinity ) )
							{
								// additional tri to make quad
								pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
								pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
								pIdx[ count++ ] = (short)edge.vertIndex[ 0 ];
								shadOp.indexData.indexCount += 3;
							}

							// Do dark cap tri
							// Use McGuire et al method, a triangle fan covering all silhouette
							// edges and one point (taken from the initial tri)
							if ( ( flags & (int)ShadowRenderableFlags.IncludeDarkCap ) > 0 )
							{
								if ( firstDarkCapTri )
								{
									darkCapStart = edge.vertIndex[ 1 ] + originalVertexCount;
									firstDarkCapTri = false;
								}
								else
								{
									pIdx[ count++ ] = (short)darkCapStart;
									pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
									pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
									shadOp.indexData.indexCount += 3;
								}
							}
						}
					}

					// Do light cap
					if ( ( flags & (int)ShadowRenderableFlags.IncludeLightCap ) > 0 )
					{
						ShadowRenderable lightCapRend = null;

						if ( si.IsLightCapSeperate )
						{
							// separate light cap
							lightCapRend = si.LightCapRenderable;
							lightShadOp = lightCapRend.GetRenderOperationForUpdate();
							lightShadOp.indexData.indexCount = 0;
							// start indexes after the current total
							// NB we don't update the total here since that's done below
							lightShadOp.indexData.indexStart =
								indexStart + shadOp.indexData.indexCount;
						}

						for ( int triCount = 0; triCount < edgeData.triangles.Count; triCount++ )
						{
							EdgeData.Triangle t = (EdgeData.Triangle)edgeData.triangles[ triCount ];

							// Light facing, and vertex set matches
							if ( t.lightFacing && t.vertexSet == eg.vertexSet )
							{
								pIdx[ count++ ] = (short)t.vertIndex[ 0 ];
								pIdx[ count++ ] = (short)t.vertIndex[ 1 ];
								pIdx[ count++ ] = (short)t.vertIndex[ 2 ];

								if ( lightShadOp != null )
								{
									lightShadOp.indexData.indexCount += 3;
								}
								else
								{
									shadOp.indexData.indexCount += 3;
								}
							}
						}
					}

					// update next indexStart (all renderables sharing the buffer)
					indexStart += shadOp.indexData.indexCount;

					// add on the light cap too
					if ( lightShadOp != null )
					{
						indexStart += lightShadOp.indexData.indexCount;
					}
				}
			}

			// Unlock index buffer
			indexBuffer.Unlock();

			Debug.Assert( indexStart <= indexBuffer.IndexCount, "Index buffer overrun while generating shadow volume!" );
		}
Example #13
0
		/// <summary>
		///		Helper method for calculating extrusion distance.
		/// </summary>
		/// <param name="objectPos"></param>
		/// <param name="light"></param>
		/// <returns></returns>
		protected float GetExtrusionDistance( Vector3 objectPos, Light light )
		{
			Vector3 diff = objectPos - light.DerivedPosition;
			return light.AttenuationRange - diff.Length;
		}
Example #14
0
		public IEnumerator GetShadowVolumeRenderableEnumerator( ShadowTechnique technique, Light light,
			HardwareIndexBuffer indexBuffer, float extrusionDistance, bool extrudeVertices )
		{
			return GetShadowVolumeRenderableEnumerator( technique, light, indexBuffer, extrudeVertices, extrusionDistance, 0 );
		}
Example #15
0
	    /// <summary>
	    ///		Gets an iterator over the renderables required to render the shadow volume.
	    /// </summary>
	    /// <remarks>
	    ///		Shadowable geometry should ideally be designed such that there is only one
	    ///		ShadowRenderable required to render the the shadow; however this is not a necessary
	    ///		limitation and it can be exceeded if required.
	    /// </remarks>
	    /// <param name="technique">The technique being used to generate the shadow.</param>
	    /// <param name="light">The light to generate the shadow from.</param>
	    /// <param name="indexBuffer">The index buffer to build the renderables into,
	    /// the current contents are assumed to be disposable.</param>
	    /// <param name="extrudeVertices">If true, this means this class should extrude
	    /// the vertices of the back of the volume in software. If false, it
	    /// will not be done (a vertex program is assumed).</param>
	    /// <param name="extrusionDistance"></param>
	    /// <param name="flags">Technique-specific flags, see <see cref="ShadowRenderableFlags"/></param>
	    /// <returns>An iterator that will allow iteration over all renderables for the full shadow volume.</returns>
	    public abstract IEnumerator GetShadowVolumeRenderableEnumerator( ShadowTechnique technique, Light light,
			HardwareIndexBuffer indexBuffer, bool extrudeVertices, float extrusionDistance, int flags );
Example #16
0
 public LightAttenuationConstantValue(Light light)
     : base(AnimableType.Float)
 {
     this.light = light;
     SetAsBaseValue(0.0f);
 }
Example #17
0
		protected override MovableObject _createInstance( string name, NamedParameterList param )
		{
			Light light = new Light( name );

			if ( param != null )
			{
				// Setting the light type first before any property specific to a certain light type
				if ( param.ContainsKey( "type" ) )
				{
					switch ( param[ "type" ].ToString() )
					{
						case "point":
							light.Type = LightType.Point;
							break;
						case "directional":
							light.Type = LightType.Directional;
							break;
						case "spot":
						case "spotlight":
							light.Type = LightType.Spotlight;
							break;
						default:
							throw new AxiomException( "Invalid light type '" + param[ "type" ] + "'." );
					}
				}

				// Common properties
				if ( param.ContainsKey( "position" ) )
				{
					light.Position = Vector3.Parse( param[ "position" ].ToString() );
				}

				if ( param.ContainsKey( "direction" ) )
				{
					light.Direction = Vector3.Parse( param[ "direction" ].ToString() );
				}

				if ( param.ContainsKey( "diffuseColour" ) )
				{
					light.Diffuse = ColorEx.Parse_0_255_String( param[ "diffuseColour" ].ToString() );
				}

				if ( param.ContainsKey( "specularColour" ) )
				{
					light.Specular = ColorEx.Parse_0_255_String( param[ "specularColour" ].ToString() );
				}

				if ( param.ContainsKey( "attenuation" ) )
				{
					Vector4 attenuation = Vector4.Parse( param[ "attenuation" ].ToString() );
					light.SetAttenuation( attenuation.x, attenuation.y, attenuation.z, attenuation.w );
				}

				if ( param.ContainsKey( "castShadows" ) )
				{
					light.CastShadows = Convert.ToBoolean( param[ "castShadows" ].ToString() );
				}

				if ( param.ContainsKey( "visible" ) )
				{
					light.CastShadows = Convert.ToBoolean( param[ "visible" ].ToString() );
				}
				// TODO: Add PowerScale Property to Light
				if ( param.ContainsKey( "powerScale" ) )
				{
					light.PowerScale = (float)Convert.ToDouble( param[ "powerScale" ].ToString() );
				}
				// TODO: Add ShadowFarDistance to Light
				if ( param.ContainsKey( "shadowFarDistance" ) )
				{
					light.ShadowFarDistance = (float)Convert.ToDouble( param[ "shadowFarDistance" ].ToString() );
				}

				// Spotlight properties
				if ( param.ContainsKey( "spotlightInner" ) )
				{
					light.SpotlightInnerAngle = (float)Convert.ToDouble( param[ "spotlightInner" ].ToString() );
				}

				if ( param.ContainsKey( "spotlightOuter" ) )
				{
					light.SpotlightOuterAngle = (float)Convert.ToDouble( param[ "spotlightOuter" ].ToString() );
				}

				if ( param.ContainsKey( "spotlightFalloff" ) )
				{
					light.SpotlightFalloff = (float)Convert.ToDouble( param[ "spotlightFalloff" ].ToString() );
				}
			}

			return light;
		}
Example #18
0
		/// <summary>
		///		Gets the world space bounding box of the dark cap, as extruded using the light provided.
		/// </summary>
		/// <param name="light"></param>
		/// <param name="dirLightExtrusionDist"></param>
		/// <returns></returns>
		public abstract AxisAlignedBox GetDarkCapBounds( Light light, float dirLightExtrusionDist );
Example #19
0
			public LightAttenuationLinearValue( Light light )
				: base( AnimableType.Float )
			{
				this.light = light;
				this.SetAsBaseValue( 0.0f );
			}
Example #20
0
		/// <summary>
		///		Internal method for rendering all the objects for a given light into the stencil buffer.
		/// </summary>
		/// <param name="light">The light source.</param>
		/// <param name="camera">The camera being viewed from.</param>
		protected virtual void RenderShadowVolumesToStencil( Light light, Camera camera )
		{
			// get the shadow caster list
			IList casters = this.FindShadowCastersForLight( light, camera );
			if ( casters.Count == 0 )
			{
				// No casters, just do nothing
				return;
			}

			// Set up scissor test (point & spot lights only)
			bool scissored = false;
			if ( light.Type != LightType.Directional &&
				 this.targetRenderSystem.Capabilities.HasCapability( Capabilities.ScissorTest ) )
			{
				// Project the sphere onto the camera
				float left, right, top, bottom;
				Sphere sphere = new Sphere( light.DerivedPosition, light.AttenuationRange );
				if ( camera.ProjectSphere( sphere, out left, out top, out right, out bottom ) )
				{
					scissored = true;
					// Turn normalised device coordinates into pixels
					int iLeft, iTop, iWidth, iHeight;
					this.currentViewport.GetActualDimensions( out iLeft, out iTop, out iWidth, out iHeight );
					int szLeft, szRight, szTop, szBottom;

					szLeft = (int)( iLeft + ( ( left + 1 ) * 0.5f * iWidth ) );
					szRight = (int)( iLeft + ( ( right + 1 ) * 0.5f * iWidth ) );
					szTop = (int)( iTop + ( ( -top + 1 ) * 0.5f * iHeight ) );
					szBottom = (int)( iTop + ( ( -bottom + 1 ) * 0.5f * iHeight ) );

					this.targetRenderSystem.SetScissorTest( true, szLeft, szTop, szRight, szBottom );
				}
			}

			this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Fragment );

			// Can we do a 2-sided stencil?
			bool stencil2sided = false;

			if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.TwoSidedStencil ) &&
				 this.targetRenderSystem.Capabilities.HasCapability( Capabilities.StencilWrap ) )
			{
				// enable
				stencil2sided = true;
			}

			// Do we have access to vertex programs?
			bool extrudeInSoftware = true;

			bool finiteExtrude = !this.shadowUseInfiniteFarPlane ||
								 !this.targetRenderSystem.Capabilities.HasCapability(
									  Capabilities.InfiniteFarPlane );

			if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.VertexPrograms ) )
			{
				extrudeInSoftware = false;
				this.EnableHardwareShadowExtrusion( light, finiteExtrude );
			}
			else
			{
				this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Vertex );
			}

			// Add light to internal list for use in render call
			tmpLightList.Clear();
			tmpLightList.Add( light );

			// Turn off color writing and depth writing
			this.targetRenderSystem.SetColorBufferWriteEnabled( false, false, false, false );
			this.targetRenderSystem.DepthBufferWriteEnabled = false;
			this.targetRenderSystem.StencilCheckEnabled = true;
			this.targetRenderSystem.DepthBufferFunction = CompareFunction.Less;

			// Calculate extrusion distance
			float extrudeDistance = 0;
			if ( light.Type == LightType.Directional )
			{
				extrudeDistance = this.shadowDirLightExtrudeDist;
			}

			// get the near clip volume
			PlaneBoundedVolume nearClipVol = light.GetNearClipVolume( camera );

			// Determine whether zfail is required
			// We need to use zfail for ALL objects if we find a single object which
			// requires it
			bool zfailAlgo = false;

			this.CheckShadowCasters( casters,
									 nearClipVol,
									 light,
									 extrudeInSoftware,
									 finiteExtrude,
									 zfailAlgo,
									 camera,
									 extrudeDistance,
									 stencil2sided,
									 tmpLightList );
			// revert colour write state
			this.targetRenderSystem.SetColorBufferWriteEnabled( true, true, true, true );
			// revert depth state
			this.targetRenderSystem.SetDepthBufferParams();

			this.targetRenderSystem.StencilCheckEnabled = false;

			this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Vertex );

			if ( scissored )
			{
				// disable scissor test
				this.targetRenderSystem.SetScissorTest( false );
			}
		}
Example #21
0
		/// <summary>
		///		Renders the texture lighting tagged in the specified light
		/// </summary>
		protected void RenderTextureLighting( Light light )
		{
			if ( !( light is TextureLight ) )
			{
				return;
			}

			var texLight = (TextureLight)light;

			if ( !texLight.IsTextureLight )
			{
				return;
			}

			if ( texLight.Type == LightType.Spotlight )
			{
				this.spotlightFrustum.Spotlight = texLight;
			}

			// no world transform required
			targetRenderSystem.WorldMatrix = Matrix4.Identity;

			// Set view / proj
			targetRenderSystem.ViewMatrix = cameraInProgress.ViewMatrix;
			targetRenderSystem.ProjectionMatrix = cameraInProgress.ProjectionMatrix;

			TextureUnitState lightTex = this.textureLightPass.GetTextureUnitState( 0 );
			TextureUnitState normalTex = this.textureLightPass.GetTextureUnitState( 1 );

			switch ( texLight.Intensity )
			{
				case LightIntensity.Normal:
					normalTex.ColorBlendMode.operation = LayerBlendOperationEx.Modulate;
					break;

				case LightIntensity.ModulateX2:
					normalTex.ColorBlendMode.operation = LayerBlendOperationEx.ModulateX2;
					break;

				case LightIntensity.ModulateX4:
					normalTex.ColorBlendMode.operation = LayerBlendOperationEx.ModulateX4;
					break;
			}

			if ( texLight.Type == LightType.Spotlight )
			{
				this.spotlightFrustum.Spotlight = texLight;
				lightTex.SetProjectiveTexturing( true, this.spotlightFrustum );
			}
			else
			{
				lightTex.SetProjectiveTexturing( false, null );
			}

			if ( texLight.Type == LightType.Directional )
			{
				// light it using only diffuse color and alpha
				normalTex.ColorBlendMode.source2 = LayerBlendSource.Diffuse;
				normalTex.AlphaBlendMode.source2 = LayerBlendSource.Diffuse;
			}
			else
			{
				// light it using the texture light
				normalTex.ColorBlendMode.source2 = LayerBlendSource.Current;
				normalTex.AlphaBlendMode.source2 = LayerBlendSource.Current;
			}

			SetPass( this.textureLightPass );

			if ( texLight.Type == LightType.Directional )
			{
				// Disable the light texture
				targetRenderSystem.SetTexture( 0, true, lightTex.TextureName );
			}

			// For each material in turn, cache rendering data & render
			IEnumerator mapEnu = this.matFaceGroupMap.Keys.GetEnumerator();

			while ( mapEnu.MoveNext() )
			{
				// Get Material
				var thisMaterial = (Material)mapEnu.Current;
				List<BspStaticFaceGroup> faceGrp = this.matFaceGroupMap[ thisMaterial ];

				// if one face group is a quake shader then the material is a quake shader
				if ( faceGrp[ 0 ].isQuakeShader )
				{
					continue;
				}

				ManualCullingMode cullMode = thisMaterial.GetTechnique( 0 ).GetPass( 0 ).ManualCullingMode;

				// Empty existing cache
				this.renderOp.indexData.indexCount = 0;

				HardwareVertexBuffer bspVertexBuffer = this.level.VertexData.vertexBufferBinding.GetBuffer( 0 );
				HardwareVertexBuffer lightTexCoordBuffer = this.level.VertexData.vertexBufferBinding.GetBuffer( 1 );

				// lock index buffer ready to receive data
#if !AXIOM_SAFE_ONLY
				unsafe
#endif
				{
					var pVertices = bspVertexBuffer.Lock( BufferLocking.ReadOnly );
					var pTexLightMap = lightTexCoordBuffer.Lock( BufferLocking.Discard );
					var pIdx = this.renderOp.indexData.indexBuffer.Lock( BufferLocking.Discard );

					for ( int i = 0; i < faceGrp.Count; i++ )
					{
						if ( faceGrp[ i ].type != FaceGroup.Patch && texLight.AffectsFaceGroup( faceGrp[ i ], cullMode ) )
						{
							// Cache each
							int numElems = CacheLightGeometry( texLight, pIdx, pTexLightMap, pVertices, faceGrp[ i ] );
							this.renderOp.indexData.indexCount += numElems;
							pIdx += numElems;
						}
					}

					// Unlock the buffers
					this.renderOp.indexData.indexBuffer.Unlock();
					lightTexCoordBuffer.Unlock();
					bspVertexBuffer.Unlock();
				}

				// Skip if no faces to process
				if ( this.renderOp.indexData.indexCount == 0 )
				{
					continue;
				}

				// Get the plain geometry texture
				TextureUnitState geometryTex = thisMaterial.GetTechnique( 0 ).GetPass( 0 ).GetTextureUnitState( 0 );
				if ( geometryTex.IsBlank )
				{
					continue;
				}

				targetRenderSystem.SetTexture( 1, true, geometryTex.TextureName );
				// OpenGL requires the addressing mode to be set before every render operation
				targetRenderSystem.SetTextureAddressingMode( 0, new UVWAddressing( TextureAddressing.Clamp ) );
				targetRenderSystem.Render( this.renderOp );
			}
		}
Example #22
0
		private void CheckShadowCasters( IList casters,
										 PlaneBoundedVolume nearClipVol,
										 Light light,
										 bool extrudeInSoftware,
										 bool finiteExtrude,
										 bool zfailAlgo,
										 Camera camera,
										 float extrudeDistance,
										 bool stencil2sided,
										 LightList tmpLightList )
		{
			int flags;
			for ( int i = 0; i < casters.Count; i++ )
			{
				ShadowCaster caster = (ShadowCaster)casters[ i ];

				if ( nearClipVol.Intersects( caster.GetWorldBoundingBox() ) )
				{
					// We have a zfail case, we must use zfail for all objects
					zfailAlgo = true;

					break;
				}
			}

			for ( int ci = 0; ci < casters.Count; ci++ )
			{
				ShadowCaster caster = (ShadowCaster)casters[ ci ];
				flags = 0;

				if ( light.Type != LightType.Directional )
				{
					extrudeDistance = caster.GetPointExtrusionDistance( light );
				}

				if ( !extrudeInSoftware && !finiteExtrude )
				{
					// hardware extrusion, to infinity (and beyond!)
					flags |= (int)ShadowRenderableFlags.ExtrudeToInfinity;
				}

				if ( zfailAlgo )
				{
					// We need to include the light and / or dark cap
					// But only if they will be visible
					if ( camera.IsObjectVisible( caster.GetLightCapBounds() ) )
					{
						flags |= (int)ShadowRenderableFlags.IncludeLightCap;
					}
				}

				// Dark cap (no dark cap for directional lights using
				// hardware extrusion to infinity)
				if ( !( ( flags & (int)ShadowRenderableFlags.ExtrudeToInfinity ) != 0 &&
						light.Type == LightType.Directional ) &&
					 camera.IsObjectVisible( caster.GetDarkCapBounds( light, extrudeDistance ) ) )
				{
					flags |= (int)ShadowRenderableFlags.IncludeDarkCap;
				}

				// get shadow renderables
				IEnumerator renderables = caster.GetShadowVolumeRenderableEnumerator(
					this.shadowTechnique, light, this.shadowIndexBuffer, extrudeInSoftware, extrudeDistance, flags );

				// If using one-sided stencil, render the first pass of all shadow
				// renderables before all the second passes
				for ( int i = 0; i < ( stencil2sided ? 1 : 2 ); i++ )
				{
					if ( i == 1 )
					{
						renderables = caster.GetLastShadowVolumeRenderableEnumerator();
					}

					while ( renderables.MoveNext() )
					{
						ShadowRenderable sr = (ShadowRenderable)renderables.Current;

						// omit hidden renderables
						if ( sr.IsVisible )
						{
							// render volume, including dark and (maybe) light caps
							this.RenderSingleShadowVolumeToStencil( sr,
																	zfailAlgo,
																	stencil2sided,
																	tmpLightList,
																	( i > 0 ) );

							// optionally render separate light cap
							if ( sr.IsLightCapSeperate
								 && ( ( flags & (int)ShadowRenderableFlags.IncludeLightCap ) ) > 0 )
							{
								// must always fail depth check
								this.targetRenderSystem.DepthBufferFunction = CompareFunction.AlwaysFail;

								Debug.Assert( sr.LightCapRenderable != null,
											  "Shadow renderable is missing a separate light cap renderable!" );

								this.RenderSingleShadowVolumeToStencil( sr.LightCapRenderable,
																		zfailAlgo,
																		stencil2sided,
																		tmpLightList,
																		( i > 0 ) );
								// reset depth function
                                this.targetRenderSystem.DepthBufferFunction = CompareFunction.Less;
							}
						}
					}
				}
			}
		}
Example #23
0
		/// <summary>
		///		Internal method for locating a list of shadow casters which
		///		could be affecting the frustum for a given light.
		/// </summary>
		/// <remarks>
		///		Custom scene managers are encouraged to override this method to add optimizations,
		///		and to add their own custom shadow casters (perhaps for world geometry)
		/// </remarks>
		/// <param name="light"></param>
		/// <param name="camera"></param>
		protected virtual IList FindShadowCastersForLight( Light light, Camera camera )
		{
			this.shadowCasterList.Clear();

			if ( light.Type == LightType.Directional )
			{
				// Basic AABB query encompassing the frustum and the extrusion of it
				AxisAlignedBox aabb = new AxisAlignedBox();
				Vector3[] corners = camera.WorldSpaceCorners;
				Vector3 min, max;
				Vector3 extrude = light.DerivedDirection * -this.shadowDirLightExtrudeDist;
				// do first corner
				min = max = corners[ 0 ];
				min.Floor( corners[ 0 ] + extrude );
				max.Ceil( corners[ 0 ] + extrude );
				for ( int c = 1; c < 8; ++c )
				{
					min.Floor( corners[ c ] );
					max.Ceil( corners[ c ] );
					min.Floor( corners[ c ] + extrude );
					max.Ceil( corners[ c ] + extrude );
				}
				aabb.SetExtents( min, max );

				if ( this.shadowCasterAABBQuery == null )
				{
					this.shadowCasterAABBQuery = this.CreateAABBRegionQuery( aabb );
				}
				else
				{
					this.shadowCasterAABBQuery.Box = aabb;
				}
				// Execute, use callback
				this.shadowCasterQueryListener.Prepare( false,
														light.GetFrustumClipVolumes( camera ),
														light,
														camera,
														this.shadowCasterList,
														light.ShadowFarDistanceSquared );
				this.shadowCasterAABBQuery.Execute( this.shadowCasterQueryListener );
			}
			else
			{
				Sphere s = new Sphere( light.DerivedPosition, light.AttenuationRange );

				// eliminate early if camera cannot see light sphere
				if ( camera.IsObjectVisible( s ) )
				{
					// create or init a sphere region query
					if ( this.shadowCasterSphereQuery == null )
					{
						this.shadowCasterSphereQuery = this.CreateSphereRegionQuery( s );
					}
					else
					{
						this.shadowCasterSphereQuery.Sphere = s;
					}

					// check if the light is within view of the camera
					bool lightInFrustum = camera.IsObjectVisible( light.DerivedPosition );

					PlaneBoundedVolumeList volumeList = null;

					// Only worth building an external volume list if
					// light is outside the frustum
					if ( !lightInFrustum )
					{
						volumeList = light.GetFrustumClipVolumes( camera );
					}

					// prepare the query and execute using the callback
					this.shadowCasterQueryListener.Prepare(
						lightInFrustum,
						volumeList,
						light,
						camera,
						this.shadowCasterList,
						light.ShadowFarDistanceSquared );

					this.shadowCasterSphereQuery.Execute( this.shadowCasterQueryListener );
				}
			}

			return this.shadowCasterList;
		}
Example #24
0
        private void SetD3D9Light( int index, Light light )
        {
            if ( light == null )
            {
                ActiveD3D9Device.EnableLight( index, false );
            }
            else
            {
                var nlight = new D3D.Light();

                switch ( light.Type )
                {
                    case LightType.Point:
                        nlight.Type = D3D.LightType.Point;
                        break;

                    case LightType.Directional:
                        nlight.Type = D3D.LightType.Directional;
                        break;

                    case LightType.Spotlight:
                        nlight.Type = D3D.LightType.Spot;
                        nlight.Falloff = light.SpotlightFalloff;
                        nlight.Theta = Utility.DegreesToRadians( light.SpotlightInnerAngle );
                        nlight.Phi = Utility.DegreesToRadians( light.SpotlightOuterAngle );
                        break;
                } // switch

                // light colors
                nlight.Diffuse = D3DHelper.ToColor( light.Diffuse );

                nlight.Specular = D3DHelper.ToColor( light.Specular );

                Vector3 vec;

                if ( light.Type != LightType.Directional )
                {
                    vec = light.DerivedPosition;
                    nlight.Position = new DX.Vector3( vec.x, vec.y, vec.z );
                }

                if ( light.Type != LightType.Point )
                {
                    vec = light.DerivedDirection;
                    nlight.Direction = new DX.Vector3( vec.x, vec.y, vec.z );
                }

                // atenuation settings
                nlight.Range = light.AttenuationRange;
                nlight.Attenuation0 = light.AttenuationConstant;
                nlight.Attenuation1 = light.AttenuationLinear;
                nlight.Attenuation2 = light.AttenuationQuadratic;

                ActiveD3D9Device.SetLight( index, nlight );
                ActiveD3D9Device.EnableLight( index, true );
            } // if
        }
Example #25
0
		private void EnableHardwareShadowExtrusion( Light light, bool finiteExtrude )
		{
			// attach the appropriate extrusion vertex program
			// Note we never unset it because support for vertex programs is constant
			this.shadowStencilPass.SetVertexProgram(
				ShadowVolumeExtrudeProgram.GetProgramName( light.Type, finiteExtrude, false ) );

			// Set params
			if ( finiteExtrude )
			{
				this.shadowStencilPass.VertexProgramParameters = this.finiteExtrusionParams;
			}
			else
			{
				this.shadowStencilPass.VertexProgramParameters = this.infiniteExtrusionParams;
			}

			if ( this.showDebugShadows )
			{
				this.shadowDebugPass.SetVertexProgram(
					ShadowVolumeExtrudeProgram.GetProgramName( light.Type, finiteExtrude, true ) );

				// Set params
				if ( finiteExtrude )
				{
					this.shadowDebugPass.VertexProgramParameters = this.finiteExtrusionParams;
				}
				else
				{
					this.shadowDebugPass.VertexProgramParameters = this.infiniteExtrusionParams;
				}
			}

			this.targetRenderSystem.BindGpuProgram( this.shadowStencilPass.VertexProgram );
		}
Example #26
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="l"></param>
		private ImportData ConfigureTerrainDefaults( Light l )
		{
			TerrainGlobalOptions.MaxPixelError = 8;
			TerrainGlobalOptions.CompositeMapDistance = 3000;
			TerrainGlobalOptions.LightMapDirection = l.DerivedDirection;
			TerrainGlobalOptions.CompositeMapAmbient = SceneManager.AmbientLight;
			TerrainGlobalOptions.CompositeMapDiffuse = l.Diffuse;

			ImportData defaultImp = terrainGroup.DefaultImportSettings;
			defaultImp.TerrainSize = TerrainSize;
			defaultImp.WorldSize = TerrainWorldSize;
			defaultImp.InputScale = 100;
			defaultImp.MinBatchSize = 33;
			defaultImp.MaxBatchSize = 65;

			defaultImp.LayerList = new List<LayerInstance>();
			LayerInstance inst = new LayerInstance();
			inst.WorldSize = 100;
			inst.TextureNames = new List<string>();
			inst.TextureNames.Add( "dirt_grayrocky_diffusespecular.dds" );
			inst.TextureNames.Add( "dirt_grayrocky_normalheight.dds" );
			defaultImp.LayerList.Add( inst );

			inst = new LayerInstance();
			inst.WorldSize = 30;
			inst.TextureNames = new List<string>();
			inst.TextureNames.Add( "grass_green-01_diffusespecular.dds" );
			inst.TextureNames.Add( "grass_green-01_normalheight.dds" );
			defaultImp.LayerList.Add( inst );

			inst = new LayerInstance();
			inst.WorldSize = 30;
			inst.TextureNames = new List<string>();
			inst.TextureNames.Add( "growth_weirdfungus-03_diffusespecular.dds" );
			inst.TextureNames.Add( "growth_weirdfungus-03_normalheight.dds" );
			defaultImp.LayerList.Add( inst );

			return defaultImp;
		}
Example #27
0
		/// <summary>
		///		Removes the specified light from the scene.
		/// </summary>
		/// <remarks>
		///		This method removes a previously added light from the scene.
		/// </remarks>
        /// <param name="light">Reference to the light to remove.</param>
		public virtual void RemoveLight( Light light )
		{
			this.DestroyMovableObject( light );
		}
Example #28
0
			public LightAttenuationValue( Light light )
				: base( AnimableType.Vector4 )
			{
				this.light = light;
			}
Example #29
0
		public override IEnumerator GetShadowVolumeRenderableEnumerator( ShadowTechnique technique, Light light,
		                                                                 HardwareIndexBuffer indexBuffer, bool extrudeVertices,
		                                                                 float extrusionDistance, int flags )
		{
			Debug.Assert( indexBuffer != null, "Only external index buffers are supported right now" );
			Debug.Assert( indexBuffer.Type == IndexType.Size16, "Only 16-bit indexes supported for now" );

			// Potentially delegate to LOD entity
			if ( this.meshLodIndex > 0 && this.mesh.IsLodManual )
			{
				Debug.Assert( this.meshLodIndex - 1 < this.lodEntityList.Count,
				              "No LOD EntityList - did you build the manual LODs after creating the entity?" );

				var lodEnt = this.lodEntityList[ this.meshLodIndex - 1 ];

				// index - 1 as we skip index 0 (original LOD)
				if ( HasSkeleton && lodEnt.HasSkeleton )
				{
					// Copy the animation state set to lod entity, we assume the lod
					// entity only has a subset animation states
					CopyAnimationStateSubset( lodEnt.animationState, this.animationState );
				}

				return lodEnt.GetShadowVolumeRenderableEnumerator( technique, light, indexBuffer, extrudeVertices, extrusionDistance,
				                                                   flags );
			}

			// Prep mesh if required
			// NB This seems to result in memory corruptions, having problems
			// tracking them down. For now, ensure that shadows are enabled
			// before any entities are created
			if ( !this.mesh.IsPreparedForShadowVolumes )
			{
				this.mesh.PrepareForShadowVolume();
				// reset frame last updated to force update of buffers
				this.frameAnimationLastUpdated = 0;
				// re-prepare buffers
				PrepareTempBlendedBuffers();
			}

			// Update any animation
			UpdateAnimation();

			// Calculate the object space light details
			var lightPos = light.GetAs4DVector();

			// Only use object-space light if we're not doing transforms
			// Since when animating the positions are already transformed into
			// world space so we need world space light position
			var isAnimated = HasSkeleton || this.mesh.HasVertexAnimation;
			if ( !isAnimated )
			{
				var world2Obj = parentNode.FullTransform.Inverse();

				lightPos = world2Obj*lightPos;
			}

			// We need to search the edge list for silhouette edges
			var edgeList = GetEdgeList();

			// Init shadow renderable list if required
			var init = ( this.shadowRenderables.Count == 0 );

			if ( init )
			{
				this.shadowRenderables.Capacity = edgeList.edgeGroups.Count;
			}

			var updatedSharedGeomNormals = false;

			EntityShadowRenderable esr = null;
			EdgeData.EdgeGroup egi;

			// note: using capacity for the loop since no items are in the list yet.
			// capacity is set to how large the collection will be in the end
			for ( var i = 0; i < this.shadowRenderables.Capacity; i++ )
			{
				egi = (EdgeData.EdgeGroup)edgeList.edgeGroups[ i ];
				var data = ( isAnimated ? FindBlendedVertexData( egi.vertexData ) : egi.vertexData );
				if ( init )
				{
					// Try to find corresponding SubEntity; this allows the
					// linkage of visibility between ShadowRenderable and SubEntity
					var subEntity = FindSubEntityForVertexData( egi.vertexData );

					// Create a new renderable, create a separate light cap if
					// we're using hardware skinning since otherwise we get
					// depth-fighting on the light cap
					esr = new EntityShadowRenderable( this, indexBuffer, data, subEntity.VertexProgramInUse || !extrudeVertices,
					                                  subEntity );

					this.shadowRenderables.Add( esr );
				}
				else
				{
					esr = (EntityShadowRenderable)this.shadowRenderables[ i ];

					if ( HasSkeleton )
					{
						// If we have a skeleton, we have no guarantee that the position
						// buffer we used last frame is the same one we used last frame
						// since a temporary buffer is requested each frame
						// therefore, we need to update the EntityShadowRenderable
						// with the current position buffer
						esr.RebindPositionBuffer( data, isAnimated );
					}
				}

				// For animated entities we need to recalculate the face normals
				if ( isAnimated )
				{
					if ( egi.vertexData != this.mesh.SharedVertexData || !updatedSharedGeomNormals )
					{
						// recalculate face normals
						edgeList.UpdateFaceNormals( egi.vertexSet, esr.PositionBuffer );

						// If we're not extruding in software we still need to update
						// the latter part of the buffer (the hardware extruded part)
						// with the latest animated positions
						if ( !extrudeVertices )
						{
							var srcPtr = esr.PositionBuffer.Lock( BufferLocking.Normal );
							var destPtr = srcPtr + ( egi.vertexData.vertexCount*12 );

							// 12 = sizeof(float) * 3
							Memory.Copy( srcPtr, destPtr, 12*egi.vertexData.vertexCount );

							esr.PositionBuffer.Unlock();
						}

						if ( egi.vertexData == this.mesh.SharedVertexData )
						{
							updatedSharedGeomNormals = true;
						}
					}
				}
				// Extrude vertices in software if required
				if ( extrudeVertices )
				{
					ExtrudeVertices( esr.PositionBuffer, egi.vertexData.vertexCount, lightPos, extrusionDistance );
				}

				// Stop suppressing hardware update now, if we were
				esr.PositionBuffer.SuppressHardwareUpdate( false );
			}

			// Calc triangle light facing
			UpdateEdgeListLightFacing( edgeList, lightPos );

			// Generate indexes and update renderables
			GenerateShadowVolume( edgeList, indexBuffer, light, this.shadowRenderables, flags );

			return this.shadowRenderables.GetEnumerator();
		}
Example #30
0
			public LightSpecularColorValue( Light light )
				: base( AnimableType.ColorEx )
			{
				this.light = light;
				this.SetAsBaseValue( ColorEx.Black );
			}