예제 #1
0
 /// <summary>
 ///    Default constructor.
 /// </summary>
 internal RenderPriorityGroup(RenderQueueGroup parent, bool splitPassesByLightingType, bool splitNoShadowPasses,
                              bool shadowCastersCannotBeReceivers)
 {
     this._parent = parent;
     // sorted list, using Pass as a key (sorted based on hashcode), and IRenderable as the value
     this.solidPasses = new SortedList(new SolidSort(), 50);
     this.solidPassesDiffuseSpecular     = new SortedList(new SolidSort(), 50);
     this.solidPassesDecal               = new SortedList(new SolidSort(), 50);
     this.solidPassesNoShadow            = new SortedList(new SolidSort(), 50);
     this.splitPassesByLightingType      = splitPassesByLightingType;
     this.splitNoShadowPasses            = splitNoShadowPasses;
     this.shadowCastersCannotBeReceivers = shadowCastersCannotBeReceivers;
 }
예제 #2
0
        /// <summary>
        ///		Adds a renderable item to the queue.
        /// </summary>
        /// <param name="item">IRenderable object to add to the queue.</param>
        /// <param name="groupID">Group to add the item to.</param>
        /// <param name="priority"></param>
        public void AddRenderable(IRenderable renderable, ushort priority, RenderQueueGroupID groupID)
        {
            RenderQueueGroup group = GetQueueGroup(groupID);

            // let the material know it has been used, which also forces a recompile if required
            if (renderable.Material != null)
            {
                renderable.Material.Touch();
            }

            // add the renderable to the appropriate group
            group.AddRenderable(renderable, priority);
        }
예제 #3
0
        /// <summary>
        ///		Get a render queue group.
        /// </summary>
        /// <remarks>
        ///		New queue groups are registered as they are requested,
        ///		therefore this method will always return a valid group.
        /// </remarks>
        /// <param name="queueID">ID of the queue group to retreive.</param>
        /// <returns></returns>
        public RenderQueueGroup GetQueueGroup(RenderQueueGroupID queueID)
        {
            var group = this.renderGroups[queueID] as RenderQueueGroup;

            // see if there is a current queue group for this group id
            if (group == null)
            {
                // create a new queue group for this group id
                group = new RenderQueueGroup(this, this.splitPassesByLightingType, this.splitNoShadowPasses,
                                             this.shadowCastersCannotBeReceivers);

                // add the new group to cached render group
                this.renderGroups.Add(queueID, group);
            }

            return(group);
        }
