Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
LightReceiverProcessor.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Collections.Specialized;
4 using System.ComponentModel;
5 using System.Linq;
6 using SiliconStudio.Paradox.DataModel;
7 using SiliconStudio.Paradox.Effects;
8 using SiliconStudio.Paradox.Engine;
9 using SiliconStudio.Paradox.EntityModel;
10 using SiliconStudio.Paradox.Games;
11 using SiliconStudio.Core;
12 using SiliconStudio.Core.Collections;
13 
14 namespace ScriptShader.Effects
15 {
16  public class LightReceiverProcessor : EntityProcessor<LightReceiverProcessor.AssociatedData>
17  {
18  private HashSet<ShadowMap> activeShadowMaps = new HashSet<ShadowMap>();
19  private LightProcessor lightProcessor;
20 
21  public LightReceiverProcessor(LightProcessor lightProcessor)
22  : base(new PropertyKey[] { MeshComponent.Key })
23  {
24  this.lightProcessor = lightProcessor;
25  var globalLights = new TrackingCollection<LightComponent>();
26  globalLights.CollectionChanged += globalLights_CollectionChanged;
27  GlobalLights = globalLights;
28  }
29 
30  void globalLights_CollectionChanged(object sender, TrackingCollectionChangedEventArgs e)
31  {
32  if (e.Action == NotifyCollectionChangedAction.Add)
33  InternalAddEntity(((LightComponent)e.Item).Entity);
34  else if (e.Action == NotifyCollectionChangedAction.Remove)
35  InternalRemoveEntity(((LightComponent)e.Item).Entity);
36  }
37 
38  public IList<LightComponent> GlobalLights { get; private set; }
39 
40  protected override AssociatedData GenerateAssociatedData(Entity entity)
41  {
42  return new AssociatedData { LightReceiverComponent = entity.GetOrCreate(LightReceiverComponent.Key), MeshComponent = entity.Get(MeshComponent.Key) };
43  }
44 
45  protected override void OnSystemAdd()
46  {
47  base.OnSystemAdd();
48 
49  lightProcessor.LightComponentAdded += LightProcessorLightComponentAdded;
50  lightProcessor.LightComponentRemoved += LightProcessorLightComponentRemoved;
51  }
52 
53  protected override void OnSystemRemove()
54  {
55  lightProcessor.LightComponentAdded -= LightProcessorLightComponentAdded;
56  lightProcessor.LightComponentRemoved -= LightProcessorLightComponentRemoved;
57  }
58 
59  private void LightProcessorLightComponentAdded(object sender, LightComponent e)
60  {
61  if (!GlobalLights.Contains(e))
62  GlobalLights.Add(e);
63  bool globalLightUpdated = (GlobalLights.Contains(e));
64  foreach (var matchingEntity in matchingEntities)
65  {
66  if (globalLightUpdated
67  || matchingEntity.Value.LightReceiverComponent.LightComponents.Contains(e))
68  {
69  matchingEntity.Value.LightingPermutationUpdated = true;
70  }
71  }
72  }
73 
74  private void LightProcessorLightComponentRemoved(object sender, LightComponent e)
75  {
76  GlobalLights.Remove(e);
77  foreach (var matchingEntity in matchingEntities)
78  {
79  matchingEntity.Value.LightingPermutationUpdated = true;
80  }
81  }
82 
83  protected override void OnEntityAdded(Entity entity, AssociatedData data)
84  {
85  base.OnEntityAdded(entity, data);
86 
87  data.LightComponentsChanged = (sender, e) =>
88  {
89  data.LightingPermutationUpdated = true;
90  };
91 
92  data.LightingPermutationUpdated = true;
93  ((TrackingCollection<LightComponent>)data.LightReceiverComponent.LightComponents).CollectionChanged += data.LightComponentsChanged;
94  }
95 
96  protected override void OnEntityRemoved(Entity entity, AssociatedData data)
97  {
98  base.OnEntityRemoved(entity, data);
99 
100  ((TrackingCollection<LightComponent>)data.LightReceiverComponent.LightComponents).CollectionChanged -= data.LightComponentsChanged;
101  }
102 
103  public override void Update()
104  {
105  foreach (var matchingEntity in enabledEntities)
106  {
107  if (matchingEntity.Value.LightingPermutationUpdated)
108  {
109  matchingEntity.Value.LightingPermutationUpdated = false;
110 
111  var lightComponents = matchingEntity.Value.LightReceiverComponent.LightComponents.Count > 0
112  ? GlobalLights.Concat(matchingEntity.Value.LightReceiverComponent.LightComponents)
113  : GlobalLights;
114 
115  int shadowMapCount = 0;
116  int normalLightCount = 0;
117 
118  // Count lights
119  foreach (var lightComponent in lightComponents)
120  {
121  if (lightComponent.Tags.ContainsKey(LightProcessor.ShadowMapKey))
122  shadowMapCount++;
123  else if (!lightComponent.Deferred)
124  normalLightCount++;
125  }
126 
127  var shadowMapPermutationArray = new ShadowMapPermutationArray { ShadowMaps = new ShadowMapPermutation[shadowMapCount] };
128  var lightBindings = new LightBinding[normalLightCount];
129 
130  // Collect lights
131  int lightingPermutationIndex = 0;
132  int shadowMapPermutationIndex = 0;
133  foreach (var lightComponent in lightComponents)
134  {
135  if (lightComponent.ShadowMap)
136  {
137  var currentLight = lightComponent.Get(LightProcessor.ShadowMapKey);
138  if (activeShadowMaps.Add(currentLight.ShadowMap))
139  {
140  //lightingPlugin.AddShadowMap(currentLight.ShadowMap);
141  }
142  shadowMapPermutationArray.ShadowMaps[shadowMapPermutationIndex++] = currentLight;
143  }
144  else if (!lightComponent.Deferred)
145  {
146  lightBindings[lightingPermutationIndex++] = new LightBinding(lightComponent.Get(LightProcessor.LightKey));
147  }
148  }
149 
150  bool forcePerPixelLighting = matchingEntity.Value.LightReceiverComponent.Get(LightReceiverComponent.ForcePerPixelLighting);
151  if (forcePerPixelLighting)
152  {
153  for (int index = 0; index < lightBindings.Length; index++)
154  {
155  lightBindings[index].LightShaderType = LightShaderType.DiffuseSpecularPixel;
156  }
157  }
158 
159  var lightingPermutation = new LightingPermutation(lightBindings);
160 
161  // Update permutations
162  matchingEntity.Value.MeshComponent.Model.Permutations.Set(LightingPermutation.Key, lightingPermutation);
163  matchingEntity.Value.MeshComponent.Model.Permutations.Set(ShadowMapPermutationArray.Key, shadowMapPermutationArray);
164  }
165  }
166  }
167 
168  public class AssociatedData
169  {
171  public EventHandler<TrackingCollectionChangedEventArgs> LightComponentsChanged;
173  public MeshComponent MeshComponent;
174  }
175  }
176 }
LightReceiverProcessor(LightProcessor lightProcessor)
Add a light to an Entity, that will be used during rendering.
Game entity. It usually aggregates multiple EntityComponent
Definition: Entity.cs:28
IList< LightComponent > LightComponents
Additional lights applied on this object.
override void OnEntityAdded(Entity entity, AssociatedData data)
Entity processor, triggered on various EntitySystem events such as Entity and Component additions and...
static readonly PropertyKey< Light > LightKey
override AssociatedData GenerateAssociatedData(Entity entity)
EventHandler< TrackingCollectionChangedEventArgs > LightComponentsChanged
object Item
Gets the added or removed item (if dictionary, value only).
NotifyCollectionChangedAction Action
Gets the type of action performed. Allowed values are NotifyCollectionChangedAction.Add and NotifyCollectionChangedAction.Remove.
static readonly PropertyKey< ShadowMapPermutation > ShadowMapKey
override void OnEntityRemoved(Entity entity, AssociatedData data)
A class that represents a tag propety.
Definition: PropertyKey.cs:17