5 using System.Collections.Generic;
7 using SiliconStudio.Core;
8 using SiliconStudio.Core.Mathematics;
9 using SiliconStudio.Paradox.Effects.Modules.Processors;
10 using SiliconStudio.Paradox.Engine;
11 using SiliconStudio.Paradox.EntityModel;
12 using SiliconStudio.Paradox.Graphics;
13 using SiliconStudio.Paradox.Shaders;
14 using SiliconStudio.Paradox.Shaders.Compiler;
16 namespace SiliconStudio.
Paradox.Effects.Modules.Renderers
23 #region Static members
47 #region Private members
52 private Dictionary<int, Effect> cubemapBlendEffects;
57 private bool useMultipleRenderTargets;
62 private List<Tuple<TextureCube, float>> selectedCubemaps;
75 cubemapBlendEffects =
new Dictionary<int, Effect>();
76 useMultipleRenderTargets =
false;
77 selectedCubemaps =
new List<Tuple<TextureCube, float>>();
83 #region Public methods
86 public override void Load()
90 useMultipleRenderTargets = GraphicsDevice.Features.Profile >= GraphicsProfile.Level_10_0;
92 for (var maxBlendCount = 2; maxBlendCount < 5; ++maxBlendCount)
96 for (var i = 0; i < maxBlendCount; ++i)
99 param.Add(CubemapBlendRenderer.CubemapKey, GetTextureCubeKey(i));
100 compilerParameterChild[i] = param;
102 compilerParameter.Set(CubemapBlendRenderer.Cubemaps, compilerParameterChild);
103 compilerParameter.Set(CubemapBlendRenderer.CubemapCount, maxBlendCount);
104 compilerParameter.Set(CubemapBlendRenderer.UseMultipleRenderTargets, useMultipleRenderTargets);
105 cubemapBlendEffects.Add(maxBlendCount, EffectSystem.LoadEffect(
"CubemapBlendEffect", compilerParameter));
111 #region Protected methods
115 var entitySystem = Services.GetServiceAs<
EntitySystem>();
117 if (cubemapBlendProcessor == null)
121 if (cubemapSourceProcessor == null)
124 var textureCubes = cubemapSourceProcessor.Cubemaps;
126 foreach (var cubemap
in cubemapBlendProcessor.Cubemaps)
128 if (cubemap.Value.Texture == null)
131 var maxCubemapBlend = cubemap.Value.MaxBlendCount;
132 var position = cubemap.Key.Transformation.Translation;
134 maxCubemapBlend = maxCubemapBlend > textureCubes.Count ? textureCubes.Count : maxCubemapBlend;
137 Effect cubemapBlendEffect = null;
138 while (maxCubemapBlend > 1)
140 if (cubemapBlendEffects.TryGetValue(maxCubemapBlend, out cubemapBlendEffect) && cubemapBlendEffect != null)
145 if (cubemapBlendEffect == null)
149 selectedCubemaps.Clear();
151 FindMostInfluencialCubemaps(textureCubes, position, maxCubemapBlend, selectedCubemaps);
155 maxCubemapBlend = maxCubemapBlend > selectedCubemaps.Count ? selectedCubemaps.Count : maxCubemapBlend;
160 var totalWeight = 0f;
161 for (var i = 0; i < maxCubemapBlend; ++i)
162 totalWeight += selectedCubemaps[i].Item2;
163 var blendIndices =
new float[maxCubemapBlend];
164 blendEffectParameters.Clear();
165 for (var i = 0; i < maxCubemapBlend; ++i)
167 blendIndices[i] = selectedCubemaps[i].Item2 / totalWeight;
168 blendEffectParameters.Set(GetTextureCubeKey(i), selectedCubemaps[i].Item1);
170 blendEffectParameters.Set(CubemapBlenderBaseKeys.BlendIndices, blendIndices);
174 GraphicsDevice.Clear(cubemap.Value.Texture.ToRenderTarget(ViewType.Full, 0, 0),
Color.
Black);
177 GraphicsDevice.SetDepthStencilState(GraphicsDevice.DepthStencilStates.None);
180 if (useMultipleRenderTargets)
182 GraphicsDevice.SetRenderTargets(cubemap.Value.RenderTargets);
183 GraphicsDevice.DrawQuad(cubemapBlendEffect, blendEffectParameters);
187 for (
int i = 0; i < 6; ++i)
190 GraphicsDevice.SetRenderTarget(cubemap.Value.RenderTargets[i]);
191 blendEffectParameters.Set(CubemapBlenderKeys.ViewIndex, i);
192 GraphicsDevice.DrawQuad(cubemapBlendEffect, blendEffectParameters);
198 private void FindClosestCubemaps(Dictionary<Entity, CubemapSourceComponent> textureCubes,
Vector3 position,
int maxCubemapBlend, List<Tuple<TextureCube, float>> selectedCubemaps)
200 foreach (var tex
in textureCubes)
202 var d = (tex.Key.Transformation.Translation - position).LengthSquared();
203 var influence = 1.0f / (d + 1);
205 for (; insertIndex < maxCubemapBlend; ++insertIndex)
207 if (insertIndex >= selectedCubemaps.Count || influence > selectedCubemaps[insertIndex].Item2)
210 if (insertIndex < maxCubemapBlend)
211 selectedCubemaps.Insert(insertIndex, Tuple.Create(tex.Value.Texture, influence));
215 private void FindMostInfluencialCubemaps(Dictionary<Entity, CubemapSourceComponent> textureCubes,
Vector3 position,
int maxCubemapBlend, List<Tuple<TextureCube, float>> selectedCubemaps)
217 foreach (var tex
in textureCubes)
221 var d = (tex.Key.Transformation.Translation - position).Length();
222 var influence = 1 - (d / tex.Value.InfluenceRadius);
225 else if (influence <= 0)
229 for (; insertIndex < maxCubemapBlend; ++insertIndex)
231 if (insertIndex >= selectedCubemaps.Count || influence > selectedCubemaps[insertIndex].Item2)
234 if (insertIndex < maxCubemapBlend)
235 selectedCubemaps.Insert(insertIndex, Tuple.Create(tex.Value.Texture, influence));
241 private void FindMostInfluencialCubemaps2(Dictionary<Entity, CubemapSourceComponent> textureCubes,
Vector3 position,
int maxCubemapBlend, List<Tuple<TextureCube, float>> selectedCubemaps)
245 var influences =
new Dictionary<Entity, float>();
246 var blendValues =
new Dictionary<Entity, float>();
248 foreach (var tex
in textureCubes)
251 var d = (tex.Key.Transformation.Translation - position).Length();
254 influences.Add(tex.Key, d);
258 var n = textureCubes.Count;
259 foreach (var influence
in influences)
261 var infl = influence.Value;
262 var blendFactor = (1 - (infl / inflSum)) / (n - 1);
263 blendFactor *= (1 - infl) / invInflSum;
264 sumBlend += blendFactor;
265 blendValues.Add(influence.Key, blendFactor);
271 var invSumBlend = 1 / sumBlend;
272 foreach (var tex
in textureCubes)
274 var influence = blendValues[tex.Key] * invSumBlend;
277 for (; insertIndex < maxCubemapBlend; ++insertIndex)
279 if (insertIndex >= selectedCubemaps.Count || influence > selectedCubemaps[insertIndex].Item2)
282 if (insertIndex < maxCubemapBlend)
283 selectedCubemaps.Insert(insertIndex, Tuple.Create(tex.Value.Texture, influence));
291 private ParameterKey<Texture> GetTextureCubeKey(
int i)
296 return TexturingKeys.TextureCube0;
298 return TexturingKeys.TextureCube1;
300 return TexturingKeys.TextureCube2;
302 return TexturingKeys.TextureCube3;
304 throw new IndexOutOfRangeException();
Key of an effect parameter.
static readonly Color Black
Black color.
Parameters used for mixin.
override void Load()
Loads this instance. This method is called when a RenderPass is attached (directly or indirectly) to ...
CubemapBlendRenderer(IServiceRegistry services)
override void OnRendering(RenderContext context)
Performs render pipeline transformations attached to a specific RenderPass.
Parameters used for compilation.
Represents a three dimensional mathematical vector.
A service registry is a IServiceProvider that provides methods to register and unregister services...
Thread-local storage context used during rendering.
Manage a collection of entities.
Represents a 32-bit color (4 bytes) in the form of RGBA (in byte order: R, G, B, A).
Keeps tracks of the active cubemaps.
Blends the cubemaps at the defined locations.
Keeps track of active cubemap blending locations.
A container to handle a hierarchical collection of effect variables.