コード例 #1
0
        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);
            }));
        }