public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { using (context.PushRenderTargetsAndRestore()) { DrawInternal(context, renderView, renderViewStage, startIndex, endIndex); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { lock (drawLock) { DrawInternal(context, renderView, renderViewStage, startIndex, endIndex); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { if (renderMeshesToGenerateAEN.Count > 0) { var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey); foreach (var renderMesh in renderMeshesToGenerateAEN) { var tessellationState = tessellationStates[renderMesh.StaticObjectNode]; if (tessellationState.GeneratedIndicesAEN != null) { continue; } var tessellationMeshDraw = tessellationState.MeshDraw; var indicesAEN = IndexExtensions.GenerateIndexBufferAEN(tessellationMeshDraw.IndexBuffer, tessellationMeshDraw.VertexBuffers[0], context.CommandList); tessellationState.GeneratedIndicesAEN = Buffer.Index.New(Context.GraphicsDevice, indicesAEN); tessellationMeshDraw.IndexBuffer = new IndexBufferBinding(tessellationState.GeneratedIndicesAEN, true, tessellationMeshDraw.IndexBuffer.Count * 12 / 3); tessellationMeshDraw.DrawCount = 12 / 3 * tessellationMeshDraw.DrawCount; } renderMeshesToGenerateAEN.Clear(false); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage) { // Update per-view resources only when view changes if (currentRenderView == renderView) { return; } var viewFeature = renderView.Features[RootRenderFeature.Index]; RenderViewLightData renderViewData; if (!renderViewDatas.TryGetValue(renderView.LightingView ?? renderView, out renderViewData) || viewFeature.Layouts.Count == 0) { return; } var viewIndex = renderViews.IndexOf(renderView); // Update PerView resources foreach (var directLightGroup in shaderPermutation.DirectLightGroups) { directLightGroup.UpdateViewResources(context, viewIndex); } foreach (var environmentLight in shaderPermutation.EnvironmentLights) { environmentLight.UpdateViewResources(context, viewIndex); } currentRenderView = renderView; }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { lock (drawLock) { context.PushRenderTargets(); DrawInternal(context, renderView, renderViewStage, startIndex, endIndex); context.PopRenderTargets(); } }
/// <inheritdoc/> public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var commandList = context.CommandList; var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey); // TODO: stackalloc? var descriptorSetsLocal = descriptorSets.Value; if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount) { descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount]; } for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; // Get effect var renderEffect = GetRenderNode(renderNodeReference).RenderEffect; if (renderEffect.Effect == null) { continue; } // Get the extra node data var nodeData = renderParticleNodeData[renderNodeReference]; if (nodeData.IndexCount <= 0) { continue; } var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference); // Update cbuffer renderEffect.Reflection.BufferUploader.Apply(commandList, ResourceGroupPool, resourceGroupOffset); // Bind descriptor sets for (int i = 0; i < descriptorSetsLocal.Length; ++i) { var resourceGroup = ResourceGroupPool[resourceGroupOffset++]; if (resourceGroup != null) { descriptorSetsLocal[i] = resourceGroup.DescriptorSet; } } commandList.SetPipelineState(renderEffect.PipelineState); commandList.SetDescriptorSets(0, descriptorSetsLocal); // Bind the buffers and draw commandList.SetVertexBuffer(0, nodeData.VertexBuffer, nodeData.VertexBufferOffset, nodeData.VertexBufferStride); commandList.SetIndexBuffer(nodeData.IndexBuffer, nodeData.IndexBufferOffset, ParticleBufferContext.IndexStride != sizeof(short)); commandList.DrawIndexed(nodeData.IndexCount, 0); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { // First do everything that doesn't change per individual render object var graphicsDevice = context.GraphicsDevice; var graphicsContext = context.GraphicsContext; var commandList = context.GraphicsContext.CommandList; // Refresh shader, might have changed during runtime _decalShader.UpdateEffect(graphicsDevice); // Set common shader parameters if needed _decalShader.Parameters.Set(TransformationKeys.ViewProjection, renderView.ViewProjection); _decalShader.Parameters.Set(TransformationKeys.ViewInverse, Matrix.Invert(renderView.View)); // Important to release it at the end of the draw, otherwise you'll run out of memory! //var depthStencil = context.Resolver.ResolveDepthStencil(commandList.DepthStencilBuffer); var depthStencil = context.Resolver.ResolveDepthStencil(graphicsDevice.Presenter.DepthStencilBuffer); // Must use the Presenter's depth buffer, otherwise it won't appear in the Game Studio _decalShader.Parameters.Set(DepthBaseKeys.DepthStencil, depthStencil); _decalShader.Parameters.Set(CameraKeys.ViewSize, renderView.ViewSize); _decalShader.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane)); _decalShader.Parameters.Set(CameraKeys.NearClipPlane, renderView.NearClipPlane); _decalShader.Parameters.Set(CameraKeys.FarClipPlane, renderView.FarClipPlane); for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var decalRendObj = (DecalRenderObject)renderNode.RenderObject; if (decalRendObj.RenderCube == null) { continue; // Next render object } // Assign shader parameters _decalShader.Parameters.Set(TransformationKeys.WorldInverse, Matrix.Invert(decalRendObj.WorldMatrix)); _decalShader.Parameters.Set(TransformationKeys.WorldViewProjection, decalRendObj.WorldMatrix * renderView.ViewProjection); _decalShader.Parameters.Set(TransformationKeys.WorldView, decalRendObj.WorldMatrix * renderView.View); _decalShader.Parameters.Set(DecalShaderKeys.DecalTexture, decalRendObj.Texture); _decalShader.Parameters.Set(DecalShaderKeys.TextureScale, decalRendObj.TextureScale); _decalShader.Parameters.Set(DecalShaderKeys.DecalColor, decalRendObj.Color); decalRendObj.RenderCube.Draw(graphicsContext, _decalShader); } context.Resolver.ReleaseDepthStenctilAsShaderResource(depthStencil); }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderBackground = (RenderBackground)renderNode.RenderObject; if (renderBackground.Texture.Dimension == TextureDimension.Texture2D) { Draw2D(context, renderBackground); } else if (renderBackground.Texture.Dimension == TextureDimension.TextureCube) { DrawCube(context, renderView, renderBackground); } } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { // First do everything that doesn't change per individual render object var graphicsDevice = context.GraphicsDevice; var graphicsContext = context.GraphicsContext; var commandList = context.GraphicsContext.CommandList; // Refresh shader, might have changed during runtime myCustomShader.UpdateEffect(graphicsDevice); // Set common shader parameters if needed //myCustomShader.Parameters.Set(TransformationKeys.ViewProjection, renderView.ViewProjection); for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var myRenderObject = (MyRenderObject)renderNode.RenderObject; if (myRenderObject.VertexBuffer == null) { continue; //next render object } // Assign shader parameters myCustomShader.Parameters.Set(TransformationKeys.WorldViewProjection, myRenderObject.WorldMatrix * renderView.ViewProjection); myCustomShader.Parameters.Set(TexturingKeys.Texture0, myRenderObject.Texture); myCustomShader.Parameters.Set(MyCustomShaderKeys.TextureScale, myRenderObject.TextureScale); myCustomShader.Parameters.Set(MyCustomShaderKeys.Color, myRenderObject.Color); // Prepare pipeline state pipelineState.State.RootSignature = myCustomShader.RootSignature; pipelineState.State.EffectBytecode = myCustomShader.Effect.Bytecode; pipelineState.State.Output.CaptureState(commandList); pipelineState.Update(); commandList.SetPipelineState(pipelineState.CurrentState); // Apply the effect myCustomShader.Apply(graphicsContext); // Set vertex buffer and draw commandList.SetVertexBuffer(0, myRenderObject.VertexBuffer, 0, MyRenderObject.VertexDeclaration.VertexStride); commandList.Draw(MyRenderObject.VertexCount, 0); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage) { float blendValue = (selectionService?.DisplaySelectionMask ?? false) ? 1.0f : MathUtil.Clamp((1.0f - (float)clockSelection.Elapsed.TotalSeconds), 0.0f, 1.0f); shader.UpdateEffect(context.GraphicsDevice); foreach (var renderNode in renderViewStage.SortedRenderNodes) { var renderMesh = renderNode.RenderObject as RenderMesh; if (renderMesh == null) { continue; } MeshDraw drawData = renderMesh.ActiveMeshDraw; // bind VB for (int slot = 0; slot < drawData.VertexBuffers.Length; slot++) { var vertexBuffer = drawData.VertexBuffers[slot]; context.CommandList.SetVertexBuffer(slot, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride); } // set shader parameters shader.Parameters.Set(SelectionWireframeShaderKeys.WorldViewProjection, renderMesh.World * renderView.ViewProjection); // matrix shader.Parameters.Set(SelectionWireframeShaderKeys.WorldScale, new Vector3(1.0001f)); // increase scale to avoid z-fight shader.Parameters.Set(SelectionWireframeShaderKeys.Viewport, new Vector4(context.RenderContext.RenderView.ViewSize, 0, 0)); shader.Parameters.Set(SelectionWireframeShaderKeys.LineWidth, LineWidth); // prepare pipeline state pipelineState.State.RootSignature = shader.RootSignature; pipelineState.State.EffectBytecode = shader.Effect.Bytecode; pipelineState.State.PrimitiveType = drawData.PrimitiveType; Draw(context, drawData, GetColor(ColorOccludedLines, blendValue), DepthStencilStates.None); // occluded Draw(context, drawData, GetColor(ColorNonOccludedLines, blendValue), DepthStencilStates.DepthRead); // non-occluded } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var commandList = context.CommandList; var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount]; for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); // Get effect // TODO: Use real effect slot var renderEffect = renderNode.RenderEffect; if (renderEffect.Effect == null) { continue; } commandList.SetPipelineState(renderEffect.PipelineState); var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference); renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset); // Bind descriptor sets for (int i = 0; i < descriptorSets.Length; ++i) { var resourceGroup = ResourceGroupPool[resourceGroupOffset++]; if (resourceGroup != null) { descriptorSets[i] = resourceGroup.DescriptorSet; } } commandList.SetDescriptorSets(0, descriptorSets); commandList.DrawQuad(); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderBackground = (RenderBackground)renderNode.RenderObject; if (renderBackground.Texture == null) { continue; } if (renderBackground.Is2D) { Draw2D(context, renderBackground); } else { Draw3D(context, renderView, renderBackground); } } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var target = context.RenderContext.Tags.GetSafe(RenderFrame.Current); var graphicsDevice = context.GraphicsDevice; var destination = new RectangleF(0, 0, 1, 1); for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderBackground = (RenderBackground)renderNode.RenderObject; var texture = renderBackground.Texture; 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); // TODO GRAPHICS REFACTOR: Disable depth once we sort properly spriteBatch.Begin(context.GraphicsContext, SpriteSortMode.FrontToBack, BlendStates.Opaque, graphicsDevice.SamplerStates.LinearClamp, DepthStencilStates.DepthRead, null, backgroundEffect); spriteBatch.Parameters.Set(BackgroundEffectKeys.Intensity, renderBackground.Intensity); spriteBatch.Draw(texture, destination, source, Color.White, 0, Vector2.Zero, layerDepth: -0.5f); spriteBatch.End(); } }
/// <inheritdoc/> public override unsafe void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var commandList = context.CommandList; // register all texture usage foreach (var renderObject in RenderObjects) { var renderParticleEmitter = (RenderParticleEmitter)renderObject; Context.StreamingManager?.StreamResources(renderParticleEmitter.ParticleEmitter.Material.Parameters); } // Per view - this code was moved here from Prepare(...) so that we can apply the correct Viewport { var view = renderView; var viewFeature = view.Features[Index]; Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection); // Copy ViewProjection to PerFrame cbuffer foreach (var viewLayout in viewFeature.Layouts) { var resourceGroup = viewLayout.Entries[view.Index].Resources; var mappedCB = resourceGroup.ConstantBuffer.Data; // PerView constant buffer var perViewOffset = viewLayout.GetConstantBufferOffset(this.perViewCBufferOffset); if (perViewOffset != -1) { var perView = (ParticleUtilitiesPerView *)((byte *)mappedCB + perViewOffset); perView->ViewMatrix = view.View; perView->ProjectionMatrix = view.Projection; perView->ViewProjectionMatrix = view.ViewProjection; perView->ViewFrustum = new Vector4(view.ViewSize.X, view.ViewSize.Y, view.NearClipPlane, view.FarClipPlane); perView->Viewport = new Vector4(0, 0, ((float)context.CommandList.Viewport.Width) / ((float)context.CommandList.RenderTarget.Width), ((float)context.CommandList.Viewport.Height) / ((float)context.CommandList.RenderTarget.Height)); } } } var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey); // TODO: stackalloc? var descriptorSetsLocal = descriptorSets.Value; if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount) { descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount]; } for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; // Get effect var renderEffect = GetRenderNode(renderNodeReference).RenderEffect; if (renderEffect.Effect == null) { continue; } // Get the extra node data var nodeData = renderParticleNodeData[renderNodeReference]; if (nodeData.IndexCount <= 0) { continue; } var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference); // Update cbuffer renderEffect.Reflection.BufferUploader.Apply(commandList, ResourceGroupPool, resourceGroupOffset); // Bind descriptor sets for (int i = 0; i < descriptorSetsLocal.Length; ++i) { var resourceGroup = ResourceGroupPool[resourceGroupOffset++]; if (resourceGroup != null) { descriptorSetsLocal[i] = resourceGroup.DescriptorSet; } } commandList.SetPipelineState(renderEffect.PipelineState); commandList.SetDescriptorSets(0, descriptorSetsLocal); // Bind the buffers and draw commandList.SetVertexBuffer(0, nodeData.VertexBuffer, nodeData.VertexBufferOffset, nodeData.VertexBufferStride); commandList.SetIndexBuffer(nodeData.IndexBuffer, nodeData.IndexBufferOffset, ParticleBufferContext.IndexStride != sizeof(short)); commandList.DrawIndexed(nodeData.IndexCount, 0); } }
public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage) { var entity = (renderObject.Source as EntityComponent)?.Entity; if (entity != null) { var entityId = service.Editor.Controller.GetAbsoluteId(entity); return(service.SelectableIds.Contains(entityId)); } return(false); }
private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var uiProcessor = SceneInstance.GetCurrent(context.RenderContext).GetProcessor <UIRenderProcessor>(); if (uiProcessor is null) { return; } // Build the list of the UI elements to render uiElementStates.Clear(); for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderElement = (RenderUIElement)renderNode.RenderObject; uiElementStates.Add(new UIElementState(renderElement)); } // Evaluate the current draw time (Game instance is null for thumbnails) var drawTime = game != null ? game.DrawTime : new GameTime(); // Update the rendering context renderingContext.GraphicsContext = context.GraphicsContext; renderingContext.Time = drawTime; renderingContext.RenderTarget = context.CommandList.RenderTargets[0]; // TODO: Avoid hardcoded index 0 // Prepare content required for Picking and MouseOver events PickingPrepare(); // Allocate temporary graphics resources if needed Texture scopedDepthBuffer = null; foreach (var uiElement in uiElementStates) { if (uiElement.RenderObject.IsFullScreen) { var renderTarget = renderingContext.RenderTarget; var description = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil); scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description); break; } } // Update view parameters and perform UI picking UIElement elementUnderMouseCursor = null; foreach (var uiElementState in uiElementStates) { var renderObject = uiElementState.RenderObject; var rootElement = renderObject.Page?.RootElement; if (rootElement is null) { continue; } UIElement loopedElementUnderMouseCursor = null; // Calculate the size of the virtual resolution depending on target size (UI canvas) var virtualResolution = renderObject.Resolution; if (renderObject.IsFullScreen) { //var targetSize = viewportSize; var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height); // Update the virtual resolution of the renderer if (renderObject.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight) { virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X; } if (renderObject.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth) { virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y; } uiElementState.Update(renderObject, virtualResolution); } else { var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current); if (cameraComponent != null) { uiElementState.Update(renderObject, cameraComponent); } } // Check if the current UI component is being picked based on the current ViewParameters (used to draw this element) using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate)) { PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime, ref loopedElementUnderMouseCursor); // Only update resulting element when this one has a value if (loopedElementUnderMouseCursor != null) { elementUnderMouseCursor = loopedElementUnderMouseCursor; } } } UIElementUnderMouseCursor = elementUnderMouseCursor; // Render the UI elements of all the entities foreach (var uiElementState in uiElementStates) { var renderObject = uiElementState.RenderObject; var rootElement = renderObject.Page?.RootElement; if (rootElement is null) { continue; } var updatableRootElement = (IUIElementUpdate)rootElement; var virtualResolution = renderObject.Resolution; // Update the rendering context values specific to this element renderingContext.Resolution = virtualResolution; renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix; renderingContext.DepthStencilBuffer = renderObject.IsFullScreen ? scopedDepthBuffer : context.CommandList.DepthStencilBuffer; renderingContext.ShouldSnapText = renderObject.SnapText && renderObject.IsBillboard && (renderObject.IsFixedSize || renderObject.IsFullScreen); // Calculate an estimate of the UI real size by projecting the element virtual resolution on the screen var virtualOrigin = uiElementState.WorldViewProjectionMatrix.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 (var i = 0; i < 4; i++) { transformedVirtualWidth[i] = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; } var viewportSize = context.CommandList.Viewport.Size; var projectedOrigin = virtualOrigin.XY() / virtualOrigin.W; var projectedVirtualWidth = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin); var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin); // Set default services rootElement.UIElementServices = new UIElementServices { Services = RenderSystem.Services }; // Set default resource dictionary // 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 // UI world is translated by a half resolution compared to its quad, which is centered around the origin var rootMatrix = Matrix.Translation(-virtualResolution / 2); updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix); updatableRootElement.UpdateElementState(0); uiElementState.RenderObject.LastRootMatrix = rootMatrix; // Clear and set the Depth buffer as required if (renderObject.IsFullScreen) { context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil); } context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget); // Start the image draw session renderingContext.StencilTestReferenceValue = 0; batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue); // Render the UI elements in the final render target RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix); // End the image draw session batch.End(); } PickingClear(); // Revert the depth stencil buffer to the default value context.CommandList.SetRenderTargets(context.CommandList.DepthStencilBuffer, context.CommandList.RenderTargetCount, context.CommandList.RenderTargets); // Release scroped texture if (scopedDepthBuffer != null) { context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer); } }
public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage) { var renderMesh = renderObject as RenderMesh; return(renderMesh != null && (HighlightRenderFeature.MaterialHighlightColors.ContainsKey(renderMesh.MaterialPass.Material) || HighlightRenderFeature.MeshHighlightColors.ContainsKey(renderMesh.Mesh) || HighlightRenderFeature.MaterialsHighlightedForModel.Contains(renderMesh.MaterialPass.Material) && HighlightRenderFeature.ModelHighlightColors.ContainsKey(renderMesh.RenderModel.ModelComponent))); }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current); var uiProcessor = renderView.SceneInstance.GetProcessor <UIRenderProcessor>(); if (uiProcessor == null) { return; } //foreach (var uiRoot in uiProcessor.UIRoots) //{ // // Perform culling on group and accept // if (!renderView.SceneCameraRenderer.CullingMask.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 = renderView.Camera; // 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)); //} // build the list of the UI elements to render uiElementStates.Clear(); for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderElement = (RenderUIElement)renderNode.RenderObject; uiElementStates.Add(renderElement); } // evaluate the current draw time (game instance is null for thumbnails) var drawTime = game != null ? game.DrawTime : new GameTime(); // update the rendering context renderingContext.GraphicsContext = context.GraphicsContext; renderingContext.Time = drawTime; renderingContext.RenderTarget = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0 var viewport = context.CommandList.Viewport; // cache the ratio between viewport and target. var viewportSize = viewport.Size; viewportTargetRatio = new Vector2(viewportSize.X / renderingContext.RenderTarget.Width, viewportSize.Y / renderingContext.RenderTarget.Height); viewportOffset = new Vector2(viewport.X / viewport.Width, viewport.Y / viewport.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 = context.RenderContext.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.Resolution; if (uiComponent.IsFullScreen) { //var targetSize = viewportSize; var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height); // update the virtual resolution of the renderer if (uiComponent.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight) { virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X; } if (uiComponent.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth) { virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y; } viewParameters.Update(uiComponent.Entity, virtualResolution); } else { var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current); if (cameraComponent != null) { 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 (var 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); // set default resource dictionary rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary; // 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.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil); } context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget); // start the image draw session renderingContext.StencilTestReferenceValue = 0; batch.Begin(context.GraphicsContext, ref viewParameters.ViewProjectionMatrix, 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.CommandList.SetRenderTargets(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets); // Release scroped texture if (scopedDepthBuffer != null) { context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer); } }
public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage) { // TODO: More general implementation (esp. if moved from this class to EditorGameComponentGizmoService) var renderMesh = renderObject as RenderMesh; if (renderMesh != null) { // TODO: Avoid having to go through entity return((renderMesh.Source as ModelComponent)?.Entity?.Tags.Get(EditorGameComponentGizmoService.SelectedKey) ?? false); } return(false); }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var batchContext = threadContext.Value; Matrix viewInverse; Matrix.Invert(ref renderView.View, out viewInverse); uint previousBatchState = uint.MaxValue; //TODO string comparison ...? var isPicking = renderViewStage.RenderStage.Name == "Picking"; bool hasBegin = false; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderSprite = (RenderSprite)renderNode.RenderObject; var spriteComp = renderSprite.SpriteComponent; var transfoComp = renderSprite.TransformComponent; var sprite = spriteComp.CurrentSprite; if (sprite == null) { continue; } // TODO: this should probably be moved to Prepare() // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f); Vector4 projectedPosition; Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition); var projectedZ = projectedPosition.Z / projectedPosition.W; // Check if the current blend state has changed in any way, if not // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method var currentBatchState = isPicking ? 0U : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? 1U : 2U) : 3U; currentBatchState = (currentBatchState << 1) + (renderSprite.SpriteComponent.IgnoreDepth ? 1U : 0U); currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.SpriteComponent.Sampler); if (previousBatchState != currentBatchState) { var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque; var currentEffect = isPicking ? batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem) : null; // TODO remove this code when material are available var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default; var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp; if (renderSprite.SpriteComponent.Sampler != SpriteComponent.SpriteSampler.LinearClamp) { switch (renderSprite.SpriteComponent.Sampler) { case SpriteComponent.SpriteSampler.PointClamp: samplerState = context.GraphicsDevice.SamplerStates.PointClamp; break; case SpriteComponent.SpriteSampler.AnisotropicClamp: samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp; break; } } if (hasBegin) { batchContext.SpriteBatch.End(); } batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, RasterizerStates.CullNone, currentEffect); hasBegin = true; } previousBatchState = currentBatchState; 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. { var compId = RuntimeIdHelper.ToRuntimeId(spriteComp); color = new Color4(compId, 0.0f, 0.0f, 0.0f); } // 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; } // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height); if (sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23; // draw the sprite batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, spriteComp.Swizzle, projectedZ); } if (hasBegin) { batchContext.SpriteBatch.End(); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { if (renderMeshesToGenerateAEN.Count > 0) { var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey); foreach (var renderMesh in renderMeshesToGenerateAEN) { var tessellationState = tessellationStates[renderMesh.StaticObjectNode]; if (tessellationState.GeneratedIndicesAEN != null) continue; var tessellationMeshDraw = tessellationState.MeshDraw; var indicesAEN = IndexExtensions.GenerateIndexBufferAEN(tessellationMeshDraw.IndexBuffer, tessellationMeshDraw.VertexBuffers[0], context.CommandList); tessellationState.GeneratedIndicesAEN = Buffer.Index.New(Context.GraphicsDevice, indicesAEN); tessellationMeshDraw.IndexBuffer = new IndexBufferBinding(tessellationState.GeneratedIndicesAEN, true, tessellationMeshDraw.IndexBuffer.Count*12/3); tessellationMeshDraw.DrawCount = 12/3*tessellationMeshDraw.DrawCount; } renderMeshesToGenerateAEN.Clear(); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var commandList = context.CommandList; var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount]; for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); // Get effect // TODO: Use real effect slot var renderEffect = renderNode.RenderEffect; if (renderEffect.Effect == null) continue; commandList.SetPipelineState(renderEffect.PipelineState); var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference); renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset); // Bind descriptor sets for (int i = 0; i < descriptorSets.Length; ++i) { var resourceGroup = ResourceGroupPool[resourceGroupOffset++]; if (resourceGroup != null) descriptorSets[i] = resourceGroup.DescriptorSet; } commandList.SetDescriptorSets(0, descriptorSets); commandList.DrawQuad(); } }
public override bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage) { var entity = ((renderObject as RenderMesh)?.Source as ModelComponent)?.Entity; return(entity != null && selectedEntities.Contains(entity)); }
private void initUIElementStates(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, ref UIElementState[] uiElementStates, int index, int storeIndex, GameTime drawTime, List <PointerEvent> events, ulong posecount) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderElement = (RenderUIElement)renderNode.RenderObject; var uiElementState = new UIElementState(renderElement); uiElementStates[storeIndex] = uiElementState; var renderObject = uiElementState.RenderObject; var rootElement = renderObject.Page?.RootElement; if (rootElement != null) { UIBatch batch = getFreeBatch(context); var virtualResolution = renderObject.Resolution; var updatableRootElement = (IUIElementUpdate)rootElement; // update the UI element disposition rootElement.Measure(virtualResolution); rootElement.Arrange(virtualResolution, false); // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen var virtualOrigin = uiElementState.WorldViewProjectionMatrix.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 (var i = 0; i < 4; i++) { transformedVirtualWidth[i] = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; } var viewportSize = context.CommandList.Viewport.Size; var projectedOrigin = virtualOrigin.XY() / virtualOrigin.W; var projectedVirtualWidth = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin); var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin); // Set default services rootElement.UIElementServices = new UIElementServices { Services = RenderSystem.Services }; // perform the time-based updates of the UI element updatableRootElement.Update(drawTime); // update the UI element hierarchical properties var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is translated by a half resolution compared to its quad, which is centered around the origin updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix); updatableRootElement.UpdateElementState(0); uiElementState.RenderObject.LastRootMatrix = rootMatrix; // set default resource dictionary // update layouting context. var layoutingContext = batch.layoutingContext as LayoutingContext; layoutingContext.VirtualResolution = virtualResolution; layoutingContext.RealResolution = viewportSize; layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y); rootElement.LayoutingContext = layoutingContext; if (renderObject.IsFullScreen) { //var targetSize = viewportSize; var targetSize = new Vector2(context.CommandList.RenderTargets[0].Width, context.CommandList.RenderTargets[0].Height); // update the virtual resolution of the renderer switch (renderObject.ResolutionStretch) { case ResolutionStretch.FixedWidthAdaptableHeight: virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X; break; case ResolutionStretch.FixedHeightAdaptableWidth: virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y; break; case ResolutionStretch.AutoFit: float aspect = targetSize.X / targetSize.Y; float virtAspect = virtualResolution.X / virtualResolution.Y; if (aspect >= virtAspect) { goto case ResolutionStretch.FixedHeightAdaptableWidth; } goto case ResolutionStretch.FixedWidthAdaptableHeight; case ResolutionStretch.AutoShrink: if (targetSize.X < virtualResolution.X || targetSize.Y < virtualResolution.Y) { goto case ResolutionStretch.AutoFit; } else { virtualResolution.X = targetSize.X * targetSize.X / virtualResolution.X; virtualResolution.Y = targetSize.Y * targetSize.Y / virtualResolution.Y; } break; } uiElementState.Update(renderObject, virtualResolution); } else { CameraComponent cameraComponent = renderView.Camera as CameraComponent; if (cameraComponent != null) { uiElementState.Update(renderObject, cameraComponent.VerticalFieldOfView, ref renderView.View, ref renderView.Projection); } } if (renderObject.Source is UIComponent uic) { uic.RenderedResolution = virtualResolution; if (posecount == 0 || posecount != uic.VRPoseUpdate) { PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime, events); uic.VRPoseUpdate = posecount; } } ReturnBatch(batch); } }
private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var uiProcessor = SceneInstance.GetCurrent(context.RenderContext).GetProcessor <UIRenderProcessor>(); if (uiProcessor == null) { return; } // evaluate the current draw time (game instance is null for thumbnails) var drawTime = game != null ? game.DrawTime : new GameTime(); // Prepare content required for Picking and MouseOver events var events = new List <PointerEvent>(); PickingPrepare(events); ulong poseCount = VirtualReality.VRDeviceSystem.GetSystem?.Device?.PoseCount ?? 0; // build the list of the UI elements to render UIElementState[] uiElementStates = new UIElementState[endIndex - startIndex]; if (uiElementStates.Length > 1 && GraphicsDevice.Platform == GraphicsPlatform.Vulkan) { Xenko.Core.Threading.Dispatcher.For(startIndex, endIndex, (index) => { initUIElementStates(context, renderView, renderViewStage, ref uiElementStates, index, index - startIndex, drawTime, events, poseCount); }); } else { for (int i = startIndex; i < endIndex; i++) { initUIElementStates(context, renderView, renderViewStage, ref uiElementStates, i, i - startIndex, drawTime, events, poseCount); } } events?.Clear(); lock (drawLocker) { UIBatch batch = getFreeBatch(context); var renderingContext = batch.renderingContext as UIRenderingContext; // update the rendering context renderingContext.GraphicsContext = context.GraphicsContext; renderingContext.Time = drawTime; DepthStencilStateDescription stencilState = uiSystem.KeepStencilValueState; // actually draw stuff for (int j = 0; j < uiElementStates.Length; j++) { var uiElementState = uiElementStates[j]; renderingContext.RenderObject = uiElementState.RenderObject; var rootElement = renderingContext.RenderObject.Page?.RootElement; if (rootElement == null || rootElement.IsVisible == false) { continue; } // update the rendering context values specific to this element renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix; switch (renderingContext.RenderObject.depthMode) { case Sprites.RenderSprite.SpriteDepthMode.Ignore: stencilState.DepthBufferWriteEnable = false; stencilState.DepthBufferEnable = false; break; case Sprites.RenderSprite.SpriteDepthMode.ReadOnly: stencilState.DepthBufferWriteEnable = false; stencilState.DepthBufferEnable = true; break; default: stencilState.DepthBufferWriteEnable = true; stencilState.DepthBufferEnable = true; break; case Sprites.RenderSprite.SpriteDepthMode.WriteOnly: stencilState.DepthBufferWriteEnable = true; stencilState.DepthBufferEnable = true; stencilState.DepthBufferFunction = CompareFunction.Always; break; } SamplerState samplerState; switch (renderingContext.RenderObject.Sampler) { default: samplerState = context.GraphicsDevice.SamplerStates.LinearClamp; break; case UIElementSampler.PointClamp: samplerState = context.GraphicsDevice.SamplerStates.PointClamp; break; case UIElementSampler.AnisotropicClamp: samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp; break; } // start the image draw session renderingContext.StencilTestReferenceValue = 0; batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, samplerState, null, stencilState, renderingContext.StencilTestReferenceValue); // Render the UI elements in the final render target RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix, batch, ref stencilState, samplerState); batch.End(); } ReturnBatch(batch); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var batchContext = threadContext.Value; Matrix viewInverse; Matrix.Invert(ref renderView.View, out viewInverse); uint previousBatchState = uint.MaxValue; //TODO string comparison ...? var isPicking = renderViewStage.RenderStage.Name == "Picking"; bool hasBegin = false; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderSprite = (RenderSprite)renderNode.RenderObject; var spriteComp = renderSprite.SpriteComponent; var transfoComp = renderSprite.TransformComponent; var sprite = spriteComp.CurrentSprite; if (sprite == null) continue; // TODO: this should probably be moved to Prepare() // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f); Vector4 projectedPosition; Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition); var projectedZ = projectedPosition.Z / projectedPosition.W; // Check if the current blend state has changed in any way, if not // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method var currentBatchState = isPicking ? 0U : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? 1U : 2U) : 3U; currentBatchState = (currentBatchState << 1) + (renderSprite.SpriteComponent.IgnoreDepth ? 1U : 0U); currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.SpriteComponent.Sampler); if (previousBatchState != currentBatchState) { var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque; var currentEffect = isPicking ? batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem) : null; // TODO remove this code when material are available var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default; var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp; if (renderSprite.SpriteComponent.Sampler != SpriteComponent.SpriteSampler.LinearClamp) { switch (renderSprite.SpriteComponent.Sampler) { case SpriteComponent.SpriteSampler.PointClamp: samplerState = context.GraphicsDevice.SamplerStates.PointClamp; break; case SpriteComponent.SpriteSampler.AnisotropicClamp: samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp; break; } } if (hasBegin) { batchContext.SpriteBatch.End(); } batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, RasterizerStates.CullNone, currentEffect); hasBegin = true; } previousBatchState = currentBatchState; 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. { var compId = RuntimeIdHelper.ToRuntimeId(spriteComp); color = new Color4(compId); } // 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; } // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height); if (sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23; // draw the sprite batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ); } if (hasBegin) { batchContext.SpriteBatch.End(); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); Matrix viewInverse; Matrix.Invert(ref renderView.View, out viewInverse); BlendStateDescription? previousBlendState = null; DepthStencilStateDescription?previousDepthStencilState = null; EffectInstance previousEffect = null; //TODO string comparison ...? var isPicking = renderViewStage.RenderStage.Name == "Picking"; bool hasBegin = false; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderSprite = (RenderSprite)renderNode.RenderObject; var spriteComp = renderSprite.SpriteComponent; var transfoComp = renderSprite.TransformComponent; var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default; var sprite = spriteComp.CurrentSprite; if (sprite == null) { continue; } // TODO: this should probably be moved to Prepare() // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f); Vector4 projectedPosition; Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition); var projectedZ = projectedPosition.Z / projectedPosition.W; // Update the sprite batch var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque; var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null; // TODO remove this code when material are available if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState) { if (hasBegin) { sprite3DBatch.End(); } sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, 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. { var compId = RuntimeIdHelper.ToRuntimeId(spriteComp); color = new Color4(compId); } // 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; } // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height); if (sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23; // draw the sprite sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ); } if (hasBegin) { sprite3DBatch.End(); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var isMultisample = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount != MultisampleCount.None; var batchContext = threadContext.Value; Matrix viewInverse; Matrix.Invert(ref renderView.View, out viewInverse); uint previousBatchState = uint.MaxValue; //TODO string comparison ...? var isPicking = RenderSystem.RenderStages[renderViewStage.Index].Name == "Picking"; bool hasBegin = false; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderSprite = (RenderSprite)renderNode.RenderObject; var sprite = renderSprite.Sprite; if (sprite == null) { continue; } // TODO: this should probably be moved to Prepare() // 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(renderSprite.WorldMatrix.TranslationVector, 1.0f); Vector4 projectedPosition; Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition); var projectedZ = projectedPosition.Z / projectedPosition.W; BlendModes blendMode; EffectInstance currentEffect = null; if (isPicking) { blendMode = BlendModes.Default; currentEffect = batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem); } else { var spriteBlend = renderSprite.BlendMode; if (spriteBlend == SpriteBlend.Auto) { spriteBlend = sprite.IsTransparent ? SpriteBlend.AlphaBlend : SpriteBlend.None; } if (spriteBlend == SpriteBlend.AlphaBlend) { blendMode = renderSprite.PremultipliedAlpha ? BlendModes.Alpha : BlendModes.NonPremultiplied; } else { blendMode = spriteBlendToBlendMode[spriteBlend]; } } // Check if the current blend state has changed in any way, if not // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method var currentBatchState = (uint)blendMode; currentBatchState = (currentBatchState << 1) + ((uint)renderSprite.DepthMode); currentBatchState = (currentBatchState << 1) + (renderSprite.IsAlphaCutoff ? 1U : 0U); currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.Sampler); if (previousBatchState != currentBatchState) { var blendState = blendModeToDescription[blendMode]; if (renderSprite.IsAlphaCutoff) { currentEffect = batchContext.GetOrCreateAlphaCutoffSpriteEffect(RenderSystem.EffectSystem); } DepthStencilStateDescription depthStencilState; switch (renderSprite.DepthMode) { case RenderSprite.SpriteDepthMode.Ignore: depthStencilState = DepthStencilStates.None; break; case RenderSprite.SpriteDepthMode.ReadOnly: depthStencilState = DepthStencilStates.DepthRead; break; default: depthStencilState = DepthStencilStates.Default; break; case RenderSprite.SpriteDepthMode.WriteOnly: depthStencilState = new DepthStencilStateDescription(false, true); break; } var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp; if (renderSprite.Sampler != SpriteSampler.LinearClamp) { switch (renderSprite.Sampler) { case SpriteSampler.PointClamp: samplerState = context.GraphicsDevice.SamplerStates.PointClamp; break; case SpriteSampler.AnisotropicClamp: samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp; break; } } if (hasBegin) { lock (batchEndLocker) { batchContext.SpriteBatch.End(); } } var rasterizerState = RasterizerStates.CullNone; if (isMultisample) { rasterizerState.MultisampleCount = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount; rasterizerState.MultisampleAntiAliasLine = true; } batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, rasterizerState, currentEffect); hasBegin = true; } previousBatchState = currentBatchState; var sourceRegion = sprite.Region; var texture = sprite.Texture; var color = renderSprite.Color; if (isPicking) // TODO move this code corresponding to picking out of the runtime code. { var compId = RuntimeIdHelper.ToRuntimeId(renderSprite.Source); color = new Color4(compId, 0.0f, 0.0f, 0.0f); } // 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 = renderSprite.WorldMatrix; if (renderSprite.SpriteType == SpriteType.Billboard) { worldMatrix = viewInverse; var worldMatrixRow1 = worldMatrix.Row1; var worldMatrixRow2 = worldMatrix.Row2; // remove scale of the camera worldMatrixRow1 /= ((Vector3)viewInverse.Row1).Length(); worldMatrixRow2 /= ((Vector3)viewInverse.Row2).Length(); // set the scale of the object worldMatrixRow1 *= ((Vector3)renderSprite.WorldMatrix.Row1).Length(); worldMatrixRow2 *= ((Vector3)renderSprite.WorldMatrix.Row2).Length(); worldMatrix.Row1 = worldMatrixRow1; worldMatrix.Row2 = worldMatrixRow2; // set the position worldMatrix.TranslationVector = renderSprite.WorldMatrix.TranslationVector; // set the rotation var localRotationZ = renderSprite.RotationEulerZ; if (localRotationZ != 0) { worldMatrix = Matrix.RotationZ(localRotationZ) * worldMatrix; } } // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height); if (sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23; // adapt the source region to match what is expected at full resolution if (texture.ViewType == ViewType.Full && texture.ViewWidth != texture.FullQualitySize.Width) { var fullQualitySize = texture.FullQualitySize; var horizontalRatio = texture.ViewWidth / (float)fullQualitySize.Width; var verticalRatio = texture.ViewHeight / (float)fullQualitySize.Height; sourceRegion.X *= horizontalRatio; sourceRegion.Width *= horizontalRatio; sourceRegion.Y *= verticalRatio; sourceRegion.Height *= verticalRatio; } // register resource usage. Context.StreamingManager?.StreamResources(texture); // draw the sprite batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, renderSprite.Swizzle, projectedZ); } if (hasBegin) { lock (batchEndLocker) { batchContext.SpriteBatch.End(); } } }
void ILowLevelAPIRender.Draw(RenderContext renderContext, RenderDrawContext drawContext, RenderView renderView, RenderViewStage renderViewStage, CommandList commandList) { foreach (var upstreamLayer in FUpstreamLayers) { upstreamLayer?.Draw(renderContext, drawContext, renderView, renderViewStage, commandList); } }
private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current); var uiProcessor = renderView.SceneInstance.GetProcessor<UIRenderProcessor>(); if (uiProcessor == null) return; // build the list of the UI elements to render uiElementStates.Clear(); for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderElement = (RenderUIElement)renderNode.RenderObject; uiElementStates.Add(new UIElementState(renderElement)); } // evaluate the current draw time (game instance is null for thumbnails) var drawTime = game != null ? game.DrawTime : new GameTime(); // update the rendering context renderingContext.GraphicsContext = context.GraphicsContext; renderingContext.Time = drawTime; renderingContext.RenderTarget = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0 // Prepare content required for Picking and MouseOver events PickingPrepare(); // allocate temporary graphics resources if needed Texture scopedDepthBuffer = null; foreach (var uiElement in uiElementStates) { if (uiElement.RenderObject.UIComponent.IsFullScreen) { var renderTarget = renderingContext.RenderTarget; var description = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil); scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description); break; } } // update view parameters and perform UI picking foreach (var uiElementState in uiElementStates) { var uiComponent = uiElementState.RenderObject.UIComponent; var rootElement = uiComponent.Page?.RootElement; if (rootElement == null) continue; // calculate the size of the virtual resolution depending on target size (UI canvas) var virtualResolution = uiComponent.Resolution; if (uiComponent.IsFullScreen) { //var targetSize = viewportSize; var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height); // update the virtual resolution of the renderer if (uiComponent.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight) virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X; if (uiComponent.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth) virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y; uiElementState.Update(uiComponent.Entity, virtualResolution); } else { var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current); if (cameraComponent != null) uiElementState.Update(uiComponent.Entity, cameraComponent); } // Check if the current UI component is being picked based on the current ViewParameters (used to draw this element) using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate)) { PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime); } } // render the UI elements of all the entities foreach (var uiElementState in uiElementStates) { var uiComponent = uiElementState.RenderObject.UIComponent; var rootElement = uiComponent.Page?.RootElement; if (rootElement == null) continue; var updatableRootElement = (IUIElementUpdate)rootElement; var virtualResolution = uiComponent.Resolution; // update the rendering context values specific to this element renderingContext.Resolution = virtualResolution; renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix; 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 = uiElementState.WorldViewProjectionMatrix.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 (var i = 0; i < 4; i++) { transformedVirtualWidth[i] = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; } var viewportSize = context.CommandList.Viewport.Size; var projectedOrigin = virtualOrigin.XY() / virtualOrigin.W; var projectedVirtualWidth = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin); var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin); // Set default services rootElement.UIElementServices = new UIElementServices { Services = RenderSystem.Services }; // set default resource dictionary rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary; // 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 translated by a half resolution compared to its quad, which is centered around the origin updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix); updatableRootElement.UpdateElementState(0); uiElementState.RenderObject.LastRootMatrix = rootMatrix; // clear and set the Depth buffer as required if (uiComponent.IsFullScreen) { context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil); } context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget); // start the image draw session renderingContext.StencilTestReferenceValue = 0; batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue); // Render the UI elements in the final render target RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix); // end the image draw session batch.End(); } PickingClear(); // revert the depth stencil buffer to the default value context.CommandList.SetRenderTargets(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets); // Release scroped texture if (scopedDepthBuffer != null) { context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer); } }
void ILowLevelAPIRender.Draw(RenderContext renderContext, RenderDrawContext drawContext, RenderView renderView, RenderViewStage renderViewStage, CommandList commandList) { FUpstreamLayer1?.Draw(renderContext, drawContext, renderView, renderViewStage, commandList); FUpstreamLayer2?.Draw(renderContext, drawContext, renderView, renderViewStage, commandList); }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { // Do not call into VL if not running var renderContext = context.RenderContext; var runtime = this.runtime ?? (this.runtime = renderContext.Services.GetService <IVLRuntime>()); if (runtime != null && !runtime.IsRunning) { return; } // Build the list of layers to render singleCallLayers.Clear(); layers.Clear(); for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderElement = (RenderLayer)renderNode.RenderObject; if (renderElement.Enabled) { if (renderElement.SingleCallPerFrame) { singleCallLayers.Add(renderElement.Layer); } else { layers.Add(renderElement.Layer); } } } // Call layers which want to get invoked only once per frame first var currentFrameNr = renderContext.Time.FrameCount; if (lastFrameNr != currentFrameNr) { lastFrameNr = currentFrameNr; foreach (var layer in singleCallLayers) { try { layer?.Draw(Context, context, renderView, renderViewStage, context.CommandList); } catch (Exception e) { RuntimeGraph.ReportException(e); } } } // Call layers which can get invoked twice per frame (for each eye) foreach (var layer in layers) { try { layer?.Draw(Context, context, renderView, renderViewStage, context.CommandList); } catch (Exception e) { RuntimeGraph.ReportException(e); } } }
/// <inheritdoc/> public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var commandList = context.CommandList; // TODO: PerView data Matrix viewInverse; Matrix.Invert(ref renderView.View, out viewInverse); var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount]; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; if (renderParticleEmitter.ParticleEmitter.VertexBuilder.ResourceContext == null) { continue; } // Generate vertices // TODO: Just just unmap/barrier here renderParticleEmitter.ParticleEmitter.BuildVertexBuffer(context.CommandList, ref viewInverse); // Get effect var renderEffect = renderNode.RenderEffect; if (renderEffect.Effect == null) { continue; } // TODO GRAPHICS REFACTOR: Extract data var particleSystemComponent = renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent; var particleSystem = particleSystemComponent.ParticleSystem; var vertexBuilder = renderParticleEmitter.ParticleEmitter.VertexBuilder; // Bind VB var vertexBuffer = vertexBuilder.ResourceContext.VertexBuffer; var indexBuffer = vertexBuilder.ResourceContext.IndexBuffer; commandList.SetVertexBuffer(0, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride); commandList.SetIndexBuffer(indexBuffer.Buffer, indexBuffer.Offset, indexBuffer.Is32Bit); var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference); // Update cbuffer renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset); // Bind descriptor sets for (int i = 0; i < descriptorSets.Length; ++i) { var resourceGroup = ResourceGroupPool[resourceGroupOffset++]; if (resourceGroup != null) { descriptorSets[i] = resourceGroup.DescriptorSet; } } commandList.SetPipelineState(renderEffect.PipelineState); commandList.SetDescriptorSets(0, descriptorSets); commandList.DrawIndexed(vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad, vertexBuilder.ResourceContext.IndexBufferPosition); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); BlendStateDescription? previousBlendState = null; DepthStencilStateDescription?previousDepthStencilState = null; EffectInstance previousEffect = null; //TODO string comparison ...? var isPicking = RenderSystem.RenderStages[renderViewStage.Index].Name == "Picking"; var hasBegin = false; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var spriteState = (RenderSpriteStudio)renderNode.RenderObject; var depthStencilState = DepthStencilStates.DepthRead; foreach (var node in spriteState.SortedNodes) { if (node.Sprite?.Texture == null || node.Sprite.Region.Width <= 0 || node.Sprite.Region.Height <= 0f || node.Hide != 0) { continue; } // Update the sprite batch BlendStateDescription spriteBlending; switch (node.BaseNode.AlphaBlending) { case SpriteStudioBlending.Mix: spriteBlending = BlendStates.AlphaBlend; break; case SpriteStudioBlending.Multiplication: spriteBlending = MultBlendState; break; case SpriteStudioBlending.Addition: spriteBlending = BlendStates.Additive; break; case SpriteStudioBlending.Subtraction: spriteBlending = SubBlendState; break; default: throw new ArgumentOutOfRangeException(); } // TODO: this should probably be moved to Prepare() // 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.WorldMatrix.TranslationVector, 1.0f); Vector4 projectedPosition; Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition); var projectedZ = projectedPosition.Z / projectedPosition.W; var blendState = isPicking ? BlendStates.Default : spriteBlending; // TODO: the current impementation to determine if the sprite is selected does not work. This should be fixed later at some point //var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : ShadowObject.IsObjectSelected(spriteState.SpriteStudioComponent) ? GetOrCreateSelectedSpriteEffect() : null; var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null; // TODO remove this code when material are available if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState) { if (hasBegin) { sprite3DBatch.End(); } sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect); hasBegin = true; } previousEffect = currentEffect; previousBlendState = blendState; previousDepthStencilState = depthStencilState; var sourceRegion = node.Sprite.Region; var texture = node.Sprite.Texture; // skip the sprite if no texture is set. if (texture == null) { continue; } var color4 = Color4.White; if (isPicking) { // TODO move this code corresponding to picking out of the runtime code. color4 = new Color4(RuntimeIdHelper.ToRuntimeId(spriteState.Source)); } else { if (node.BlendFactor > 0.0f) { switch (node.BlendType) //todo this should be done in a shader { case SpriteStudioBlending.Mix: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Multiplication: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Addition: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; case SpriteStudioBlending.Subtraction: color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency; break; default: throw new ArgumentOutOfRangeException(); } } else { color4 *= node.FinalTransparency; } } Matrix.Multiply(ref node.ModelTransform, ref spriteState.WorldMatrix, out var worldMatrix); // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(node.Sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - node.Sprite.Center.Y / sourceRegion.Height); if (node.Sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var size = node.Sprite.Size; var centerOffset = Vector2.Modulate(normalizedCenter, size); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; // draw the sprite sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref size, ref color4, node.Sprite.Orientation, SwizzleMode.None, projectedZ); } } if (hasBegin) { sprite3DBatch.End(); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); Matrix viewInverse; Matrix.Invert(ref renderView.View, out viewInverse); BlendStateDescription? previousBlendState = null; DepthStencilStateDescription? previousDepthStencilState = null; EffectInstance previousEffect = null; //TODO string comparison ...? var isPicking = renderViewStage.RenderStage.Name == "Picking"; bool hasBegin = false; for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderSprite = (RenderSprite)renderNode.RenderObject; var spriteComp = renderSprite.SpriteComponent; var transfoComp = renderSprite.TransformComponent; var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default; var sprite = spriteComp.CurrentSprite; if (sprite == null) continue; // TODO: this should probably be moved to Prepare() // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f); Vector4 projectedPosition; Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition); var projectedZ = projectedPosition.Z / projectedPosition.W; // Update the sprite batch var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque; var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null; // TODO remove this code when material are available if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState) { if (hasBegin) { sprite3DBatch.End(); } sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, 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. { var compId = RuntimeIdHelper.ToRuntimeId(spriteComp); color = new Color4(compId); } // 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; } // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image) var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height); if (sprite.Orientation == ImageOrientation.Rotated90) { var oldCenterX = normalizedCenter.X; normalizedCenter.X = -normalizedCenter.Y; normalizedCenter.Y = oldCenterX; } // apply the offset due to the center of the sprite var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal); worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21; worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22; worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23; // draw the sprite sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ); } if(hasBegin) sprite3DBatch.End(); }