예제 #1
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
        {
            var graphicsDevice = context.GraphicsDevice;
            var destination    = new RectangleF(0, 0, 1, 1);

            // find the last background to display with valid texture
            BackgroundComponent background = null;

            for (var i = toIndex; i >= fromIndex; --i)
            {
                background = (BackgroundComponent)renderItems[i].DrawContext;
                if (background.Texture != null)
                {
                    break;
                }
            }

            // Abort if not valid background component
            if (background == null || background.Texture == null)
            {
                return;
            }

            var texture             = background.Texture;
            var target              = CurrentRenderFrame;
            var imageBufferMinRatio = Math.Min(texture.ViewWidth / (float)target.Width, texture.ViewHeight / (float)target.Height);
            var sourceSize          = new Vector2(target.Width * imageBufferMinRatio, target.Height * imageBufferMinRatio);
            var source              = new RectangleF((texture.ViewWidth - sourceSize.X) / 2, (texture.ViewHeight - sourceSize.Y) / 2, sourceSize.X, sourceSize.Y);

            spriteBatch.Parameters.Add(BackgroundEffectKeys.Intensity, background.Intensity);
            spriteBatch.Begin(SpriteSortMode.FrontToBack, graphicsDevice.BlendStates.Opaque, graphicsDevice.SamplerStates.LinearClamp, graphicsDevice.DepthStencilStates.None, null, backgroundEffect);
            spriteBatch.Draw(texture, destination, source, Color.White, 0, Vector2.Zero);
            spriteBatch.End();
        }
예제 #2
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItemList, int fromIndex, int toIndex)
        {
            // Get all meshes from render models
            meshesToRender.Clear();
            for (int i = fromIndex; i <= toIndex; i++)
            {
                meshesToRender.Add((RenderMesh)renderItemList[i].DrawContext);
            }

            // Slow path there is a callback
            if (Callbacks.UpdateMeshes != null)
            {
                Callbacks.UpdateMeshes(context, meshesToRender);
            }

            // Fetch callback on PreRenderGroup
            var preRenderMesh = Callbacks.PreRenderMesh;

            foreach (var mesh in meshesToRender)
            {
                // If the EntityGroup is changing, call the callback to allow to plug specific parameters for this group
                if (preRenderMesh != null)
                {
                    preRenderMesh(context, mesh);
                }

                // Update Effect and mesh
                UpdateEffect(context, mesh, context.Parameters);

                // Draw the mesh
                mesh.Draw(context);
            }
        }
예제 #3
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
        {
            var graphicsDevice = context.GraphicsDevice;
            var destination    = new RectangleF(0, 0, 1, 1);

            spriteBatch.Begin(SpriteSortMode.FrontToBack, graphicsDevice.BlendStates.Opaque, graphicsDevice.SamplerStates.LinearClamp, graphicsDevice.DepthStencilStates.None);

            for (var i = fromIndex; i <= toIndex; ++i)
            {
                var background = (BackgroundComponent)renderItems[i].DrawContext;
                var texture    = background.Texture;
                if (texture == null)
                {
                    continue;
                }

                var target = CurrentRenderFrame;

                var imageBufferMinRatio = Math.Min(texture.ViewWidth / (float)target.Width, texture.ViewHeight / (float)target.Height);
                var sourceSize          = new Vector2(target.Width * imageBufferMinRatio, target.Height * imageBufferMinRatio);
                var source = new RectangleF((texture.ViewWidth - sourceSize.X) / 2, (texture.ViewHeight - sourceSize.Y) / 2, sourceSize.X, sourceSize.Y);

                spriteBatch.Draw(texture, destination, source, Color.White, 0, Vector2.Zero);
            }

            spriteBatch.End();
        }
예제 #4
0
        protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            var cameraState = context.GetCurrentCamera();

            if (cameraState == null)
                return;

            UpdateParameters(context, cameraState);
        }
