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; } } } }
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 ImperativeRenderer MakeSubgroup(bool nextLayer = true, Action <DeviceManager, object> before = null, Action <DeviceManager, object> after = null, object userData = null) { var result = this; var group = BatchGroup.New(Container, Layer, before: before, after: after, userData: userData); group.Dispose(); result.Container = group; result.Layer = 0; if (nextLayer) { Layer += 1; } return(result); }
/// <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()); } } }