diff --git a/BeefSpace.toml b/BeefSpace.toml index 200a5c4..4fa1d8e 100644 --- a/BeefSpace.toml +++ b/BeefSpace.toml @@ -2,7 +2,7 @@ FileVersion = 1 Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, DirectXTK = {Path = "GlitchyEngine/vendor/DirectXTK/DirectXTK-beef"}, LodePng = {Path = "vendor/lodepng-beef/lodepng-beef"}, FreeType = {Path = "GlitchyEngine/vendor/freetype"}, cgltf-beef = {Path = "GlitchyEngine/vendor/gltf/cgltf-beef"}, GlitchyEditor = {Path = "GlitchyEditor"}, msdfgen-beef = {Path = "GlitchyEngine/vendor/msdfgen/msdfgen-beef"}, ImGui = {Path = "GlitchyEngine/vendor/imgui/ImGui"}, ImGuiImplDX11 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplDX11"}, ImGuiImplWin32 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplWin32"}, ImGuizmo = {Path = "GlitchyEngine/vendor/imgui/ImGuizmo"}} [Workspace] -StartupProject = "GlitchyEditor" +StartupProject = "Sandbox" [Configs.Debug.Win64] AllocType = "CRT" diff --git a/GlitchyEngine/src/Application.bf b/GlitchyEngine/src/Application.bf index ea480f4..8a7fa53 100644 --- a/GlitchyEngine/src/Application.bf +++ b/GlitchyEngine/src/Application.bf @@ -16,11 +16,11 @@ namespace GlitchyEngine private bool _running = true; private bool _isMinimized = false; - private LayerStack _layerStack = new LayerStack() ~ delete _; + private LayerStack _layerStack = new LayerStack(); private ImGuiLayer _imGuiLayer; - private GameTime _gameTime = new GameTime(true) ~ delete _; + private GameTime _gameTime = new GameTime(true); public bool IsRunning => _running; public Window Window => _window; @@ -57,7 +57,10 @@ namespace GlitchyEngine public ~this() { + delete _layerStack; SamplerStateManager.Uninit(); + Renderer.Deinit(); + delete _gameTime; } public void OnEvent(Event e) diff --git a/GlitchyEngine/src/Renderer/BufferVariable.bf b/GlitchyEngine/src/Renderer/BufferVariable.bf index aa0e7fa..8573bd9 100644 --- a/GlitchyEngine/src/Renderer/BufferVariable.bf +++ b/GlitchyEngine/src/Renderer/BufferVariable.bf @@ -113,6 +113,12 @@ namespace GlitchyEngine.Renderer *(T*)firstByte = value; } + [Inline] + private T GetData() + { + return *(T*)firstByte; + } + public void SetData(bool value) => SetData(value); public void SetData(float value) => SetData(value); diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 3e2750d..1fc68f0 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -15,7 +15,7 @@ namespace GlitchyEngine.Renderer public Matrix Transform; } - static GraphicsContext _context ~ _?.ReleaseRef(); + static internal GraphicsContext _context ~ _?.ReleaseRef(); //static Buffer _sceneConstants ~ _?.ReleaseRef(); @@ -39,10 +39,16 @@ namespace GlitchyEngine.Renderer */ RenderCommand.Init(); + Renderer2D.Init(); InitLineRenderer(effectLibrary); } + public static void Deinit() + { + Renderer2D.Deinit(); + } + static void InitLineRenderer(EffectLibrary effectLibrary) { LineEffect = effectLibrary.Load("content\\Shaders\\lineShader.hlsl"); diff --git a/GlitchyEngine/src/Renderer/Renderer2D.bf b/GlitchyEngine/src/Renderer/Renderer2D.bf index e19829d..fd6ccc5 100644 --- a/GlitchyEngine/src/Renderer/Renderer2D.bf +++ b/GlitchyEngine/src/Renderer/Renderer2D.bf @@ -2,13 +2,61 @@ using GlitchyEngine.Math; using System.Collections; using System; using System.Diagnostics; +using GlitchyEngine.Renderer.Text; namespace GlitchyEngine.Renderer { using internal GlitchyEngine.Renderer; - public class Renderer2D + public static class Renderer2D { + [CRepr] + struct QuadVertex : IVertexData + { + public Vector2 Position; + public Vector2 Texcoord; + + public this(Vector2 position, Vector2 texcoord) + { + Position = position; + Texcoord = texcoord; + } + + public this(float x, float y, float texX, float texY) + { + Position = .(x, y); + Texcoord = .(texX, texY); + } + + public static VertexElement[] VertexElements ~ delete _; + + public static VertexElement[] IVertexData.VertexElements => VertexElements; + + static this() + { + VertexElements = new VertexElement[] + ( + VertexElement(.R32G32_Float, "POSITION"), + VertexElement(.R32G32_Float, "TEXCOORD"), + ); + } + } + + [CRepr] + struct BatchVertex + { + public Matrix Transform; + public ColorRGBA Color; + public Vector4 UVTransform; + + public this(Matrix transform, ColorRGBA color, Vector4 uvTransform) + { + Transform = transform; + Color = color; + UVTransform = uvTransform; + } + } + enum DrawOrder { /// Immediately draw the sprites. @@ -30,96 +78,55 @@ namespace GlitchyEngine.Renderer FrontToBack } - struct RenderVertex : IVertexData + struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture2D Texture, float Depth, Vector4 uvTransform) { } + +#if DEBUG + private static bool s_initialized; + private static bool s_sceneRunning; +#endif + + private static Effect s_textureColorEffect; + private static Effect s_batchEffect; + + private static GeometryBinding s_quadGeometry; + + private static Texture2D s_whiteTexture; + + private static GeometryBinding s_batchBinding; + private static VertexBuffer s_instanceBuffer; + + private static BatchVertex[] s_rawInstances; + private static uint32 s_setInstances; + + private static List s_instanceQueue; + + private static DrawOrder s_drawOrder; + + /// The effect that is currently used to draw the sprites. + private static Effect s_currentEffect; + + private static void InitEffect() { - public Vector2 Position; - - public this(Vector2 position) - { - Position = position; - } - - public this(float x, float y) - { - Position = .(x, y); - } - - public static VertexElement[] VertexElements ~ delete _; - - public static VertexElement[] IVertexData.VertexElements => VertexElements; - - static this() - { - VertexElements = new VertexElement[] - ( - VertexElement(.R32G32_Float, "POSITION") - ); - } + s_textureColorEffect = new Effect(Renderer._context, "content\\Shaders\\textureColor.hlsl"); + s_batchEffect = new Effect(Renderer._context, "content\\Shaders\\spritebatch.hlsl"); } - [Ordered] - struct BatchVertex + private static void InitGeometry() { - public Matrix Transform; - public Color Color; - public Vector4 UVTransform; + VertexLayout layout = new VertexLayout(Renderer._context, QuadVertex.VertexElements, false, s_textureColorEffect.VertexShader); - public this(Matrix transform, Color color, Vector4 uvTransform) - { - Transform = transform; - Color = color; - UVTransform = uvTransform; - } - } + VertexBuffer quadVertices = new VertexBuffer(Renderer._context, typeof(QuadVertex), 4, .Immutable); - private GraphicsContext _context ~ _?.ReleaseRef(); - - private Vector2 _virtualResolution; - - private Effect quadEffect ~ _?.ReleaseRef(); - private GeometryBinding quadBinding ~ _?.ReleaseRef(); - - private Effect instancingEffect ~ _?.ReleaseRef(); - private GeometryBinding instancingBinding ~ _?.ReleaseRef(); - private VertexBuffer instanceBuffer ~ _?.ReleaseRef(); - - private Texture2D whiteTexture ~ _.ReleaseRef(); - - private BatchVertex[] _rawInstances = new BatchVertex[1024] ~ delete _; - private uint32 _setInstances = 0; - - Matrix _projection; - - DrawOrder _drawOrder; - - /// The effect that is currently being used to draw the sprites. - private Effect _currentEffect ~ _?.ReleaseRef(); - - public this(GraphicsContext context, EffectLibrary effectLibrary) - { - _context = context..AddRef(); - Init(effectLibrary); - InitInstancing(effectLibrary); - } - - void Init(EffectLibrary effectLibrary) - { - quadEffect = effectLibrary.Load("content\\Shaders\\render2dShader.hlsl", "Renderer2D"); - - VertexLayout layout = new VertexLayout(_context, RenderVertex.VertexElements, false, quadEffect.VertexShader); - - VertexBuffer quadVertices = new VertexBuffer(_context, typeof(RenderVertex), 4, .Immutable); - - RenderVertex[4] vertices = .( - .(0, 0), - .(0, 1), - .(1, 1), - .(1, 0) + QuadVertex[4] vertices = .( + .(-0.5f,-0.5f, 0, 1), + .(-0.5f, 0.5f, 0, 0), + .( 0.5f, 0.5f, 1, 0), + .( 0.5f,-0.5f, 1, 1) ); quadVertices.SetData(vertices); - IndexBuffer quadIndices = new IndexBuffer(_context, 6, .Immutable); + IndexBuffer quadIndices = new IndexBuffer(Renderer._context, 6, .Immutable); uint16[6] indices = .( 0, 1, 2, @@ -128,194 +135,227 @@ namespace GlitchyEngine.Renderer quadIndices.SetData(indices); - quadBinding = new GeometryBinding(_context); - quadBinding.SetVertexLayout(layout..ReleaseRefNoDelete()); - quadBinding.SetPrimitiveTopology(.TriangleList); - quadBinding.SetVertexBufferSlot(quadVertices, 0); - quadBinding.SetIndexBuffer(quadIndices); + s_quadGeometry = new GeometryBinding(Renderer._context); + s_quadGeometry.SetVertexLayout(layout..ReleaseRefNoDelete()); + s_quadGeometry.SetPrimitiveTopology(.TriangleList); + s_quadGeometry.SetVertexBufferSlot(quadVertices, 0); + s_quadGeometry.SetIndexBuffer(quadIndices); quadVertices.ReleaseRef(); quadIndices.ReleaseRef(); - - Texture2DDesc tex2Ddesc; - tex2Ddesc.Format = .R8G8B8A8_UNorm; - tex2Ddesc.Width = 1; - tex2Ddesc.Height = 1; - tex2Ddesc.MipLevels = 1; - tex2Ddesc.ArraySize = 1; - tex2Ddesc.Usage = .Immutable; - tex2Ddesc.CpuAccess = .None; - whiteTexture = new Texture2D(_context, tex2Ddesc); - - Color color = .White; - whiteTexture.SetData(&color); - - SamplerState sampler = SamplerStateManager.GetSampler(SamplerStateDescription()); - - whiteTexture.SamplerState = sampler; - - sampler..ReleaseRef(); } - void InitInstancing(EffectLibrary effectLibrary) + private static void InitInstancingGeometry() { - instancingEffect = effectLibrary.Load("content\\Shaders\\render2dShaderInst.hlsl", "Renderer2DInstancing"); - - instanceBuffer = new VertexBuffer(_context, typeof(BatchVertex), 1024, .Dynamic, .Write); - instanceBuffer.SetData(0); + s_instanceBuffer = new VertexBuffer(Renderer._context, typeof(BatchVertex), 1024, .Dynamic, .Write); + s_instanceBuffer.SetData(0); VertexElement[] vertexElements = new .( VertexElement(.R32G32_Float, "POSITION", false, 0, 0, 0, .PerVertexData, 0), + VertexElement(.R32G32_Float, "TEXCOORD", false, 0, 0, (.)-1, .PerVertexData, 0), VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 0, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 1, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 2, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 3, 1, (.)-1, .PerInstanceData, 1), - VertexElement( .R8G8B8A8_UNorm, "COLOR", false, 0, 1, (.)-1, .PerInstanceData, 1), - VertexElement(.R32G32B32A32_Float, "TEXCOORD", false, 0, 1, (.)-1, .PerInstanceData, 1) + VertexElement(.R32G32B32A32_Float, "COLOR", false, 0, 1, (.)-1, .PerInstanceData, 1), + VertexElement(.R32G32B32A32_Float, "TEXCOORD", false, 1, 1, (.)-1, .PerInstanceData, 1) ); - VertexLayout instancingLayout = new VertexLayout(_context, vertexElements, true, instancingEffect.VertexShader); + VertexLayout batchLayout = new VertexLayout(Renderer._context, vertexElements, true, s_batchEffect.VertexShader); - instancingBinding = new GeometryBinding(_context); - instancingBinding.SetVertexLayout(instancingLayout..ReleaseRefNoDelete()); - instancingBinding.SetPrimitiveTopology(.TriangleList); - instancingBinding.SetVertexBufferSlot(quadBinding.GetVertexBuffer(0), 0); - instancingBinding.SetVertexBufferSlot(instanceBuffer, 1); - instancingBinding.SetIndexBuffer(quadBinding.GetIndexBuffer(), 0); + s_batchBinding = new GeometryBinding(Renderer._context); + s_batchBinding.SetVertexLayout(batchLayout..ReleaseRefNoDelete()); + s_batchBinding.SetPrimitiveTopology(.TriangleList); + + s_batchBinding.SetVertexBufferSlot(s_quadGeometry.GetVertexBuffer(0), 0); + s_batchBinding.SetIndexBuffer(s_quadGeometry.GetIndexBuffer(), 0); + + s_batchBinding.SetVertexBufferSlot(s_instanceBuffer, 1); + + s_rawInstances = new BatchVertex[1024]; + s_setInstances = 0; + + s_instanceQueue = new List(1024); } - /** - * Initializes the renderer. - * @param drawOrder Determines if and how the sprites will be ordered before rendering. - * @param virtualResolution The virtual resolution used for rendering. - * Can be used to draw resolution independent stuff. // TODO: find a better explanation - */ // TODO: RenderMode (Immediate, Deferred) - public void Begin(DrawOrder drawOrder = .SortByTexture, Vector2 virtualResolution = .Zero, float maxDepth = 100, Effect effect = null) + private static void InitWhitetexture() { - _drawOrder = drawOrder; + // Create a texture with a single white pixel + Texture2DDesc tex2Ddesc = .{ + Format = .R8G8B8A8_UNorm, + Width = 1, + Height = 1, + MipLevels = 1, + ArraySize = 1, + Usage = .Immutable, + CpuAccess = .None + }; + s_whiteTexture = new Texture2D(Renderer._context, tex2Ddesc); - _virtualResolution = virtualResolution; + Color color = .White; + s_whiteTexture.SetData(&color); - if(virtualResolution == .Zero) - { - _virtualResolution = .(_context.SwapChain.BackbufferViewport.Width, _context.SwapChain.BackbufferViewport.Height); - } + // Create the default sampler for the white texture + SamplerState sampler = SamplerStateManager.GetSampler(SamplerStateDescription()); + s_whiteTexture.SamplerState = sampler; + + sampler.ReleaseRef(); + } + + public static void Init() + { + InitEffect(); + InitGeometry(); + InitInstancingGeometry(); + InitWhitetexture(); + + FontRenderer.Init(); + +#if DEBUG + s_initialized = true; +#endif + } + + public static void Deinit() + { + Log.EngineLogger.AssertDebug(s_initialized, "Renderer2D was not initialized."); + + FontRenderer.Deinit(); + + s_textureColorEffect.ReleaseRef(); + s_batchEffect.ReleaseRef(); + + s_quadGeometry.ReleaseRef(); + + s_whiteTexture.ReleaseRef(); - _projection = .(2.0f / _virtualResolution.X, 0, 0, 0, - 0, -2.0f / _virtualResolution.Y, 0, 0, - 0, 0, 1.0f / maxDepth, 0, - -1, 1, 0, 1); + s_batchBinding.ReleaseRef(); + s_instanceBuffer.ReleaseRef(); + delete s_rawInstances; + delete s_instanceQueue; + + s_currentEffect?.ReleaseRef(); + +#if DEBUG + s_initialized = false; +#endif + } + + public static void BeginScene(OrthographicCamera camera, DrawOrder drawOrder = .SortByTexture, Effect effect = null) + { + Log.EngineLogger.AssertDebug(s_initialized, "Renderer2D was not initialized."); + Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene."); + + //s_textureColorEffect.Bind(Renderer._context); + if(effect != null) { - _currentEffect?.ReleaseRef(); - _currentEffect = effect..AddRef(); + s_currentEffect?.ReleaseRef(); + s_currentEffect = effect..AddRef(); } else { - _currentEffect = instancingEffect..AddRef(); + s_currentEffect = s_batchEffect..AddRef(); } + + s_currentEffect.Variables["ViewProjection"].SetData(camera.ViewProjection); + s_textureColorEffect.Variables["ViewProjection"].SetData(camera.ViewProjection); + + s_drawOrder = drawOrder; + +#if DEBUG + s_sceneRunning = true; +#endif } - struct QueuedQuad: this(Matrix Transform, Color Color, Texture2D Texture, float Depth, Vector4 uvTransform) { } - - List _quads = new .(128) ~ delete _; - - public void Draw(Texture2D texture, float x, float y, float width, float height, Color color = .White, float depth = 0.0f, Vector4 uvTransform = .(0, 0, 1, 1)) + public static void EndScene() { - Matrix transform = .(width, 0, 0, 0, - 0, height, 0, 0, - 0, 0, 1, 0, - x, y, depth, 1) * _projection; + Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene."); - if(_drawOrder == .Immediate) - { - /* - texture.Bind(); - - quadEffect.Variables["World"].SetData(transform); - quadEffect.Variables["Color"].SetData(color); - quadEffect.Variables["HasTexture"].SetData(true); - quadEffect.Bind(_context); - - quadBinding.Bind(_context); - RenderCommand.DrawIndexed(quadBinding); - */ - _quads.Add(.(transform, color, texture ?? whiteTexture, depth, uvTransform)); + Flush(); +#if DEBUG + s_sceneRunning = false; +#endif + } + + public static void Flush() + { + Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene."); + + if(s_drawOrder != .Immediate) DrawDeferred(); - } - else - { - _quads.Add(.(transform, color, texture ?? whiteTexture, depth, uvTransform)); - } } - public void End() + /// Adds a quad instance to the instance queue. + [Inline] + private static void QueueQuadInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, Vector4 uvTransform) { - if(_drawOrder != .Immediate) - { - DrawDeferred(); - } + s_instanceQueue.Add(QueueQuad(transform, color, texture ?? s_whiteTexture, depth, uvTransform)); } - - void FlushInstances() + + private static void FlushInstances() { - if(_setInstances == 0) + if(s_setInstances == 0) return; - instanceBuffer.SetData(_rawInstances.Ptr, _setInstances, 0, .WriteDiscard); + s_instanceBuffer.SetData(s_rawInstances.Ptr, s_setInstances, 0, .WriteDiscard); - _currentEffect.Bind(_context); - instancingBinding.InstanceCount = _setInstances; - instancingBinding.Bind(_context); - RenderCommand.DrawIndexedInstanced(instancingBinding); + s_currentEffect.Bind(Renderer._context); + s_batchBinding.InstanceCount = s_setInstances; + s_batchBinding.Bind(Renderer._context); + RenderCommand.DrawIndexedInstanced(s_batchBinding); - _setInstances = 0; + s_setInstances = 0; } - int TextureComparison(QueuedQuad lhs, QueuedQuad rhs) + private static int TextureComparison(QueueQuad lhs, QueueQuad rhs) { return (int)Internal.UnsafeCastToPtr(lhs.Texture) - (int)Internal.UnsafeCastToPtr(rhs.Texture); } - int FrontToBackComparison(QueuedQuad lhs, QueuedQuad rhs) + private static int BackToFrontComparison(QueueQuad lhs, QueueQuad rhs) { return rhs.Depth <=> lhs.Depth; } - int BackToFrontComparison(QueuedQuad lhs, QueuedQuad rhs) + private static int FrontToBackComparison(QueueQuad lhs, QueueQuad rhs) { return lhs.Depth <=> rhs.Depth; } - private void SortQuads() + private static void SortQuads() { - switch(_drawOrder) + s_instanceQueue.Sort(scope => TextureComparison); + + switch(s_drawOrder) { case .SortByTexture: - _quads.Sort(scope => TextureComparison); + s_instanceQueue.Sort(scope => TextureComparison); case .BackToFront: - _quads.Sort(scope => BackToFrontComparison); + s_instanceQueue.Sort(scope => BackToFrontComparison); case .FrontToBack: - _quads.Sort(scope => FrontToBackComparison); + s_instanceQueue.Sort(scope => FrontToBackComparison); + case .Immediate: default: + Log.EngineLogger.Error("Unknown instance draw order."); } } - private void DrawDeferred() + private static void DrawDeferred() { - if(_quads.Count == 0) + if(s_instanceQueue.IsEmpty) return; SortQuads(); - Texture2D texture = _quads[0].Texture; - _currentEffect.SetTexture("Texture", texture); + Texture2D texture = s_instanceQueue[0].Texture; + s_currentEffect.SetTexture("Texture", texture); - _setInstances = 0; + s_setInstances = 0; - for(int i < _quads.Count) + for(int i < s_instanceQueue.Count) { - var quad = ref _quads[i]; + var quad = ref s_instanceQueue[i]; // flush every time the texture changes if(quad.Texture != texture) @@ -323,12 +363,12 @@ namespace GlitchyEngine.Renderer FlushInstances(); texture = quad.Texture; - _currentEffect.SetTexture("Texture", texture); + s_currentEffect.SetTexture("Texture", texture); } - _rawInstances[_setInstances++] = .(quad.Transform, quad.Color, quad.uvTransform); + s_rawInstances[s_setInstances++] = .(quad.Transform, quad.Color, quad.uvTransform); - if(_setInstances == _rawInstances.Count) + if(s_setInstances == s_rawInstances.Count) { FlushInstances(); } @@ -336,9 +376,78 @@ namespace GlitchyEngine.Renderer FlushInstances(); - _quads.Clear(); + s_instanceQueue.Clear(); + } - Debug.Assert(_quads.Count == 0); + private static void DrawImmediate(Matrix transform, ColorRGBA color, Texture2D texture, Vector4 uvTransform) + { + s_textureColorEffect.SetTexture("Texture", texture ?? s_whiteTexture); + + s_textureColorEffect.Variables["World"].SetData(transform); + s_textureColorEffect.Variables["Color"].SetData(color); + s_textureColorEffect.Variables["UVTransform"].SetData(uvTransform); + + s_textureColorEffect.Bind(Renderer._context); + + s_quadGeometry.Bind(Renderer._context); + RenderCommand.DrawIndexed(s_quadGeometry); + } + + // Primitives + + public static void DrawQuad(Vector2 position, Vector2 size, float rotation, ColorRGBA color) + { + DrawQuad(Vector3(position, 0.0f), size, rotation, s_whiteTexture, color); + } + + /// Like DrawQuad but the pivot point is the top left corner + public static void DrawQuadPivotCorner(Vector2 position, Vector2 size, float rotation, ColorRGBA color) + { + DrawQuadPivotCorner(Vector3(position, 0.0f), size, rotation, s_whiteTexture, color); + } + + public static void DrawQuad(Vector3 position, Vector2 size, float rotation, ColorRGBA color) + { + DrawQuad(position, size, rotation, s_whiteTexture, color); + } + + public static void DrawQuadPivotCorner(Vector3 position, Vector2 size, float rotation, ColorRGBA color) + { + DrawQuadPivotCorner(position, size, rotation, s_whiteTexture, color); + } + + public static void DrawQuad(Vector2 position, Vector2 size, float rotation, Texture2D texture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1)) + { + DrawQuad(Vector3(position, 0.0f), size, rotation, texture, color, uvTransform); + } + + public static void DrawQuadPivotCorner(Vector2 position, Vector2 size, float rotation, Texture2D texture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1)) + { + DrawQuadPivotCorner(Vector3(position, 0.0f), size, rotation, texture, color, uvTransform); + } + + public static void DrawQuad(Vector3 position, Vector2 size, float rotation, Texture2D texture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1)) + { + Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene."); + + Matrix transform = Matrix.Translation(position) * Matrix.RotationZ(rotation) * Matrix.Scaling(size.X, size.Y, 1.0f); + + if(s_drawOrder == .Immediate) + { + //DrawImmediate(transform, color, texture, uvTransform); + QueueQuadInstance(transform, color, texture, position.Z, uvTransform); + DrawDeferred(); + //Flush(); + } + else + { + QueueQuadInstance(transform, color, texture, position.Z, uvTransform); + } + } + + public static void DrawQuadPivotCorner(Vector3 position, Vector2 size, float rotation, Texture2D texture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1)) + { + DrawQuad(position + Vector3(size.X / 2, size.Y / -2, 0), size, rotation, texture, color, uvTransform); } } } diff --git a/GlitchyEngine/src/Renderer/Text/Font.bf b/GlitchyEngine/src/Renderer/Text/Font.bf index 2e09bef..0fe5b5b 100644 --- a/GlitchyEngine/src/Renderer/Text/Font.bf +++ b/GlitchyEngine/src/Renderer/Text/Font.bf @@ -107,20 +107,21 @@ namespace GlitchyEngine.Renderer.Text public this(GraphicsContext context, String fontPath, uint32 fontSize, bool hasColor = true, char32 firstChar = '\0', uint32 charCount = 128, int32 faceIndex = 0) { + // Make sure the fontrenderer is initialized (Font only cares about freetype) + FontRenderer.Init(); + _context = context..AddRef(); // Set default sampler Sampler = null; - FontRenderer.InitLibrary(); - _glyphs.Add('\0', new GlyphDescriptor(){Font = this}); _fontSize = fontSize; _faceIndex = faceIndex; _hasColor = hasColor; - var res = FreeType.New_Face(FontRenderer.Library, fontPath, faceIndex, &_face); + var res = FreeType.New_Face(FontRenderer.s_Library, fontPath, faceIndex, &_face); Log.EngineLogger.Assert(res.Success, scope $"New_Face failed({(int)res}): {res}"); res = FreeType.Set_Pixel_Sizes(_face, 0, _fontSize); @@ -408,11 +409,8 @@ namespace GlitchyEngine.Renderer.Text desc.TranslationX = translationX; desc.TranslationY = translationY; - //desc.AdjustToBaseLine = (float)(- height + _range + (_face.glyph.metrics.height / 64 - _face.glyph.metrics.horiBearingY / 64) * _geometryScaler); - //(float)(- height + translationY * _geometryScaler + (_face.glyph.metrics.height / 64 - _face.glyph.metrics.horiBearingY / 64) * _geometryScaler); - desc.AdjustToBaseLine = (float)(-height + translationY * _geometryScaler); + desc.AdjustToBaseLine = (float)(-translationY * _geometryScaler); - //desc.AdjustToPen = (float)(- _range + (_face.glyph.metrics.horiBearingX / 64) * _geometryScaler); desc.AdjustToPen = (float)(-translationX); return true; diff --git a/GlitchyEngine/src/Renderer/Text/FontRenderer.bf b/GlitchyEngine/src/Renderer/Text/FontRenderer.bf index e4f4a78..275d98d 100644 --- a/GlitchyEngine/src/Renderer/Text/FontRenderer.bf +++ b/GlitchyEngine/src/Renderer/Text/FontRenderer.bf @@ -5,41 +5,51 @@ using GlitchyEngine.Math; using System.Collections; using internal GlitchyEngine.Renderer.Text; +using internal GlitchyEngine.Renderer; namespace GlitchyEngine.Renderer.Text { public static class FontRenderer { - internal static FT_Library Library ~ FreeType.Done_FreeType(_); - - internal static void InitLibrary() - { - if(Library == null) - { - var res = FreeType.Init_FreeType(&Library); - Log.EngineLogger.Assert(res.Success, scope $"Init_FreeType failed({(int)res}): {res}"); - } - } + internal static FT_Library s_Library; public static Effect _msdfEffect; - static this() + internal static bool s_isInitialized; + + internal static void Init() { - FontRenderer.InitLibrary(); + if(s_isInitialized) + return; + + InitFreetype(); + + _msdfEffect = new Effect(Renderer._context, "content\\Shaders\\msdfShader.hlsl"); + + s_isInitialized = true; } - public static void Init(EffectLibrary effectLibrary) + internal static void Deinit() { - if(effectLibrary.Exists("msdfShader")) - _msdfEffect = effectLibrary.Get("msdfShader"); - else - _msdfEffect = effectLibrary.Load("content\\Shaders\\msdfShader.hlsl"); + _msdfEffect.ReleaseRef(); + + DeinitFreetype(); + + s_isInitialized = false; + } + + private static void InitFreetype() + { + if(s_Library == null) + { + var res = FreeType.Init_FreeType(&s_Library); + Log.EngineLogger.Assert(res.Success, scope $"Failed to initialize freetype ({(int)res}): {res}"); + } } - public static void DeInit() + private static void DeinitFreetype() { - _msdfEffect?.ReleaseRef(); - _msdfEffect = null; + FreeType.Done_FreeType(s_Library); } /** @brief Draws a given text using a specified font stack and renderer. @@ -52,24 +62,33 @@ namespace GlitchyEngine.Renderer.Text * @param bitmapColor The (default) color used for glyphs that are bitmaps (e.g. emojies, if the font provies them as bitmap). * @param lineGapOffset Can be used to manually increase or decrease the gap between lines. */ - public static void DrawText(Renderer2D renderer, Font font, String text, float x, float y, float fontSize, Color fontColor = .White, Color bitmapColor = .White, float lineGapOffset = 0) + public static void DrawText(Font font, String text, float x, float y, float fontSize, Color fontColor = .White, Color bitmapColor = .White, float lineGapOffset = 0) { if(text.IsWhiteSpace) return; - renderer.End(); - var lastEffect = renderer.[Friend]_currentEffect; - renderer.[Friend]_currentEffect = _msdfEffect..AddRef(); - + Renderer2D.Flush(); + + // TODO: this is very not good! + var lastEffect = Renderer2D.[Friend]s_currentEffect; + Renderer2D.[Friend]s_currentEffect = _msdfEffect..AddRef(); + // TODO: oh no.... + // Copy viewProjection from current effect + Matrix viewProjection = lastEffect.Variables["ViewProjection"].[Friend]GetData(); + _msdfEffect.Variables["ViewProjection"].SetData(viewProjection); + float scale = (float)fontSize / (float)font._fontSize; - + _msdfEffect.Variables["screenPixelRange"].SetData(scale * 4.0f); + + Vector2 unitRange = Vector2((float)font._range) / Vector2(font._atlas.Width, font._atlas.Height); + _msdfEffect.Variables["UnitRange"].SetData(unitRange); // Space between two baselines float linespace = (((font._face.size.metrics.ascender - font._face.size.metrics.descender) / 64) + lineGapOffset) * scale; // The line we are writing on - float baseline = y + linespace; + float baseline = y;// + linespace; //renderer.Draw(null, x, baseline, 10000, 1, .Blue); @@ -80,7 +99,6 @@ namespace GlitchyEngine.Renderer.Text int movedLines = 0; List atlasses = scope .(); - // We render every char with a slightly greater depth, so that the chars don't cull each other. // In order to do that we increment an integer for each glyph and use it as the depth for the next one. // Whenn passing the depth to the renderer we treat the integer as the binary representation of a float. @@ -88,8 +106,8 @@ namespace GlitchyEngine.Renderer.Text // smallest possible increase a float can represent. // Note: This might do funky stuff when objects are very close to each other. But realistically whe have to do // about 8 million (2^23) increments to reach a depth of 1 so I think it's safe enough. - float f = 1.0f; - int32 depthInt = *(int32*)&f; + //float f = 1.0f; + //int32 depthInt = *(int32*)&f; // enumerate through the unicode codepoints for(char32 char in text.DecodedChars) @@ -104,7 +122,7 @@ namespace GlitchyEngine.Renderer.Text if(movedLines != 0) { // move baseline - baseline += linespace * movedLines; + baseline -= linespace * movedLines; // TODO: make carriage return optional? // return pen to start of line @@ -155,18 +173,22 @@ namespace GlitchyEngine.Renderer.Text texRect /= Vector4(atlasSize, atlasSize); - renderer.Draw(atlas, viewportRect.X, viewportRect.Y, viewportRect.Z, viewportRect.W, glyphColor, *(float*)(&depthInt), texRect); + Renderer2D.DrawQuad(Vector2(viewportRect.X + viewportRect.Z / 2, viewportRect.Y + viewportRect.W / 2), .(viewportRect.Z, viewportRect.W), 0, atlas, glyphColor, texRect); + + //renderer.Draw(atlas, viewportRect.X, viewportRect.Y, viewportRect.Z, viewportRect.W, glyphColor, *(float*)(&depthInt), texRect); penPosition += glyphDesc.Advance * glyphFontScale; // Increase depth for the next glyph - depthInt--; + //depthInt--; } - renderer.End(); + Renderer2D.Flush(); + // TODO: not good! + // Change back effect _msdfEffect.ReleaseRef(); - renderer.[Friend]_currentEffect = lastEffect; + Renderer2D.[Friend]s_currentEffect = lastEffect; // release all atlas textures for(int i < atlasses.Count) diff --git a/Sandbox/content/Shaders/msdfShader.hlsl b/Sandbox/content/Shaders/msdfShader.hlsl index 635de11..25b0c8e 100644 --- a/Sandbox/content/Shaders/msdfShader.hlsl +++ b/Sandbox/content/Shaders/msdfShader.hlsl @@ -3,30 +3,33 @@ SamplerState Sampler : register(s0); cbuffer Constants { + float4x4 ViewProjection; + float2 UnitRange; float screenPixelRange = 2; } struct VS_Input { float2 Position : POSITION; + float2 Texcoord : TEXCOORD0; float4x4 Tranform : TRANSFORM; float4 Color : COLOR; - float4 UVTransform : TEXCOORD; + float4 UVTransform : TEXCOORD1; }; struct PS_Input { float4 Position : SV_Position; float2 TexCoord : TEXCOORD0; - float4 Color : COLOR; + float4 Color : COLOR; }; PS_Input VS(VS_Input input) { PS_Input output; - output.Position = mul(float4(input.Position, 0.0f, 1.0f), input.Tranform); - output.TexCoord = input.UVTransform.xy + input.UVTransform.zw * input.Position; + output.Position = mul(ViewProjection, mul(input.Tranform, float4(input.Position, 0.0f, 1.0f))); + output.TexCoord = input.UVTransform.xy + input.UVTransform.zw * input.Texcoord; output.Color = input.Color; return output; @@ -36,14 +39,17 @@ float median(float r, float g, float b) { return max(min(r, g), min(max(r, g), b)); } +float ScreenPxRange(float2 texcoord) { + float2 screenTexSize = 1.0f / fwidth(texcoord); + return max(0.5f * dot(UnitRange, screenTexSize), 1.0f); +} + float4 PS(PS_Input input) : SV_Target0 { float3 msd = Texture.Sample(Sampler, input.TexCoord); float sd = median(msd.r, msd.g, msd.b); - float screenPxDistance = screenPixelRange * (sd - 0.5); + float screenPxDistance = ScreenPxRange(input.TexCoord) * (sd - 0.5); float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); - //float4 color = lerp(float4(1, 0, 0, 1), input.Color, opacity); - //return color; return float4(input.Color.rgb, opacity * input.Color.a); } diff --git a/Sandbox/content/Shaders/spritebatch.hlsl b/Sandbox/content/Shaders/spritebatch.hlsl new file mode 100644 index 0000000..be544ec --- /dev/null +++ b/Sandbox/content/Shaders/spritebatch.hlsl @@ -0,0 +1,41 @@ +Texture2D Texture : register(t0); +SamplerState Sampler : register(s0); + +cbuffer Constants : register(b0) +{ + float4x4 ViewProjection; +}; + +struct VS_Input +{ + float2 Position : POSITION; + float2 Texcoord : TEXCOORD0; + float4x4 Transform : TRANSFORM; + float4 Color : COLOR; + float4 UVTransform : TEXCOORD1; +}; + +struct PS_Input +{ + float4 Position : SV_Position; + float2 Texcoord : TEXCOORD; + float4 Color : COLOR; +}; + +PS_Input VS(VS_Input input) +{ + PS_Input output; + + output.Position = mul(ViewProjection, mul(input.Transform, float4(input.Position, 0.0f, 1.0f))); + output.Texcoord = input.UVTransform.xy + input.UVTransform.zw * input.Texcoord; + output.Color = input.Color; + + return output; +} + +float4 PS(PS_Input input) : SV_Target0 +{ + return Texture.Sample(Sampler, input.Texcoord) * input.Color; +} + +#effect[VS=VS, PS=PS] \ No newline at end of file diff --git a/Sandbox/content/Shaders/textureColor.hlsl b/Sandbox/content/Shaders/textureColor.hlsl new file mode 100644 index 0000000..cd485b6 --- /dev/null +++ b/Sandbox/content/Shaders/textureColor.hlsl @@ -0,0 +1,42 @@ +Texture2D Texture : register(t0); +SamplerState Sampler : register(s0); + +cbuffer Constants : register(b0) +{ + float4x4 World; + + // TODO: move ViewProjection to seperate cbuffer + float4x4 ViewProjection; + + float4 Color; + float4 UVTransform; +}; + +struct VS_Input +{ + float2 Position : POSITION; + float2 Texcoord : TEXCOORD; +}; + +struct PS_Input +{ + float4 Position : SV_Position; + float2 Texcoord : TEXCOORD; +}; + +PS_Input VS(VS_Input input) +{ + PS_Input output; + + output.Position = mul(ViewProjection, mul(World, float4(input.Position, 0.0f, 1.0f))); + output.Texcoord = UVTransform.xy + UVTransform.zw * input.Texcoord; + + return output; +} + +float4 PS(PS_Input input) : SV_Target0 +{ + return Texture.Sample(Sampler, input.Texcoord) * Color; +} + +#effect[VS=VS, PS=PS] \ No newline at end of file diff --git a/Sandbox/content/Shaders/textureViewerShader.hlsl b/Sandbox/content/Shaders/textureViewerShader.hlsl index e3ac105..afd6945 100644 --- a/Sandbox/content/Shaders/textureViewerShader.hlsl +++ b/Sandbox/content/Shaders/textureViewerShader.hlsl @@ -3,6 +3,8 @@ SamplerState Sampler : register(s0); cbuffer Constants { + float4x4 ViewProjection; + float ColorOffset = 0.5f; float AlphaOffset = 0.0f; float ColorScale = 0.5f; @@ -13,16 +15,17 @@ cbuffer Constants struct VS_Input { - float2 Position : POSITION; - float4x4 Tranform : TRANSFORM; - float4 Color : COLOR; - float4 UVTransform : TEXCOORD; + float2 Position : POSITION; + float2 Texcoord : TEXCOORD0; + float4x4 Transform : TRANSFORM; + float4 Color : COLOR; + float4 UVTransform : TEXCOORD1; }; struct PS_Input { float4 Position : SV_Position; - float2 TexCoord : TEXCOORD0; + float2 Texcoord : TEXCOORD0; float4 Color : COLOR; }; @@ -30,8 +33,8 @@ PS_Input VS(VS_Input input) { PS_Input output; - output.Position = mul(float4(input.Position, 0.0f, 1.0f), input.Tranform); - output.TexCoord = input.UVTransform.xy + input.UVTransform.zw * input.Position; + output.Position = mul(ViewProjection, mul(input.Transform, float4(input.Position, 0.0f, 1.0f))); + output.Texcoord = input.UVTransform.xy + input.UVTransform.zw * input.Texcoord; output.Color = input.Color; return output; @@ -39,7 +42,7 @@ PS_Input VS(VS_Input input) float4 PS(PS_Input input) : SV_Target0 { - float4 color = Texture.Sample(Sampler, input.TexCoord); + float4 color = Texture.Sample(Sampler, input.Texcoord); float4 final = float4(ColorOffset.xxx, AlphaOffset) + color * float4(ColorScale.xxx, AlphaScale); diff --git a/Sandbox/src/SandboxApp2D.bf b/Sandbox/src/ExampleLayer2D.bf similarity index 85% rename from Sandbox/src/SandboxApp2D.bf rename to Sandbox/src/ExampleLayer2D.bf index 970c657..effc862 100644 --- a/Sandbox/src/SandboxApp2D.bf +++ b/Sandbox/src/ExampleLayer2D.bf @@ -49,7 +49,6 @@ namespace Sandbox DepthStencilTarget _depthTarget ~ _?.ReleaseRef(); Texture2D _texture ~ _?.ReleaseRef(); - Texture2D _ge_logo ~ _?.ReleaseRef(); BlendState _alphaBlendState ~ _?.ReleaseRef(); BlendState _opaqueBlendState ~ _?.ReleaseRef(); @@ -58,9 +57,7 @@ namespace Sandbox EcsWorld _world = new EcsWorld() ~ delete _; - Renderer2D Renderer2D ~ delete _; - - Texture2D _testTexture ~ _?.ReleaseRef(); + //Renderer2D Renderer2D ~ delete _; String testText ~ delete _; @@ -78,22 +75,22 @@ namespace Sandbox _effectLibrary.LoadNoRefInc("content\\Shaders\\basicShader.hlsl"); // Create rasterizer state - GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true); + GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, false); _rasterizerState = new RasterizerState(_context, rsDesc); _depthTarget = new DepthStencilTarget(_context, _context.SwapChain.Width, _context.SwapChain.Height); _texture = new Texture2D(_context, "content/Textures/Checkerboard.dds"); - _ge_logo = new Texture2D(_context, "content/Textures/GE_Logo.dds"); let sampler = SamplerStateManager.GetSampler( SamplerStateDescription() { - MagFilter = .Point + MagFilter = .Point, + AddressModeU = .Wrap, + AddressModeV = .Wrap, }); _texture.SamplerState = sampler; - _ge_logo.SamplerState = sampler; sampler.ReleaseRef(); @@ -104,7 +101,7 @@ namespace Sandbox InitEcs(); - Renderer2D = new Renderer2D(_context, _effectLibrary); + //Renderer2D = new Renderer2D(_context, _effectLibrary); //Init2D(); Texture2DDesc desc = .(); @@ -116,14 +113,6 @@ namespace Sandbox desc.MipLevels = 1; desc.Usage = .Default; - _testTexture = new Texture2D(_context, desc); - - Color[4] colors = .( - .Red, .Green, - .Blue, .White); - - _testTexture.SetData(&colors, 0, 1, 1, 1); - fonty = new Font(_context, "C:\\Windows\\Fonts\\arial.ttf", 64, true, 'A', 16); var japanese = new Font(_context, "C:\\Windows\\Fonts\\YuGothM.ttc", 64, true, '\0', 1); var emojis = new Font(_context, "C:\\Windows\\Fonts\\seguiemj.ttf", 64, true, '😂' - 10, 1); @@ -135,15 +124,12 @@ namespace Sandbox // Load test text File.ReadAllText("test.txt", testText = new String(), true); - _textureViewer = new TextureViewer(_context, Renderer2D, _effectLibrary); + _textureViewer = new TextureViewer(); - FontRenderer.Init(_effectLibrary); + controller = new OrthographicCameraController(16 / 9f); } - public ~this() - { - FontRenderer.DeInit(); - } + OrthographicCameraController controller; Font fonty ~ _.ReleaseRef(); @@ -262,20 +248,41 @@ namespace Sandbox var camera = _world.GetComponent(_cameraEntity); camera.Aspect = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width / Application.Get().Window.Context.SwapChain.BackbufferViewport.Height; + + controller.Update(gameTime); TransformSystem.Update(_world); RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f)); + RenderCommand.Clear(_depthTarget, 1.0f, 0, .Depth); - _depthTarget..Clear(1.0f, 0, .Depth).Bind(); // Draw test geometry _context.SetRenderTarget(null); + _depthTarget.Bind(); _context.BindRenderTargets(); _context.SetRasterizerState(_rasterizerState); RenderCommand.SetViewport(_context.SwapChain.BackbufferViewport); + Renderer2D.BeginScene(controller.Camera, .BackToFront); + + _alphaBlendState.Bind(); + + for(int x < 10) + for(int y < 10) + { + int i = (x + y) % 2; + + Renderer2D.DrawQuad(Vector3(2 * x, 2 * y, 0.5f), Vector2(1.5f, 1), MathHelper.PiOverFour, (i == 0) ? _squareColor0 : _squareColor1); + } + + Renderer2D.DrawQuad(Vector3(0, 0, 1), Vector2(10), 0, _texture, .White, .(0, 0, 1, 1)); + + FontRenderer.DrawText(fonty, "Hallo! gjy", 0, 0, 64, .White, .White); + + Renderer2D.EndScene(); + /* Renderer2D.Begin(.FrontToBack, .(80, 80)); @@ -322,8 +329,7 @@ namespace Sandbox Renderer2D.End(); */ - - _alphaBlendState.Bind(); + /* Renderer2D.Begin(.FrontToBack, .(_context.SwapChain.Width, _context.SwapChain.Height)); Renderer2D.End(); @@ -331,9 +337,10 @@ namespace Sandbox _alphaBlendState.Bind(); Renderer2D.Begin(.FrontToBack, .(_context.SwapChain.Width, _context.SwapChain.Height), 100); - FontRenderer.DrawText(Renderer2D, fonty, "Hallo! gjy", 0, 0, 512, .White, .White); + FontRenderer.DrawText(Renderer2D, fonty, "Hallo! gjy", 0, 0, 64, .White, .White); Renderer2D.End(); + */ } int32 size = 500; @@ -348,40 +355,20 @@ namespace Sandbox dispatcher.Dispatch(scope (e) => OnImGuiRender(e)); dispatcher.Dispatch(scope (e) => OnWindowResize(e)); + + controller.OnEvent(event); } private bool OnImGuiRender(ImGuiRenderEvent e) { - /* - ImGui.Begin("SDF Test"); - - ImGui.InputInt("Size", &size); - - float f = (size / 64f * 4.0f); - - ImGui.Text($"SPR: {f}"); - - ImGui.End(); - */ - //return true; - - /* - return true; - ImGui.Begin("Test"); - ImGui.ColorEdit3("Square Color", ref _squareColor0); + ImGui.ColorPicker4("Color", *(float[4]*)&_squareColor0); _squareColor1 = ColorRGBA.White - _squareColor0; - - //ImGui.Begin - - //ImGui.Image(fonty.[Friend]_atlas.[Friend]nativeView, .(100, 200)); - //ImGui.Scrollbar(.X); - //ImGui.Image(fonty.[Friend]_atlas.[Friend]nativeView, .(fonty.[Friend]_atlas.Width, fonty.[Friend]_atlas.Height), .(0.0f, 0.0f), .(1.0f, 1.0f), .(1.0f, 1.0f, 1.0f, 1.0f), .(1.0f, 0, 0, 1)); + _squareColor1.A = _squareColor0.A; ImGui.End(); - */ _textureViewer.ViewTexture(fonty.[Friend]_atlas); @@ -400,20 +387,4 @@ namespace Sandbox return false; } } - - class SandboxApp2D : Application - { - public this() - { - PushLayer(new ExampleLayer2D()); - } - -#if SANDBOX_2D - [Export, LinkName("CreateApplication")] -#endif - public static Application CreateApplication() - { - return new SandboxApp2D(); - } - } } \ No newline at end of file diff --git a/Sandbox/src/SandboxApp.bf b/Sandbox/src/SandboxApp.bf index e11d7c0..10fe19a 100644 --- a/Sandbox/src/SandboxApp.bf +++ b/Sandbox/src/SandboxApp.bf @@ -570,12 +570,14 @@ namespace Sandbox { public this() { +#if SANDBOX_2D + PushLayer(new ExampleLayer2D()); +#else PushLayer(new ExampleLayer()); +#endif } -#if !SANDBOX_2D [Export, LinkName("CreateApplication")] -#endif public static Application CreateApplication() { return new SandboxApp(); diff --git a/Sandbox/src/TextureViewer.bf b/Sandbox/src/TextureViewer.bf index c323cd9..b7bf04c 100644 --- a/Sandbox/src/TextureViewer.bf +++ b/Sandbox/src/TextureViewer.bf @@ -24,8 +24,6 @@ namespace Sandbox Effect _effect ~ _.ReleaseRef(); - Renderer2D _renderer; - float _zoom = 1.0f; BackgroundMode _backgroundMode = .Checkerboard; @@ -39,29 +37,18 @@ namespace Sandbox SamplerState _samplerPoint ~ _.ReleaseRef(); SamplerState _samplerLinear ~ _.ReleaseRef(); - public this(GraphicsContext context, Renderer2D renderer2D, EffectLibrary effectLibrary = null) + public this() { - Log.EngineLogger.AssertDebug(context != null); + _context = Renderer.[Friend]_context..AddRef(); - _context = context; - _renderer = renderer2D; - - InitEffect(effectLibrary); + InitEffect(); InitState(); // TODO: rasterizerstate and depthstencilstate } - private void InitEffect(EffectLibrary effectLibrary) + private void InitEffect() { - var effectLibrary; - - if(effectLibrary == null) - { - effectLibrary = new EffectLibrary(_context); - defer:: delete effectLibrary; - } - - _effect = effectLibrary.Load("content\\Shaders\\textureViewerShader.hlsl"); + _effect = new Effect(_context, "content\\Shaders\\textureViewerShader.hlsl"); } private void InitState() @@ -174,6 +161,8 @@ namespace Sandbox } } + OrthographicCamera _camera = new OrthographicCamera() ~ delete _; + private void RenderTexture(Texture2D viewedTexture) { Viewport vp = .(0, 0, _target.Width, _target.Height); @@ -198,28 +187,38 @@ namespace Sandbox _effect.Variables["AlphaOffset"].SetData(_alphaOffset); _effect.Variables["AlphaScale"].SetData(_alphaScale); - _renderer.Begin(.SortByTexture, targetSize); + _camera.Left = 0; + _camera.Top = 0; + _camera.Right = targetSize.X; + _camera.Bottom = -targetSize.Y; + _camera.NearPlane = -5; + _camera.FarPlane = 5; + _camera.Update(); + Renderer2D.BeginScene(_camera); + switch(_backgroundMode) { case .Black: - _renderer.Draw(null, 0, 0, targetSize.X, targetSize.Y, .Black, 1); + Renderer2D.DrawQuadPivotCorner(Vector3(0, 0, 1), targetSize, 0, .Black); case .White: - _renderer.Draw(null, 0, 0, targetSize.X, targetSize.Y, .White, 1); + Renderer2D.DrawQuadPivotCorner(Vector3(0, 0, 1), targetSize, 0, .White); case .Checkerboard: float quadSize = 50.0f; - - for(int x = 0; x < (targetSize.X / 500f) * 10f; x++) + + Vector2 numQuads = (targetSize / 500f) * 10f; + + for(float x = 0; x < numQuads.X; x++) { - for(int y = 0; y < (targetSize.Y / 500f) * 10f; y++) + for(float y = 0; y < numQuads.Y; y++) { - _renderer.Draw(null, x * quadSize, y * quadSize, quadSize, quadSize, ((x + y) % 2 == 0) ? .White : .Gray, 1); + Renderer2D.DrawQuadPivotCorner(Vector3(x * quadSize, -y * quadSize, 1), quadSize.XX, 0, ((x + y) % 2 == 0) ? .White : .Gray); } } break; } - _renderer.End(); + Renderer2D.EndScene(); var sampler = viewedTexture.SamplerState; @@ -231,11 +230,11 @@ namespace Sandbox viewedTexture.SamplerState = _samplerLinear; } - _renderer.Begin(.SortByTexture, targetSize, 100, _effect); + Renderer2D.BeginScene(_camera, .SortByTexture, _effect); - _renderer.Draw(viewedTexture, _position.X, _position.Y, zoomedTextureSize.X, zoomedTextureSize.Y); + Renderer2D.DrawQuadPivotCorner(Vector3(_position * .(1, -1), 0), zoomedTextureSize, 0, viewedTexture); - _renderer.End(); + Renderer2D.EndScene(); viewedTexture.SamplerState = sampler; }