2 using System.Collections.Generic;
5 using System.Threading.Tasks;
6 using SiliconStudio.Paradox.Effects.Modules;
7 using SiliconStudio.Paradox.EntityModel;
8 using SiliconStudio.Paradox.Games;
9 using SiliconStudio.Paradox.Graphics;
10 using SiliconStudio.Core;
11 using SiliconStudio.Core.Collections;
12 using SiliconStudio.Core.Mathematics;
14 namespace SiliconStudio.
Paradox.Effects
18 private UpdatePassesDelegate updatePassesAction;
27 private HashSet<Request> requestResults =
new HashSet<Request>();
28 private List<Request> pendingRequests =
new List<Request>();
29 private int currentPickingFrameIndex;
39 public int PickingDistance {
get; set; }
41 public override void Load()
45 if (OfflineCompilation)
52 Parameters.AddSources(MainPlugin.ViewParameters);
54 Parameters.RegisterParameter(EffectPlugin.BlendStateKey);
56 var filteredPasses =
new FastList<RenderPass>();
58 RenderPass.UpdatePasses += updatePassesAction = (
RenderPass currentRenderPass, ref FastList<RenderPass> currentPasses) =>
60 var originalPasses = currentPasses;
61 filteredPasses.Clear();
62 currentPasses = filteredPasses;
64 Parameters.Set(PickingFrameIndex, ++currentPickingFrameIndex);
67 lock (pendingRequests)
70 if (pendingRequests.Count == 0)
73 requests = pendingRequests.ToArray();
74 pendingRequests.Clear();
77 foreach (var request
in requests)
79 requestResults.Add(request);
82 if (originalPasses == null)
87 foreach (var pass
in originalPasses)
89 meshIndex += pass.Passes.Count;
97 var meshPasses =
new EffectMesh[meshIndex];
101 throw new NotImplementedException();
112 foreach (var request
in requests)
114 var pickingRenderPass =
new RenderPass(
"Picking");
116 pickingRenderPass.StartPass.AddFirst = (threadContext) =>
118 threadContext.GraphicsDevice.Clear(renderTargets[0], Color.Black);
119 threadContext.GraphicsDevice.Clear(renderTargets[1], Color.Black);
120 threadContext.Parameters.Set(PickingScreenPosition, request.Location);
121 threadContext.GraphicsDevice.SetViewport(
new Viewport(0, 0, renderTargets[0].Description.Width, renderTargets[0].Description.Height));
123 threadContext.GraphicsDevice.Clear(depthStencilBuffer, DepthStencilClearOptions.DepthBuffer);
124 threadContext.GraphicsDevice.SetRenderTargets(depthStencilBuffer, renderTargets);
126 pickingRenderPass.EndPass.AddLast = (threadContext) =>
128 threadContext.Parameters.Reset(PickingScreenPosition);
129 threadContext.GraphicsDevice.Copy(renderTargets[0]
.Texture, request.ResultTextures[0]);
130 threadContext.GraphicsDevice.Copy(renderTargets[1]
.Texture, request.ResultTextures[1]);
133 throw new NotImplementedException();
135 request.MeshPasses = meshPasses;
137 currentPasses.Add(pickingRenderPass);
139 request.HasResults =
true;
142 request.FrameCounter = 2;
146 RenderSystem.GlobalPass.EndPass.AddLast = CheckPickingResults;
148 var backBuffer = GraphicsDevice.BackBuffer;
150 int pickingArea = 1 + PickingDistance * 2;
151 renderTargets[0] = Texture2D.New(
GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32_UInt, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget().KeepAliveBy(ActiveObjects);
152 renderTargets[1] = Texture2D.New(GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32G32B32A32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget().KeepAliveBy(ActiveObjects);
154 depthStencilTexture = Texture2D.New(GraphicsDevice, pickingArea, pickingArea, PixelFormat.D32_Float, TextureFlags.ShaderResource | TextureFlags.DepthStencil).KeepAliveBy(ActiveObjects);
155 depthStencilBuffer = depthStencilTexture.ToDepthStencilBuffer(
false);
157 Parameters.AddDynamic(PickingMatrix, ParameterDynamicValue.New(PickingScreenPosition, (ref
Vector2 pickingPosition, ref
Matrix picking) =>
160 picking = Matrix.Translation(1.0f - (pickingPosition.X) / backBuffer.Width * 2.0f, -1.0f + (pickingPosition.Y) / backBuffer.Height * 2.0f, 0.0f)
161 *
Matrix.
Scaling((
float)backBuffer.Width / (
float)pickingArea, (
float)backBuffer.Height / (
float)pickingArea, 1.0f);
167 if (!OfflineCompilation)
169 RenderPass.UpdatePasses = (UpdatePassesDelegate)Delegate.Remove(
RenderPass.UpdatePasses, updatePassesAction);
170 Parameters.RemoveSource(MainPlugin.ViewParameters);
171 RenderSystem.GlobalPass.EndPass -= CheckPickingResults;
177 private unsafe
void CheckPickingResults(ThreadContext threadContext)
179 if (requestResults.Count == 0)
182 foreach (var request
in requestResults.ToArray())
184 if (request.HasResults)
186 if (--request.FrameCounter > 0)
232 request.PickedMesh = null;
233 request.PickedPosition =
new Vector3(
float.NaN,
float.NaN,
float.NaN);
236 request.MeshPasses = null;
238 request.ResultTextures[0].Release();
239 request.ResultTextures[1].Release();
241 request.TaskCompletionSource.SetResult(
true);
243 requestResults.Remove(request);
249 var request =
new Request();
250 request.Location = location;
253 int pickingArea = 1 + PickingDistance * 2;
254 request.ResultTextures =
new Texture2D[2];
255 request.ResultTextures[0] = Texture2D.New(
GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32_UInt, TextureFlags.None, usage: GraphicsResourceUsage.Staging);
256 request.ResultTextures[0].Name =
"PickingTextureStaging";
258 request.ResultTextures[1] = Texture2D.New(GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32G32B32A32_Float, TextureFlags.None, usage: GraphicsResourceUsage.Staging);
259 request.ResultTextures[1].Name =
"PickingTextureStaging";
261 request.ResultTextures[0].AddReference();
262 request.ResultTextures[1].AddReference();
264 lock (pendingRequests)
266 pendingRequests.Add(request);
272 return new Result { EffectMesh = request.PickedMesh, Position = request.PickedPosition };
275 private class Request
277 public int FrameCounter;
278 public bool HasResults;
281 public TaskCompletionSource<bool> TaskCompletionSource =
new TaskCompletionSource<bool>();
282 public EffectMesh[] MeshPasses;
283 public EffectMesh PickedMesh;
Key of an effect parameter.
Represents a two dimensional mathematical vector.
A renderable texture view.
static void Scaling(ref Vector3 scale, out Matrix result)
Creates a matrix that scales along the x-axis, y-axis, and y-axis.
async Task< Result > Pick(Vector2 location)
Represents a three dimensional mathematical vector.
System.Threading.Tasks.Task Task
Performs primitive-based rendering, creates resources, handles system-level variables, adjusts gamma ramp levels, and creates shaders. See The+GraphicsDevice+class to learn more about the class.
Defines the window dimensions of a render-target surface onto which a 3D volume projects.
Plugin used for the main rendering view.
A Texture 2D frontend to SharpDX.Direct3D11.Texture2D.
SiliconStudio.Core.Mathematics.Vector3 Vector3
RenderPass is a hierarchy that defines how to collect and render meshes.
A class that represents a tag propety.
Base class for texture resources.
Represents a 4x4 mathematical matrix.