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(); }
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); } }
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(); }
protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList) { var cameraState = context.GetCurrentCamera(); if (cameraState == null) return; UpdateParameters(context, cameraState); }
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); }
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)); } }
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; } }
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); } } }
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)); } }
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); } } }
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 } }
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); } }
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); }
protected override void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList) { modelRenderer.Prepare(context, opaqueList, transparentList); }
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(); }
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); }
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(); }
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)); } } }
/// <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); }
protected abstract void DrawCore(RenderContext context, RenderItemCollection renderItems, int fromIndex, int toIndex);
protected abstract void PrepareCore(RenderContext context, RenderItemCollection opaqueList, RenderItemCollection transparentList);
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(); }
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)); } }
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); } }
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); }
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)); } } }