예제 #4
0
		/// <summary>
		///		Render a group with the added complexity of modulative texture shadows.
		/// </summary>
		/// <param name="group">Render queue group.</param>
		protected virtual void RenderModulativeTextureShadowedQueueGroupObjects( RenderQueueGroup group )
		{
			/* For each light, we need to render all the solids from each group,
			then do the modulative shadows, then render the transparents from
			each group.
			Now, this means we are going to reorder things more, but that is required
			if the shadows are to look correct. The overall order is preserved anyway,
			it's just that all the transparents are at the end instead of them being
			interleaved as in the normal rendering loop.
			*/
			// Iterate through priorities
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Sort the queue first
				priorityGroup.Sort( this.cameraInProgress );

				// Do solids
				this.RenderSolidObjects( priorityGroup.solidPasses, true );
				this.renderingNoShadowQueue = true;
				this.RenderSolidObjects( priorityGroup.solidPassesNoShadow, true );
				this.renderingNoShadowQueue = false;
			}

			// Iterate over lights, render received shadows
			// only perform this if we're in the 'normal' render stage, to avoid
			// doing it during the render to texture
			if ( this.illuminationStage == IlluminationRenderStage.None )
			{
				this.illuminationStage = IlluminationRenderStage.RenderReceiverPass;

				int sti = 0;
				foreach ( Light light in this.lightsAffectingFrustum )
				{
					// Check limit reached
					if ( sti == this.shadowTextures.Count )
						break;

					if ( !light.CastShadows )
					{
						continue;
					}

					Texture shadowTex = this.shadowTextures[ sti ];
					Camera cam = shadowTex.GetBuffer().GetRenderTarget().GetViewport( 0 ).Camera;

					// Hook up receiver texture
					Pass targetPass = this.shadowTextureCustomReceiverPass != null
										  ? this.shadowTextureCustomReceiverPass
										  : this.shadowReceiverPass;
					TextureUnitState textureUnit = targetPass.GetTextureUnitState( 0 );
					textureUnit.SetTextureName( shadowTex.Name );

					// Hook up projection frustum if fixed-function, but also need to
					// disable it explicitly for program pipeline.
					textureUnit.SetProjectiveTexturing( !targetPass.HasVertexProgram, cam );

					// clamp to border color in case this is a custom material
                    textureUnit.SetTextureAddressingMode( TextureAddressing.Border );
					textureUnit.TextureBorderColor = ColorEx.White;

					this.autoParamDataSource.TextureProjector = cam;

					// if this light is a spotlight, we need to add the spot fader layer
					// BUT not if using a custom projection matrix, since then it will be
					// inappropriately shaped most likely
					if ( light.Type == LightType.Spotlight && !cam.IsCustomProjectionMatrixEnabled )
					{
						// remove all TUs except 0 & 1
						// (only an issue if additive shadows have been used)
						while ( targetPass.TextureUnitStageCount > 2 )
						{
							targetPass.RemoveTextureUnitState( 2 );
						}

						// Add spot fader if not present already
						if ( targetPass.TextureUnitStageCount == 2 &&
							 targetPass.GetTextureUnitState( 1 ).TextureName == "spot_shadow_fade.png" )
						{
							// Just set
							TextureUnitState tex = targetPass.GetTextureUnitState( 1 );
							tex.SetProjectiveTexturing( !targetPass.HasVertexProgram, cam );
						}
						else
						{
							// Remove any non-conforming spot layers
							while ( targetPass.TextureUnitStageCount > 1 )
							{
								targetPass.RemoveTextureUnitState( 1 );
							}

							TextureUnitState tex = targetPass.CreateTextureUnitState( "spot_shadow_fade.png" );
							tex.SetProjectiveTexturing( !targetPass.HasVertexProgram, cam );
							tex.SetColorOperation( LayerBlendOperation.Add );
                            tex.SetTextureAddressingMode( TextureAddressing.Clamp );
						}
					}
					else
					{
						// remove all TUs except 0 including spot
						while ( targetPass.TextureUnitStageCount > 1 )
						{
							targetPass.RemoveTextureUnitState( 1 );
						}
					}

					// Set lighting / blending modes
					targetPass.SetSceneBlending( SceneBlendFactor.DestColor, SceneBlendFactor.Zero );
					targetPass.LightingEnabled = false;

					targetPass.Load();

					// Fire pre-reciever event
					// fireShadowTexturesPreReceiver(light, cam);

					this.RenderTextureShadowReceiverQueueGroupObjects( group );
					++sti;
				} // for each light

				this.illuminationStage = IlluminationRenderStage.None;
			}

			// Iterate again
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Do transparents
				this.RenderTransparentObjects( priorityGroup.transparentPasses, true );
			} // for each priority
		}
예제 #5
0
		/// <summary>
		///		Render a group rendering only shadow casters.
		/// </summary>
		/// <param name="group">Render queue group.</param>
		protected virtual void RenderTextureShadowCasterQueueGroupObjects( RenderQueueGroup group )
		{
			// This is like the basic group render, except we skip all transparents
			// and we also render any non-shadowed objects
			// Note that non-shadow casters will have already been eliminated during
			// FindVisibleObjects

			// Override auto param ambient to force vertex programs and fixed function to
			// use shadow colour
			if ( this.IsShadowTechniqueAdditive )
			{
				this.autoParamDataSource.AmbientLight = ColorEx.Black;
				this.targetRenderSystem.AmbientLight = ColorEx.Black;
			}
			else
			{
				this.autoParamDataSource.AmbientLight = this.shadowColor;
				this.targetRenderSystem.AmbientLight = this.shadowColor;
			}

			// Iterate through priorities
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Sort the queue first
				priorityGroup.Sort( this.cameraInProgress );

				// Do solids, override light list in case any vertex programs use them
				this.RenderSolidObjects( priorityGroup.solidPasses, false, this.nullLightList );
				this.renderingNoShadowQueue = true;
				this.RenderSolidObjects( priorityGroup.solidPassesNoShadow, false, this.nullLightList );
				this.renderingNoShadowQueue = false;

				// Do transparents that cast shadows
				this.RenderTransparentShadowCasterObjects( priorityGroup.transparentPasses, false, this.nullLightList );
			} // for each priority

			// reset ambient light
			this.autoParamDataSource.AmbientLight = this.ambientColor;
			this.targetRenderSystem.AmbientLight = this.ambientColor;
		}
