/// <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 }
public SceneManager( string name ) : base() { this.cameraList = new CameraCollection(); this.sceneNodeList = new SceneNodeCollection(); this.animationList = new AnimationCollection(); this.animationStateList = new AnimationStateSet(); this.regionList = new List<StaticGeometry.Region>(); this.shadowCasterQueryListener = new ShadowCasterSceneQueryListener( this ); // create the root scene node this.rootSceneNode = new SceneNode( this, "Root" ); this.rootSceneNode.SetAsRootNode(); this.defaultRootNode = this.rootSceneNode; this.name = name; // default to no fog this.fogMode = FogMode.None; // no shadows by default this.shadowTechnique = ShadowTechnique.None; // setup default shadow camera setup this._defaultShadowCameraSetup = new DefaultShadowCameraSetup(); this.illuminationStage = IlluminationRenderStage.None; this.renderingNoShadowQueue = false; this.renderingMainGroup = false; this.shadowColor.a = this.shadowColor.r = this.shadowColor.g = this.shadowColor.b = 0.25f; this.shadowDirLightExtrudeDist = 10000; this.shadowIndexBufferSize = 51200; this.shadowTextureOffset = 0.6f; this.shadowTextureFadeStart = 0.7f; this.shadowTextureFadeEnd = 0.9f; this.shadowTextureSize = 512; this.shadowTextureCount = 1; this.findVisibleObjects = true; this.suppressRenderStateChanges = false; this.suppressShadows = false; this.shadowUseInfiniteFarPlane = true; }
/// <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 }
/// <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 }
private void _preFindVisibleObjects( SceneManager source, IlluminationRenderStage irs, Viewport v ) { //Early-out if ( !IsLoaded ) { return; } // check deferred updates var currMillis = Root.Instance.Timer.Milliseconds; var elapsedMillis = currMillis - this.mLastMillis; if ( this.mCompositeMapUpdateCountdown > 0 && elapsedMillis > 0 ) { if ( elapsedMillis > this.mCompositeMapUpdateCountdown ) { this.mCompositeMapUpdateCountdown = 0; } else { this.mCompositeMapUpdateCountdown -= elapsedMillis; } if ( this.mCompositeMapUpdateCountdown == 0 ) { UpdateCompositeMap(); } } this.mLastMillis = currMillis; // only calculate LOD once per LOD camera, per frame, per viewport height var lodCamera = v.Camera.LodCamera; var frameNum = (ulong)Root.Instance.NextFrameNumber; var vpHeight = v.ActualHeight; if ( this.mLastLODCamera != lodCamera || frameNum != this.mLastLODFrame || this.mLastViewportHeight != vpHeight ) { this.mLastLODCamera = lodCamera; this.mLastLODFrame = frameNum; this.mLastViewportHeight = vpHeight; CalculateCurrentLod( v ); } }
/// <summary> /// Internal method for preparing shadow textures ready for use in a regular render /// </summary> /// <param name="camera"></param> /// <param name="viewPort"></param> protected internal virtual void PrepareShadowTextures( Camera camera, Viewport viewPort ) { // Set the illumination stage, prevents recursive calls IlluminationRenderStage savedStage = this.illuminationStage; this.illuminationStage = IlluminationRenderStage.RenderToTexture; // Determine far shadow distance float shadowDist = this.shadowFarDistance; if ( shadowDist == 0.0f ) { // need a shadow distance, make one up shadowDist = camera.Near * 300; } // set fogging to hide the shadow edge float shadowOffset = shadowDist * this.shadowTextureOffset; // Precalculate fading info float shadowEnd = shadowDist + shadowOffset; float fadeStart = shadowEnd * this.shadowTextureFadeStart; float fadeEnd = shadowEnd * this.shadowTextureFadeEnd; // Additive lighting should not use fogging, since it will overbrighten; use border clamp if ( !this.IsShadowTechniqueAdditive ) { this.shadowReceiverPass.SetFog( true, FogMode.Linear, ColorEx.White, 0, fadeStart, fadeEnd ); // if we have a custom receiver material, then give it the fog params too if ( this.shadowTextureCustomReceiverPass != null ) { this.shadowTextureCustomReceiverPass.SetFog( true, FogMode.Linear, ColorEx.White, 0, fadeStart, fadeEnd ); } } else { // disable fogging explicitly this.shadowReceiverPass.SetFog( true, FogMode.None ); // if we have a custom receiver material, then give it the fog params too if ( this.shadowTextureCustomReceiverPass != null ) { this.shadowTextureCustomReceiverPass.SetFog( true, FogMode.None ); } } // Iterate over the lights we've found, max out at the limit of light textures int sti = 0; foreach ( Light light in this.lightsAffectingFrustum ) { // Check limit reached if ( sti == this.shadowTextures.Count ) break; // Skip non-shadowing lights if ( !light.CastShadows ) { continue; } Texture shadowTex = this.shadowTextures[ sti ]; RenderTarget shadowRTT = shadowTex.GetBuffer().GetRenderTarget(); Viewport shadowView = shadowRTT.GetViewport( 0 ); Camera texCam = this.shadowTextureCameras[ sti ]; // rebind camera, incase another SM in use which has switched to its cam shadowView.Camera = texCam; // Associate main view camera as LOD camera texCam.LodCamera = camera; //Vector3 dir; // set base if ( light.Type == LightType.Point ) texCam.Direction = light.DerivedDirection; if ( light.Type == LightType.Directional ) texCam.Position = light.DerivedPosition; // Use the material scheme of the main viewport // This is required to pick up the correct shadow_caster_material and similar properties. shadowView.MaterialScheme = viewPort.MaterialScheme; if ( light.CustomShadowCameraSetup == null ) { _defaultShadowCameraSetup.GetShadowCamera( this, camera, viewPort, light, texCam, sti ); } else { light.CustomShadowCameraSetup.GetShadowCamera( this, camera, viewPort, light, texCam, sti ); } shadowView.BackgroundColor = ColorEx.White; // Fire shadow caster update, callee can alter camera settings // fireShadowTexturesPreCaster(light, texCam); // Update target shadowRTT.Update(); ++sti; } // Set the illumination stage, prevents recursive calls this.illuminationStage = savedStage; //fireShadowTexturesUpdated( std::min(mLightsAffectingFrustum.size(), mShadowTextures.size())); }
public SceneManager(string smName) { this.smName = smName; cameraList = new Dictionary<string, Camera>(); //lightList = new LightList(); //entityList = new EntityList(); movableObjectCollectionMap = new Dictionary<string, Dictionary<string, MovableObject>>(); sceneNodeList = new Dictionary<string, SceneNode>(); //billboardSetList = new Dictionary<string, BillboardSet>(); animationList = new Dictionary<string, Animation>(); animationStateList = new AnimationStateSet(); regionList = new List<Region>(); // create the root scene node rootSceneNode = new SceneNode(this, "Root"); defaultRootNode = rootSceneNode; // default to no fog fogMode = FogMode.None; // no shadows by default shadowTechnique = ShadowTechnique.None; illuminationStage = IlluminationRenderStage.None; renderingNoShadowQueue = false; renderingMainGroup = false; shadowColor = new ColorEx(0.25f, 0.25f, 0.25f); shadowDirLightExtrudeDist = 10000; shadowIndexBufferSize = 51200; shadowTextureOffset = 0.6f; shadowTextureFadeStart = 0.7f; shadowTextureFadeEnd = 0.9f; shadowTextureSize = 512; shadowTextureConfigDirty = true; ShadowTextureCount = 1; findVisibleObjects = true; suppressRenderStateChanges = false; suppressShadows = false; shadowUseInfiniteFarPlane = true; shadowCasterRenderBackFaces = true; defaultShadowCameraSetup = new DefaultShadowCameraSetup(); }
/// <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 }
/// <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 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> /// Internal method for preparing shadow textures ready for use in a regular render /// </summary> /// <param name="camera"></param> /// <param name="viewPort"></param> protected internal virtual void PrepareShadowTextures(Camera camera, Viewport viewPort) { prepareShadowTexturesMeter.Enter(); // create shadow textures if needed EnsureShadowTexturesCreated(); // Set the illumination stage, prevents recursive calls IlluminationRenderStage savedStage = illuminationStage; illuminationStage = IlluminationRenderStage.RenderToTexture; // Determine far shadow distance float shadowDist = shadowFarDistance; if (shadowDist == 0.0f) { // need a shadow distance, make one up shadowDist = camera.Near * 300; } // set fogging to hide the shadow edge float shadowOffset = shadowDist * shadowTextureOffset; // Precalculate fading info float shadowEnd = shadowDist + shadowOffset; float fadeStart = shadowEnd * shadowTextureFadeStart; float fadeEnd = shadowEnd * shadowTextureFadeEnd; // set auto param for the start and end of the shadow fade region autoParamDataSource.ShadowFadeParams = new Vector4(fadeStart, fadeEnd, 0, 0); // Additive lighting should not use fogging, since it will overbrighten; use border clamp if (!IsShadowTechniqueAdditive) { shadowReceiverPass.SetFog(true, FogMode.Linear, ColorEx.White, 0, fadeStart, fadeEnd); // if we have a custom receiver material, then give it the fog params too if (shadowTextureCustomReceiverPass != null) shadowTextureCustomReceiverPass.SetFog(true, FogMode.Linear, ColorEx.White, 0, fadeStart, fadeEnd); } else { // disable fogging explicitly shadowReceiverPass.SetFog(true, FogMode.None); // if we have a custom receiver material, then give it the fog params too if (shadowTextureCustomReceiverPass != null) shadowTextureCustomReceiverPass.SetFog(true, FogMode.None); } // Iterate over the lights we've found, max out at the limit of light textures for (int i = 0, sti = 0; i < lightsAffectingFrustum.Count && sti < shadowTextures.Count; i++) { Light light = lightsAffectingFrustum[i]; // Skip non-shadowing lights if (!light.CastShadows) continue; Texture shadowTex = shadowTextures[sti]; RenderTarget shadowRTT = shadowTex.GetBuffer().GetRenderTarget(); Viewport shadowView = shadowRTT.GetViewport(0); Camera texCam = shadowTextureCameras[sti]; // rebind camera, incase another SM in use which has switched to its cam // This seems pretty silly - - is there any reason to do it? shadowView.Camera = texCam; // update shadow cam - light mapping shadowCamLightMapping[texCam] = light; if (light.CustomShadowCameraSetup == null) defaultShadowCameraSetup.GetShadowCamera(this, camera, shadowView, light, texCam); else light.CustomShadowCameraSetup.GetShadowCamera(this, camera, shadowView, light, texCam); // Setup background colour shadowView.BackgroundColor = ColorEx.White; // Fire shadow caster update, callee can alter camera settings // fireShadowTexturesPreCaster(light, texCam); // Update target shadowRTT.Update(); sti++; } illuminationStage = savedStage; //fireShadowTexturesUpdated(Math.Min(lightsAffectingFrustum.Count, shadowTextures.Count)); ShadowTextureManager.Instance.ClearUnused(); prepareShadowTexturesMeter.Exit(); }