internal void AddGeometry(Vertex[] vertices, RenderProgram renderProgram) { // Find a batch with matching render programs or create a new one if it does not exist GeometryBatch batch = FindBatch(renderProgram) ?? CreateBatch(renderProgram); batch.AddVertices(vertices); }
public void RenderOutlines(IBatchContainer container, int layer, bool showLights, Color?lineColor = null, Color?lightColor = null) { using (var group = BatchGroup.New(container, layer)) { using (var gb = GeometryBatch.New(group, 0, IlluminantMaterials.DebugOutlines)) { VisualizerLineWriterInstance.Batch = gb; VisualizerLineWriterInstance.Color = lineColor.GetValueOrDefault(Color.White); foreach (var lo in Environment.Obstructions) { lo.GenerateLines(VisualizerLineWriterInstance); } VisualizerLineWriterInstance.Batch = null; } int i = 0; if (showLights) { foreach (var lightSource in Environment.LightSources) { var cMax = lightColor.GetValueOrDefault(Color.White); var cMin = cMax * 0.25f; using (var gb = GeometryBatch.New(group, i + 1, IlluminantMaterials.DebugOutlines)) { gb.AddFilledRing(lightSource.Position, 0f, 2f, cMax, cMax); gb.AddFilledRing(lightSource.Position, lightSource.RampStart - 1f, lightSource.RampStart + 1f, cMax, cMax); gb.AddFilledRing(lightSource.Position, lightSource.RampEnd - 1f, lightSource.RampEnd + 1f, cMin, cMin); } i += 1; } } } }
private void RemoveBatch(GeometryBatch batch) { for (int i = Batches.Count - 1; i >= 0; i--) { if (Batches[i] == batch) { Batches.RemoveAt(i); break; } } SortBatchesByDrawLayer(); }
private void ParallelPrepareOrbs(int partitionIndex, int partitionCount, DrawArgs args) { Orb orb; int i = 0; GeometryBatch batch = null; using (var e = Orbs.GetParallelEnumerator(partitionIndex, partitionCount)) while (e.GetNext(out orb)) { if (batch == null) { batch = GeometryBatch.New(args.Frame, 1, Materials.WorldSpaceGeometry); } // Compute the position of this orb at the current time var position = Orb.Interpolator( Orb.InterpolatorSource, ref orb, 0, (args.Now - orb.LastUpdateAt) / orb.Duration ); // AddFilledRing is actually pretty computationally intensive compared to drawing a quad // so on XBox 360 you can get much higher performance by switching from filled rings to quads if (UseQuads) { batch.AddFilledQuad( position - orb.Size, position + orb.Size, orb.Color ); } else { batch.AddFilledRing( position, Vector2.Zero, orb.Size, orb.Color, Color.Transparent ); } i += 1; if ((i % BatchSize) == 0) { // Once our batch contains enough objects, we 'dispose' it to tell the renderer that it is done being prepared. // This normally looks like 'using (batch)', which is (IMO) easier to understand... still, kind of a nasty hack. batch.Dispose(); batch = null; } } if (batch != null) { batch.Dispose(); } }
internal GeometryBatch CreateBatch(RenderProgram renderProgram) { GeometryBatch newBatch = new GeometryBatch(renderProgram); Batches.Add(newBatch); SortBatchesByDrawLayer(); if (BatchesAreHot) { newBatch.Begin(); } return(newBatch); }
public GeometryBatch GetGeometryBatch(int?layer, bool?worldSpace, BlendState blendState) { if (Materials == null) { throw new InvalidOperationException("You cannot use the argumentless ImperativeRenderer constructor."); } var actualLayer = layer.GetValueOrDefault(Layer); var actualWorldSpace = worldSpace.GetValueOrDefault(WorldSpace); var desiredBlendState = blendState ?? BlendState; CachedBatch cacheEntry; if (!Cache.TryGet <GeometryBatch>( out cacheEntry, CachedBatchType.Geometry, container: Container, layer: actualLayer, worldSpace: actualWorldSpace, rasterizerState: RasterizerState, depthStencilState: DepthStencilState, blendState: desiredBlendState, samplerState: null, customMaterial: null, useZBuffer: UseZBuffer )) { var material = Materials.GetGeometryMaterial( actualWorldSpace, rasterizerState: RasterizerState, depthStencilState: DepthStencilState, blendState: desiredBlendState ); cacheEntry.Batch = GeometryBatch.New(Container, actualLayer, material); Cache.InsertAtFront(ref cacheEntry, null); } if (AutoIncrementLayer && !layer.HasValue) { Layer += 1; } return((GeometryBatch)cacheEntry.Batch); }
public override void Draw(Squared.Render.Frame frame) { const float LightmapScale = 1f; LightmapMaterials.ViewportScale = new Vector2(1f / LightmapScale); LightmapMaterials.ProjectionMatrix = Matrix.CreateOrthographicOffCenter( 0, Width, Height, 0, 0, 1 ); ClearBatch.AddNew(frame, 0, Game.ScreenMaterials.Clear, clearColor: Color.Black); Renderer.RenderLighting(frame, frame, 1); if (ShowOutlines) { Renderer.RenderOutlines(frame, 2, true); } using (var gb = GeometryBatch.New(frame, 3, Game.ScreenMaterials.Get(Game.ScreenMaterials.ScreenSpaceGeometry, blendState: BlendState.Opaque))) for (var i = 0; i < Receivers.Length; i++) { var r = Receivers[i]; if (!r.ReceivedLight.HasValue) { continue; } var size = new Vector2(8, 8); var bounds = new Bounds(r.Position - size, r.Position + size); var color = new Color(r.ReceivedLight.Value.X, r.ReceivedLight.Value.Y, r.ReceivedLight.Value.Z, 1.0f) * r.ReceivedLight.Value.W; // Console.WriteLine("Receiver {0} at {1}: {2}", i, r.Position, r.ReceivedLight); gb.AddFilledQuad(bounds, color); } }
public unsafe GraphicsCanvas([NotNull] GraphicsDevice device, [NotNull] RenderTargetView renderTarget, Vector2f canvasUnits) { info = new GraphicsCanvasInfo(this); // Initialize shaders. Initialize(); this.unitSize = canvasUnits; this.device = device; this.renderTarget = renderTarget; this.batch = Geometry.CreateBatch(VertexData.Format, new IndexFormat(true), MaxVerticesInBatch, MaxIndicesInBatch, CyclicBufferCount); // We also immediatelly bind it to device. this.batch.BindToDevice(device); // We create vertex constants buffer. { TypelessBuffer vertexConstBuffer = new TypelessBuffer(Usage.Dynamic, BufferUsage.ConstantBuffer, CPUAccess.Write, GraphicsLocality.DeviceOrSystemMemory, 16 * 4 * 2); vertexConstBuffer.DisposeOnViewDispose = true; ConstantBufferLayoutBuilder vertexBufferLayout = new ConstantBufferLayoutBuilder(); vertexBufferLayout.AppendElement("PositionTransform", PinFormat.Float4x4); vertexBufferLayout.AppendElement("TextureTransform", PinFormat.Float4x4); vertexConstants = vertexConstBuffer.CreateConstantBuffer(vertexBufferLayout.CreateLayout()); } // We create pixel constants buffer. pixelConstants = new TypelessBuffer(Usage.Dynamic, BufferUsage.ConstantBuffer, CPUAccess.Write, GraphicsLocality.DeviceOrSystemMemory, ConstantBufferView.MaxSize); }
public override void Draw(GameTime gameTime, Frame frame) { ClearBatch.AddNew(frame, 4, Materials.Clear, clearColor: new Color(16, 32, 48)); var alphaGeometry = Materials.Get(Materials.ScreenSpaceGeometry, blendState: BlendState.AlphaBlend); using (var gb = GeometryBatch.New(frame, 5, alphaGeometry)) { gb.AddGradientFilledQuad( Vector2.Zero, new Vector2(Graphics.PreferredBackBufferWidth, Graphics.PreferredBackBufferHeight), Color.DarkSlateGray, Color.DarkSlateGray, Color.SlateBlue, Color.SlateBlue ); } using (var gb = GeometryBatch.New(frame, 6, alphaGeometry)) { var alphaBlack = new Color(0, 0, 0, 192); var alphaBlack2 = new Color(0, 0, 0, 64); gb.AddQuadBorder( Playfield.Bounds.TopLeft + new Vector2(32 + 24, 0), Playfield.Bounds.BottomRight + new Vector2(-32 - 24, 0), alphaBlack2, alphaBlack, 24 ); } // Render the contents of the trail buffer to the screen using additive blending using (var bb = BitmapBatch.New(frame, 7, Materials.Trail)) { bb.Add(new BitmapDrawCall( TrailBuffer, Vector2.Zero, (float)TrailScale )); } // Render the paddles and ball to both the framebuffer and the trail buffer (note the different layer values) using (var gb = GeometryBatch.New(frame, 8, alphaGeometry)) using (var gb2 = GeometryBatch.New(frame, 9, alphaGeometry)) using (var trailBatch = GeometryBatch.New(frame, 2, alphaGeometry)) { foreach (var paddle in Paddles) { gb.AddFilledQuad( paddle.Bounds.TopLeft, paddle.Bounds.BottomRight, Color.White ); gb2.AddQuadBorder( paddle.Bounds.TopLeft, paddle.Bounds.BottomRight, Color.Black, Color.Black, 2.25f ); trailBatch.AddFilledQuad( paddle.Bounds.TopLeft, paddle.Bounds.BottomRight, Color.White ); } gb.AddFilledRing(Ball.Position, 0.0f, Ball.Radius, Color.White, Color.White); gb2.AddFilledRing(Ball.Position, Ball.Radius, Ball.Radius + 2.0f, Color.Black, Color.Black); trailBatch.AddFilledRing(Ball.Position, 0.0f, Ball.Radius, Color.White, Color.White); } // Render the score values using a stringbatch (unfortunately this uses spritebatch to render spritefonts :( ) { var ir = new ImperativeRenderer(frame, Materials, 10, blendState: BlendState.AlphaBlend); ir.DrawString( Font, String.Format("Player 1: {0:00}", Scores[0]), new Vector2(16, 16) ); var player2Text = String.Format("Player 2: {0:00}", Scores[1]); ir.DrawString( Font, player2Text, new Vector2(Graphics.PreferredBackBufferWidth - 16 - Font.MeasureString(player2Text).X, 16) ); } // The first stage of our frame involves selecting the trail buffer as our render target (note that it's layer 0) SetRenderTargetBatch.AddNew(frame, 0, TrailBuffer); if (FirstFrame) { // If it's the first time we've rendered, we erase the trail buffer since it could contain anything ClearBatch.AddNew(frame, 1, Materials.Clear, clearColor: Color.Black); FirstFrame = false; } else { // Otherwise, we fade out the contents of the trail buffer using (var gb = GeometryBatch.New(frame, 1, Materials.SubtractiveGeometry)) { gb.AddFilledQuad( new Bounds(Vector2.Zero, new Vector2(Graphics.PreferredBackBufferWidth, Graphics.PreferredBackBufferHeight)), new Color(12, 12, 12, 0) ); } } // After the trail buffer has been updated, we turn it off and begin rendering to the framebuffer. Note layer 3. SetRenderTargetBatch.AddNew(frame, 3, null); }