예제 #6
0
		/// <summary>
		///		Render a group with the added complexity of modulative stencil shadows.
		/// </summary>
		/// <param name="group">Render queue group.</param>
		protected virtual void RenderModulativeStencilShadowedQueueGroupObjects( RenderQueueGroup group )
		{
			/* For each light, we need to render all the solids from each group,
			then do the modulative shadows, then render the transparents from
			each group.
			Now, this means we are going to reorder things more, but that it required
			if the shadows are to look correct. The overall order is preserved anyway,
			it's just that all the transparents are at the end instead of them being
			interleaved as in the normal rendering loop.
			*/
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// sort the group first
				priorityGroup.Sort( this.cameraInProgress );

				// do solids
				this.RenderSolidObjects( priorityGroup.solidPasses, true );
			}

			// iterate over lights, rendering all volumes to the stencil buffer
			foreach ( Light light in this.lightsAffectingFrustum )
			{
				if ( light.CastShadows )
				{
					// clear the stencil buffer
					this.targetRenderSystem.ClearFrameBuffer( FrameBufferType.Stencil );
					this.RenderShadowVolumesToStencil( light, this.cameraInProgress );

					// render full-screen shadow modulator for all lights
					this.SetPass( this.shadowModulativePass );

					// turn the stencil check on
					this.targetRenderSystem.StencilCheckEnabled = true;

					// we render where the stencil is not equal to zero to render shadows, not lit areas
					this.targetRenderSystem.SetStencilBufferParams( CompareFunction.NotEqual, 0 );
					this.RenderSingleObject( this.fullScreenQuad, this.shadowModulativePass, false );

					// reset stencil buffer params
					this.targetRenderSystem.SetStencilBufferParams();
					this.targetRenderSystem.StencilCheckEnabled = false;
					this.targetRenderSystem.SetDepthBufferParams();
				}
			} // for each light

			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Do non-shadowable solids
				this.renderingNoShadowQueue = true;
				this.RenderSolidObjects( priorityGroup.solidPassesNoShadow, true );
				this.renderingNoShadowQueue = false;
			} // for each priority

			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Do transparents
				this.RenderTransparentObjects( priorityGroup.transparentPasses, true );
			} // for each priority
		}
예제 #7
0
		/// <summary>
		///		Render a group with the added complexity of additive stencil shadows.
		/// </summary>
		/// <param name="group">Render queue group.</param>
		protected virtual void RenderAdditiveStencilShadowedQueueGroupObjects( RenderQueueGroup group )
		{
			LightList tempLightList = new LightList();

			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// sort the group first
				priorityGroup.Sort( this.cameraInProgress );

				// Clear light list
				tempLightList.Clear();

				// Render all the ambient passes first, no light iteration, no lights
				this.illuminationStage = IlluminationRenderStage.Ambient;
				this.RenderSolidObjects( priorityGroup.solidPasses, false, tempLightList );
				// Also render any objects which have receive shadows disabled
				this.renderingNoShadowQueue = true;
				this.RenderSolidObjects( priorityGroup.solidPassesNoShadow, true );
				this.renderingNoShadowQueue = false;

				// Now iterate per light
				this.illuminationStage = IlluminationRenderStage.PerLight;

				foreach ( Light light in lightsAffectingFrustum )
				{
					// Set light state

					if ( light.CastShadows )
					{
						// Clear stencil
						this.targetRenderSystem.ClearFrameBuffer( FrameBufferType.Stencil );
						this.RenderShadowVolumesToStencil( light, this.cameraInProgress );
						// turn stencil check on
						this.targetRenderSystem.StencilCheckEnabled = true;
						// NB we render where the stencil is equal to zero to render lit areas
						this.targetRenderSystem.SetStencilBufferParams( CompareFunction.Equal, 0 );
					}

					// render lighting passes for this light
					tempLightList.Clear();
					tempLightList.Add( light );

					this.RenderSolidObjects( priorityGroup.solidPassesDiffuseSpecular, false, tempLightList );

					// Reset stencil params
					this.targetRenderSystem.SetStencilBufferParams();
					this.targetRenderSystem.StencilCheckEnabled = false;
					this.targetRenderSystem.SetDepthBufferParams();
				} // for each light

				// Now render decal passes, no need to set lights as lighting will be disabled
				this.illuminationStage = IlluminationRenderStage.Decal;
				this.RenderSolidObjects( priorityGroup.solidPassesDecal, false );
			} // for each priority

			// reset lighting stage
			this.illuminationStage = IlluminationRenderStage.None;

			// Iterate again
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Do transparents
				this.RenderTransparentObjects( priorityGroup.transparentPasses, true );
			} // for each priority
		}
예제 #8
0
		private void UpdateRenderQueueGroupSplitOptions( RenderQueueGroup group,
														 bool suppressShadows,
														 bool suppressRenderState )
		{
			if ( this.IsShadowTechniqueStencilBased )
			{
				// Casters can always be receivers
				group.ShadowCastersCannotBeReceivers = false;
			}
			else if ( this.IsShadowTechniqueTextureBased )
			{
				group.ShadowCastersCannotBeReceivers = !this.shadowTextureSelfShadow;
			}

			if ( !suppressShadows && this.currentViewport.ShowShadows && this.IsShadowTechniqueAdditive )
			{
				// Additive lighting, we need to split everything by illumination stage
				group.SplitPassesByLightingType = true;
			}
			else
			{
				group.SplitPassesByLightingType = false;
			}

			if ( !suppressShadows && this.currentViewport.ShowShadows && this.IsShadowTechniqueInUse )
			{
				// Tell render queue to split off non-shadowable materials
				group.SplitNoShadowPasses = true;
			}
			else
			{
				group.SplitNoShadowPasses = false;
			}
		}
