/// <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 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 RenderSolidObjects(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; }
/// <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 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 (IsShadowTechniqueAdditive) { autoParamDataSource.AmbientLight = ColorEx.Black; targetRenderSystem.AmbientLight = ColorEx.Black; } else { autoParamDataSource.AmbientLight = shadowColor; targetRenderSystem.AmbientLight = shadowColor; } // 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, override light list in case any vertex programs use them RenderSolidObjects(priorityGroup.solidPasses, false, nullLightList); renderingNoShadowQueue = true; RenderSolidObjects(priorityGroup.solidPassesNoShadow, false, nullLightList); renderingNoShadowQueue = false; // Do transparents that cast shadows RenderTransparentShadowCasterObjects(priorityGroup.transparentPasses, false, nullLightList); }// for each priority // reset ambient light autoParamDataSource.AmbientLight = ambientColor; targetRenderSystem.AmbientLight = ambientColor; }
/// <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 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. */ for(int i = 0; i < group.NumPriorityGroups; i++) { RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i); // sort the group first priorityGroup.Sort(cameraInProgress); // do solids RenderSolidObjects(priorityGroup.solidPasses, true); } // iterate over lights, rendering all volumes to the stencil buffer for(int i = 0; i < lightsAffectingFrustum.Count; i++) { Light light = lightsAffectingFrustum[i]; if(light.CastShadows) { // clear the stencil buffer targetRenderSystem.ClearFrameBuffer(FrameBuffer.Stencil); RenderShadowVolumesToStencil(light, cameraInProgress); // render full-screen shadow modulator for all lights SetPass(shadowModulativePass); // turn the stencil check on targetRenderSystem.StencilCheckEnabled = true; // we render where the stencil is not equal to zero to render shadows, not lit areas targetRenderSystem.SetStencilBufferParams(CompareFunction.NotEqual, 0); RenderSingleObject(fullScreenQuad, shadowModulativePass, false); // reset stencil buffer params targetRenderSystem.SetStencilBufferParams(); targetRenderSystem.StencilCheckEnabled = false; targetRenderSystem.SetDepthBufferParams(); } }// for each light for(int i = 0; i < group.NumPriorityGroups; i++) { RenderPriorityGroup priorityGroup = group.GetPriorityGroup(i); // Do non-shadowable solids renderingNoShadowQueue = true; RenderSolidObjects(priorityGroup.solidPassesNoShadow, true); renderingNoShadowQueue = 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 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 }