예제 #5
0
 public void Draw(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
 {
     if (Enabled)
     {
         PreDrawCoreInternal(context);
         DrawCore(context, renderItems, fromIndex, toIndex);
         PostDrawCoreInternal(context);
     }
 }
        public void Prepare(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            if (Context == null)
            {
                Initialize(context);
            }
            else if (Context != context)
            {
                throw new InvalidOperationException("Cannot use a different context between Load and Draw");
            }

            PrepareCore(context, opaqueList, transparentList);
        }
예제 #7
0
        protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            var uiProcessor = SceneInstance.GetProcessor <UIComponentProcessor>();

            if (uiProcessor == null)
            {
                return;
            }

            foreach (var uiRoot in uiProcessor.UIRoots)
            {
                // Perform culling on group and accept
                if (!CurrentCullingMask.Contains(uiRoot.UIComponent.Entity.Group))
                {
                    continue;
                }

                // skips empty UI elements
                if (uiRoot.UIComponent.RootElement == null)
                {
                    continue;
                }

                // Project the position
                // TODO: This code is duplicated from SpriteComponent -> unify it at higher level?
                var worldPosition = new Vector4(uiRoot.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                float projectedZ;
                if (uiRoot.UIComponent.IsFullScreen)
                {
                    projectedZ = -uiRoot.TransformComponent.WorldMatrix.M43;
                }
                else
                {
                    Vector4 projectedPosition;
                    var     cameraComponent = context.Tags.Get(CameraComponentRenderer.Current);
                    if (cameraComponent == null)
                    {
                        continue;
                    }

                    Vector4.Transform(ref worldPosition, ref cameraComponent.ViewProjectionMatrix, out projectedPosition);
                    projectedZ = projectedPosition.Z / projectedPosition.W;
                }

                transparentList.Add(new RenderItem(this, uiRoot, projectedZ));
            }
        }
예제 #8
0
        private void Draw(RenderContext context, RenderItemCollection renderItems, IComparer <RenderItem> comparer)
        {
            // Early exit
            if (renderItems.Count == 0)
            {
                return;
            }

            // Sort the list
            renderItems.Sort(comparer);

            var renderer  = renderItems[0].Renderer;
            int fromIndex = 0;
            var lastIndex = renderItems.Count - 1;

            for (int i = 0; i < renderItems.Count; i++)
            {
                var  renderItem    = renderItems[i];
                bool isNewRenderer = !ReferenceEquals(renderItem.Renderer, renderer);
                bool isLastIndex   = i == lastIndex;

                if (isLastIndex)
                {
                    if (isNewRenderer)
                    {
                        DrawRendererInternal(context, renderer, renderItems, fromIndex, i - 1);

                        context.GraphicsDevice.ResetStates();

                        DrawRendererInternal(context, renderItem.Renderer, renderItems, lastIndex, lastIndex);
                    }
                    else
                    {
                        DrawRendererInternal(context, renderer, renderItems, fromIndex, lastIndex);
                    }
                }
                else if (isNewRenderer)
                {
                    DrawRendererInternal(context, renderer, renderItems, fromIndex, i - 1);
                    fromIndex = i;
                }


                renderer = renderItem.Renderer;
            }
        }
예제 #9
0
        protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // If EffectName is not setup, exit
            if (effectName == null)
            {
                return;
            }

            if (dynamicEffectCompiler == null)
            {
                dynamicEffectCompiler = new DynamicEffectCompiler(Services, effectName);
            }

            // If we don't have yet a render slot, create a new one
            if (modelRenderSlot < 0)
            {
                var pipelineModelState = GetOrCreateModelRendererState(context);

                // Allocate (or reuse) a slot for the pass of this processor
                // Note: The slot is passed as out, so that when ModelRendererState.ModelSlotAdded callback is fired,
                // ModelRenderer.modelRenderSlot is valid (it might call PrepareModelForRendering recursively).
                modelRenderSlot = pipelineModelState.AllocateModelSlot(EffectName);
            }

            if (UseCustomRenderModelList)
            {
                PrepareModels(context, CustomRenderModelList, opaqueList, transparentList);
            }
            else
            {
                // Get all meshes from the render model processor
                var modelProcessor = SceneInstance.GetProcessor <ModelProcessor>();
                foreach (var renderModelGroup in modelProcessor.ModelGroups)
                {
                    // Perform culling on group and accept
                    if (!CurrentCullingMask.Contains(renderModelGroup.Group))
                    {
                        continue;
                    }

                    PrepareModels(context, renderModelGroup, opaqueList, transparentList);
                }
            }
        }