예제 #9
0
		/// <summary>
		///		Get a render queue group.
		/// </summary>
		/// <remarks>
		///		New queue groups are registered as they are requested, 
		///		therefore this method will always return a valid group.
		/// </remarks>
		/// <param name="queueID">ID of the queue group to retreive.</param>
		/// <returns></returns>
		public RenderQueueGroup GetQueueGroup( RenderQueueGroupID queueID )
		{
			var group = this.renderGroups[ queueID ] as RenderQueueGroup;

			// see if there is a current queue group for this group id
			if ( group == null )
			{
				// create a new queue group for this group id
				group = new RenderQueueGroup( this, this.splitPassesByLightingType, this.splitNoShadowPasses,
				                              this.shadowCastersCannotBeReceivers );

				// add the new group to cached render group
				this.renderGroups.Add( queueID, group );
			}

			return group;
		}
예제 #10
0
		/// <summary>
		///		Render the objects in a given queue group.
		/// </summary>
		/// <param name="group">Group containing the objects to render.</param>
		protected virtual void RenderQueueGroupObjects( RenderQueueGroup group )
		{
			// Redirect to alternate versions if stencil shadows in use
			bool doShadows = group.ShadowsEnabled && this.currentViewport.ShowShadows &&
							 !this.suppressShadows && !this.suppressRenderStateChanges;
			if ( doShadows && this.shadowTechnique == ShadowTechnique.StencilAdditive )
			{
				this.RenderAdditiveStencilShadowedQueueGroupObjects( group );
			}
			else if ( doShadows && this.shadowTechnique == ShadowTechnique.StencilModulative )
			{
				this.RenderModulativeStencilShadowedQueueGroupObjects( group );
			}
			else if ( this.IsShadowTechniqueTextureBased )
			{
				// Modulative texture shadows in use
				if ( this.illuminationStage == IlluminationRenderStage.RenderToTexture )
				{
					// Shadow caster pass
					if ( this.currentViewport.ShowShadows && !this.suppressShadows && !this.suppressRenderStateChanges )
					{
						this.RenderTextureShadowCasterQueueGroupObjects( group );
					}
				}
				else
				{
					// Ordinary + receiver pass
					if ( doShadows )
					{
						if ( this.IsShadowTechniqueAdditive )
						{
							this.RenderAdditiveTextureShadowedQueueGroupObjects( group );
						}
						else
						{
							this.RenderModulativeTextureShadowedQueueGroupObjects( group );
						}
					}
					else
					{
						this.RenderBasicQueueGroupObjects( group );
					}
				}
			}
			else
			{
				// No shadows, ordinary pass
				this.RenderBasicQueueGroupObjects( group );
			}
		}
        /// <summary>
        ///		Render a group with the added complexity of additive texture shadows.
        /// </summary>
        /// <param name="group">Render queue group.</param>
        void RenderAdditiveTextureShadowedQueueGroupObjects(RenderQueueGroup group)
        {
            List<Light> tempLightList = new List<Light>();
            for(int i = 0; i < group.NumPriorityGroups; i++) {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // Sort the queue first
                priorityGroup.Sort(cameraInProgress);

                // Clear light list
                tempLightList.Clear();

                // Render all the ambient passes first, no light iteration, no lights
                RenderSolidObjects(priorityGroup.solidPasses, false, tempLightList);
                // Also render any objects which have receive shadows disabled
                renderingNoShadowQueue = true;
                RenderSolidObjects(priorityGroup.solidPassesNoShadow, true);
                renderingNoShadowQueue = false;

                // only perform this next part if we're in the 'normal' render stage, to avoid
                // doing it during the render to texture
                if (illuminationStage == IlluminationRenderStage.None) {

                    ICollection<MovableObject> lightList = GetMovableObjectCollection("Light");
                    List<Light> lightList2 = new List<Light>();
                    foreach (Light l in lightList)
                        lightList2.Add(l);
                    lightList2.Sort();

                    // Iterate over lights, render masked
                    for (int li = 0, sti = 0; li < lightsAffectingFrustum.Count; li++) {
                        Light light = lightsAffectingFrustum[li];
                        // Set light state
                        if (light.CastShadows && sti < shadowTextures.Count) {
                            Texture shadowTex = shadowTextures[sti];
                            // Get camera for current shadow texture
                            Camera camera = shadowTex.GetBuffer().GetRenderTarget().GetViewport(0).Camera;
                            // Hook up receiver texture
                            Pass targetPass = shadowTextureCustomReceiverPass != null ?
                                shadowTextureCustomReceiverPass : shadowReceiverPass;
                            targetPass.GetTextureUnitState(0).SetTextureName(shadowTex.Name);
                            // Hook up projection frustum
                            targetPass.GetTextureUnitState(0).SetProjectiveTexturing(true, camera);
                            autoParamDataSource.TextureProjector = camera;
                            // Remove any spot fader layer
                            if (targetPass.NumTextureUnitStages > 1 &&
                                targetPass.GetTextureUnitState(1).TextureName == "spot_shadow_fade.png") {
                                // remove spot fader layer (should only be there if
                                // we previously used modulative shadows)
                                targetPass.RemoveTextureUnitState(1);
                            }
                            // Set lighting / blending modes
                            targetPass.SetSceneBlending(SceneBlendFactor.One, SceneBlendFactor.One);
                            targetPass.LightingEnabled = true;
                            targetPass.Load();
                            // increment shadow texture since used
                            ++sti;
                            illuminationStage = IlluminationRenderStage.RenderModulativePass;
                        }
                        else {
                            illuminationStage = IlluminationRenderStage.None;
                        }

                        // render lighting passes for this light
                        if (tempLightList.Count == 0)
                            tempLightList.Add(light);
                        else
                            tempLightList[0] = light;

                        RenderSolidObjects(priorityGroup.solidPassesDiffuseSpecular, false, lightList2);

                    }// for each light
                    illuminationStage = IlluminationRenderStage.None;

                    // Now render decal passes, no need to set lights as lighting will be disabled
                    RenderSolidObjects(priorityGroup.solidPassesDecal, false);
                }

            }// for each priority

            for(int i = 0; i < group.NumPriorityGroups; i++) {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // Do transparents
                RenderTransparentObjects(priorityGroup.transparentPasses, true);
            }// for each priority
        }
