public Renderer(RenderSurface surface) { Surface = surface; ContentArchive content; using (var stream = GetType().Assembly.GetManifestResourceStream("DemoRenderer.DemoRenderer.contentarchive")) { content = ContentArchive.Load(stream); } Shapes = new ShapesExtractor(looper, pool); SphereRenderer = new RayTracedRenderer <SphereInstance>(content, @"ShapeDrawing\RenderSpheres"); CapsuleRenderer = new RayTracedRenderer <CapsuleInstance>(content, @"ShapeDrawing\RenderCapsules"); CylinderRenderer = new RayTracedRenderer <CylinderInstance>(content, @"ShapeDrawing\RenderCylinders"); BoxRenderer = new BoxRenderer(content); TriangleRenderer = new TriangleRenderer(content); MeshRenderer = new MeshRenderer(Shapes.MeshCache, content); Lines = new LineExtractor(pool, looper); LineRenderer = new LineRenderer(content); Background = new BackgroundRenderer(content); CompressToSwap = new CompressToSwap(content); ImageRenderer = new ImageRenderer(content); ImageBatcher = new ImageBatcher(pool); GlyphRenderer = new GlyphRenderer(content); TextBatcher = new TextBatcher(); UILineRenderer = new UILineRenderer(content); UILineBatcher = new UILineBatcher(); OnResize(); }
public void Draw(TextBuilder text, TextBatcher textBatcher, DemoSet demoSet, Vector2 position, float textHeight, Vector3 textColor, Font font) { if (TrackingInput) { text.Clear().Append("Swap demo to: "); if (TargetDemoIndex >= 0) { text.Append(TargetDemoIndex); } else { text.Append("_"); } textBatcher.Write(text, position, textHeight, textColor, font); var lineSpacing = textHeight * 1.1f; position.Y += textHeight * 0.5f; textHeight *= 0.8f; for (int i = 0; i < demoSet.Count; ++i) { position.Y += lineSpacing; text.Clear().Append(demoSet.GetName(i)); textBatcher.Write(text.Clear().Append(i).Append(": ").Append(demoSet.GetName(i)), position, textHeight, textColor, font); } } }
public void Render(Camera camera) { if (Surface.Resolution.X != depthBuffer.Description.Width || Surface.Resolution.Y != depthBuffer.Description.Height) { OnResize(); } var context = Surface.Context; Shapes.MeshCache.FlushPendingUploads(context); context.Rasterizer.SetViewport(0, 0, Surface.Resolution.X, Surface.Resolution.Y, 0.0f, 1.0f); //Note reversed depth. context.ClearDepthStencilView(dsv, DepthStencilClearFlags.Depth, 0, 0); context.ClearRenderTargetView(rtv, new SharpDX.Mathematics.Interop.RawColor4()); context.OutputMerger.SetRenderTargets(dsv, rtv); context.Rasterizer.State = rasterizerState; context.OutputMerger.SetDepthStencilState(opaqueDepthState); //All ray traced shapes use analytic coverage writes to get antialiasing. context.OutputMerger.SetBlendState(a2cBlendState); SphereRenderer.Render(context, camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.spheres.Span), 0, Shapes.spheres.Count); CapsuleRenderer.Render(context, camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.capsules.Span), 0, Shapes.capsules.Count); CylinderRenderer.Render(context, camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.cylinders.Span), 0, Shapes.cylinders.Count); //Non-raytraced shapes just use regular opaque rendering. context.OutputMerger.SetBlendState(opaqueBlendState); BoxRenderer.Render(context, camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.boxes.Span), 0, Shapes.boxes.Count); TriangleRenderer.Render(context, camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.triangles.Span), 0, Shapes.triangles.Count); MeshRenderer.Render(context, camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.meshes.Span), 0, Shapes.meshes.Count); LineRenderer.Render(context, camera, Surface.Resolution, SpanConverter.AsSpan(Lines.lines.Span), 0, Lines.lines.Count); Background.Render(context, camera); //Resolve MSAA rendering down to a single sample buffer for screenspace work. //Note that we're not bothering to properly handle tonemapping during the resolve. That's going to hurt quality a little, but the demos don't make use of very wide ranges. //(If for some reason you end up expanding the demos to make use of wider HDR, you can make this a custom resolve pretty easily.) context.ResolveSubresource(colorBuffer, 0, resolvedColorBuffer, 0, Format.R16G16B16A16_Float); context.OutputMerger.SetRenderTargets(resolvedRTV); //Glyph and screenspace line drawing rely on the same premultiplied alpha blending transparency. We'll handle their state out here. context.OutputMerger.SetBlendState(uiBlendState); context.OutputMerger.SetDepthStencilState(uiDepthState); ImageRenderer.PreparePipeline(context); ImageBatcher.Flush(context, Surface.Resolution, ImageRenderer); UILineBatcher.Flush(context, Surface.Resolution, UILineRenderer); GlyphRenderer.PreparePipeline(context); TextBatcher.Flush(context, Surface.Resolution, GlyphRenderer); //Note that, for now, the compress to swap handles its own depth state since it's the only post processing stage. context.OutputMerger.SetBlendState(opaqueBlendState); context.Rasterizer.State = rasterizerState; CompressToSwap.Render(context, resolvedSRV, Surface.RTV); }
public void Render(Camera camera) { if (Surface.Resolution.X != width || Surface.Resolution.Y != height) { OnResize(); } Shapes.MeshCache.FlushPendingUploads(); GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer); //Note reversed depth. GL.ClearDepth(0.0f); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.DepthTest); GL.DepthFunc(DepthFunction.Greater); //All ray traced shapes use analytic coverage writes to get antialiasing. GL.Enable(EnableCap.SampleAlphaToCoverage); SphereRenderer.Render(camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.spheres.Span), 0, Shapes.spheres.Count); CapsuleRenderer.Render(camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.capsules.Span), 0, Shapes.capsules.Count); CylinderRenderer.Render(camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.cylinders.Span), 0, Shapes.cylinders.Count); //Non-raytraced shapes just use regular opaque rendering. GL.Disable(EnableCap.SampleAlphaToCoverage); BoxRenderer.Render(camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.boxes.Span), 0, Shapes.boxes.Count); TriangleRenderer.Render(camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.triangles.Span), 0, Shapes.triangles.Count); MeshRenderer.Render(camera, Surface.Resolution, SpanConverter.AsSpan(Shapes.meshes.Span), 0, Shapes.meshes.Count); LineRenderer.Render(camera, Surface.Resolution, SpanConverter.AsSpan(Lines.lines.Span), 0, Lines.lines.Count); Background.Render(camera); GL.Disable(EnableCap.CullFace); GL.Disable(EnableCap.DepthTest); //Resolve MSAA rendering down to a single sample buffer for screenspace work. //Note that we're not bothering to properly handle tonemapping during the resolve. That's going to hurt quality a little, but the demos don't make use of very wide ranges. //(If for some reason you end up expanding the demos to make use of wider HDR, you can make this a custom resolve pretty easily.) GL.BlitNamedFramebuffer(framebuffer, resolvedFramebuffer, 0, 0, width, height, 0, 0, width, height, ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Nearest); GL.BindFramebuffer(FramebufferTarget.Framebuffer, resolvedFramebuffer); //Glyph and screenspace line drawing rely on the same premultiplied alpha blending transparency. We'll handle their state out here. GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha); GL.BlendEquation(BlendEquationMode.FuncAdd); ImageRenderer.PreparePipeline(); ImageBatcher.Flush(Surface.Resolution, ImageRenderer); UILineBatcher.Flush(Surface.Resolution, UILineRenderer); GlyphRenderer.PreparePipeline(); TextBatcher.Flush(Surface.Resolution, GlyphRenderer); GL.Disable(EnableCap.Blend); GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); CompressToSwap.Render(resolvedColorBuffer); }
public void Render(Camera camera) { if (Surface.Resolution.X != depthBuffer.Description.Width || Surface.Resolution.Y != depthBuffer.Description.Height) { OnResize(); } var context = Surface.Context; context.Rasterizer.SetViewport(0, 0, Surface.Resolution.X, Surface.Resolution.Y, 0.0f, 1.0f); //Note reversed depth. context.ClearDepthStencilView(dsv, DepthStencilClearFlags.Depth, 0, 0); //The background render is going to fill out the entire color buffer, but having a clear can be useful- e.g. clearing out MSAA history. //We don't use MSAA right now, but the cost of doing this clear is negligible and it avoids a surprise later. context.ClearRenderTargetView(rtv, new SharpDX.Mathematics.Interop.RawColor4()); context.OutputMerger.SetRenderTargets(dsv, rtv); context.Rasterizer.State = rasterizerState; context.OutputMerger.SetBlendState(opaqueBlendState); context.OutputMerger.SetDepthStencilState(opaqueDepthState); SphereRenderer.Render(context, camera, Surface.Resolution, Shapes.spheres.Span.Memory, 0, Shapes.spheres.Count); CapsuleRenderer.Render(context, camera, Surface.Resolution, Shapes.capsules.Span.Memory, 0, Shapes.capsules.Count); BoxRenderer.Render(context, camera, Surface.Resolution, Shapes.boxes.Span.Memory, 0, Shapes.boxes.Count); LineRenderer.Render(context, camera, Surface.Resolution, Lines.lines.Span.Memory, 0, Lines.lines.Count); Background.Render(context, camera); //Glyph and screenspace line drawing rely on the same premultiplied alpha blending transparency. We'll handle their state out here. context.OutputMerger.SetBlendState(uiBlendState); context.OutputMerger.SetDepthStencilState(uiDepthState); UILineBatcher.Flush(context, Surface.Resolution, UILineRenderer); GlyphRenderer.PreparePipeline(context); TextBatcher.Flush(context, Surface.Resolution, GlyphRenderer); //Note that, for now, the compress to swap handles its own depth state since it's the only post processing stage. context.OutputMerger.SetBlendState(opaqueBlendState); context.Rasterizer.State = rasterizerState; CompressToSwap.Render(context, srv, Surface.RTV); }
public Renderer(RenderSurface surface) { looper = new ParallelLooper(); Surface = surface; using (var stream = GetType().Assembly.GetManifestResourceStream("DemoRenderer.DemoRenderer.shaderarchive")) { ShaderCache = ShaderCache.Load(stream); } pool = new BufferPool(); Shapes = new ShapesExtractor(Surface.Device, looper, pool); SphereRenderer = new RayTracedRenderer <SphereInstance>(surface.Device, ShaderCache, @"ShapeDrawing\RenderSpheres.hlsl"); CapsuleRenderer = new RayTracedRenderer <CapsuleInstance>(surface.Device, ShaderCache, @"ShapeDrawing\RenderCapsules.hlsl"); BoxRenderer = new BoxRenderer(surface.Device, ShaderCache); TriangleRenderer = new TriangleRenderer(surface.Device, ShaderCache); MeshRenderer = new MeshRenderer(surface.Device, Shapes.MeshCache, ShaderCache); Lines = new LineExtractor(pool, looper); LineRenderer = new LineRenderer(surface.Device, ShaderCache); Background = new BackgroundRenderer(surface.Device, ShaderCache); CompressToSwap = new CompressToSwap(surface.Device, ShaderCache); GlyphRenderer = new GlyphRenderer(surface.Device, surface.Context, ShaderCache); TextBatcher = new TextBatcher(); UILineRenderer = new UILineRenderer(surface.Device, ShaderCache); UILineBatcher = new UILineBatcher(); OnResize(); var rasterizerStateDescription = RasterizerStateDescription.Default(); rasterizerStateDescription.IsFrontCounterClockwise = true; rasterizerStateDescription.CullMode = CullMode.Back; rasterizerState = new RasterizerState(Surface.Device, rasterizerStateDescription); rasterizerState.DebugName = "Default Rasterizer State"; var opaqueDepthStencilDescription = new DepthStencilStateDescription { IsDepthEnabled = true, DepthWriteMask = DepthWriteMask.All, //Note depth reversal. DepthComparison = Comparison.Greater, IsStencilEnabled = false }; opaqueDepthState = new DepthStencilState(Surface.Device, opaqueDepthStencilDescription); opaqueDepthState.DebugName = "Opaque Depth State"; var opaqueBlendStateDescription = BlendStateDescription.Default(); opaqueBlendState = new BlendState(Surface.Device, opaqueBlendStateDescription); opaqueBlendState.DebugName = "Opaque Blend State"; var a2cBlendStateDescription = BlendStateDescription.Default(); a2cBlendStateDescription.AlphaToCoverageEnable = true; a2cBlendState = new BlendState(Surface.Device, a2cBlendStateDescription); a2cBlendState.DebugName = "A2C Blend State"; var uiDepthStateDescription = new DepthStencilStateDescription { IsDepthEnabled = false, DepthWriteMask = DepthWriteMask.Zero, //Note depth reversal. DepthComparison = Comparison.Greater, IsStencilEnabled = false }; uiDepthState = new DepthStencilState(Surface.Device, uiDepthStateDescription); uiDepthState.DebugName = "UI Depth State"; //The UI will use premultiplied alpha. var uiBlendStateDescription = BlendStateDescription.Default(); uiBlendStateDescription.RenderTarget[0].IsBlendEnabled = true; uiBlendStateDescription.RenderTarget[0].SourceBlend = BlendOption.One; uiBlendStateDescription.RenderTarget[0].SourceAlphaBlend = BlendOption.One; uiBlendStateDescription.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha; uiBlendStateDescription.RenderTarget[0].DestinationAlphaBlend = BlendOption.InverseSourceAlpha; uiBlendStateDescription.RenderTarget[0].BlendOperation = BlendOperation.Add; uiBlendStateDescription.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add; uiBlendStateDescription.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All; uiBlendState = new BlendState(Surface.Device, uiBlendStateDescription); uiBlendState.DebugName = "UI Blend State"; }
public void Draw(TextBuilder characters, UILineBatcher lines, TextBatcher text) { //Collect information to define data window ranges. int minX = int.MaxValue; int maxX = int.MinValue; var minY = double.MaxValue; var maxY = double.MinValue; for (int i = 0; i < graphSeries.Count; ++i) { var data = graphSeries[i].Data; if (minX > data.Start) { minX = data.Start; } if (maxX < data.End) { maxX = data.End; } for (int j = data.Start; j < data.End; ++j) { var value = data[j]; if (minY > value) { minY = value; } if (maxY < value) { maxY = value; } } } //If no data series contain values, then just use a default size. if (minY == float.MinValue) { minY = 0; maxY = 1; } //You could make use of this earlier to avoid comparisons but it doesn't really matter! if (description.ForceVerticalAxisMinimumToZero) { minY = 0; if (maxY < 0) { maxY = 1; } } //Calculate the data span that takes into account rounding. We want intervals to be evenly spaced, but also to match nicely rounded numbers. //That means the span must be equal to some rounded number multiplied by the number of intervals. var yDataSpan = maxY - minY; var yIntervalCount = description.TargetVerticalTickCount + 1; var rawIntervalLength = yDataSpan / yIntervalCount; var roundingOffset = 0.5 * Math.Pow(0.1, description.VerticalIntervalLabelRounding); yDataSpan = Math.Round(rawIntervalLength * description.VerticalIntervalValueScale + roundingOffset, description.VerticalIntervalLabelRounding) * (yIntervalCount / description.VerticalIntervalValueScale); //Draw the graph body axes. var lowerLeft = description.BodyMinimum + new Vector2(0, description.BodySpan.Y); var upperRight = description.BodyMinimum + new Vector2(description.BodySpan.X, 0); var lowerRight = description.BodyMinimum + description.BodySpan; lines.Draw(description.BodyMinimum, lowerLeft, description.AxisLineRadius, description.BodyLineColor); lines.Draw(lowerLeft, lowerRight, description.AxisLineRadius, description.BodyLineColor); //Draw axis labels. characters.Clear().Append(description.HorizontalAxisLabel); var baseAxisLabelDistance = description.IntervalTickLength + description.IntervalTextHeight * description.LineSpacingMultiplier; var verticalAxisLabelDistance = baseAxisLabelDistance + 2 * description.VerticalTickTextPadding; var horizontalAxisLabelDistance = baseAxisLabelDistance + 2 * description.HorizontalTickTextPadding + description.AxisLabelHeight * description.LineSpacingMultiplier; text.Write(characters, lowerLeft + new Vector2((description.BodySpan.X - GlyphBatch.MeasureLength(characters, description.Font, description.AxisLabelHeight)) * 0.5f, horizontalAxisLabelDistance), description.AxisLabelHeight, description.TextColor, description.Font); characters.Clear().Append(description.VerticalAxisLabel); text.Write(characters, description.BodyMinimum + new Vector2(-verticalAxisLabelDistance, (description.BodySpan.Y + GlyphBatch.MeasureLength(characters, description.Font, description.AxisLabelHeight)) * 0.5f), description.AxisLabelHeight, new Vector2(0, -1), description.TextColor, description.Font); //Position tickmarks, tick labels, and background lines along the axes. { var xDataIntervalSize = (maxX - minX) / (description.TargetHorizontalTickCount + 1f); var previousTickValue = int.MinValue; float valueToPixels = description.BodySpan.X / (maxX - minX); for (int i = 0; i < description.TargetHorizontalTickCount + 2; ++i) { //Round pen offset such that the data tick lands on an integer. var valueAtTick = i * xDataIntervalSize; var tickValue = (int)Math.Round(valueAtTick); if (tickValue == previousTickValue) { //Don't bother creating redundant ticks. continue; } previousTickValue = tickValue; var penPosition = lowerLeft + new Vector2(tickValue * valueToPixels, 0); var tickEnd = penPosition + new Vector2(0, description.IntervalTickLength); var backgroundEnd = penPosition - new Vector2(0, description.BodySpan.Y); lines.Draw(penPosition, tickEnd, description.IntervalTickRadius, description.BodyLineColor); lines.Draw(penPosition, backgroundEnd, description.BackgroundLineRadius, description.BodyLineColor); characters.Clear().Append(tickValue); text.Write(characters, tickEnd + new Vector2(GlyphBatch.MeasureLength(characters, description.Font, description.IntervalTextHeight) * -0.5f, description.HorizontalTickTextPadding + description.IntervalTextHeight * description.LineSpacingMultiplier), description.IntervalTextHeight, description.TextColor, description.Font); } } { var yDataIntervalSize = yDataSpan / (description.TargetVerticalTickCount + 1f); var previousTickValue = double.MinValue; //Note the inclusion of the scale. Rounding occurs post-scale; moving back to pixels requires undoing the scale. var valueToPixels = description.BodySpan.Y / (yDataSpan * description.VerticalIntervalValueScale); for (int i = 0; i < description.TargetVerticalTickCount + 2; ++i) { var tickValue = Math.Round((minY + yDataIntervalSize * i) * description.VerticalIntervalValueScale, description.VerticalIntervalLabelRounding); if (tickValue == previousTickValue) { //Don't bother creating redundant ticks. continue; } previousTickValue = tickValue; var penPosition = lowerLeft - new Vector2(0, (float)(tickValue * valueToPixels)); var tickEnd = penPosition - new Vector2(description.IntervalTickLength, 0); var backgroundEnd = penPosition + new Vector2(description.BodySpan.X, 0); lines.Draw(penPosition, tickEnd, description.IntervalTickRadius, description.BodyLineColor); lines.Draw(penPosition, backgroundEnd, description.BackgroundLineRadius, description.BodyLineColor); characters.Clear().Append(tickValue, description.VerticalIntervalLabelRounding); text.Write(characters, tickEnd + new Vector2(-description.VerticalTickTextPadding, 0.5f * GlyphBatch.MeasureLength(characters, description.Font, description.IntervalTextHeight)), description.IntervalTextHeight, new Vector2(0, -1), description.TextColor, description.Font); } } //Draw the line graphs on top of the body. { var dataToPixelsScale = new Vector2(description.BodySpan.X / (maxX - minX), (float)(description.BodySpan.Y / yDataSpan)); Vector2 DataToScreenspace(int x, double y) { var graphCoordinates = new Vector2(x - minX, (float)(y - minY)) * dataToPixelsScale; var screenCoordinates = graphCoordinates; screenCoordinates.Y = description.BodySpan.Y - screenCoordinates.Y; screenCoordinates += description.BodyMinimum; return(screenCoordinates); } for (int i = 0; i < graphSeries.Count; ++i) { var series = graphSeries[i]; var data = series.Data; var count = data.End - data.Start; if (count > 0) { var previousScreenPosition = DataToScreenspace(data.Start, data[data.Start]); if (count > 1) { for (int j = data.Start + 1; j < data.End; ++j) { var currentScreenPosition = DataToScreenspace(j, data[j]); lines.Draw(previousScreenPosition, currentScreenPosition, series.LineRadius, series.LineColor); previousScreenPosition = currentScreenPosition; } } else { //Only one datapoint. Draw a zero length line just to draw a dot. (The shader can handle it without producing nans.) lines.Draw(previousScreenPosition, previousScreenPosition, series.LineRadius, series.LineColor); } } } } //Draw the legend entry last. Alpha blending will put it on top in case the legend is positioned on top of the body. { var penPosition = description.LegendMinimum; var legendLineSpacing = description.LegendNameHeight * 1.5f; penPosition.Y += legendLineSpacing; for (int i = 0; i < graphSeries.Count; ++i) { var series = graphSeries[i]; var lineStart = new Vector2(penPosition.X, penPosition.Y); var lineEnd = lineStart + new Vector2(description.LegendLineLength, -0.7f * description.LegendNameHeight); lines.Draw(lineStart, lineEnd, series.LineRadius, series.LineColor); var textStart = new Vector2(lineEnd.X + series.LineRadius + description.LegendNameHeight * 0.2f, penPosition.Y); characters.Clear().Append(series.Name); text.Write(characters, textStart, description.LegendNameHeight, description.TextColor, description.Font); penPosition.Y += legendLineSpacing; } } }
public Renderer(RenderSurface surface) { looper = new ParallelLooper(); Surface = surface; using (var stream = new MemoryStream(Resources.DemoRendererShaders)) { ShaderCache = ShaderCache.Load(stream); } Shapes = new ShapesExtractor(looper); SphereRenderer = new SphereRenderer(surface.Device, ShaderCache); Lines = new LineExtractor(looper); LineRenderer = new LineRenderer(surface.Device, ShaderCache); Background = new BackgroundRenderer(surface.Device, ShaderCache); CompressToSwap = new CompressToSwap(surface.Device, ShaderCache); GlyphRenderer = new GlyphRenderer(surface.Device, surface.Context, ShaderCache); TextBatcher = new TextBatcher(); UILineRenderer = new UILineRenderer(surface.Device, ShaderCache); UILineBatcher = new UILineBatcher(); OnResize(); var rasterizerStateDescription = RasterizerStateDescription.Default(); rasterizerStateDescription.IsFrontCounterClockwise = true; rasterizerStateDescription.CullMode = CullMode.None; rasterizerState = new RasterizerState(Surface.Device, rasterizerStateDescription); rasterizerState.DebugName = "Default Rasterizer State"; var opaqueDepthStencilDescription = new DepthStencilStateDescription { IsDepthEnabled = true, DepthWriteMask = DepthWriteMask.All, //Note depth reversal. DepthComparison = Comparison.Greater, IsStencilEnabled = false }; opaqueDepthState = new DepthStencilState(Surface.Device, opaqueDepthStencilDescription); opaqueDepthState.DebugName = "Opaque Depth State"; var opaqueBlendStateDescription = BlendStateDescription.Default(); opaqueBlendState = new BlendState(Surface.Device, opaqueBlendStateDescription); opaqueBlendState.DebugName = "Opaque Blend State"; var uiDepthStateDescription = new DepthStencilStateDescription { IsDepthEnabled = false, DepthWriteMask = DepthWriteMask.Zero, //Note depth reversal. DepthComparison = Comparison.Greater, IsStencilEnabled = false }; uiDepthState = new DepthStencilState(Surface.Device, uiDepthStateDescription); uiDepthState.DebugName = "UI Depth State"; //The UI will use premultiplied alpha. var uiBlendStateDescription = BlendStateDescription.Default(); uiBlendStateDescription.RenderTarget[0].IsBlendEnabled = true; uiBlendStateDescription.RenderTarget[0].SourceBlend = BlendOption.One; uiBlendStateDescription.RenderTarget[0].SourceAlphaBlend = BlendOption.One; uiBlendStateDescription.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha; uiBlendStateDescription.RenderTarget[0].DestinationAlphaBlend = BlendOption.InverseSourceAlpha; uiBlendStateDescription.RenderTarget[0].BlendOperation = BlendOperation.Add; uiBlendStateDescription.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add; uiBlendStateDescription.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All; uiBlendState = new BlendState(Surface.Device, uiBlendStateDescription); uiBlendState.DebugName = "UI Blend State"; }