예제 #10
0
        protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            spriteProcessor = SceneInstance.GetProcessor <SpriteProcessor>();
            if (spriteProcessor == null)
            {
                return;
            }

            // If no camera, early exit
            var camera = context.GetCurrentCamera();

            if (camera == null)
            {
                return;
            }
            var viewProjectionMatrix = camera.ViewProjectionMatrix;

            foreach (var spriteState in spriteProcessor.Sprites)
            {
                var sprite = spriteState.SpriteComponent.CurrentSprite;
                if (sprite == null)
                {
                    continue;
                }

                // Perform culling on group and accept
                if (!CurrentCullingMask.Contains(spriteState.SpriteComponent.Entity.Group))
                {
                    continue;
                }

                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(spriteState.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref viewProjectionMatrix, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                var list = sprite.IsTransparent ? transparentList : opaqueList;

                list.Add(new RenderItem(this, spriteState, projectedZ));
            }
        }
예제 #11
0
 protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
 {
     // If there is a list of models to render, use this list directly
     if (RenderModels != null)
     {
         PrepareModels(context, RenderModels, opaqueList, transparentList);
     }
     else
     {
         // Otherwise, use the models from the ModelProcessor
         var modelProcessor = SceneInstance.GetProcessor <ModelProcessor>();
         renderModelCollections.Clear();
         modelProcessor.QueryModelGroupsByMask(CurrentCullingMask, renderModelCollections);
         foreach (var renderModelGroup in renderModelCollections)
         {
             PrepareModels(context, renderModelGroup, opaqueList, transparentList);
         }
     }
 }
예제 #12
0
        protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            var backgroundProcessor = SceneInstance.GetProcessor <BackgroundComponentProcessor>();

            if (backgroundProcessor == null)
            {
                return;
            }

            foreach (var backgroundComponent in backgroundProcessor.Backgrounds)
            {
                // Perform culling on group and accept
                if (!CurrentCullingMask.Contains(backgroundComponent.Entity.Group))
                {
                    continue;
                }

                opaqueList.Add(new RenderItem(this, backgroundComponent, float.NegativeInfinity)); // render background first so that it can replace a clear frame
                return;                                                                            // draw only one background by group
            }
        }
예제 #13
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItemList, int fromIndex, int toIndex)
        {
            if (dynamicEffectCompiler == null)
            {
                throw new InvalidOperationException("This instance is not correctly initialized (no EffectName)");
            }

            // Get all meshes from render models
            meshesToRender.Clear();
            for (int i = fromIndex; i <= toIndex; i++)
            {
                meshesToRender.Add((RenderMesh)renderItemList[i].DrawContext);
            }

            // Slow path there is a callback
            if (Callbacks.UpdateMeshes != null)
            {
                Callbacks.UpdateMeshes(context, ref meshesToRender);
            }

            // Fetch callback on PreRenderGroup
            var preRenderMesh = Callbacks.PreRenderMesh;

            for (int i = 0; i < meshesToRender.Count; i++)
            {
                var renderMesh = meshesToRender[i];

                // If the EntityGroup is changing, call the callback to allow to plug specific parameters for this group
                if (preRenderMesh != null)
                {
                    preRenderMesh(context, renderMesh);
                }

                // Update Effect and mesh
                UpdateEffect(context, renderMesh, context.Parameters);

                // Draw the mesh
                renderMesh.Draw(context);
            }
        }
예제 #14
0
        public void Prepare(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            if (!Enabled)
            {
                return;
            }

            if (Context == null)
            {
                Initialize(context);
            }
            else if (Context != context)
            {
                throw new InvalidOperationException("Cannot use a different context between Load and Draw");
            }

            if (SceneCameraRenderer != null)
            {
                CurrentCullingMask = SceneCameraRenderer.CullingMask;
            }

            PrepareCore(context, opaqueList, transparentList);
        }
        protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // If no camera, early exit
            var camera = context.GetCurrentCamera();

            if (camera == null)
            {
                return;
            }

            // Copy the ViewProjectionMatrix from the camera as it is not automatically picked up by the ModelComponentRenderer
            modelRenderer.ViewProjectionMatrix = camera.ViewProjectionMatrix;
            var sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
            var cameraRenderMode    = sceneCameraRenderer != null ? sceneCameraRenderer.Mode : null;

            if (cameraRenderMode != null)
            {
                modelRenderer.RasterizerState = cameraRenderMode.GetDefaultRasterizerState(false);
                modelRenderer.RasterizerStateForInvertedGeometry = cameraRenderMode.GetDefaultRasterizerState(true);
            }

            modelRenderer.Prepare(context, opaqueList, transparentList);
        }