예제 #12
0
		/// <summary>
		///		Render a group with the added complexity of additive texture shadows.
		/// </summary>
		/// <param name="group">Render queue group.</param>
		private void RenderAdditiveTextureShadowedQueueGroupObjects( RenderQueueGroup group )
		{
			LightList tempLightList = new LightList();
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Sort the queue first
				priorityGroup.Sort( this.cameraInProgress );

				// Clear light list
				tempLightList.Clear();

				// Render all the ambient passes first, no light iteration, no lights
				this.RenderSolidObjects( priorityGroup.solidPasses, false, tempLightList );
				// Also render any objects which have receive shadows disabled
				this.renderingNoShadowQueue = true;
				this.RenderSolidObjects( priorityGroup.solidPassesNoShadow, true );
				this.renderingNoShadowQueue = false;

				// only perform this next part if we're in the 'normal' render stage, to avoid
				// doing it during the render to texture
				if ( this.illuminationStage == IlluminationRenderStage.None )
				{
					// Iterate over lights, render masked
					int sti = 0;
					foreach ( Light light in this.lightsAffectingFrustum )
					{
						// Set light state
						if ( light.CastShadows && sti < this.shadowTextures.Count )
						{
							Texture shadowTex = this.shadowTextures[ sti ];
							// Get camera for current shadow texture
							Camera camera = shadowTex.GetBuffer().GetRenderTarget().GetViewport( 0 ).Camera;
							// Hook up receiver texture
							Pass targetPass = this.shadowTextureCustomReceiverPass != null
												  ? this.shadowTextureCustomReceiverPass
												  : this.shadowReceiverPass;
							targetPass.GetTextureUnitState( 0 ).SetTextureName( shadowTex.Name );
							// Hook up projection frustum
							targetPass.GetTextureUnitState( 0 ).SetProjectiveTexturing( true, camera );
							this.autoParamDataSource.TextureProjector = camera;
							// Remove any spot fader layer
							if ( targetPass.TextureUnitStageCount > 1 &&
								 targetPass.GetTextureUnitState( 1 ).TextureName == "spot_shadow_fade.png" )
							{
								// remove spot fader layer (should only be there if
								// we previously used modulative shadows)
								targetPass.RemoveTextureUnitState( 1 );
							}
							// Set lighting / blending modes
							targetPass.SetSceneBlending( SceneBlendFactor.One, SceneBlendFactor.One );
							targetPass.LightingEnabled = true;
							targetPass.Load();
							// increment shadow texture since used
							++sti;
							this.illuminationStage = IlluminationRenderStage.RenderReceiverPass;
						}
						else
						{
							this.illuminationStage = IlluminationRenderStage.None;
						}

						// render lighting passes for this light
						tempLightList.Clear();
						tempLightList.Add( light );

						this.RenderSolidObjects( priorityGroup.solidPassesDiffuseSpecular, false, tempLightList );
					} // for each light
					this.illuminationStage = IlluminationRenderStage.None;

					// Now render decal passes, no need to set lights as lighting will be disabled
					this.RenderSolidObjects( priorityGroup.solidPassesDecal, false );
				}
			} // for each priority

			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Do transparents
				this.RenderTransparentObjects( priorityGroup.transparentPasses, true );
			} // for each priority
		}
        /// <summary>
        ///		Render the objects in a given queue group.
        /// </summary>
        /// <param name="group">Group containing the objects to render.</param>
        protected virtual void RenderQueueGroupObjects(RenderQueueGroup group)
        {
            // Redirect to alternate versions if stencil shadows in use
            bool doShadows = group.ShadowsEnabled && currentViewport.ShadowsEnabled &&
                !suppressShadows && !suppressRenderStateChanges;
            renderQueueGroupMeter.Enter();
            if(doShadows && shadowTechnique == ShadowTechnique.StencilAdditive) {
                renderAdditiveGroupMeter.Enter();
                RenderAdditiveStencilShadowedQueueGroupObjects(group);
                renderAdditiveGroupMeter.Exit();
            }
            else if(doShadows && shadowTechnique == ShadowTechnique.StencilModulative) {
                renderModulativeGroupMeter.Enter();
                RenderModulativeStencilShadowedQueueGroupObjects(group);
                renderModulativeGroupMeter.Exit();
            }
            else if (IsShadowTechniqueTextureBased) {
                // Modulative texture shadows in use
                if (illuminationStage == IlluminationRenderStage.RenderToTexture) {
                    // Shadow caster pass
                    if (currentViewport.ShadowsEnabled && !suppressShadows && !suppressRenderStateChanges) {
                        renderTextureCasterGroupMeter.Enter();
                        RenderTextureShadowCasterQueueGroupObjects(group);
                        renderTextureCasterGroupMeter.Exit();
                    }
                }
                else {
                    // Ordinary + receiver pass
                    if (doShadows) {
                        renderTextureShadowedGroupMeter.Enter();
                        if (IsShadowTechniqueAdditive)
                            RenderAdditiveTextureShadowedQueueGroupObjects(group);
                        else
                            RenderModulativeTextureShadowedQueueGroupObjects(group);
                        renderTextureShadowedGroupMeter.Exit();
                    }
                    else
                        RenderBasicQueueGroupObjects(group);
                }
            }
            else
                // No shadows, ordinary pass
                RenderBasicQueueGroupObjects(group);

            renderQueueGroupMeter.Exit();
        }
        /// <summary>
        ///		Render a group with the added complexity of modulative texture shadows.
        /// </summary>
        /// <param name="group">Render queue group.</param>
        protected virtual void RenderModulativeTextureShadowedQueueGroupObjects(RenderQueueGroup group)
        {
            /* For each light, we need to render all the solids from each group,
            then do the modulative shadows, then render the transparents from
            each group.
            Now, this means we are going to reorder things more, but that is required
            if the shadows are to look correct. The overall order is preserved anyway,
            it's just that all the transparents are at the end instead of them being
            interleaved as in the normal rendering loop.
            */
            // Iterate through priorities
            renderModulativeGroupsMeter.Enter();
            for(int i = 0; i < group.NumPriorityGroups; i++) {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // Sort the queue first
                priorityGroup.Sort(cameraInProgress);

                // Do solids
                RenderSolidObjects(priorityGroup.solidPasses, true);
                renderingNoShadowQueue = true;
                RenderSolidObjects(priorityGroup.solidPassesNoShadow, true);
                renderingNoShadowQueue = false;
            }
            renderModulativeGroupsMeter.Exit();

            renderModulativeLightsMeter.Enter();
            // Iterate over lights, render received shadows
            // only perform this if we're in the 'normal' render stage, to avoid
            // doing it during the render to texture
            if (illuminationStage == IlluminationRenderStage.None) {
                illuminationStage = IlluminationRenderStage.RenderModulativePass;

                for (int i = 0, sti = 0;
                    i < lightsAffectingFrustum.Count && sti < shadowTextures.Count; i++) {
                    Light light = lightsAffectingFrustum[i];

                    if (!light.CastShadows)
                        continue;

                    Texture shadowTex = shadowTextures[sti];
                    Camera cam = shadowTex.GetBuffer().GetRenderTarget().GetViewport(0).Camera;

                    // Hook up receiver texture
                    Pass targetPass = shadowTextureCustomReceiverPass != null ?
                        shadowTextureCustomReceiverPass : shadowReceiverPass;
                    targetPass.GetTextureUnitState(0).SetTextureName(shadowTex.Name);
                    // Hook up projection frustum
                    targetPass.GetTextureUnitState(0).SetProjectiveTexturing(true, cam);
                    autoParamDataSource.TextureProjector = cam;

                    // if this light is a spotlight, we need to add the spot fader layer
                    if (light.Type == LightType.Spotlight) {
                        // remove all TUs except 0 & 1
                        // (only an issue if additive shadows have been used)
                        while (targetPass.NumTextureUnitStages > 2)
                            targetPass.RemoveTextureUnitState(2);

                        // Add spot fader if not present already
                        if (targetPass.NumTextureUnitStages == 2 &&
                            targetPass.GetTextureUnitState(1).TextureName == "spot_shadow_fade.png") {
                            // Just set
                            TextureUnitState tex =
                                targetPass.GetTextureUnitState(1);
                            tex.SetProjectiveTexturing(true, cam);
                        }
                        else {
                            // Remove any non-conforming spot layers
                            while (targetPass.NumTextureUnitStages > 1)
                                targetPass.RemoveTextureUnitState(1);

                            TextureUnitState tex =
                                targetPass.CreateTextureUnitState("spot_shadow_fade.png");
                            tex.SetProjectiveTexturing(true, cam);
                            tex.SetColorOperation(LayerBlendOperation.Add);
                            tex.TextureAddressing = TextureAddressing.Clamp;
                        }
                    }
                    else {
                        // remove all TUs except 0 including spot
                        while (targetPass.NumTextureUnitStages > 1)
                            targetPass.RemoveTextureUnitState(1);
                    }

                    // Set lighting / blending modes
                    targetPass.SetSceneBlending(SceneBlendFactor.DestColor, SceneBlendFactor.Zero);
                    targetPass.LightingEnabled = false;

                    targetPass.Load();

                    // Fire pre-reciever event
                    // fireShadowTexturesPreReceiver(light, cam);

                    RenderTextureShadowReceiverQueueGroupObjects(group);
                    ++sti;

                } // for each light

                illuminationStage = IlluminationRenderStage.None;
            }
            renderModulativeLightsMeter.Exit();

            // Iterate again
            for (int i = 0; i < group.NumPriorityGroups; i++) {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // Do transparents
                RenderTransparentObjects(priorityGroup.transparentPasses, true);
            } // for each priority
        }
        /// <summary>
        ///		Render a group in the ordinary way
        /// </summary>
        /// <param name="group">Group containing the objects to render.</param>
        protected virtual void RenderBasicQueueGroupObjects(RenderQueueGroup group)
        {
            // Basic render loop
            // Iterate through priorities
            for(int i = 0; i < group.NumPriorityGroups; i++) {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // Sort the queue first
                priorityGroup.Sort(cameraInProgress);

                // Do solids
                RenderSolidObjects(priorityGroup.solidPasses, true);

                // Do transparents
                RenderTransparentObjects(priorityGroup.transparentPasses, true);
            }// for each priority
        }
        /// <summary>
        ///		Render a group with the added complexity of additive stencil shadows.
        /// </summary>
        /// <param name="group">Render queue group.</param>
        protected virtual void RenderAdditiveStencilShadowedQueueGroupObjects(RenderQueueGroup group)
        {
            List<Light> tempLightList = new List<Light>();

            for(int i = 0; i < group.NumPriorityGroups; i++) {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // sort the group first
                priorityGroup.Sort(cameraInProgress);

                // Clear light list
                tempLightList.Clear();

                // Render all the ambient passes first, no light iteration, no lights
                illuminationStage = IlluminationRenderStage.Ambient;
                RenderSolidObjects(priorityGroup.solidPasses, false, tempLightList);
                // Also render any objects which have receive shadows disabled
                renderingNoShadowQueue = true;
                RenderSolidObjects(priorityGroup.solidPassesNoShadow, true);
                renderingNoShadowQueue = false;

                // Now iterate per light
                illuminationStage = IlluminationRenderStage.PerLight;

                for (int li = 0; li < lightsAffectingFrustum.Count; li++) {
                    Light light = lightsAffectingFrustum[li];
                    // Set light state

                    if (light.CastShadows) {
                        // Clear stencil
                        targetRenderSystem.ClearFrameBuffer(FrameBuffer.Stencil);
                        RenderShadowVolumesToStencil(light, cameraInProgress);
                        // turn stencil check on
                        targetRenderSystem.StencilCheckEnabled = true;
                        // NB we render where the stencil is equal to zero to render lit areas
                        targetRenderSystem.SetStencilBufferParams(CompareFunction.Equal, 0);
                    }

                    // render lighting passes for this light
                    if (tempLightList.Count == 0) {
                        tempLightList.Add(light);
                    }
                    else {
                        tempLightList[0] = light;
                    }

                    RenderSolidObjects(priorityGroup.solidPassesDiffuseSpecular, false, tempLightList);

                    // Reset stencil params
                    targetRenderSystem.SetStencilBufferParams();
                    targetRenderSystem.StencilCheckEnabled = false;
                    targetRenderSystem.SetDepthBufferParams();

                }// for each light

                // Now render decal passes, no need to set lights as lighting will be disabled
                illuminationStage = IlluminationRenderStage.Decal;
                RenderSolidObjects(priorityGroup.solidPassesDecal, false);

            }// for each priority

            // reset lighting stage
            illuminationStage = IlluminationRenderStage.None;

            // Iterate again
            for(int i = 0; i < group.NumPriorityGroups; i++) {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // Do transparents
                RenderTransparentObjects(priorityGroup.transparentPasses, true);

            }// for each priority
        }
        /// <summary>
        ///		Render a group rendering only shadow receivers.
        ///		We have our own version here to add some optimizations
        /// </summary>
        /// <param name="group">Render queue group.</param>
        protected override void RenderTextureShadowReceiverQueueGroupObjects(RenderQueueGroup group)
        {
            // Override auto param ambient to force vertex programs to go full-bright
            autoParamDataSource.AmbientLight = ColorEx.White;
            targetRenderSystem.AmbientLight = ColorEx.White;

            // Iterate through priorities
            for (int i = 0; i < group.NumPriorityGroups; i++)
            {
                RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i);

                // Do solids, override light list in case any vertex programs use them
                RenderShadowReceiverObjects(priorityGroup.SolidPasses, false, nullLightList);

                // Don't render transparents or passes which have shadow receipt disabled

            }// for each priority

            // reset ambient
            autoParamDataSource.AmbientLight = ambientColor;
            targetRenderSystem.AmbientLight = ambientColor;
        }
