/// <summary> /// Set a new state. /// </summary> /// <param name="newState">The state to set.</param> /// <param name="force">Whether to set it regardless of the previous state.</param> public void SetState(RenderState newState, bool force = false) { FlushRenderStream(); RenderState currentState = Engine.Renderer.CurrentState; // Check which state changes should apply, by checking which were set and which differ from the current. PerfProfiler.FrameEventStart("ShaderSet"); if (newState.Shader != null && (force || newState.Shader != currentState.Shader)) { ShaderProgram.EnsureBound(newState.Shader.Pointer); Engine.Renderer.CurrentState.Shader = newState.Shader; Engine.Renderer.SyncShader(); } PerfProfiler.FrameEventEnd("ShaderSet"); PerfProfiler.FrameEventStart("Depth/Stencil/Blend Set"); if (newState.DepthTest != null && (force || newState.DepthTest != currentState.DepthTest)) { SetDepthTest((bool)newState.DepthTest); } if (newState.StencilTest != null && (force || newState.StencilTest != currentState.StencilTest)) { SetStencilTest((bool)newState.StencilTest); } if (newState.SFactorRgb != null && newState.SFactorRgb != currentState.SFactorRgb || newState.DFactorRgb != null && newState.DFactorRgb != currentState.DFactorRgb || newState.SFactorA != null && newState.SFactorA != currentState.SFactorA || newState.DFactorA != null && newState.DFactorA != currentState.DFactorA) { SetAlphaBlendType( newState.SFactorRgb ?? currentState.SFactorRgb !.Value, newState.DFactorRgb ?? currentState.DFactorRgb !.Value, newState.SFactorA ?? currentState.SFactorA !.Value, newState.DFactorA ?? currentState.DFactorA !.Value); } if (newState.AlphaBlending != null && (force || newState.AlphaBlending != currentState.AlphaBlending)) { SetAlphaBlend((bool)newState.AlphaBlending); } PerfProfiler.FrameEventEnd("Depth/Stencil/Blend Set"); PerfProfiler.FrameEventStart("View/Clip Set"); if (force || newState.ViewMatrix != null && newState.ViewMatrix != currentState.ViewMatrix) { SetUseViewMatrix((bool)newState.ViewMatrix); } if (force || newState.ProjectionBehavior != null && newState.ProjectionBehavior != currentState.ProjectionBehavior) { SetProjectionBehavior((ProjectionBehavior)newState.ProjectionBehavior); } if (force || newState.ClipRect != currentState.ClipRect) { SetClipRect(newState.ClipRect); } PerfProfiler.FrameEventEnd("Depth/Stencil/Blend Set"); }
/// <summary> /// Invalidates the current batch - flushing it to the current buffer. /// This should be done when the state changes in some way because calls afterwards will differ from those before and /// cannot be batched. /// </summary> public void InvalidateStateBatches() { if (ActiveQuadBatch == null || ActiveQuadBatch.BatchedSprites == 0) { return; } PerfProfiler.FrameEventStart($"RenderBatch {ActiveQuadBatch.BatchedSprites} Sprites {ActiveQuadBatch.TextureSlotUtilization} Textures"); ActiveQuadBatch.Render(this); ActiveQuadBatch.Recycle(); PerfProfiler.FrameEventEnd($"RenderBatch {ActiveQuadBatch.BatchedSprites} Sprites {ActiveQuadBatch.TextureSlotUtilization} Textures"); }
public void RenderObjects(RenderComposer composer) { // Check if anything is loaded. List <T> objects = QueryObjectsToRender(); PerfProfiler.FrameEventStart("TileMap: Objects"); for (var i = 0; i < objects.Count; i++) { objects[i].Render(composer); } PerfProfiler.FrameEventEnd("TileMap: Objects"); }
/// <summary> /// Set whether to use depth testing. /// </summary> /// <param name="depth">Whether to use depth testing.</param> public void SetDepthTest(bool depth) { PerfProfiler.FrameEventStart("StateChange: DepthTest"); FlushRenderStream(); if (depth) { Gl.Enable(EnableCap.DepthTest); Gl.DepthFunc(DepthFunction.Lequal); } else { Gl.Disable(EnableCap.DepthTest); } Engine.Renderer.CurrentState.DepthTest = depth; PerfProfiler.FrameEventEnd("StateChange: DepthTest"); }
/// <summary> /// Set whether to use alpha blending. /// This causes transparent objects to blend their colors when drawn on top of each other. /// </summary> /// <param name="alphaBlend">Whether to use alpha blending.</param> public void SetAlphaBlend(bool alphaBlend) { PerfProfiler.FrameEventStart("StateChange: AlphaBlend"); FlushRenderStream(); if (alphaBlend) { Gl.Enable(EnableCap.Blend); Gl.BlendFuncSeparate(CurrentState.SFactorRgb !.Value, CurrentState.DFactorRgb !.Value, CurrentState.SFactorA !.Value, CurrentState.DFactorA !.Value); } else { Gl.Disable(EnableCap.Blend); } Engine.Renderer.CurrentState.AlphaBlending = alphaBlend; PerfProfiler.FrameEventEnd("StateChange: AlphaBlend"); }
/// <summary> /// Whether, and where to clip. /// </summary> /// <param name="clip">The rectangle to clip outside of.</param> public void SetClipRect(Rectangle?clip) { PerfProfiler.FrameEventStart("StateChange: Clip"); FlushRenderStream(); if (clip == null) { Gl.Disable(EnableCap.ScissorTest); } else { Gl.Enable(EnableCap.ScissorTest); Rectangle c = clip.Value; Gl.Scissor((int)c.X, (int)(Engine.Renderer.CurrentTarget.Viewport.Height - c.Height - c.Y), (int)c.Width, (int)c.Height); } Engine.Renderer.CurrentState.ClipRect = clip; PerfProfiler.FrameEventEnd("StateChange: Clip"); }
/// <summary> /// Enable or disable stencil testing. /// When enabling the stencil buffer is cleared. /// </summary> /// <param name="stencil">Whether to enable or disable stencil testing.</param> public void SetStencilTest(bool stencil) { PerfProfiler.FrameEventStart("StateChange: Stencil"); FlushRenderStream(); // Set the stencil test to it's default state - don't write to it. if (stencil) { Gl.Enable(EnableCap.StencilTest); // Clear after enabling. ClearStencil(); StencilStateDefault(); } else { Gl.Disable(EnableCap.StencilTest); StencilStateDefault(); // Some drivers don't understand that off means off } Engine.Renderer.CurrentState.StencilTest = stencil; PerfProfiler.FrameEventEnd("StateChange: Stencil"); }