예제 #16
0
 protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList)
 {
     modelRenderer.Prepare(context, opaqueList, transparentList);
 }
예제 #17
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
        {
            var viewParameters = context.Parameters;

            var device         = context.GraphicsDevice;
            var viewInverse    = Matrix.Invert(viewParameters.Get(TransformationKeys.View));
            var viewProjection = viewParameters.Get(TransformationKeys.ViewProjection);

            BlendState        previousBlendState        = null;
            DepthStencilState previousDepthStencilState = null;
            Effect            previousEffect            = null;

            var isPicking = context.IsPicking();

            bool hasBegin = false;

            for (var i = fromIndex; i <= toIndex; i++)
            {
                var renderItem        = renderItems[i];
                var spriteState       = (SpriteProcessor.SpriteComponentState)renderItem.DrawContext;
                var spriteComp        = spriteState.SpriteComponent;
                var transfoComp       = spriteState.TransformComponent;
                var depthStencilState = spriteState.SpriteComponent.IgnoreDepth ? device.DepthStencilStates.None : device.DepthStencilStates.Default;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                {
                    continue;
                }

                // Update the sprite batch
                var blendState    = isPicking ? device.BlendStates.Opaque : renderItems.HasTransparency ? (spriteComp.PremultipliedAlpha ? device.BlendStates.AlphaBlend : device.BlendStates.NonPremultiplied) : device.BlendStates.Opaque;
                var currentEffect = isPicking? GetOrCreatePickingSpriteEffect(): spriteComp.Tags.Get(IsEntitySelected)? GetOrCreateSelectedSpriteEffect(): null; // TODO remove this code when material are available
                if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState)
                {
                    if (hasBegin)
                    {
                        sprite3DBatch.End();
                    }
                    sprite3DBatch.Begin(viewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, device.RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousEffect            = currentEffect;
                previousBlendState        = blendState;
                previousDepthStencilState = depthStencilState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = spriteComp.Color;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    color = (Color) new Color4(spriteComp.Id);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // apply the offset due to the center of the sprite
                var normalizedCenter = new Vector2(sprite.SizeInternal.X * (sprite.Center.X / sourceRegion.Width - 0.5f), sprite.SizeInternal.Y * (0.5f - sprite.Center.Y / sourceRegion.Height));
                worldMatrix.M41 -= normalizedCenter.X * worldMatrix.M11 + normalizedCenter.Y * worldMatrix.M21;
                worldMatrix.M42 -= normalizedCenter.X * worldMatrix.M12 + normalizedCenter.Y * worldMatrix.M22;
                worldMatrix.M43 -= normalizedCenter.X * worldMatrix.M13 + normalizedCenter.Y * worldMatrix.M23;

                // draw the sprite
                sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, renderItem.Depth);
            }

            sprite3DBatch.End();
        }
