public override void Load()
{
base.Load();
if (OfflineCompilation)
return;
var renderTargets = new RenderTarget[2];
DepthStencilBuffer depthStencilBuffer = null;
Texture2D depthStencilTexture = null;
Parameters.AddSources(MainPlugin.ViewParameters);
Parameters.RegisterParameter(EffectPlugin.BlendStateKey);
var filteredPasses = new FastList<RenderPass>();
RenderPass.UpdatePasses += updatePassesAction = (RenderPass currentRenderPass, ref FastList<RenderPass> currentPasses) =>
{
var originalPasses = currentPasses;
filteredPasses.Clear();
currentPasses = filteredPasses;
Parameters.Set(PickingFrameIndex, ++currentPickingFrameIndex);
Request[] requests;
lock (pendingRequests)
{
// No picking request or no mesh to pick?
if (pendingRequests.Count == 0)
return;
requests = pendingRequests.ToArray();
pendingRequests.Clear();
}
foreach (var request in requests)
{
requestResults.Add(request);
}
if (originalPasses == null)
return;
// Count mesh passes
int meshIndex = 0;
foreach (var pass in originalPasses)
{
meshIndex += pass.Passes.Count;
}
// No mesh to pick?
if (meshIndex == 0)
return;
// Copy mesh passes and assign indices
var meshPasses = new EffectMesh[meshIndex];
meshIndex = 0;
foreach (var pass in RenderPass.Passes)
{
throw new NotImplementedException();
//foreach (var effectMeshPass in pass.Meshes)
//{
// meshPasses[meshIndex] = (EffectMesh)effectMeshPass;
// // Prefix increment so that 0 means no rendering.
// effectMeshPass.Parameters.Set(PickingMeshIndex, ++meshIndex);
//}
}
// For now, it generates one rendering per picking.
// It would be quite easy to optimize it by make Picking shader works on multiple picking points at a time.
foreach (var request in requests)
{
var pickingRenderPass = new RenderPass("Picking");
pickingRenderPass.StartPass.AddFirst = (threadContext) =>
{
threadContext.GraphicsDevice.Clear(renderTargets[0], Color.Black);
threadContext.GraphicsDevice.Clear(renderTargets[1], Color.Black);
threadContext.Parameters.Set(PickingScreenPosition, request.Location);
threadContext.GraphicsDevice.SetViewport(new Viewport(0, 0, renderTargets[0].Description.Width, renderTargets[0].Description.Height));
threadContext.GraphicsDevice.Clear(depthStencilBuffer, DepthStencilClearOptions.DepthBuffer);
threadContext.GraphicsDevice.SetRenderTargets(depthStencilBuffer, renderTargets);
};
pickingRenderPass.EndPass.AddLast = (threadContext) =>
{
threadContext.Parameters.Reset(PickingScreenPosition);
threadContext.GraphicsDevice.Copy(renderTargets[0].Texture, request.ResultTextures[0]);
threadContext.GraphicsDevice.Copy(renderTargets[1].Texture, request.ResultTextures[1]);
};
//pickingRenderPass.PassesInternal = originalPasses;
throw new NotImplementedException();
request.MeshPasses = meshPasses;
currentPasses.Add(pickingRenderPass);
request.HasResults = true;
// Wait 2 frames before pulling the results.
request.FrameCounter = 2;
}
};
RenderSystem.GlobalPass.EndPass.AddLast = CheckPickingResults;
var backBuffer = GraphicsDevice.BackBuffer;
int pickingArea = 1 + PickingDistance * 2;
renderTargets[0] = Texture.New2D(GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32_UInt, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget().KeepAliveBy(ActiveObjects);
renderTargets[1] = Texture.New2D(GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32G32B32A32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget().KeepAliveBy(ActiveObjects);
depthStencilTexture = Texture.New2D(GraphicsDevice, pickingArea, pickingArea, PixelFormat.D32_Float, TextureFlags.ShaderResource | TextureFlags.DepthStencil).KeepAliveBy(ActiveObjects);
depthStencilBuffer = depthStencilTexture.ToDepthStencilBuffer(false);
Parameters.AddDynamic(PickingMatrix, ParameterDynamicValue.New(PickingScreenPosition, (ref Vector2 pickingPosition, ref Matrix picking) =>
{
// Move center to picked position, and zoom (it is supposed to stay per-pixel according to render target size)
picking = Matrix.Translation(1.0f - (pickingPosition.X) / backBuffer.Width * 2.0f, -1.0f + (pickingPosition.Y) / backBuffer.Height * 2.0f, 0.0f)
* Matrix.Scaling((float)backBuffer.Width / (float)pickingArea, (float)backBuffer.Height / (float)pickingArea, 1.0f);
}));
}