예제 #18
0
		/// <summary>
		///		Render a group rendering only shadow receivers.
		/// </summary>
		/// <param name="group">Render queue group.</param>
		protected virtual void RenderTextureShadowReceiverQueueGroupObjects( RenderQueueGroup group )
		{
			// Override auto param ambient to force vertex programs to go full-bright
			this.autoParamDataSource.AmbientLight = ColorEx.White;
			this.targetRenderSystem.AmbientLight = ColorEx.White;

			// Iterate through priorities
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Do solids, override light list in case any vertex programs use them
				this.RenderSolidObjects( priorityGroup.solidPasses, false, this.nullLightList );

				// Don't render transparents or passes which have shadow receipt disabled
			} // for each priority

			// reset ambient
			this.autoParamDataSource.AmbientLight = this.ambientColor;
			this.targetRenderSystem.AmbientLight = this.ambientColor;
		}
예제 #19
0
		internal void Invoke( RenderQueueGroup queueGroup, SceneManager sceneManager )
		{
			throw new NotImplementedException();
		}
예제 #20
0
		/// <summary>
		///		Render a group in the ordinary way
		/// </summary>
		/// <param name="group">Group containing the objects to render.</param>
		protected virtual void RenderBasicQueueGroupObjects( RenderQueueGroup group )
		{
			// Basic render loop
			// Iterate through priorities
			foreach ( RenderPriorityGroup priorityGroup in group.PriorityGroups.Values )
			{
				// Sort the queue first
				priorityGroup.Sort( this.cameraInProgress );

				// Do solids
				this.RenderSolidObjects( priorityGroup.solidPasses, true );

				// Do transparents
				this.RenderTransparentObjects( priorityGroup.transparentPasses, true );
			} // for each priority
		}
        /// <summary>
        ///		Get a render queue group.
        /// </summary>
        /// <remarks>
        ///		New queue groups are registered as they are requested, 
        ///		therefore this method will always return a valid group.
        /// </remarks>
        /// <param name="queueID">ID of the queue group to retreive.</param>
        /// <returns></returns>
        public RenderQueueGroup GetQueueGroup(RenderQueueGroupID queueID)
        {
            RenderQueueGroup group = null;

            // see if there is a current queue group for this group id
            if(renderGroups[queueID] == null) {
                // create a new queue group for this group id
                group = new RenderQueueGroup(this, splitPassesByLightingType,
                                             splitNoShadowPasses,
                                             shadowCastersCannotBeReceivers);

                // add the new group to cached render group
                renderGroups.Add(queueID, group);
            }
            else {
                // retreive the existing queue group
                group = (RenderQueueGroup)renderGroups[queueID];
            }

            return group;
        }