예제 #18
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
        {
            // build the list of the UI elements to render
            uiElementStates.Clear();
            for (var i = fromIndex; i <= toIndex; ++i)
            {
                var renderItem = renderItems[i];
                uiElementStates.Add((UIComponentProcessor.UIComponentState)renderItem.DrawContext);
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // update the rendering context
            renderingContext.Time         = drawTime;
            renderingContext.RenderTarget = CurrentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0

            // cache the ratio between viewport and target.
            var viewportSize = context.GraphicsDevice.Viewport.Size;

            viewportTargetRatio = new Vector2(viewportSize.X / renderingContext.RenderTarget.Width, viewportSize.Y / renderingContext.RenderTarget.Height);

            // compact all the pointer events that happened since last frame to avoid performing useless hit tests.
            CompactPointerEvents();

            // allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;

            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.UIComponent.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description  = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = PushScopedResource(context.Allocator.GetTemporaryTexture(description));
                    break;
                }
            }

            // render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.UIComponent;
                var rootElement = uiComponent.RootElement;
                if (rootElement == null)
                {
                    continue;
                }

                var updatableRootElement = (IUIElementUpdate)rootElement;

                // calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = uiComponent.VirtualResolution;
                var targetSize        = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);
                if (uiComponent.IsFullScreen)
                {
                    // update the virtual resolution of the renderer
                    if (uiComponent.VirtualResolutionMode == VirtualResolutionMode.FixedWidthAdaptableHeight)
                    {
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    }
                    if (uiComponent.VirtualResolutionMode == VirtualResolutionMode.FixedHeightAdaptableWidth)
                    {
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;
                    }
                }

                // Update the view parameters
                if (uiComponent.IsFullScreen)
                {
                    viewParameters.Update(uiComponent.Entity, virtualResolution);
                }
                else
                {
                    var cameraComponent = context.Tags.Get(CameraComponentRenderer.Current);
                    viewParameters.Update(uiComponent.Entity, cameraComponent);
                }

                // Analyze the input and trigger the UI element touch and key events
                // Note: this is done before measuring/arranging/drawing the element in order to avoid one frame latency on clicks.
                //       But by doing so the world matrices taken for hit test are the ones calculated during last frame.
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    foreach (var uiState in uiElementStates)
                    {
                        if (uiState.UIComponent.RootElement == null)
                        {
                            continue;
                        }

                        UpdateMouseOver(uiState);
                        UpdateTouchEvents(uiState, drawTime);
                    }
                }

                // update the rendering context values specific to this element
                renderingContext.Resolution           = virtualResolution;
                renderingContext.ViewMatrix           = viewParameters.ViewMatrix;
                renderingContext.ProjectionMatrix     = viewParameters.ProjectionMatrix;
                renderingContext.ViewProjectionMatrix = viewParameters.ViewProjectionMatrix;
                renderingContext.DepthStencilBuffer   = uiComponent.IsFullScreen ? scopedDepthBuffer : CurrentRenderFrame.DepthStencil;
                renderingContext.ShouldSnapText       = uiComponent.SnapText;

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin            = viewParameters.ViewProjectionMatrix.Row4;
                var virtualWidth             = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight            = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth  = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (int i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i]  = virtualWidth[0] * viewParameters.ViewProjectionMatrix[0 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * viewParameters.ViewProjectionMatrix[4 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                }
                var projectedOrigin        = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth  = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // update layouting context.
                layoutingContext.VirtualResolution          = virtualResolution;
                layoutingContext.RealResolution             = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is rotated of 180degrees along Ox
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.LastRootMatrix = rootMatrix;

                // clear and set the Depth buffer as required
                if (uiComponent.IsFullScreen)
                {
                    context.GraphicsDevice.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
                }
                context.GraphicsDevice.SetDepthAndRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(ref viewParameters.ViewProjectionMatrix, context.GraphicsDevice.BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                ReccursiveDrawWithClipping(context, rootElement);

                // end the image draw session
                batch.End();
            }

            // clear the list of compacted pointer events of time frame
            ClearPointerEvents();

            // revert the depth stencil buffer to the default value
            context.GraphicsDevice.SetDepthAndRenderTargets(CurrentRenderFrame.DepthStencil, CurrentRenderFrame.RenderTargets);
        }
예제 #19
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
        {
            // TODO: Check how to integrate sprites in a Camera renderer instead of this
            var viewParameters = context.Parameters;

            var device         = context.GraphicsDevice;
            var cullMode       = device.RasterizerStates.CullNone;
            var viewInverse    = Matrix.Invert(viewParameters.Get(TransformationKeys.View));
            var viewProjection = viewParameters.Get(TransformationKeys.ViewProjection);

            BlendState previousBlendState = null;
            Effect     previousEffect     = null;

            var isPicking = context.IsPicking();

            bool hasBegin = false;

            for (var i = fromIndex; i <= toIndex; i++)
            {
                var renderItem  = renderItems[i];
                var spriteState = (SpriteProcessor.SpriteComponentState)renderItem.DrawContext;
                var spriteComp  = spriteState.SpriteComponent;
                var transfoComp = spriteState.TransformComponent;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                {
                    continue;
                }

                // Update the sprite batch
                var blendState    = isPicking ? device.BlendStates.Opaque : renderItems.HasTransparency ? (spriteComp.PremultipliedAlpha ? device.BlendStates.AlphaBlend : device.BlendStates.NonPremultiplied) : device.BlendStates.Opaque;
                var currentEffect = (!isPicking && spriteComp.Tags.Get(IsEntitySelected)) ? GetOrCreateSelectedSpriteEffect(): null; // TODO remove this code when material are available
                if (previousEffect != currentEffect || blendState != previousBlendState)
                {
                    if (hasBegin)
                    {
                        sprite3DBatch.End();
                    }
                    sprite3DBatch.Begin(viewProjection, SpriteSortMode.Deferred, blendState, null, context.GraphicsDevice.DepthStencilStates.None, cullMode, currentEffect);
                    hasBegin = true;
                }
                previousEffect     = currentEffect;
                previousBlendState = blendState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = spriteComp.Color;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    texture = device.GetSharedWhiteTexture();
                    color   = (Color) new Color4(spriteComp.Id);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the size of the element depending on the extrusion method.
                var elementSize = Vector2.One;
                if (spriteComp.ExtrusionMethod == SpriteExtrusionMethod.UnitHeightSpriteRatio)
                {
                    elementSize.X = sourceRegion.Width / sourceRegion.Height;
                }
                else if (spriteComp.ExtrusionMethod == SpriteExtrusionMethod.UnitWidthSpriteRatio)
                {
                    elementSize.Y = sourceRegion.Height / sourceRegion.Width;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // draw the sprite
                sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref elementSize, ref color, sprite.Orientation, SwizzleMode.None, renderItem.Depth);
            }

            sprite3DBatch.End();
        }
