public PhotonTracer(Scene scene, RenderStrategy renderStrategy, int maxPhotons) : base(scene, renderStrategy) { this.scene = scene; this.maxPhotons = maxPhotons; this.indirectEnlightenment = new PhotonMap(maxPhotons); this.causticsEnlightenment = new PhotonMap(maxPhotons); this.buildPhotonMaps = true; this.scene.Primitives.CollectionChanged += Primitives_CollectionChanged; this.scene.Lights.CollectionChanged += Lights_CollectionChanged; this.scene.Materials.CollectionChanged += Materials_CollectionChanged; }
/// <summary> /// Begins calculating a light mapping solution. /// </summary> /// <exception cref="System.ApplicationException"> /// Thrown when no BSP is in the current scene graph. /// </exception> public void Begin() { // MdxRender.RenderDebug = false; SetOperation("Loading scenario..."); _scenario = Prometheus.Instance.ProjectManager.ScenarioTag as ScenarioBase; if (_scenario == null) { throw new RadiosityException("The current project has no scenario tag or the scenario tag is invalid."); } if (_scenario.BspList.Count <= 0) { throw new RadiosityException("The current project's scenario tag does not contain a bsp tag or the bsp tag is invalid."); } SetOperation("Retrieving lighting information..."); m_bsp = _scenario.BspList; WorldBounds bounds = m_bsp[0].WorldBounds; foreach (IBsp bsp in m_bsp) { bounds &= bsp.WorldBounds; } // We need to find the six planes of world bounds. m_worldBounds = bounds.CalculatePlanes(); // Try and obtain any lighting information. if (Prometheus.Instance.ProjectManager.ScenarioTag != null) { this.m_lights = _scenario.WorldLighting; this.m_models = _scenario.StaticModels; if (m_models == null) { m_models = new List <IModel>(); } } else { ICamera camera = MdxRender.Camera; List <RadiosityLight> lights = new List <RadiosityLight>(); this.m_lights = new List <ILight>(); m_lights.Add(new RadiosityLight(camera.Position, new RealColor(1f, 1f, 1.0f), 20f)); } // Get each lightmap from the currently loaded BSP. for (int i = 0; i < m_bsp.Count; i++) { // Add the DirectX texture to the high dynamic range texture collection. foreach (BaseTexture _texture in m_bsp[i].Lightmaps) { TextureMap _lightmap = new TextureMap(_texture); m_textures.AddTexture(_lightmap); } } // TODO: Figure out the number of photons each light gets. For now, set them all to use the same amount. float totalPower = 0f; float maxPower = 0f; foreach (ILight light in m_lights) { totalPower += light.Power; maxPower = Math.Max(light.Power, maxPower); } int directionalPhotons = 0; foreach (ILight light in m_lights) { int photonCount = (int)((float)m_maxPhotons * light.Power / totalPower);//(int)Math.Round((light.Power / totalPower) * (float)m_maxPhotons); light.PhotonCount = photonCount; light.Color.Multiply(light.Power); if (light is DirectionalLight) { directionalPhotons += photonCount; } } bool[,] importance; int count; ChangeStage(RadiosityStage.CreatingImportanceMap, directionalPhotons); SetOperation("Optimizing Pass..."); for (int l = 0; l < m_lights.Count; l++) { if (m_lights[l] is DirectionalLight) { DirectionalLight light = m_lights[l] as DirectionalLight; if (light.PhotonCount > 0) { importance = CreateImportanceMap(light.Direction, light.PhotonCount, bounds, out count); } else { importance = null; count = 0; } RadiosityHelper.ImportanceMap = importance; RadiosityHelper.ImportanceMapOnPixels = count; } } //currentOperation = "Saving any unsaved data..."; //this.SaveAll(); photonMap = new PhotonMap(m_maxBounces * m_maxPhotons); SetOperation("Perform radiosity..."); // Process collisions. this.ProcessCollisions(); ChangeStage(RadiosityStage.Done, 100); Interfaces.Output.Write(Interfaces.OutputTypes.Information, m_photonsLost + " photon(s) lost during radiosity."); if (OnComplete != null) { OnComplete(); } }