예제 #1
0
        /// <inheritdoc/>
        public override unsafe void Prepare(RenderDrawContext context)
        {
            var blendValue   = (selectionService?.DisplaySelectionMask ?? false) ? 1.0f : MathUtil.Clamp((1.0f - (float)clockSelection.Elapsed.TotalSeconds) / 1.0f, 0, 1);
            var perDrawValue = new PerDraw
            {
                FrontColor = ((Color3)Color.FromBgra(0xFFFFDC51)).ToColorSpace(Context.GraphicsDevice.ColorSpace),
                BackColor  = ((Color3)Color.FromBgra(0xFFFF8300)).ToColorSpace(Context.GraphicsDevice.ColorSpace),
                ColorBlend = 0.3f * blendValue,
                AlphaBlend = 0.1f * blendValue
            };

            foreach (var renderNode in ((RootEffectRenderFeature)RootRenderFeature).RenderNodes)
            {
                var perDrawLayout = renderNode.RenderEffect.Reflection?.PerDrawLayout;
                if (perDrawLayout == null)
                {
                    continue;
                }

                var perDrawDataOffset = perDrawLayout.GetConstantBufferOffset(this.perDrawData);
                if (perDrawDataOffset == -1)
                {
                    continue;
                }

                var mappedCB = renderNode.Resources.ConstantBuffer.Data;
                var perDraw  = (PerDraw *)((byte *)mappedCB + perDrawDataOffset);
                *   perDraw  = perDrawValue;
            }
        }
        /// <param name="context"></param>
        /// <inheritdoc/>
        public unsafe override void Prepare(RenderDrawContext context)
        {
            // Compute WorldView, WorldViewProj
            var renderModelObjectInfoData = RootRenderFeature.RenderData.GetData(renderModelObjectInfoKey);
            var renderModelViewInfoData = RootRenderFeature.RenderData.GetData(renderModelViewInfoKey);

            // Update PerFrame (time)
            // TODO Move that to RootEffectRenderFeature?
            foreach (var frameLayout in ((RootEffectRenderFeature)RootRenderFeature).FrameLayouts)
            {
                var timeOffset = frameLayout.GetConstantBufferOffset(time);
                if (timeOffset == -1)
                    continue;

                var resourceGroup = frameLayout.Entry.Resources;
                var mappedCB = resourceGroup.ConstantBuffer.Data;

                var perFrameTime = (PerFrameTime*)((byte*)mappedCB + timeOffset);
                perFrameTime->Time = (float)Context.Time.Total.TotalSeconds;
                perFrameTime->TimeStep = (float)Context.Time.Elapsed.TotalSeconds;
            }

            // Update PerView (View, Proj, etc...)
            for (int index = 0; index < RenderSystem.Views.Count; index++)
            {
                var view = RenderSystem.Views[index];
                var viewFeature = view.Features[RootRenderFeature.Index];

                // Compute WorldView and WorldViewProjection
                Dispatcher.ForEach(viewFeature.ViewObjectNodes, renderPerViewNodeReference =>
                {
                    var renderPerViewNode = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference);
                    var renderModelFrameInfo = renderModelObjectInfoData[renderPerViewNode.ObjectNode];

                    var renderModelViewInfo = new RenderModelViewInfo();
                    Matrix.Multiply(ref renderModelFrameInfo.World, ref view.View, out renderModelViewInfo.WorldView);
                    Matrix.Multiply(ref renderModelFrameInfo.World, ref view.ViewProjection, out renderModelViewInfo.WorldViewProjection);

                    // TODO: Use ref locals or Utilities instead, to avoid double copy
                    renderModelViewInfoData[renderPerViewNodeReference] = renderModelViewInfo;
                });

                // Copy ViewProjection to PerView cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var viewProjectionOffset = viewLayout.GetConstantBufferOffset(this.view);
                    if (viewProjectionOffset == -1)
                        continue;

                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB = resourceGroup.ConstantBuffer.Data;

                    var perView = (PerView*)((byte*)mappedCB + viewProjectionOffset);

                    // Fill PerView
                    perView->View = view.View;
                    Matrix.Invert(ref view.View, out perView->ViewInverse);
                    perView->Projection = view.Projection;
                    Matrix.Invert(ref view.Projection, out perView->ProjectionInverse);
                    perView->ViewProjection = view.ViewProjection;
                    perView->ProjScreenRay = new Vector2(-1.0f / view.Projection.M11, 1.0f / view.Projection.M22);
                    // TODO GRAPHICS REFACTOR avoid cbuffer read
                    perView->Eye = new Vector4(perView->ViewInverse.M41, perView->ViewInverse.M42, perView->ViewInverse.M43, 1.0f);
                }

                // Copy Camera to PerView cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var cameraOffset = viewLayout.GetConstantBufferOffset(camera);
                    if (cameraOffset == -1)
                        continue;

                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB = resourceGroup.ConstantBuffer.Data;

                    var perViewCamera = (PerViewCamera*)((byte*)mappedCB + cameraOffset);

                    perViewCamera->NearClipPlane = view.NearClipPlane;
                    perViewCamera->FarClipPlane = view.FarClipPlane;
                    perViewCamera->ZProjection = CameraKeys.ZProjectionACalculate(view.NearClipPlane, view.FarClipPlane);
                    perViewCamera->ViewSize = view.ViewSize;
                    perViewCamera->AspectRatio = view.ViewSize.X / Math.Max(view.ViewSize.Y, 1.0f);
                }
            }

            // Update PerDraw (World, WorldViewProj, etc...)
            // Copy Entity.World to PerDraw cbuffer
            // TODO: Have a PerObject cbuffer?
            Dispatcher.ForEach(((RootEffectRenderFeature)RootRenderFeature).RenderNodes, (ref RenderNode renderNode) =>
            {
                var perDrawLayout = renderNode.RenderEffect.Reflection.PerDrawLayout;
                if (perDrawLayout == null)
                    return;

                var worldOffset = perDrawLayout.GetConstantBufferOffset(this.world);
                if (worldOffset == -1)
                    return;

                var renderModelObjectInfo = renderModelObjectInfoData[renderNode.RenderObject.ObjectNode];
                var renderModelViewInfo = renderModelViewInfoData[renderNode.ViewObjectNode];

                var mappedCB = renderNode.Resources.ConstantBuffer.Data;
                var perDraw = (PerDraw*)((byte*)mappedCB + worldOffset);


                // Fill PerDraw
                var perDrawData = new PerDraw
                {
                    World = renderModelObjectInfo.World,
                    WorldView = renderModelViewInfo.WorldView,
                    WorldViewProjection = renderModelViewInfo.WorldViewProjection
                };

                Matrix.Invert(ref renderModelObjectInfo.World, out perDrawData.WorldInverse);
                Matrix.Transpose(ref perDrawData.WorldInverse, out perDrawData.WorldInverseTranspose);
                Matrix.Invert(ref renderModelViewInfo.WorldView, out perDrawData.WorldViewInverse);

                perDrawData.WorldScale = new Vector3(
                    ((Vector3)renderModelObjectInfo.World.Row1).Length(),
                    ((Vector3)renderModelObjectInfo.World.Row2).Length(),
                    ((Vector3)renderModelObjectInfo.World.Row3).Length());
                
                perDrawData.EyeMS = new Vector4(perDrawData.WorldInverse.M41, perDrawData.WorldInverse.M42, perDrawData.WorldInverse.M43, 1.0f);

                *perDraw = perDrawData;
            });
        }
        /// <param name="context"></param>
        /// <inheritdoc/>
        public unsafe override void Prepare(RenderDrawContext context)
        {
            // Compute WorldView, WorldViewProj
            var renderModelObjectInfoData = RootRenderFeature.RenderData.GetData(renderModelObjectInfoKey);
            var renderModelViewInfoData   = RootRenderFeature.RenderData.GetData(renderModelViewInfoKey);

            // Update PerFrame (time)
            // TODO Move that to RootEffectRenderFeature?
            foreach (var frameLayout in ((RootEffectRenderFeature)RootRenderFeature).FrameLayouts)
            {
                var timeOffset = frameLayout.GetConstantBufferOffset(time);
                if (timeOffset == -1)
                {
                    continue;
                }

                var resourceGroup = frameLayout.Entry.Resources;
                var mappedCB      = resourceGroup.ConstantBuffer.Data;

                var perFrameTime = (PerFrameTime *)((byte *)mappedCB + timeOffset);
                perFrameTime->Time     = (float)Context.Time.Total.TotalSeconds;
                perFrameTime->TimeStep = (float)Context.Time.Elapsed.TotalSeconds;
            }

            // Update PerView (View, Proj, etc...)
            for (int index = 0; index < RenderSystem.Views.Count; index++)
            {
                var view        = RenderSystem.Views[index];
                var viewFeature = view.Features[RootRenderFeature.Index];

                // Compute WorldView and WorldViewProjection
                Dispatcher.ForEach(viewFeature.ViewObjectNodes, renderPerViewNodeReference =>
                {
                    var renderPerViewNode    = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference);
                    var renderModelFrameInfo = renderModelObjectInfoData[renderPerViewNode.ObjectNode];

                    var renderModelViewInfo = new RenderModelViewInfo();
                    Matrix.Multiply(ref renderModelFrameInfo.World, ref view.View, out renderModelViewInfo.WorldView);
                    Matrix.Multiply(ref renderModelFrameInfo.World, ref view.ViewProjection, out renderModelViewInfo.WorldViewProjection);

                    // TODO: Use ref locals or Utilities instead, to avoid double copy
                    renderModelViewInfoData[renderPerViewNodeReference] = renderModelViewInfo;
                });

                // Copy ViewProjection to PerView cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var viewProjectionOffset = viewLayout.GetConstantBufferOffset(this.view);
                    if (viewProjectionOffset == -1)
                    {
                        continue;
                    }

                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB      = resourceGroup.ConstantBuffer.Data;

                    var perView = (PerView *)((byte *)mappedCB + viewProjectionOffset);

                    // Fill PerView
                    perView->View = view.View;
                    Matrix.Invert(ref view.View, out perView->ViewInverse);
                    perView->Projection = view.Projection;
                    Matrix.Invert(ref view.Projection, out perView->ProjectionInverse);
                    perView->ViewProjection = view.ViewProjection;
                    perView->ProjScreenRay  = new Vector2(-1.0f / view.Projection.M11, 1.0f / view.Projection.M22);
                    // TODO GRAPHICS REFACTOR avoid cbuffer read
                    perView->Eye = new Vector4(perView->ViewInverse.M41, perView->ViewInverse.M42, perView->ViewInverse.M43, 1.0f);
                }

                // Copy Camera to PerView cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var cameraOffset = viewLayout.GetConstantBufferOffset(camera);
                    if (cameraOffset == -1)
                    {
                        continue;
                    }

                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB      = resourceGroup.ConstantBuffer.Data;

                    var perViewCamera = (PerViewCamera *)((byte *)mappedCB + cameraOffset);

                    perViewCamera->NearClipPlane = view.NearClipPlane;
                    perViewCamera->FarClipPlane  = view.FarClipPlane;
                    perViewCamera->ZProjection   = CameraKeys.ZProjectionACalculate(view.NearClipPlane, view.FarClipPlane);
                    perViewCamera->ViewSize      = view.ViewSize;
                    perViewCamera->AspectRatio   = view.ViewSize.X / Math.Max(view.ViewSize.Y, 1.0f);
                }
            }

            // Update PerDraw (World, WorldViewProj, etc...)
            // Copy Entity.World to PerDraw cbuffer
            // TODO: Have a PerObject cbuffer?
            Dispatcher.ForEach(((RootEffectRenderFeature)RootRenderFeature).RenderNodes, (ref RenderNode renderNode) =>
            {
                var perDrawLayout = renderNode.RenderEffect.Reflection.PerDrawLayout;
                if (perDrawLayout == null)
                {
                    return;
                }

                var worldOffset = perDrawLayout.GetConstantBufferOffset(this.world);
                if (worldOffset == -1)
                {
                    return;
                }

                var renderModelObjectInfo = renderModelObjectInfoData[renderNode.RenderObject.ObjectNode];
                var renderModelViewInfo   = renderModelViewInfoData[renderNode.ViewObjectNode];

                var mappedCB = renderNode.Resources.ConstantBuffer.Data;
                var perDraw  = (PerDraw *)((byte *)mappedCB + worldOffset);


                // Fill PerDraw
                var perDrawData = new PerDraw
                {
                    World               = renderModelObjectInfo.World,
                    WorldView           = renderModelViewInfo.WorldView,
                    WorldViewProjection = renderModelViewInfo.WorldViewProjection
                };

                Matrix.Invert(ref renderModelObjectInfo.World, out perDrawData.WorldInverse);
                Matrix.Transpose(ref perDrawData.WorldInverse, out perDrawData.WorldInverseTranspose);
                Matrix.Invert(ref renderModelViewInfo.WorldView, out perDrawData.WorldViewInverse);

                perDrawData.WorldScale = new Vector3(
                    ((Vector3)renderModelObjectInfo.World.Row1).Length(),
                    ((Vector3)renderModelObjectInfo.World.Row2).Length(),
                    ((Vector3)renderModelObjectInfo.World.Row3).Length());

                perDrawData.EyeMS = new Vector4(perDrawData.WorldInverse.M41, perDrawData.WorldInverse.M42, perDrawData.WorldInverse.M43, 1.0f);

                *perDraw = perDrawData;
            });
        }