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); })); }