diff --git a/GlitchyEditor/content/Shaders/linebatch.hlsl b/GlitchyEditor/content/Shaders/linebatch.hlsl new file mode 100644 index 0000000..272d90b --- /dev/null +++ b/GlitchyEditor/content/Shaders/linebatch.hlsl @@ -0,0 +1,61 @@ +#define EDITOR + +cbuffer Constants : register(b0) +{ + float4x4 ViewProjection; +}; + +struct VS_Input +{ + float4 Position : POSITION; + float4 Color : COLOR; +#ifdef EDITOR + uint EntityId : ENTITYID; +#endif +}; + +typedef struct PS_Input +{ + float4 Position : SV_Position; + float4 Color : COLOR; +#ifdef EDITOR + nointerpolation uint EntityId : ENTITYID; +#endif +} VS_Output; + +VS_Output VS(VS_Input input) +{ + VS_Output output; + + output.Position = mul(ViewProjection, input.Position); + output.Color = input.Color; + +#ifdef EDITOR + output.EntityId = input.EntityId; +#endif + + return output; +} + +struct PS_Output +{ + float4 Color : SV_TARGET0; +#ifdef EDITOR + uint EntityId : SV_TARGET1; +#endif +}; + +PS_Output PS(PS_Input input) +{ + PS_Output output; + + output.Color = input.Color; + +#ifdef EDITOR + output.EntityId = input.EntityId; +#endif + + return output; +} + +#pragma Effect[VS=VS; PS=PS] \ No newline at end of file diff --git a/GlitchyEditor/content/Shaders/linebatch.hlsl.ass b/GlitchyEditor/content/Shaders/linebatch.hlsl.ass new file mode 100644 index 0000000..ccd76fa --- /dev/null +++ b/GlitchyEditor/content/Shaders/linebatch.hlsl.ass @@ -0,0 +1,4 @@ +{ + AssetLoader = "EffectAssetLoader", + Config = (GlitchyEditor.Assets.EffectAssetLoaderConfig){}/* No reflection data for GlitchyEditor.Assets.EffectAssetLoaderConfig. Add [BonTarget] or force it */ +} \ No newline at end of file diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 0641514..ee89ab6 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -235,7 +235,7 @@ namespace GlitchyEditor { if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene))) { - DebugRenderer.DrawViewFrustum(transform.WorldTransform, camera.Camera.Projection, _camera.Projection * _camera.View, .White); + DebugRenderer.DrawViewFrustum(transform.WorldTransform, camera.Camera.Projection, .White); } Matrix world = Billboard(transform.WorldTransform); diff --git a/GlitchyEngine/src/Renderer/DebugRenderer.bf b/GlitchyEngine/src/Renderer/DebugRenderer.bf index d7de1da..dacd911 100644 --- a/GlitchyEngine/src/Renderer/DebugRenderer.bf +++ b/GlitchyEngine/src/Renderer/DebugRenderer.bf @@ -59,7 +59,7 @@ namespace GlitchyEngine.Renderer * @param observerVP The view projection of the rendering camera. * @param color The color of the frustum. */ - public static void DrawViewFrustum(Matrix worldTransform, Matrix projection, Matrix observerVP, ColorRGBA color = .Red) + public static void DrawViewFrustum(Matrix worldTransform, Matrix projection, ColorRGBA color = .Red) { /*if (_frustumGeometry == null) { @@ -184,7 +184,7 @@ namespace GlitchyEngine.Renderer uint16 index0 = indices[i]; uint16 index1 = indices[i + 1]; - Renderer.DrawLine(corners[index0], corners[index1], color, worldTransform, observerVP); + Renderer2D.DrawLine(worldTransform * corners[index0], worldTransform * corners[index1], color); } } diff --git a/GlitchyEngine/src/Renderer/RenderCommand.bf b/GlitchyEngine/src/Renderer/RenderCommand.bf index 197ec3a..82358a1 100644 --- a/GlitchyEngine/src/Renderer/RenderCommand.bf +++ b/GlitchyEngine/src/Renderer/RenderCommand.bf @@ -96,7 +96,7 @@ namespace GlitchyEngine.Renderer { _rendererAPI.SetDepthStencilState(depthStencilState, stencilReference); } - + [Inline] public static void DrawIndexed(GeometryBinding geometry) { diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 3343170..7400de1 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -80,7 +80,7 @@ namespace GlitchyEngine.Renderer static SceneConstants _sceneConstants; - static AssetHandle LineEffect; + //static AssetHandle LineEffect; static VertexBuffer LineVertices; static GeometryBinding LineGeometry; @@ -133,7 +133,7 @@ namespace GlitchyEngine.Renderer { Debug.Profiler.ProfileFunction!(); - LineEffect = Content.LoadAsset("Shaders\\lineShader.hlsl"); + //LineEffect = Content.LoadAsset("Shaders\\lineShader.hlsl"); LineGeometry = new GeometryBinding(); LineGeometry.SetPrimitiveTopology(.LineList); @@ -487,9 +487,10 @@ namespace GlitchyEngine.Renderer * @param end The end point of the line. * @param color The color of the line. */ - public static void DrawLine(Vector3 start, Vector3 end, Color color) + public static void DrawLine(Vector3 start, Vector3 end, ColorRGBA color) { - DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), (ColorRGBA)color, .Identity); + Renderer2D.DrawLine(start, end, color); + //DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), (ColorRGBA)color, .Identity); } /** @brief Draws a line. @@ -500,7 +501,7 @@ namespace GlitchyEngine.Renderer */ public static void DrawLine(Vector3 start, Vector3 end, ColorRGBA color, Matrix transform) { - DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), color, transform); + Renderer2D.DrawLine(transform * Vector4(start, 1.0f), transform * Vector4(end, 1.0f), color); } /** @brief Draws a ray. @@ -510,7 +511,7 @@ namespace GlitchyEngine.Renderer */ public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color) { - DrawLine(Vector4(start, 1.0f), Vector4(direction, 0.0f), color, .Identity); + Renderer2D.DrawRay(start, direction, color); } /** @brief Draws a ray. @@ -521,50 +522,7 @@ namespace GlitchyEngine.Renderer */ public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color, Matrix transform) { - DrawLine(Vector4(start, 1.0f), Vector4(direction, 0.0f), color, transform); - } - - /** @brief Draws a line. - * @param start The start point of the line. - * @param end The end point of the line. - * @param color The color of the line. - * @param transform A transform matrix transforming the line. - */ - public static void DrawLine(Vector4 start, Vector4 end, ColorRGBA color, Matrix transform) - { - Debug.Profiler.ProfileRendererFunction!(); - - LineVertices.SetData(Vector4[2](start, end), 0, .WriteDiscard); - LineEffect.Variables["ViewProjection"].SetData(_sceneConstants.ViewProjection * transform); - LineEffect.Variables["Color"].SetData(color); - - LineEffect.ApplyChanges(); - LineEffect.Bind(); - - LineGeometry.Bind(); - RenderCommand.DrawIndexed(LineGeometry); - } - - /** @brief Draws a line. - * @param start The start point of the line. - * @param end The end point of the line. - * @param color The color of the line. - * @param transform A transform matrix transforming the line. - * @param viewProjection The observing cameras viewprojection - */ - public static void DrawLine(Vector4 start, Vector4 end, ColorRGBA color, Matrix transform, Matrix viewProjection) - { - Debug.Profiler.ProfileRendererFunction!(); - - LineVertices.SetData(Vector4[2](start, end), 0, .WriteDiscard); - LineEffect.Variables["ViewProjection"].SetData(viewProjection * transform); - LineEffect.Variables["Color"].SetData(color); - - LineEffect.ApplyChanges(); - LineEffect.Bind(); - - LineGeometry.Bind(); - RenderCommand.DrawIndexed(LineGeometry); + Renderer2D.DrawLine(transform * Vector4(start, 1.0f), transform * Vector4(direction, 0.0f), color); } } } diff --git a/GlitchyEngine/src/Renderer/Renderer2D.bf b/GlitchyEngine/src/Renderer/Renderer2D.bf index 7c053c7..e521991 100644 --- a/GlitchyEngine/src/Renderer/Renderer2D.bf +++ b/GlitchyEngine/src/Renderer/Renderer2D.bf @@ -42,9 +42,25 @@ namespace GlitchyEngine.Renderer ); } } + + [CRepr] + struct LineBatchVertex + { + public Vector4 Position; + public ColorRGBA Color; + + public uint32 EntityId; + + public this(Vector4 position, ColorRGBA color, uint32 entityId) + { + Position = position; + Color = color; + EntityId = entityId; + } + } [CRepr] - struct BatchVertex + struct QuadBatchVertex { public Matrix Transform; public ColorRGBA Color; @@ -62,7 +78,7 @@ namespace GlitchyEngine.Renderer } [CRepr] - struct CircleBatchVertex : BatchVertex + struct CircleBatchVertex : QuadBatchVertex { public float InnerRadius; @@ -93,6 +109,8 @@ namespace GlitchyEngine.Renderer */ FrontToBack } + + struct QueueLine: this(Vector4 Start, Vector4 End, ColorRGBA Color, float Depth, uint32 entityId = uint32.MaxValue) { } struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, Vector4 uvTransform, uint32 entityId = uint32.MaxValue) { } @@ -112,32 +130,40 @@ namespace GlitchyEngine.Renderer private static bool s_sceneRunning; #endif - private static Effect s_batchEffect; + private static Effect s_quadBatchEffect; private static Effect s_circleBatchEffect; - + private static Effect s_lineBatchEffect; + private static GeometryBinding s_quadGeometry; private static Texture2D s_whiteTexture; private static GeometryBinding s_quadBatchBinding; private static GeometryBinding s_circleBatchBinding; + private static GeometryBinding s_lineBatchBinding; private static VertexBuffer s_quadInstanceBuffer; private static VertexBuffer s_circleInstanceBuffer; + private static VertexBuffer s_lineInstanceBuffer; private static uint32 s_maxInstancesPerBatch = 8192; - private static BatchVertex[] s_rawQuadInstances; + private static QuadBatchVertex[] s_rawQuadInstances; private static CircleBatchVertex[] s_rawCircleInstances; - private static uint32 s_setInstances = 0; + private static LineBatchVertex[] s_rawLineVertices; + private static uint32 s_setQuadInstances = 0; + private static uint32 s_setCircleInstances = 0; + private static uint32 s_setLineInstances = 0; private static List s_QuadinstanceQueue; private static List s_circleInstanceQueue; + private static List s_lineInstanceQueue; private static DrawOrder s_drawOrder; /// The effect that is currently used to draw the sprites. - private static Effect s_currentEffect; + private static Effect s_currentQuadEffect; private static Effect s_currentCircleEffect; + private static Effect s_currentLineEffect; public static uint32 MaxInstancesPerBatch { @@ -157,8 +183,9 @@ namespace GlitchyEngine.Renderer { Debug.Profiler.ProfileFunction!(); - s_batchEffect = new Effect("content\\Shaders\\spritebatch.hlsl"); + s_quadBatchEffect = new Effect("content\\Shaders\\spritebatch.hlsl"); s_circleBatchEffect = new Effect("content\\Shaders\\circlebatch.hlsl"); + s_lineBatchEffect = new Effect("content\\Shaders\\linebatch.hlsl"); } private static void InitGeometry() @@ -252,6 +279,23 @@ namespace GlitchyEngine.Renderer s_circleBatchBinding.SetIndexBuffer(s_quadGeometry.GetIndexBuffer(), 0); } + // Line + { + VertexElement[] vertexElements = new .( + VertexElement(.R32G32B32A32_Float, "POSITION", false, 0, 0, 0, .PerVertexData, 0), + VertexElement(.R32G32B32A32_Float, "COLOR", false, 0, 0, (.)-1, .PerVertexData, 0), + VertexElement(.R32_UInt, "ENTITYID", false, 0, 0, (.)-1, .PerVertexData, 0) + ); + + s_lineBatchBinding = new GeometryBinding(); + s_lineBatchBinding.SetPrimitiveTopology(.LineList); + + using (var lineBatchLayout = new VertexLayout(vertexElements, true)) + { + s_lineBatchBinding.SetVertexLayout(lineBatchLayout); + } + } + ApplyInstanceCount(); } @@ -262,7 +306,7 @@ namespace GlitchyEngine.Renderer // Quads { - VertexBuffer quadInstanceBuffer = new VertexBuffer(typeof(BatchVertex), s_maxInstancesPerBatch, .Dynamic, .Write); + VertexBuffer quadInstanceBuffer = new VertexBuffer(typeof(QuadBatchVertex), s_maxInstancesPerBatch, .Dynamic, .Write); quadInstanceBuffer.SetData(0); s_quadInstanceBuffer?.ReleaseRef(); @@ -271,7 +315,7 @@ namespace GlitchyEngine.Renderer delete s_rawQuadInstances; delete s_QuadinstanceQueue; - s_rawQuadInstances = new BatchVertex[s_maxInstancesPerBatch]; + s_rawQuadInstances = new QuadBatchVertex[s_maxInstancesPerBatch]; s_QuadinstanceQueue = new List(s_maxInstancesPerBatch); } @@ -290,6 +334,21 @@ namespace GlitchyEngine.Renderer s_rawCircleInstances = new CircleBatchVertex[s_maxInstancesPerBatch]; s_circleInstanceQueue = new List(s_maxInstancesPerBatch); } + + // Lines + { + VertexBuffer lineInstanceBuffer = new VertexBuffer(typeof(LineBatchVertex), s_maxInstancesPerBatch, .Dynamic, .Write); + lineInstanceBuffer.SetData(0); + + s_lineInstanceBuffer?.ReleaseRef(); + s_lineInstanceBuffer = lineInstanceBuffer; + s_lineBatchBinding.SetVertexBufferSlot(s_lineInstanceBuffer, 0); + + delete s_rawLineVertices; + delete s_lineInstanceQueue; + s_rawLineVertices = new LineBatchVertex[s_maxInstancesPerBatch]; + s_lineInstanceQueue = new List(s_maxInstancesPerBatch); + } } private static void InitWhitetexture() @@ -366,8 +425,9 @@ namespace GlitchyEngine.Renderer FontRenderer.Deinit(); - s_batchEffect.ReleaseRef(); + s_quadBatchEffect.ReleaseRef(); s_circleBatchEffect.ReleaseRef(); + s_lineBatchEffect.ReleaseRef(); s_quadGeometry.ReleaseRef(); @@ -375,16 +435,21 @@ namespace GlitchyEngine.Renderer s_quadBatchBinding.ReleaseRef(); s_circleBatchBinding.ReleaseRef(); + s_lineBatchBinding.ReleaseRef(); s_quadInstanceBuffer.ReleaseRef(); s_circleInstanceBuffer.ReleaseRef(); + s_lineInstanceBuffer.ReleaseRef(); delete s_rawQuadInstances; delete s_rawCircleInstances; + delete s_rawLineVertices; delete s_QuadinstanceQueue; delete s_circleInstanceQueue; + delete s_lineInstanceQueue; - s_currentEffect?.ReleaseRef(); + s_currentQuadEffect?.ReleaseRef(); s_currentCircleEffect?.ReleaseRef(); + s_currentLineEffect?.ReleaseRef(); s_opaqueBlendState.ReleaseRef(); s_transparentBlendState.ReleaseRef(); @@ -405,14 +470,14 @@ namespace GlitchyEngine.Renderer //s_textureColorEffect.Bind(Renderer._context); - s_currentEffect?.ReleaseRef(); + s_currentQuadEffect?.ReleaseRef(); if(effect != null) { - s_currentEffect = effect..AddRef(); + s_currentQuadEffect = effect..AddRef(); } else { - s_currentEffect = s_batchEffect..AddRef(); + s_currentQuadEffect = s_quadBatchEffect..AddRef(); } s_currentCircleEffect?.ReleaseRef(); @@ -425,7 +490,7 @@ namespace GlitchyEngine.Renderer s_currentCircleEffect = s_circleBatchEffect..AddRef(); } - s_currentEffect.Variables["ViewProjection"].SetData(camera.ViewProjection); + s_currentQuadEffect.Variables["ViewProjection"].SetData(camera.ViewProjection); s_currentCircleEffect.Variables["ViewProjection"].SetData(camera.ViewProjection); s_drawOrder = drawOrder; @@ -445,14 +510,14 @@ namespace GlitchyEngine.Renderer //s_textureColorEffect.Bind(Renderer._context); - s_currentEffect?.ReleaseRef(); + s_currentQuadEffect?.ReleaseRef(); if(effect != null) { - s_currentEffect = effect..AddRef(); + s_currentQuadEffect = effect..AddRef(); } else { - s_currentEffect = s_batchEffect..AddRef(); + s_currentQuadEffect = s_quadBatchEffect..AddRef(); } s_currentCircleEffect?.ReleaseRef(); @@ -464,11 +529,22 @@ namespace GlitchyEngine.Renderer { s_currentCircleEffect = s_circleBatchEffect..AddRef(); } + + s_currentLineEffect?.ReleaseRef(); + /*if(circleEffect != null) + { + s_currentLineEffect = effect..AddRef(); + } + else + {*/ + s_currentLineEffect = s_lineBatchEffect..AddRef(); + //} Matrix viewProjection = camera.Projection * Matrix.Invert(transform); - s_currentEffect.Variables["ViewProjection"].SetData(viewProjection); + s_currentQuadEffect.Variables["ViewProjection"].SetData(viewProjection); s_currentCircleEffect.Variables["ViewProjection"].SetData(viewProjection); + s_currentLineEffect.Variables["ViewProjection"].SetData(viewProjection); s_drawOrder = drawOrder; @@ -487,14 +563,14 @@ namespace GlitchyEngine.Renderer //s_textureColorEffect.Bind(Renderer._context); - s_currentEffect?.ReleaseRef(); + s_currentQuadEffect?.ReleaseRef(); if(effect != null) { - s_currentEffect = effect..AddRef(); + s_currentQuadEffect = effect..AddRef(); } else { - s_currentEffect = s_batchEffect..AddRef(); + s_currentQuadEffect = s_quadBatchEffect..AddRef(); } s_currentCircleEffect?.ReleaseRef(); @@ -506,11 +582,22 @@ namespace GlitchyEngine.Renderer { s_currentCircleEffect = s_circleBatchEffect..AddRef(); } + + s_currentLineEffect?.ReleaseRef(); + /*if(circleEffect != null) + { + s_currentLineEffect = effect..AddRef(); + } + else + {*/ + s_currentLineEffect = s_lineBatchEffect..AddRef(); + //} Matrix viewProjection = camera.Projection * camera.View; - s_currentEffect.Variables["ViewProjection"].SetData(viewProjection); + s_currentQuadEffect.Variables["ViewProjection"].SetData(viewProjection); s_currentCircleEffect.Variables["ViewProjection"].SetData(viewProjection); + s_currentLineEffect.Variables["ViewProjection"].SetData(viewProjection); s_drawOrder = drawOrder; @@ -558,23 +645,31 @@ namespace GlitchyEngine.Renderer s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius, id)); s_statistics.CircleCount++; } - - private static void FlushInstances() + + /// Adds a line instance to the instance queue. + [Inline] + private static void QueueLineInstance(Vector4 start, Vector4 end, ColorRGBA color, uint32 id = uint32.MaxValue) + { + s_lineInstanceQueue.Add(QueueLine(start, end, color, id)); + s_statistics.LineCount++; + } + + private static void FlushQuadInstances() { Debug.Profiler.ProfileRendererFunction!(); - if(s_setInstances == 0) + if(s_setQuadInstances == 0) return; - s_quadInstanceBuffer.SetData(s_rawQuadInstances.Ptr, s_setInstances, 0, .WriteDiscard); + s_quadInstanceBuffer.SetData(s_rawQuadInstances.Ptr, s_setQuadInstances, 0, .WriteDiscard); - s_currentEffect.ApplyChanges(); - s_currentEffect.Bind(); - s_quadBatchBinding.InstanceCount = s_setInstances; + s_currentQuadEffect.ApplyChanges(); + s_currentQuadEffect.Bind(); + s_quadBatchBinding.InstanceCount = s_setQuadInstances; s_quadBatchBinding.Bind(); RenderCommand.DrawIndexedInstanced(s_quadBatchBinding); - s_setInstances = 0; + s_setQuadInstances = 0; s_statistics.QuadDrawCalls++; } @@ -583,21 +678,41 @@ namespace GlitchyEngine.Renderer { Debug.Profiler.ProfileRendererFunction!(); - if(s_setInstances == 0) + if(s_setCircleInstances == 0) return; - s_circleInstanceBuffer.SetData(s_rawCircleInstances.Ptr, s_setInstances, 0, .WriteDiscard); + s_circleInstanceBuffer.SetData(s_rawCircleInstances.Ptr, s_setCircleInstances, 0, .WriteDiscard); s_currentCircleEffect.ApplyChanges(); s_currentCircleEffect.Bind(); - s_circleBatchBinding.InstanceCount = s_setInstances; + s_circleBatchBinding.InstanceCount = s_setCircleInstances; s_circleBatchBinding.Bind(); RenderCommand.DrawIndexedInstanced(s_circleBatchBinding); - s_setInstances = 0; + s_setCircleInstances = 0; s_statistics.CircleDrawCalls++; } + + private static void FlushLineInstances() + { + Debug.Profiler.ProfileRendererFunction!(); + + if(s_setLineInstances == 0) + return; + + s_lineInstanceBuffer.SetData(s_rawLineVertices.Ptr, s_setLineInstances, 0, .WriteDiscard); + + s_currentLineEffect.ApplyChanges(); + s_currentLineEffect.Bind(); + s_lineBatchBinding.VertexCount = (.)s_setLineInstances; + s_lineBatchBinding.Bind(); + RenderCommand.DrawIndexed(s_lineBatchBinding); + + s_setLineInstances = 0; + + s_statistics.LineDrawCalls++; + } // Quad comparison private static int TextureComparison(QueueQuad lhs, QueueQuad rhs) @@ -627,6 +742,20 @@ namespace GlitchyEngine.Renderer return lhs.Depth <=> rhs.Depth; } + // Line comparison + /*private static int TextureComparison(QueueLine lhs, QueueLine rhs) + { + return (int)Internal.UnsafeCastToPtr(lhs.Texture) - (int)Internal.UnsafeCastToPtr(rhs.Texture); + }*/ + private static int BackToFrontComparison(QueueLine lhs, QueueLine rhs) + { + return rhs.Depth <=> lhs.Depth; + } + private static int FrontToBackComparison(QueueLine lhs, QueueLine rhs) + { + return lhs.Depth <=> rhs.Depth; + } + private static void SortInstances() { Debug.Profiler.ProfileRendererFunction!(); @@ -636,12 +765,16 @@ namespace GlitchyEngine.Renderer case .SortByTexture: s_QuadinstanceQueue.Sort(scope => TextureComparison); s_circleInstanceQueue.Sort(scope => TextureComparison); + /*Lines cant be sorted by texture*/ + s_lineInstanceQueue.Sort(scope => BackToFrontComparison); case .BackToFront: s_QuadinstanceQueue.Sort(scope => BackToFrontComparison); s_circleInstanceQueue.Sort(scope => BackToFrontComparison); + s_lineInstanceQueue.Sort(scope => BackToFrontComparison); case .FrontToBack: s_QuadinstanceQueue.Sort(scope => FrontToBackComparison); s_circleInstanceQueue.Sort(scope => FrontToBackComparison); + s_lineInstanceQueue.Sort(scope => FrontToBackComparison); case .Immediate: default: Log.EngineLogger.Error("Unknown instance draw order."); @@ -652,13 +785,14 @@ namespace GlitchyEngine.Renderer { Debug.Profiler.ProfileRendererFunction!(); - if(s_QuadinstanceQueue.IsEmpty && s_circleInstanceQueue.IsEmpty) + if(s_QuadinstanceQueue.IsEmpty && s_circleInstanceQueue.IsEmpty && s_lineInstanceQueue.IsEmpty) return; SortInstances(); DrawDeferredQuads(); DrawDeferredCircles(); + DrawDeferredLines(); } private static void DrawDeferredQuads() @@ -672,9 +806,9 @@ namespace GlitchyEngine.Renderer RenderCommand.SetBlendState(s_transparentBlendState); Texture texture = s_QuadinstanceQueue[0].Texture; - s_currentEffect.SetTexture("Texture", texture); + s_currentQuadEffect.SetTexture("Texture", texture); - s_setInstances = 0; + s_setQuadInstances = 0; for(int i < s_QuadinstanceQueue.Count) { @@ -683,21 +817,21 @@ namespace GlitchyEngine.Renderer // flush every time the texture changes if(quad.Texture != texture) { - FlushInstances(); + FlushQuadInstances(); texture = quad.Texture; - s_currentEffect.SetTexture("Texture", texture); + s_currentQuadEffect.SetTexture("Texture", texture); } - s_rawQuadInstances[s_setInstances++] = .(quad.Transform, quad.Color, quad.uvTransform, quad.entityId); + s_rawQuadInstances[s_setQuadInstances++] = .(quad.Transform, quad.Color, quad.uvTransform, quad.entityId); - if(s_setInstances == s_rawQuadInstances.Count) + if(s_setQuadInstances == s_rawQuadInstances.Count) { - FlushInstances(); + FlushQuadInstances(); } } - FlushInstances(); + FlushQuadInstances(); s_QuadinstanceQueue.Clear(); } @@ -715,7 +849,7 @@ namespace GlitchyEngine.Renderer Texture texture = s_circleInstanceQueue[0].Texture; s_currentCircleEffect.SetTexture("Texture", texture); - s_setInstances = 0; + s_setCircleInstances = 0; for(int i < s_circleInstanceQueue.Count) { @@ -730,9 +864,9 @@ namespace GlitchyEngine.Renderer s_currentCircleEffect.SetTexture("Texture", texture); } - s_rawCircleInstances[s_setInstances++] = .(circle.Transform, circle.Color, circle.uvTransform, circle.InnerRadius, circle.entityId); + s_rawCircleInstances[s_setCircleInstances++] = .(circle.Transform, circle.Color, circle.uvTransform, circle.InnerRadius, circle.entityId); - if(s_setInstances == s_rawCircleInstances.Count) + if(s_setCircleInstances == s_rawCircleInstances.Count) { FlushCircleInstances(); } @@ -743,6 +877,36 @@ namespace GlitchyEngine.Renderer s_circleInstanceQueue.Clear(); } + private static void DrawDeferredLines() + { + Debug.Profiler.ProfileRendererFunction!(); + + if(s_lineInstanceQueue.IsEmpty) + return; + + // TODO: per object blendstate + RenderCommand.SetBlendState(s_transparentBlendState); + + s_setLineInstances = 0; + + for(int i < s_lineInstanceQueue.Count) + { + let line = ref s_lineInstanceQueue[i]; + + s_rawLineVertices[s_setLineInstances++] = .(line.Start, line.Color, line.entityId); + s_rawLineVertices[s_setLineInstances++] = .(line.End, line.Color, line.entityId); + + if(s_setLineInstances == s_rawLineVertices.Count) + { + FlushLineInstances(); + } + } + + FlushLineInstances(); + + s_lineInstanceQueue.Clear(); + } + /// A specialized function that calculates the 2D transform matrix private static Matrix Calculate2DTransform(Vector3 translation, Vector2 scale, float rotation) { @@ -762,6 +926,85 @@ namespace GlitchyEngine.Renderer } // Primitives + + /** @brief Draws a line. + * @param start The start point of the line. + * @param end The end point of the line. + * @param color The color of the line. + * @param entityId The optional ID of the entity that belongs to this line (for picking). + */ + public static void DrawLine(Vector3 start, Vector3 end, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue) + { + DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), color, entityId); + } + + /** @brief Draws a ray. + * @param start The start point of the ray. + * @param direction The direction of the ray. + * @param color The color of the ray. + * @param entityId The optional ID of the entity that belongs to this ray (for picking). + */ + public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue) + { + DrawLine(Vector4(start, 1.0f), Vector4(direction, 0.0f), color, entityId); + } + + /** @brief Draws a rectangle. + * @param position The center of the rectangle. + * @param size The size of the rectangle. + * @param color The color of the rectangle. + * @param entityId The optional ID of the entity that belongs to this rectangle (for picking). + */ + public static void DrawRect(Vector2 position, Vector2 size, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue) + { + Vector2 halfSize = size / 2; + + Vector4 p0 = Vector4(position + Vector2(-halfSize.X, -halfSize.Y), 0.0f, 1.0f); + Vector4 p1 = Vector4(position + Vector2(halfSize.X, -halfSize.Y), 0.0f, 1.0f); + Vector4 p2 = Vector4(position + Vector2(halfSize.X, halfSize.Y), 0.0f, 1.0f); + Vector4 p3 = Vector4(position + Vector2(-halfSize.X, halfSize.Y), 0.0f, 1.0f); + + DrawLine(p0, p1, color, entityId); + DrawLine(p1, p2, color, entityId); + DrawLine(p2, p3, color, entityId); + DrawLine(p3, p0, color, entityId); + } + + /** @brief Draws a rectangle. + * @param transform The transform of the rectangle. + * @param color The color of the rectangle. + * @param entityId The optional ID of the entity that belongs to this rectangle (for picking). + */ + public static void DrawRect(Matrix transform, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue) + { + Vector2 halfSize = Vector2.One / 2.0f; + + Vector4 p0 = transform * Vector4(-halfSize.X, -halfSize.Y, 0.0f, 1.0f); + Vector4 p1 = transform * Vector4(halfSize.X, -halfSize.Y, 0.0f, 1.0f); + Vector4 p2 = transform * Vector4(halfSize.X, halfSize.Y, 0.0f, 1.0f); + Vector4 p3 = transform * Vector4(-halfSize.X, halfSize.Y, 0.0f, 1.0f); + + DrawLine(p0, p1, color, entityId); + DrawLine(p1, p2, color, entityId); + DrawLine(p2, p3, color, entityId); + DrawLine(p3, p0, color, entityId); + } + + public static void DrawLine(Vector4 start, Vector4 end, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue) + { + Debug.Profiler.ProfileRendererFunction!(); + +#if DEBUG + Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene."); +#endif + + QueueLineInstance(start, end, color, entityId); + + if(s_drawOrder == .Immediate) + { + DrawDeferred(); + } + } // Colored Quad @@ -939,21 +1182,26 @@ namespace GlitchyEngine.Renderer { public uint32 QuadDrawCalls = 0; public uint32 CircleDrawCalls = 0; + public uint32 LineDrawCalls = 0; + public uint32 QuadCount = 0; public uint32 CircleCount = 0; + public uint32 LineCount = 0; - public uint32 TotalDrawCalls => QuadDrawCalls + CircleDrawCalls; - public uint32 TotalInstanceCount => QuadCount + CircleCount; - public uint32 TotalVertexCount => TotalInstanceCount * 4; - public uint32 TotalTriangleCount => TotalInstanceCount * 2; - public uint32 TotalIndexCount => TotalInstanceCount * 6; + public uint32 TotalDrawCalls => QuadDrawCalls + CircleDrawCalls + LineDrawCalls; + public uint32 TotalInstanceCount => QuadCount + CircleCount + LineCount; + public uint32 TotalVertexCount => (QuadCount + CircleCount) * 4 + LineCount * 2; + public uint32 TotalTriangleCount => (QuadCount + CircleCount) * 2; + public uint32 TotalIndexCount => (QuadCount + CircleCount) * 6; public void Reset() mut { QuadDrawCalls = 0; CircleDrawCalls = 0; + LineDrawCalls = 0; QuadCount = 0; CircleCount = 0; + LineCount = 0; } } diff --git a/GlitchyEngine/src/Renderer/Text/FontRenderer.bf b/GlitchyEngine/src/Renderer/Text/FontRenderer.bf index 7e42279..93d11ec 100644 --- a/GlitchyEngine/src/Renderer/Text/FontRenderer.bf +++ b/GlitchyEngine/src/Renderer/Text/FontRenderer.bf @@ -333,8 +333,8 @@ namespace GlitchyEngine.Renderer.Text Renderer2D.Flush(); // TODO: this is very not good! - var lastEffect = Renderer2D.[Friend]s_currentEffect; - Renderer2D.[Friend]s_currentEffect = _msdfEffect..AddRef(); + var lastEffect = Renderer2D.[Friend]s_currentQuadEffect; + Renderer2D.[Friend]s_currentQuadEffect = _msdfEffect..AddRef(); // TODO: oh no.... // Copy viewProjection from current effect Matrix viewProjection = lastEffect.Variables["ViewProjection"].[Friend]GetData(); @@ -410,7 +410,7 @@ namespace GlitchyEngine.Renderer.Text // TODO: not good! // Change back effect _msdfEffect.ReleaseRef(); - Renderer2D.[Friend]s_currentEffect = lastEffect; + Renderer2D.[Friend]s_currentQuadEffect = lastEffect; // release all atlas textures for(int i < atlasses.Count) @@ -439,8 +439,8 @@ namespace GlitchyEngine.Renderer.Text Renderer2D.Flush(); // TODO: this is very not good! - var lastEffect = Renderer2D.[Friend]s_currentEffect; - Renderer2D.[Friend]s_currentEffect = _msdfEffect..AddRef(); + var lastEffect = Renderer2D.[Friend]s_currentQuadEffect; + Renderer2D.[Friend]s_currentQuadEffect = _msdfEffect..AddRef(); // TODO: oh no.... // Copy viewProjection from current effect Matrix viewProjection = lastEffect.Variables["ViewProjection"].[Friend]GetData(); @@ -664,7 +664,7 @@ namespace GlitchyEngine.Renderer.Text // TODO: not good! // Change back effect _msdfEffect.ReleaseRef(); - Renderer2D.[Friend]s_currentEffect = lastEffect; + Renderer2D.[Friend]s_currentQuadEffect = lastEffect; // release all atlas textures for(int i < atlasses.Count) diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index df80b3b..1a6e486 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -383,6 +383,14 @@ namespace GlitchyEngine.World Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index); } + Renderer2D.DrawLine(Vector3.Zero, Vector3.Up, .Red); + Renderer2D.DrawLine(Vector3.Zero, Vector3(0, 0, 1), .Green); + Renderer2D.DrawRay(Vector3.Zero, Vector3(1, 0, 0), .Blue); + + Renderer2D.DrawRect(Vector2(2.0f, 1.0f), Vector2(1.0f, 2.0f), .Yellow); + + Renderer2D.DrawRect(Matrix.Translation(2, 2, 1) * Matrix.RotationZ(MathHelper.PiOverFour), .Purple); + Renderer2D.EndScene(); Renderer2D.BeginScene(camera, .BackToFront);