예제 #20
0
        private void PrepareModels(RenderContext context, List <RenderModel> renderModels, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // If no camera, early exit
            var camera = context.GetCurrentCamera();

            if (camera == null)
            {
                return;
            }

            var viewProjectionMatrix = camera.ViewProjectionMatrix;
            var preRenderModel       = Callbacks.PreRenderModel;

            var sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
            var cullingMode         = CullingModeOverride.HasValue ? CullingModeOverride.Value : sceneCameraRenderer != null ? sceneCameraRenderer.CullingMode : CullingMode.None;
            var frustum             = new BoundingFrustum(ref viewProjectionMatrix);

            var cameraRenderMode = sceneCameraRenderer != null ? sceneCameraRenderer.Mode : null;

            foreach (var renderModel in renderModels)
            {
                // If Model is null, then skip it
                if (renderModel.Model == null)
                {
                    continue;
                }

                if (preRenderModel != null)
                {
                    if (!preRenderModel(context, renderModel))
                    {
                        continue;
                    }
                }

                // Always prepare the slot for the render meshes even if they are not used.
                EnsureRenderMeshes(renderModel);

                var meshes = PrepareModelForRendering(context, renderModel);

                foreach (var renderMesh in meshes)
                {
                    if (!renderMesh.Enabled)
                    {
                        continue;
                    }

                    // Perform frustum culling
                    if (cullingMode == CullingMode.Frustum)
                    {
                        // Always render meshes with unspecified bounds
                        // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                        if (renderMesh.BoundingBox.Extent != Vector3.Zero)
                        {
                            // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                            // Compute transformed AABB (by world)
                            if (!frustum.Contains(ref renderMesh.BoundingBox))
                            {
                                continue;
                            }
                        }
                    }

                    // Project the position
                    // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                    var     worldPosition = new Vector4(renderMesh.WorldMatrix.TranslationVector, 1.0f);
                    Vector4 projectedPosition;
                    Vector4.Transform(ref worldPosition, ref viewProjectionMatrix, out projectedPosition);
                    var projectedZ = projectedPosition.Z / projectedPosition.W;

                    // TODO: Should this be set somewhere else?
                    var rasterizerState = cameraRenderMode != null?cameraRenderMode.GetDefaultRasterizerState(renderMesh.IsGeometryInverted) : null;

                    renderMesh.RasterizerState = RasterizerState ?? rasterizerState;

                    renderMesh.UpdateMaterial();
                    var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                    list.Add(new RenderItem(this, renderMesh, projectedZ));
                }
            }
        }
예제 #21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GraphicsRendererCollection{IEntityComponentRenderer}"/> class.
 /// </summary>
 public EntityComponentRendererBatch()
 {
     opaqueRenderItems      = new RenderItemCollection(1024, false);
     transparentRenderItems = new RenderItemCollection(1024, true);
 }
예제 #22
0
 protected abstract void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex);
예제 #23
0
 protected abstract void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList);
예제 #24
0
        private void DrawRendererInternal(RenderContext context, IEntityComponentRenderer renderer, RenderItemCollection renderItems, int fromIndex, int toIndex)
        {
            var graphicsDevice = context.GraphicsDevice;

            graphicsDevice.PushState();
            renderer.Draw(context, renderItems, fromIndex, toIndex);
            graphicsDevice.PopState();
        }
