Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
RenderingSetup.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using System.Text;
6 using SiliconStudio.Paradox.Engine.Xaml;
7 using SiliconStudio.Paradox.EntityModel;
8 using SiliconStudio.Paradox.Games;
9 using SiliconStudio.Core.IO;
10 using SiliconStudio.Core.Xaml;
11 using SiliconStudio.Paradox;
12 using SiliconStudio.Paradox.DataModel;
13 using SiliconStudio.Paradox.Effects;
14 using SiliconStudio.Paradox.Effects.Modules;
15 #if PARADOX_YEBIS
16 using SiliconStudio.Paradox.Effects.Yebis;
17 #endif
18 using SiliconStudio.Paradox.Engine;
19 using SiliconStudio.Paradox.Configuration;
20 using SiliconStudio.Core.Extensions;
21 using SiliconStudio.Paradox.Graphics;
22 using SiliconStudio.Core.Mathematics;
23 using SiliconStudio.Paradox.ObjectModel;
24 using ScriptShader.Effects;
25 
26 namespace ScriptTest
27 {
28  /// <summary>
29  /// TODO: Update summary.
30  /// </summary>
31  public class RenderingSetup
32  {
33  private bool lightingRegistered;
34 
35  public static readonly RenderingSetup Singleton = new RenderingSetup();
36  private IRenderSystem renderSystem;
37  private IGraphicsDeviceService graphicsDeviceService;
38  private IEffectSystemOld effectSystemOld;
39  private IEntitySystem entitySystem;
40 
41  private RenderConfigContext RenderConfigContext { get; set; }
42 
44  public MainPlugin MainPlugin { get; set; }
45 
46  public void Initialize(IServiceRegistry registry, string effectFilename = null, string[] optionalFeatures = null)
47  {
48  // Missing features compared to before: ZInverse support, Picking/Wireframe, Heat Shimmering and light shafts bounding boxes.
49  // Other stuff to implement: Enable features by RenderPipeline, reloading, access of plugins through a flexible interface, yebis config.
50  renderSystem = registry.GetSafeServiceAs<IRenderSystem>();
51  graphicsDeviceService = registry.GetSafeServiceAs<IGraphicsDeviceService>();
52  this.effectSystemOld = registry.GetSafeServiceAs<IEffectSystemOld>();
53  entitySystem = registry.GetSafeServiceAs<IEntitySystem>();
54 
55  var rootRenderPass = renderSystem.RootRenderPass;
56  var dataContext = RenderConfigContext = renderSystem.ConfigContext;
57  var graphicsDevice = graphicsDeviceService.GraphicsDevice;
58 
59  if (effectFilename == null)
60  effectFilename = Path.Combine("/shaders/effects.xml");
61 
62  var context = new ParadoxXamlSchemaContext(dataContext);
63  var xamlObjectWriter = new XamlObjectWriter(context);
64 
65  using (var fileStream = VirtualFileSystem.OpenStream(effectFilename, VirtualFileMode.Open, VirtualFileAccess.Read))
66  XamlServices.Transform(new XamlXmlReader(fileStream, context), xamlObjectWriter);
67 
68  var effectConfig = (RenderConfig)xamlObjectWriter.Result;
69 
70  foreach (var renderPass in effectConfig.Content.OfType<RenderPass>())
71  {
72  dataContext.RenderPasses.Add(renderPass.Name, renderPass);
73  rootRenderPass.AddPass(renderPass);
74  }
75 
76  foreach (var item in effectConfig.Content)
77  {
78  var plugin = item as RenderPassPlugin;
79  if (plugin != null)
80  {
81  dataContext.RenderPassPlugins.Add(plugin.Name, plugin);
82  }
83 
84  var setter = item as Setter;
85  if (setter != null)
86  {
87  PropertyPath.SetNextValue(setter.Target, setter.Property, setter.Value);
88  }
89  }
90 
91  MainPlugin = dataContext.RenderPassPlugins.Select(x => x.Value).OfType<MainPlugin>().First();
92  MainTargetPlugin = dataContext.RenderPassPlugins.Select(x => x.Value).OfType<RenderTargetsPlugin>().FirstOrDefault(x => x.Name == "MainTargetPlugin");
93 
94  var mainBackBuffer = graphicsDevice.BackBuffer;
95  MainPlugin.RenderTarget = graphicsDevice.BackBuffer;
96 
97  // Depth Stencil target needs to be shader resource only if Yebis or GBuffer is active (need more robust way to decide)
98  var depthStencilTexture = Texture2D.New(graphicsDevice, mainBackBuffer.Width, mainBackBuffer.Height, PixelFormat.D32_Float,
99  (RenderConfigContext.RenderPassPlugins.Any(x => x.Value is YebisPlugin || x.Value is GBufferPlugin) ? TextureFlags.ShaderResource : 0) | TextureFlags.DepthStencil);
100  MainPlugin.DepthStencil = depthStencilTexture.ToDepthStencilBuffer(false);
101 
102  if (DepthStencilBuffer.IsReadOnlySupported(graphicsDevice))
103  MainPlugin.DepthStencilReadOnly = depthStencilTexture.ToDepthStencilBuffer(true);
104 
105  // TODO: Temporary setup (should be done through an Entity and its Manager)
106  HeatShimmerPlugin heatShimmerPlugin;
107  if (RenderConfigContext.RenderPassPlugins.TryGetValueCast("HeatShimmerPlugin", out heatShimmerPlugin))
108  {
109  throw new NotImplementedException();
110  //heatShimmerPlugin.BoundingBoxes.Add(new MeshData { MeshData = MeshDataHelper.CreateBox(1, 1, 1, Color.White, true), Parameters = new ParameterCollectionData { { TransformationKeys.World, Matrix.Scaling(8200, 3000, 1500) * Matrix.Translation(2700, 0, 300) } } });
111  //heatShimmerPlugin.BoundingBoxes.Add(new MeshData { MeshData = MeshDataHelper.CreateBox(1, 1, 1, Color.White, true), Parameters = new ParameterCollectionData { { TransformationKeys.World, Matrix.Scaling(2000, 2000, 3500) * Matrix.RotationZ(0.5f) * Matrix.Translation(-7000, -4000, 1500) } } });
112  //heatShimmerPlugin.BoundingBoxes.Add(new MeshData { MeshData = MeshDataHelper.CreateBox(1, 1, 1, Color.White, true), Parameters = new ParameterCollectionData { { TransformationKeys.World, Matrix.Scaling(2000, 3000, 3500) * Matrix.Translation(-7800, 900, 1500) } } });
113  }
114 
115  // Generates intermediate render targets
116  var plugins = dataContext.RenderPassPlugins
117  .OrderBy(x => rootRenderPass.Passes.IndexOf(x.Value.RenderPass)).ToArray();
118 
119  // Weave render targets from last to first plugin.
120  // TODO: Instead of guessing through interface and non-null/null values, it would be better if plugin had flags to inform of its intentions.
121  var currentTarget = mainBackBuffer;
122  for (int i = plugins.Length - 1; i >= 0; --i)
123  {
124  var plugin = plugins[i];
125 
126  var targetPlugin = plugin.Value as IRenderPassPluginTarget;
127  if (targetPlugin != null)
128  {
129  if (targetPlugin.RenderTarget == null)
130  targetPlugin.RenderTarget = currentTarget;
131 
132  currentTarget = targetPlugin.RenderTarget;
133  }
134 
135  var sourcePlugin = plugin.Value as IRenderPassPluginSource;
136  if (sourcePlugin != null)
137  {
138  if (sourcePlugin.RenderSource == null)
139  {
140  sourcePlugin.RenderSource = Texture2D.New(graphicsDevice, mainBackBuffer.Width, mainBackBuffer.Height, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
141  }
142 
143  currentTarget = sourcePlugin.RenderSource.ToRenderTarget();
144  }
145  }
146 
147  foreach (var plugin in dataContext.RenderPassPlugins)
148  {
149  renderSystem.RenderPassPlugins.Add(plugin.Value);
150  }
151 
152  foreach (var effectBuilder in effectConfig.Content.OfType<EffectBuilder>())
153  {
154  foreach (var plugin in effectBuilder.Plugins)
155  {
156  plugin.Services = registry;
157  }
158  this.effectSystemOld.Effects.Add(effectBuilder);
159  }
160 
161 #if PARADOX_YEBIS
162  YebisPlugin yebisPlugin;
163  if (RenderConfigContext.RenderPassPlugins.TryGetValueCast("YebisPlugin", out yebisPlugin))
164  {
165  yebisPlugin.AntiAlias = true;
166 
167  yebisPlugin.ToneMap.Gamma = 2.2f;
168  yebisPlugin.ToneMap.Type = ToneMapType.SensiToMetric;
169  yebisPlugin.ToneMap.AutoExposure.Enable = true;
170  yebisPlugin.ToneMap.AutoExposure.MiddleGray = 0.25f;
171  yebisPlugin.ToneMap.AutoExposure.AdaptationSensitivity = 0.5f;
172  yebisPlugin.ToneMap.AutoExposure.AdaptationScale = 0.8f;
173  yebisPlugin.ToneMap.AutoExposure.AdaptationSpeedLimit = 4.0f;
174  yebisPlugin.ToneMap.AutoExposure.DarkAdaptationSensitivity = 0.9f;
175  yebisPlugin.ToneMap.AutoExposure.DarkAdaptationScale = 0.6f;
176  yebisPlugin.ToneMap.AutoExposure.DarkAdaptationSpeedLimit = 4.0f;
177  yebisPlugin.ToneMap.AutoExposure.LightDarkExposureBorder = 1.0f;
178 
179  yebisPlugin.Glare.Enable = true;
180  //yebisPlugin.Glare.RemapFactor = 1.0f;
181  //yebisPlugin.Glare.Threshold = 0.0f;
182 
183  yebisPlugin.Lens.Vignette.Enable = true;
184 
185  yebisPlugin.Lens.Distortion.Enable = false;
186  yebisPlugin.Lens.Distortion.Power = 0.2f;
187  yebisPlugin.Lens.Distortion.EdgeSmoothness = 0.2f;
188 
189  yebisPlugin.DepthOfField.Enable = true;
190  yebisPlugin.DepthOfField.AutoFocus = true;
191  yebisPlugin.DepthOfField.Aperture = 2.0f;
192  yebisPlugin.DepthOfField.ImageSensorHeight = 40.0f;
193 
194  //yebisPlugin.ColorCorrection.ColorTemperature = 4500;
195 
196  yebisPlugin.HeatShimmer.Enable = false;
197  //YebisPlugin.LightShaft.Enable = true;
198  //YebisPlugin.LightShaft.ScreenPosition = new Vector2(0.5f, 0.1f);
199  }
200 #endif
201 
202  // Adds the particle system if the ParticlePlugin is used in the config
203  ParticlePlugin particlePlugin;
204  if (RenderConfigContext.RenderPassPlugins.TryGetValueCast("ParticlePlugin", out particlePlugin))
205  {
206  var particleSystem = new ParticleProcessor(particlePlugin);
207  entitySystem.Processors.Add(particleSystem);
208  }
209  }
210 
211  public bool ToggleWireframe()
212  {
213  RenderTargetsPlugin wireframePlugin;
214  if (RenderConfigContext.RenderPassPlugins.TryGetValueCast("WireframePlugin", out wireframePlugin))
215  return wireframePlugin.RenderPass.Enabled = !wireframePlugin.RenderPass.Enabled;
216 
217  return false;
218  }
219 
220  public void RegisterLighting()
221  {
222  if (lightingRegistered)
223  return;
224 
225  lightingRegistered = true;
226 
227  // Add LightProcessor if used in effect config file
228  LightingPrepassPlugin lightingPrepassPlugin;
229  LightingPlugin lightingPlugin;
230  RenderConfigContext.RenderPassPlugins.TryGetValueCast("LightingPrepassPlugin", out lightingPrepassPlugin);
231  RenderConfigContext.RenderPassPlugins.TryGetValueCast("LightingPlugin", out lightingPlugin);
232  if (lightingPrepassPlugin != null || lightingPlugin != null)
233  {
234  RenderTargetsPlugin editorTargetPlugin;
235  RenderConfigContext.RenderPassPlugins.TryGetValueCast("EditorTargetPlugin", out editorTargetPlugin);
236  var lightProcessor = new LightProcessor(lightingPlugin, editorTargetPlugin, lightingPrepassPlugin != null ? lightingPrepassPlugin.Lights : null, false);
237  entitySystem.Processors.Add(lightProcessor);
238 
239  // LightShafts enabled?
240  RenderPass lightShaftsPass;
241  if (RenderConfigContext.RenderPasses.TryGetValue("LightShaftsPass", out lightShaftsPass))
242  entitySystem.Processors.Add(new LightShaftsProcessor(MainPlugin, MainTargetPlugin, lightShaftsPass));
243 
244  entitySystem.Processors.Add(new LightReceiverProcessor(lightProcessor));
245  }
246  }
247  }
248 }
Service providing method to access GraphicsDevice life-cycle.
void Initialize(IServiceRegistry registry, string effectFilename=null, string[] optionalFeatures=null)
SiliconStudio.Core.IServiceRegistry IServiceRegistry
Definition: ModelRenderer.cs:9
Plugin used to render to a GBuffer from a MainPlugin.
TODO: Update summary.
static readonly RenderingSetup Singleton
Plugin used for the main rendering view.
Definition: MainPlugin.cs:15
Level10 render pass using a depth buffer and a render target.
RenderTargetsPlugin MainTargetPlugin
RenderPass is a hierarchy that defines how to collect and render meshes.
Definition: RenderPass.cs:19