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); using (var bg = BatchGroup.New(frame, 2)) { var dc = new BitmapDrawCall(TestImage, new Vector2(0, 550), 0.55f); using (var bb = BitmapBatch.New(bg, 0, Renderer.Materials.ScreenSpaceBitmap)) bb.Add(ref dc); dc.Position.X += 600; dc.Textures = new TextureSet(dc.Texture, RampTexture); using (var bb2 = BitmapBatch.New(bg, 1, Renderer.IlluminantMaterials.ScreenSpaceRampBitmap, samplerState2: SamplerState.LinearClamp)) bb2.Add(ref dc); } if (ShowOutlines) { Renderer.RenderOutlines(frame, 2, true); } }
public override void Draw(GameTime gameTime, Frame frame) { ClearBatch.AddNew(frame, -1, materials.Clear, clearColor: Color.CornflowerBlue); level.Draw(gameTime, frame, materials); DrawHud(frame); }
public override void Draw(GameTime gameTime, Frame frame) { ClearBatch.AddNew(frame, 0, Materials.Clear, clearColor: Color.Black); ParallelDrawer.UserData.Now = (float)Time.Seconds; ParallelDrawer.UserData.Frame = frame; ParallelDrawer.Invoke(); }
public override void Draw(GameTime gameTime, Frame frame) { // HACK: We never set the blend state explicitly anywhere (unlike what SpriteBatch did), // but it's sufficient to just set it once per frame here. // Normally you would do this in batch setup, but this is fine. graphics.GraphicsDevice.BlendState = BlendState.AlphaBlend; ClearBatch.AddNew(frame, -1, materials.Clear, clearColor: Color.CornflowerBlue); level.Draw(gameTime, frame, materials); DrawHud(frame); }
/// <summary> /// Adds a clear batch. Note that this will *always* advance the layer unless you specify a layer index explicitly. /// </summary> public void Clear( int?layer = null, Color?color = null, float?z = null, int?stencil = null ) { int _layer = layer.GetValueOrDefault(Layer); ClearBatch.AddNew(Container, _layer, Materials.Clear, color, z, stencil); if (!layer.HasValue) { Layer += 1; } }
public override void Draw(GameTime gameTime, Frame frame) { ClearBatch.AddNew(frame, -1, Materials.Clear, clearColor: ClearColor); const int width = 1280; const int height = 720; var options = new ParallelOptions { // MaxDegreeOfParallelism = 1 }; int layer = 0; Parallel.For( 0, height, options, // One batch per worker thread () => BitmapBatch.New( frame, // Suppress batch combining Interlocked.Increment(ref layer), Materials.ScreenSpaceBitmap ), (y, loopState, bb) => { var drawCall = new BitmapDrawCall(WhitePixel, new Vector2(0, y)); float fx = 0; var range = bb.ReserveSpace(width); var array = range.Array; var offset = range.Offset; for (int x = 0; x < width; x++, fx++) { drawCall.Texture = ((x % 2) == 0) ? WhitePixel : GrayPixel; drawCall.Position.X = fx; drawCall.MultiplyColor = new Color(255, x % 255, y % 255); array[offset + x] = drawCall; } return(bb); }, (bb) => bb.Dispose() ); }
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 ); CreateRenderTargets(); var args = new float[] { MagnitudeScale, MiddleGray, AppliedAverageLuminance, MaximumLuminance }; using (var bg = BatchGroup.ForRenderTarget( frame, -1, Lightmap, (dm, _) => Renderer.IlluminantMaterials.SetGammaCompressionParameters(args[0], args[1], args[2], args[3]) )) { ClearBatch.AddNew(bg, 0, LightmapMaterials.Clear, clearColor: Color.Black, clearZ: 0, clearStencil: 0); Renderer.RenderLighting(frame, bg, 1, intensityScale: 1 / MagnitudeScale); }; ClearBatch.AddNew(frame, 0, Game.ScreenMaterials.Clear, clearColor: Color.Black); using (var bb = BitmapBatch.New( frame, 1, Game.ScreenMaterials.Get(Renderer.IlluminantMaterials.ScreenSpaceGammaCompressedBitmap, blendState: BlendState.Opaque) )) bb.Add(new BitmapDrawCall(Lightmap, Vector2.Zero)); if (ShowOutlines) { Renderer.RenderOutlines(frame, 2, true); } }
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); } }
/// <summary> /// Renders all light sources into the target batch container on the specified layer. /// </summary> /// <param name="frame">Necessary for bookkeeping.</param> /// <param name="container">The batch container to render lighting into.</param> /// <param name="layer">The layer to render lighting into.</param> /// <param name="intensityScale">A factor to scale the intensity of all light sources. You can use this to rescale the intensity of light values for HDR.</param> public void RenderLighting(Frame frame, IBatchContainer container, int layer, float intensityScale = 1.0f) { // FIXME var pointLightVertexCount = Environment.LightSources.Count * 4; var pointLightIndexCount = Environment.LightSources.Count * 6; if (PointLightVertices.Length < pointLightVertexCount) { PointLightVertices = new PointLightVertex[1 << (int)Math.Ceiling(Math.Log(pointLightVertexCount, 2))]; } if ((PointLightIndices == null) || (PointLightIndices.Length < pointLightIndexCount)) { PointLightIndices = new short[pointLightIndexCount]; int i = 0, j = 0; while (i < pointLightIndexCount) { PointLightIndices[i++] = (short)(j + 0); PointLightIndices[i++] = (short)(j + 1); PointLightIndices[i++] = (short)(j + 3); PointLightIndices[i++] = (short)(j + 1); PointLightIndices[i++] = (short)(j + 2); PointLightIndices[i++] = (short)(j + 3); j += 4; } } var needStencilClear = true; int vertexOffset = 0, indexOffset = 0; LightSource batchFirstLightSource = null; BatchGroup currentLightGroup = null; int layerIndex = 0; using (var sortedLights = BufferPool <LightSource> .Allocate(Environment.LightSources.Count)) using (var resultGroup = BatchGroup.New(container, layer, before: StoreScissorRect, after: RestoreScissorRect)) { if (Render.Tracing.RenderTrace.EnableTracing) { Render.Tracing.RenderTrace.Marker(resultGroup, -9999, "Frame {0:0000} : LightingRenderer {1:X4} : Begin", frame.Index, this.GetHashCode()); } int i = 0; var lightCount = Environment.LightSources.Count; foreach (var lightSource in Environment.LightSources) { sortedLights.Data[i++] = lightSource; } Array.Sort(sortedLights.Data, 0, lightCount, LightSourceComparerInstance); int lightGroupIndex = 1; for (i = 0; i < lightCount; i++) { var lightSource = sortedLights.Data[i]; if (lightSource.Opacity <= 0) { continue; } if (batchFirstLightSource != null) { var needFlush = (needStencilClear) || (batchFirstLightSource.ClipRegion.HasValue != lightSource.ClipRegion.HasValue) || (batchFirstLightSource.NeutralColor != lightSource.NeutralColor) || (batchFirstLightSource.Mode != lightSource.Mode) || (batchFirstLightSource.RampMode != lightSource.RampMode) || (batchFirstLightSource.RampTexture != lightSource.RampTexture) || (batchFirstLightSource.RampTextureFilter != lightSource.RampTextureFilter); if (needFlush) { if (Render.Tracing.RenderTrace.EnableTracing) { Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Point Light Flush ({2} point(s))", frame.Index, this.GetHashCode(), PointLightBatchBuffer.Count); } FlushPointLightBatch(ref currentLightGroup, ref batchFirstLightSource, ref layerIndex); indexOffset = 0; } } if (batchFirstLightSource == null) { batchFirstLightSource = lightSource; } if (currentLightGroup == null) { currentLightGroup = BatchGroup.New(resultGroup, lightGroupIndex++, before: RestoreScissorRect); } var lightBounds = new Bounds(lightSource.Position - new Vector2(lightSource.RampEnd), lightSource.Position + new Vector2(lightSource.RampEnd)); Bounds clippedLightBounds; if (lightSource.ClipRegion.HasValue) { var clipBounds = lightSource.ClipRegion.Value; if (!lightBounds.Intersection(ref lightBounds, ref clipBounds, out clippedLightBounds)) { continue; } } else { clippedLightBounds = lightBounds; } if (needStencilClear) { if (Render.Tracing.RenderTrace.EnableTracing) { Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Stencil Clear", frame.Index, this.GetHashCode()); } ClearBatch.AddNew(currentLightGroup, layerIndex++, IlluminantMaterials.ClearStencil, clearStencil: StencilFalse); needStencilClear = false; } NativeBatch stencilBatch = null; SpatialCollection <LightObstructionBase> .Sector currentSector; using (var e = Environment.Obstructions.GetSectorsFromBounds(lightBounds)) while (e.GetNext(out currentSector)) { var cachedSector = GetCachedSector(frame, currentSector.Index); if (cachedSector.VertexCount <= 0) { continue; } if (stencilBatch == null) { if (Render.Tracing.RenderTrace.EnableTracing) { Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Begin Stencil Shadow Batch", frame.Index, this.GetHashCode()); } stencilBatch = NativeBatch.New(currentLightGroup, layerIndex++, IlluminantMaterials.Shadow, ShadowBatchSetup, lightSource); stencilBatch.Dispose(); needStencilClear = true; if (Render.Tracing.RenderTrace.EnableTracing) { Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : End Stencil Shadow Batch", frame.Index, this.GetHashCode()); } } stencilBatch.Add(new NativeDrawCall( PrimitiveType.TriangleList, cachedSector.ObstructionVertexBuffer, 0, cachedSector.ObstructionIndexBuffer, 0, 0, cachedSector.VertexCount, 0, cachedSector.PrimitiveCount )); } PointLightVertex vertex; vertex.LightCenter = lightSource.Position; vertex.Color = lightSource.Color; vertex.Color.W *= (lightSource.Opacity * intensityScale); vertex.Ramp = new Vector2(lightSource.RampStart, lightSource.RampEnd); vertex.Position = clippedLightBounds.TopLeft; PointLightVertices[vertexOffset++] = vertex; vertex.Position = clippedLightBounds.TopRight; PointLightVertices[vertexOffset++] = vertex; vertex.Position = clippedLightBounds.BottomRight; PointLightVertices[vertexOffset++] = vertex; vertex.Position = clippedLightBounds.BottomLeft; PointLightVertices[vertexOffset++] = vertex; var newRecord = new PointLightRecord { VertexOffset = vertexOffset - 4, IndexOffset = indexOffset, VertexCount = 4, IndexCount = 6 }; if (PointLightBatchBuffer.Count > 0) { var oldRecord = PointLightBatchBuffer[PointLightBatchBuffer.Count - 1]; if ( (newRecord.VertexOffset == oldRecord.VertexOffset + oldRecord.VertexCount) && (newRecord.IndexOffset == oldRecord.IndexOffset + oldRecord.IndexCount) ) { oldRecord.VertexCount += newRecord.VertexCount; oldRecord.IndexCount += newRecord.IndexCount; PointLightBatchBuffer[PointLightBatchBuffer.Count - 1] = oldRecord; } else { PointLightBatchBuffer.Add(newRecord); } } else { PointLightBatchBuffer.Add(newRecord); } indexOffset += 6; } if (PointLightBatchBuffer.Count > 0) { if (Render.Tracing.RenderTrace.EnableTracing) { Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Point Light Flush ({2} point(s))", frame.Index, this.GetHashCode(), PointLightBatchBuffer.Count); } FlushPointLightBatch(ref currentLightGroup, ref batchFirstLightSource, ref layerIndex); } if (Render.Tracing.RenderTrace.EnableTracing) { Render.Tracing.RenderTrace.Marker(resultGroup, 9999, "Frame {0:0000} : LightingRenderer {1:X4} : End", frame.Index, this.GetHashCode()); } } }
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); }
public override void Draw(Squared.Render.Frame frame) { CreateRenderTargets(); LightmapMaterials.ViewportScale = new Vector2(1f / LightmapScale); LightmapMaterials.ProjectionMatrix = Matrix.CreateOrthographicOffCenter( 0, BackgroundLightmap.Width, BackgroundLightmap.Height, 0, 0, 1 ); using (var backgroundGroup = BatchGroup.ForRenderTarget(frame, 0, Background)) { ClearBatch.AddNew(backgroundGroup, 1, Game.ScreenMaterials.Clear, clearColor: Color.Transparent); using (var bb = BitmapBatch.New(backgroundGroup, 2, Game.ScreenMaterials.WorldSpaceBitmap)) { for (var i = 0; i < 1; i++) { var layer = Layers[i]; var dc = new BitmapDrawCall(layer, Vector2.Zero); dc.SortKey = i; bb.Add(dc); } } } using (var foregroundGroup = BatchGroup.ForRenderTarget(frame, 1, Foreground)) { ClearBatch.AddNew(foregroundGroup, 1, Game.ScreenMaterials.Clear, clearColor: Color.Transparent); using (var bb = BitmapBatch.New(foregroundGroup, 2, Game.ScreenMaterials.WorldSpaceBitmap)) { for (var i = 1; i < Layers.Length; i++) { var layer = Layers[i]; var dc = new BitmapDrawCall(layer, Vector2.Zero); dc.SortKey = i; bb.Add(dc); } } } using (var backgroundLightGroup = BatchGroup.ForRenderTarget(frame, 4, BackgroundLightmap)) { ClearBatch.AddNew(backgroundLightGroup, 1, LightmapMaterials.Clear, clearColor: new Color(32, 32, 32, 255), clearZ: 0, clearStencil: 0); BackgroundRenderer.RenderLighting(frame, backgroundLightGroup, 2); } using (var foregroundLightGroup = BatchGroup.ForRenderTarget(frame, 5, ForegroundLightmap)) { ClearBatch.AddNew(foregroundLightGroup, 1, LightmapMaterials.Clear, clearColor: new Color(96, 96, 96, 255), clearZ: 0, clearStencil: 0); ForegroundRenderer.RenderLighting(frame, foregroundLightGroup, 2); } SetRenderTargetBatch.AddNew(frame, 49, null); ClearBatch.AddNew(frame, 50, Game.ScreenMaterials.Clear, clearColor: Color.Black, clearZ: 0, clearStencil: 0); if (ShowLightmap) { using (var bb = BitmapBatch.New(frame, 55, Game.ScreenMaterials.WorldSpaceBitmap)) { var dc = new BitmapDrawCall(BackgroundLightmap, Vector2.Zero, LightmapScale); bb.Add(dc); } ParticleRenderer.Draw(frame, 56); } else { var dc = new BitmapDrawCall(Background, Vector2.Zero); var material = LightmapMaterials.Get(LightmapMaterials.WorldSpaceLightmappedBitmap, blendState: BlendState.AlphaBlend); using (var bb = BitmapBatch.New(frame, 55, material)) { dc.Textures = new TextureSet(Background, BackgroundLightmap); dc.SortKey = 0; bb.Add(dc); } ParticleRenderer.Draw(frame, 56); using (var bb = BitmapBatch.New(frame, 57, material)) { dc.Textures = new TextureSet(Foreground, ForegroundLightmap); dc.SortKey = 1; bb.Add(dc); } } if (ShowOutlines || (Dragging != null)) { BackgroundRenderer.RenderOutlines(frame, 59, true); } }
public override void Draw(GameTime gameTime, Frame frame) { if (false) { var stats = RenderManager.GetMemoryStatistics(); Console.WriteLine( "managed: {0:0000000}kb vertex: {1:0000000}kb index: {2:0000000}kb", (stats.ManagedIndexBytes + stats.ManagedVertexBytes) / 1024.0, stats.UnmanagedVertexBytes / 1024.0, stats.UnmanagedIndexBytes / 1024.0 ); } ClearBatch.AddNew(frame, -1, Materials.Clear, clearColor: ClearColor); const int width = 1280; const int height = 720; var options = new ParallelOptions { // MaxDegreeOfParallelism = 1 }; int layer = 0; Parallel.For( 0, height, options, // One batch per worker thread () => BitmapBatch.New( frame, // Suppress batch combining Interlocked.Increment(ref layer), Materials.ScreenSpaceBitmap ), (y, loopState, bb) => { var drawCall = new BitmapDrawCall(WhitePixel, new Vector2(0, y)); float fx = 0; var range = bb.ReserveSpace(width); var array = range.Array; var offset = range.Offset; for (int x = 0; x < width; x++, fx++) { drawCall.Texture = ((x % 2) == 0) ? WhitePixel : GrayPixel; drawCall.Position.X = fx; drawCall.MultiplyColor = new Color(255, x % 255, y % 255); array[offset + x] = drawCall; } return(bb); }, (bb) => bb.Dispose() ); var ir = new ImperativeRenderer( frame, Materials, blendState: BlendState.Opaque, depthStencilState: DepthStencilState.None, rasterizerState: RasterizerState.CullNone, worldSpace: false, layer: 9999 ); DrawPerformanceStats(ref ir); }
public override void Draw(Squared.Render.Frame frame) { CreateRenderTargets(); LightmapMaterials.ViewportScale = new Vector2(1f / LightmapScale); LightmapMaterials.ProjectionMatrix = Matrix.CreateOrthographicOffCenter( 0, BackgroundLightmap.Width, BackgroundLightmap.Height, 0, 0, 1 ); using (var backgroundGroup = BatchGroup.ForRenderTarget(frame, 0, Background)) { ClearBatch.AddNew(backgroundGroup, 1, Game.ScreenMaterials.Clear, clearColor: Color.Transparent); using (var bb = BitmapBatch.New(backgroundGroup, 2, Game.ScreenMaterials.WorldSpaceBitmap)) { for (var i = 0; i < 1; i++) { var layer = Layers[i]; var dc = new BitmapDrawCall(layer, Vector2.Zero); dc.SortKey = i; bb.Add(dc); } } } using (var foregroundGroup = BatchGroup.ForRenderTarget(frame, 1, Foreground)) { ClearBatch.AddNew(foregroundGroup, 1, Game.ScreenMaterials.Clear, clearColor: Color.Transparent); using (var bb = BitmapBatch.New(foregroundGroup, 2, Game.ScreenMaterials.WorldSpaceBitmap)) { for (var i = 1; i < Layers.Length; i++) { var layer = Layers[i]; var dc = new BitmapDrawCall(layer, Vector2.Zero); dc.SortKey = i; bb.Add(dc); } } } if (ShowBrickSpecular) { using (var bricksLightGroup = BatchGroup.ForRenderTarget(frame, 2, ForegroundLightmap)) { ClearBatch.AddNew(bricksLightGroup, 1, LightmapMaterials.Clear, clearColor: new Color(0, 0, 0, 255), clearZ: 0, clearStencil: 0); ForegroundRenderer.RenderLighting(frame, bricksLightGroup, 2); } } if (ShowAOShadow) { using (var aoShadowFirstPassGroup = BatchGroup.ForRenderTarget(frame, 3, AOShadowScratch)) { ClearBatch.AddNew(aoShadowFirstPassGroup, 1, LightmapMaterials.Clear, clearColor: Color.Transparent); using (var bb = BitmapBatch.New(aoShadowFirstPassGroup, 2, Game.ScreenMaterials.ScreenSpaceHorizontalGaussianBlur5Tap)) { bb.Add(new BitmapDrawCall(Foreground, Vector2.Zero, 1f / LightmapScale)); } } } using (var backgroundLightGroup = BatchGroup.ForRenderTarget(frame, 4, BackgroundLightmap)) { ClearBatch.AddNew(backgroundLightGroup, 1, LightmapMaterials.Clear, clearColor: new Color(40, 40, 40, 255), clearZ: 0, clearStencil: 0); BackgroundRenderer.RenderLighting(frame, backgroundLightGroup, 2); if (ShowBrickSpecular) { using (var foregroundLightBatch = BitmapBatch.New(backgroundLightGroup, 3, MaskedForegroundMaterial)) { var dc = new BitmapDrawCall( ForegroundLightmap, Vector2.Zero ); dc.Textures = new TextureSet(dc.Textures.Texture1, BricksLightMask); foregroundLightBatch.Add(dc); } } else { ForegroundRenderer.RenderLighting(frame, backgroundLightGroup, 3); } if (ShowAOShadow) { using (var aoShadowBatch = BitmapBatch.New(backgroundLightGroup, 4, AOShadowMaterial)) { var dc = new BitmapDrawCall( AOShadowScratch, new Vector2(0, 4) ); dc.MultiplyColor = Color.Black; dc.AddColor = Color.White; aoShadowBatch.Add(dc); } } } using (var foregroundLightGroup = BatchGroup.ForRenderTarget(frame, 5, ForegroundLightmap)) { ClearBatch.AddNew(foregroundLightGroup, 1, LightmapMaterials.Clear, clearColor: new Color(127, 127, 127, 255), clearZ: 0, clearStencil: 0); ForegroundRenderer.RenderLighting(frame, foregroundLightGroup, 2); } SetRenderTargetBatch.AddNew(frame, 49, null); ClearBatch.AddNew(frame, 50, Game.ScreenMaterials.Clear, clearColor: Color.Black, clearZ: 0, clearStencil: 0); if (ShowLightmap) { using (var bb = BitmapBatch.New(frame, 55, Game.ScreenMaterials.WorldSpaceBitmap)) { var dc = new BitmapDrawCall(BackgroundLightmap, Vector2.Zero, LightmapScale); bb.Add(dc); } } else { var dc = new BitmapDrawCall(Background, Vector2.Zero); var material = LightmapMaterials.Get(LightmapMaterials.WorldSpaceLightmappedBitmap, blendState: BlendState.AlphaBlend); using (var bb = BitmapBatch.New(frame, 55, material)) { dc.Textures = new TextureSet(Background, BackgroundLightmap); dc.SortKey = 0; bb.Add(dc); } ParticleRenderer.Draw(frame, 56); using (var bb = BitmapBatch.New(frame, 57, material)) { dc.Textures = new TextureSet(Foreground, ForegroundLightmap); dc.SortKey = 1; bb.Add(dc); } } if (ShowOutlines || (Dragging != null)) { BackgroundRenderer.RenderOutlines(frame, 59, true); } }