/// <summary> /// Internal method for clearing the illumination pass list. /// </summary> protected void ClearIlluminationPasses() { for (int i = 0; i < illuminationPasses.Count; i++) { IlluminationPass iPass = (IlluminationPass)illuminationPasses[i]; if (iPass.DestroyOnShutdown) { iPass.Pass.QueueForDeletion(); } } illuminationPasses.Clear(); }
/// <summary> /// Loads resources required by this Technique. /// </summary> public void Load() { Debug.Assert(isSupported, "This technique is not supported."); // load each pass for (int i = 0; i < passes.Count; i++) { ((Pass)passes[i]).Load(); } // load each illumination pass for (int i = 0; i < illuminationPasses.Count; i++) { IlluminationPass pass = (IlluminationPass)illuminationPasses[i]; if (pass.Pass != pass.OriginalPass) { pass.Pass.Load(); } } }
/// <summary> /// Internal method for adding a solid renderable ot the group based on lighting stage. /// </summary> /// <param name="technique">Technique to use for this renderable.</param> /// <param name="renderable">Renderable to add to the queue.</param> protected void AddSolidRenderableSplitByLightType(Technique technique, IRenderable renderable) { // Divide the passes into the 3 categories for (int i = 0; i < technique.IlluminationPassCount; i++) { // Insert into solid list IlluminationPass illpass = technique.GetIlluminationPass(i); SortedList passMap = null; switch (illpass.Stage) { case IlluminationStage.Ambient: passMap = solidPasses; break; case IlluminationStage.PerLight: passMap = solidPassesDiffuseSpecular; break; case IlluminationStage.Decal: passMap = solidPassesDecal; break; } RenderableList solidList = (RenderableList)passMap[illpass.Pass]; if (solidList == null) { // add a new list to hold renderables for this pass solidList = new RenderableList(); passMap.Add(illpass.Pass, solidList); } solidList.Add(renderable); } }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(IlluminationPass obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
/// <summary> /// Internal method for splitting the passes into illumination passes. /// </summary> public void CompileIlluminationPasses() { ClearIlluminationPasses(); // don't need to split transparent passes since they are rendered seperately if (this.IsTransparent) { return; } // start off with ambient passes IlluminationStage stage = IlluminationStage.Ambient; bool hasAmbient = false; for (int i = 0; i < passes.Count; /* increment in logic */) { Pass pass = (Pass)passes[i]; IlluminationPass iPass; switch (stage) { case IlluminationStage.Ambient: // keep looking for ambient only if (pass.IsAmbientOnly) { iPass = new IlluminationPass(); iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; illuminationPasses.Add(iPass); hasAmbient = true; // progress to the next pass i++; } else { // split off any ambient part if (pass.Ambient.CompareTo(ColorEx.Black) != 0 || pass.Emissive.CompareTo(ColorEx.Black) != 0 || pass.AlphaRejectFunction != CompareFunction.AlwaysPass) { Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); if (newPass.AlphaRejectFunction != CompareFunction.AlwaysPass) { // Alpha rejection passes must retain their transparency, so // we allow the texture units, but override the colour functions for (int tindex = 0; tindex < newPass.NumTextureUnitStages; tindex++) { TextureUnitState tus = newPass.GetTextureUnitState(tindex); tus.SetColorOperationEx(LayerBlendOperationEx.Source1, LayerBlendSource.Current, LayerBlendSource.Current); } } else { // remove any texture units newPass.RemoveAllTextureUnitStates(); } // also remove any fragment program if (newPass.HasFragmentProgram) { newPass.SetFragmentProgram(""); } // We have to leave vertex program alone (if any) and // just trust that the author is using light bindings, which // we will ensure there are none in the ambient pass newPass.Diffuse = new ColorEx(newPass.Diffuse.a, 0f, 0f, 0f); // Preserving alpha newPass.Specular = ColorEx.Black; // Calculate hash value for new pass, because we are compiling // illumination passes on demand, which will loss hash calculate // before it add to render queue first time. newPass.RecalculateHash(); iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); hasAmbient = true; } if (!hasAmbient) { // make up a new basic pass Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); newPass.Ambient = ColorEx.Black; newPass.Diffuse = ColorEx.Black; // Calculate hash value for new pass, because we are compiling // illumination passes on demand, which will loss hash calculate // before it add to render queue first time. newPass.RecalculateHash(); iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); hasAmbient = true; } // this means we are done with ambients, progress to per-light stage = IlluminationStage.PerLight; } break; case IlluminationStage.PerLight: if (pass.RunOncePerLight) { // if this is per-light already, use it directly iPass = new IlluminationPass(); iPass.DestroyOnShutdown = false; iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; illuminationPasses.Add(iPass); // progress to the next pass i++; } else { // split off per-light details (can only be done for one) if (pass.LightingEnabled && (pass.Diffuse.CompareTo(ColorEx.Black) != 0 || pass.Specular.CompareTo(ColorEx.Black) != 0)) { // copy existing pass Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); if (newPass.AlphaRejectFunction != CompareFunction.AlwaysPass) { // Alpha rejection passes must retain their transparency, so // we allow the texture units, but override the colour functions for (int tindex = 0; tindex < newPass.NumTextureUnitStages; tindex++) { TextureUnitState tus = newPass.GetTextureUnitState(tindex); tus.SetColorOperationEx(LayerBlendOperationEx.Source1, LayerBlendSource.Current, LayerBlendSource.Current); } } else { // remove any texture units newPass.RemoveAllTextureUnitStates(); } // also remove any fragment program if (newPass.HasFragmentProgram) { newPass.SetFragmentProgram(""); } // Cannot remove vertex program, have to assume that // it will process diffuse lights, ambient will be turned off newPass.Ambient = ColorEx.Black; newPass.Emissive = ColorEx.Black; // must be additive newPass.SetSceneBlending(SceneBlendFactor.One, SceneBlendFactor.One); iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); } // This means the end of per-light passes stage = IlluminationStage.Decal; } break; case IlluminationStage.Decal: // We just want a 'lighting off' pass to finish off // and only if there are texture units if (pass.NumTextureUnitStages > 0) { if (!pass.LightingEnabled) { // we assume this pass already combines as required with the scene iPass = new IlluminationPass(); iPass.DestroyOnShutdown = false; iPass.OriginalPass = pass; iPass.Pass = pass; iPass.Stage = stage; illuminationPasses.Add(iPass); } else { // Copy the pass and tweak away the lighting parts Pass newPass = new Pass(this, pass.Index); pass.CopyTo(newPass); newPass.Ambient = ColorEx.Black; newPass.Diffuse = new ColorEx(newPass.Diffuse.a, 0f, 0f, 0f); // Preserving alpha newPass.Specular = ColorEx.Black; newPass.Emissive = ColorEx.Black; newPass.LightingEnabled = false; // modulate newPass.SetSceneBlending(SceneBlendFactor.DestColor, SceneBlendFactor.Zero); // Calculate hash value for new pass, because we are compiling // illumination passes on demand, which will loss hash calculate // before it add to render queue first time. newPass.RecalculateHash(); // there is nothing we can do about vertex & fragment // programs here, so people will just have to make their // programs friendly-like if they want to use this technique iPass = new IlluminationPass(); iPass.DestroyOnShutdown = true; iPass.OriginalPass = pass; iPass.Pass = newPass; iPass.Stage = stage; illuminationPasses.Add(iPass); } } // always increment on decal, since nothing more to do with this pass i++; break; } } }