예제 #25
0
        private void PrepareRenderMeshes(RenderModel renderModel, List <Mesh> meshes, ref FastListStruct <RenderMesh> renderMeshes, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // Add new render meshes
            for (int i = renderMeshes.Count; i < meshes.Count; i++)
            {
                var renderMesh = new RenderMesh(renderModel, meshes[i]);
                renderMeshes.Add(renderMesh);
            }

            // Create the bounding frustum locally on the stack, so that frustum.Contains is performed with boundingBox that is also on the stack
            var frustum = new BoundingFrustum(ref ViewProjectionMatrix);

            for (int i = 0; i < renderMeshes.Count; i++)
            {
                var renderMesh = renderMeshes[i];
                // Update the model hierarchy
                var modelViewHierarchy = renderModel.ModelComponent.ModelViewHierarchy;
                modelViewHierarchy.UpdateRenderMesh(renderMesh);

                if (!renderMesh.Enabled)
                {
                    continue;
                }

                // Upload skinning blend matrices
                BoundingBoxExt boundingBox;
                skinningUpdater.Update(modelViewHierarchy, renderMesh, out boundingBox);

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Compute transformed AABB (by world)
                // TODO: CullingMode should be pluggable
                // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                if (CullingMode == CullingMode.Frustum && boundingBox.Extent != Vector3.Zero && !frustum.Contains(ref boundingBox))
                {
                    continue;
                }

                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var     worldPosition = new Vector4(renderMesh.WorldMatrix.TranslationVector, 1.0f);
                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref ViewProjectionMatrix, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                renderMesh.RasterizerState = renderMesh.IsGeometryInverted ? RasterizerStateForInvertedGeometry : RasterizerState;

                renderMesh.UpdateMaterial();

                var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                list.Add(new RenderItem(this, renderMesh, projectedZ));
            }
        }
예제 #26
0
        private void PrepareModels(RenderContext context, List <RenderModel> renderModels, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            var preRenderModel = Callbacks.PreRenderModel;

            foreach (var renderModel in renderModels)
            {
                var modelComponent = renderModel.ModelComponent;
                var meshes         = modelComponent.Model.Meshes;
                int meshCount      = meshes.Count;
                if (meshCount == 0)
                {
                    continue;
                }

                if (preRenderModel != null && !preRenderModel(context, renderModel))
                {
                    continue;
                }

                // Always prepare the slot for the render meshes even if they are not used.
                for (int i = renderModel.RenderMeshesPerEffectSlot.Count; i <= modelRenderSlot; i++)
                {
                    renderModel.RenderMeshesPerEffectSlot.Add(new FastListStruct <RenderMesh>(meshCount));
                }

                PrepareRenderMeshes(renderModel, meshes, ref renderModel.RenderMeshesPerEffectSlot.Items[modelRenderSlot], opaqueList, transparentList);
            }
        }
예제 #27
0
 protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
 {
     // Nothing to draw for this camera
 }
 protected override void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex)
 {
     modelRenderer.Draw(context, renderItems, fromIndex, toIndex);
 }
예제 #29
0
        private void PrepareModels(RenderContext context, List <RenderModel> renderModels, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // If no camera, early exit
            var camera = context.GetCurrentCamera();

            if (camera == null)
            {
                return;
            }

            var viewProjectionMatrix = camera.ViewProjectionMatrix;
            var preRenderModel       = Callbacks.PreRenderModel;

            foreach (var renderModel in renderModels)
            {
                // If Model is null, then skip it
                if (renderModel.Model == null)
                {
                    continue;
                }

                if (preRenderModel != null)
                {
                    if (!preRenderModel(context, renderModel))
                    {
                        continue;
                    }
                }

                // Always prepare the slot for the render meshes even if they are not used.
                EnsureRenderMeshes(renderModel);

                var meshes = PrepareModelForRendering(context, renderModel);

                foreach (var renderMesh in meshes)
                {
                    if (!renderMesh.Enabled)
                    {
                        continue;
                    }

                    // Project the position
                    // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                    var     worldPosition = new Vector4(renderMesh.Parameters.Get(TransformationKeys.World).TranslationVector, 1.0f);
                    Vector4 projectedPosition;
                    Vector4.Transform(ref worldPosition, ref viewProjectionMatrix, out projectedPosition);
                    var projectedZ = projectedPosition.Z / projectedPosition.W;

                    renderMesh.UpdateMaterial();
                    var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                    list.Add(new RenderItem(this, renderMesh, projectedZ));
                }
            }
        }