예제 #1
0
        public void FramebufferResizing()
        {
            Runner.ExecuteAsLoop(_ =>
            {
                FrameBuffer testBuffer = new FrameBuffer(new Vector2(1000, 1000)).WithColor();

                RenderComposer composer = Engine.Renderer.StartFrame();

                composer.RenderToAndClear(testBuffer);
                composer.RenderSprite(new Vector3(0, 0, 0), new Vector2(1000, 1000), Color.Red);
                composer.RenderTo(null);

                composer.RenderSprite(new Vector3(0, 0, 0), new Vector2(100, 100), Color.White, testBuffer.Texture);
                testBuffer.Resize(new Vector2(500, 500), true);

                composer.RenderToAndClear(testBuffer);
                composer.RenderSprite(new Vector3(0, 0, 0), new Vector2(500, 500), Color.Green);
                composer.RenderTo(null);

                composer.RenderFrameBuffer(testBuffer, new Vector2(100, 100), new Vector3(100, 0, 0));

                Engine.Renderer.EndFrame();
                Runner.VerifyScreenshot(ResultDb.FramebufferResizing);

                testBuffer.Dispose();
            }).WaitOne();
        }
예제 #2
0
        public void TestDepthFromOtherFrameBuffer()
        {
            Runner.ExecuteAsLoop(_ =>
            {
                FrameBuffer testBuffer = new FrameBuffer(Engine.Renderer.DrawBuffer.Size).WithColor().WithDepth(true);
                var shader             = Engine.AssetLoader.Get <ShaderAsset>("Shaders/DepthTest.xml");

                RenderComposer composer = Engine.Renderer.StartFrame();
                composer.RenderTo(testBuffer);
                composer.ClearFrameBuffer();
                composer.RenderSprite(new Vector3(0, 0, 10), new Vector2(100, 100), Color.Green);
                composer.RenderTo(null);

                composer.SetUseViewMatrix(false);
                composer.SetShader(shader.Shader);
                shader.Shader.SetUniformInt("depthTexture", 1);
                Texture.EnsureBound(testBuffer.DepthTexture.Pointer, 1);
                composer.RenderSprite(new Vector3(0, 0, 0), testBuffer.Texture.Size, Color.White, testBuffer.Texture);
                composer.SetShader();
                composer.SetUseViewMatrix(true);

                composer.RenderSprite(new Vector3(20, 20, 15), new Vector2(100, 100), Color.Blue);
                composer.RenderSprite(new Vector3(10, 10, 0), new Vector2(100, 100), Color.Red);

                Engine.Renderer.EndFrame();
                Runner.VerifyScreenshot(ResultDb.TestDepthFromOtherFrameBuffer);

                testBuffer.Dispose();
            }).WaitOne();
        }
예제 #3
0
        public void Draw(RenderComposer composer)
        {
            composer.RenderToAndClear(_fbo);
            composer.SetUseViewMatrix(false);
            composer.RenderSprite(new Vector3(0, 0, 0), new Vector2(100, 100), new Color(_currentRedValue, (byte)50, (byte)50));
            composer.RenderTo(null);
            composer.SetUseViewMatrix(true);
            composer.RenderSprite(new Vector3(10, -50, 0), new Vector2(100, 100), new Color(_currentRedValue, (byte)50, (byte)50));

            if (_asyncSample)
            {
                if (_sampleReq == null || _sampleReq.Finished)
                {
                    if (_sampleReq != null && _sampleReq.Finished)
                    {
                        _lastColorResult = new Color(_sampleReq.Data[0], _sampleReq.Data[1], _sampleReq.Data[2], _sampleReq.Data[3]);
                    }
                    _sampleReq = _fbo.SampleAsync(new Rectangle(0, 0, 1, 1), OpenGL.PixelFormat.Rgba);
                }
            }
            else
            {
                byte[] sampleReq = _fbo.Sample(new Rectangle(0, 0, 1, 1), OpenGL.PixelFormat.Rgba);
                _lastColorResult = new Color(sampleReq[0], sampleReq[1], sampleReq[2], sampleReq[3]);
            }

            composer.RenderSprite(new Vector3(-100, -50, 10), new Vector2(100, 100), _lastColorResult);
        }
예제 #4
0
        private void RenderMouseOverTiles(RenderComposer composer)
        {
            var mouseRect = new Rectangle(Engine.Renderer.Camera.ScreenToWorld(Vector2.Zero), new Vector2(1, 1))
            {
                Center = Engine.Renderer.Camera.ScreenToWorld(Engine.InputManager.MousePosition)
            };

            composer.RenderOutline(new Vector3(mouseRect.Position, 10), mouseRect.Size, Color.Magenta, 2);

            //composer.PushModelMatrix(Matrix4x4.CreateTranslation(new Vector3(-mouseRect.Position, 0)));
            composer.RenderTo(_frameBuffer);
            _drawMemory.Clear();
            quadTree.GetObjects(mouseRect, ref _drawMemory);
            for (var i = 0; i < _drawMemory.Count; i++)
            {
                var tile = _drawMemory[i];

                var a    = composer.GetBatch();
                var data = a.GetData(null);
                data[0].Vertex = tile.Vertex0.ToVec3();
                data[0].Color  = new Color(50 + i, i, 0).ToUint();

                data[1].Vertex = tile.Vertex1.ToVec3();
                data[1].Color  = new Color(i * 20, i, 0).ToUint();

                data[2].Vertex = tile.Vertex2.ToVec3();
                data[2].Color  = new Color(i * 20, i * 20, 0).ToUint();

                data[3].Vertex = tile.Vertex3.ToVec3();
                data[3].Color  = new Color(i, i * 20, 0).ToUint();
            }

            composer.PushCommand(new ExecCodeCommand()
            {
                Func = () =>
                {
                    byte[] pixels = _frameBuffer.Sample(new Rectangle(Engine.InputManager.MousePosition, Vector2.One));

                    _lastMouseX = pixels[3];
                    _lastMouseY = pixels[2];
                }
            });

            //composer.PopModelMatrix();
            composer.RenderTo(null);
        }
예제 #5
0
        private void RenderSaveSection(RenderComposer composer)
        {
            // Saving
            ImGui.InputText("Name", ref _saveName, 100);
            ImGui.SameLine();
            if (string.IsNullOrEmpty(_saveName))
            {
                ImGui.TextDisabled("Save");
                ImGui.SameLine();
                ImGui.TextDisabled("SaveToFile");
            }
            else
            {
                ImGui.SameLine();
                if (ImGui.Button("SaveToFile"))
                {
                    string saveName = _saveName.ToLower();
                    if (!saveName.Contains(".anim")) saveName += ".anim";

                    // Fixups
                    if (AnimController?.MirrorXAnchors != null)
                    {
                        var emptyMirrorAnchors = true;
                        for (var i = 0; i < AnimController.MirrorXAnchors.Length; i++)
                        {
                            if (AnimController.MirrorXAnchors[i] == Vector2.Zero) continue;
                            emptyMirrorAnchors = false;
                            break;
                        }

                        if (emptyMirrorAnchors) AnimController.MirrorXAnchors = null;
                    }

                    try
                    {
                        string saveData;
                        // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                        if (AnimController != null)
                            saveData = XMLFormat.To(AnimController);
                        else
                            saveData = XMLFormat.To(Animation);

                        Engine.AssetLoader.Save(Encoding.UTF8.GetBytes(saveData), saveName);
                    }
                    catch (Exception ex)
                    {
                        Engine.Log.Error(ex);
                    }
                }

                if (ImGui.Button("Save Packed Texture"))
                {
                    string saveName = _saveName.ToLower();
                    if (!saveName.Contains(".png")) saveName += ".png";
                    Rectangle[] frames = AnimController != null ? AnimController.AnimTex.Frames : Animation.Frames;
                    var preBinnedFrames = new Rectangle[frames.Length];
                    Array.Copy(frames, preBinnedFrames, frames.Length);
                    Texture spriteSheetTexture = Animation.Texture;

                    var spacing = 2;
                    for (var i = 0; i < frames.Length; i++)
                    {
                        Rectangle frame = frames[i];
                        frames[i] = frame.Inflate(spacing, spacing);
                    }

                    Vector2 totalSize = Binning.FitRectangles(frames, true);
                    FrameBuffer texture = new FrameBuffer(totalSize).WithColor();
                    composer.RenderTo(texture);
                    for (var i = 0; i < frames.Length; i++)
                    {
                        composer.RenderSprite(frames[i].Deflate(spacing, spacing), Color.White, spriteSheetTexture, preBinnedFrames[i]);
                    }

                    composer.RenderTo(null);

                    byte[] pixelsDownload = texture.Sample(new Rectangle(0, 0, totalSize), PixelFormat.Rgba);
                    ImageUtil.FlipImageY(pixelsDownload, (int) totalSize.Y);
                    byte[] pngFile = PngFormat.Encode(pixelsDownload, totalSize, PixelFormat.Rgba);
                    Engine.AssetLoader.Save(pngFile, saveName);
                }
            }
        }
예제 #6
0
        private void RenderAnimationPreview(RenderComposer c)
        {
            AnimatedSprite             currentFileContext = _currentAsset !.Content !;
            SpriteAnimationFrameSource frameSource        = currentFileContext.FrameSource;

            if (_animatedPreviewInvalidated)
            {
                var size = new Vector2();
                for (var i = 0; i < frameSource.GetFrameCount(); i++)
                {
                    Rectangle frameUV = frameSource.GetFrameUV(i);

                    size.X = MathF.Max(size.X, frameUV.Width);
                    size.Y = MathF.Max(size.Y, frameUV.Height);
                }

                if (size.X > size.Y)
                {
                    size.Y = size.X;
                }
                else if (size.Y > size.X)
                {
                    size.X = size.Y;
                }

                size *= 2;

                GLThread.ExecuteGLThreadAsync(() =>
                {
                    if (_animatedPreviewFb == null)
                    {
                        _animatedPreviewFb = new FrameBuffer(size).WithColor();
                    }
                    else
                    {
                        _animatedPreviewFb.Resize(size, true);
                    }
                });

                _animatedPreviewInvalidated = false;
            }

            if (_animatedPreviewFb != null)
            {
                c.RenderToAndClear(_animatedPreviewFb);

                Vector2 size = _animatedPreviewFb.Size;
                c.RenderSprite(Vector3.Zero, size, new Color(32, 32, 32));
                c.RenderLine(new Vector2(0, size.Y / 2), new Vector2(size.X, size.Y / 2), Color.White * 0.2f);
                c.RenderLine(new Vector2(size.X / 2, 0), new Vector2(size.X / 2, size.Y), Color.White * 0.2f);

                if (_animatedPreviewAnchorMode)
                {
                    // Draw a shadow of the previous frame.
                    if (_frameAnchor != 0)
                    {
                        _controller.GetRenderDataForFrame(_frameAnchor - 1, out Vector3 renderPosSh, out Texture textureSh, out Rectangle uvSh);
                        renderPosSh = renderPosSh.RoundClosest();
                        c.RenderSprite((size / 2f).RoundClosest().ToVec3() + renderPosSh, uvSh.Size, Color.White * 0.3f, textureSh, uvSh);
                    }

                    _controller.GetRenderDataForFrame(_frameAnchor, out Vector3 renderPos, out Texture texture, out Rectangle uv);
                    renderPos = renderPos.RoundClosest();
                    c.RenderSprite((size / 2f).RoundClosest().ToVec3() + renderPos, uv.Size, Color.White, texture, uv);
                }
                else
                {
                    _controller.GetRenderData(out Vector3 renderPos, out Texture texture, out Rectangle uv);
                    renderPos = renderPos.RoundClosest();
                    c.RenderSprite((size / 2f).RoundClosest().ToVec3() + renderPos, uv.Size, Color.White, texture, uv);
                }

                c.RenderTo(null);
            }
        }
예제 #7
0
        protected override bool RenderInternal(RenderComposer c)
        {
            var open = true;

            ImGui.SetNextWindowPos(new Vector2(0, 20), ImGuiCond.Always);
            ImGui.SetNextWindowSize(c.CurrentTarget.Size - new Vector2(0, 20));
            ImGui.Begin(Title, ref open, ImGuiWindowFlags.MenuBar | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove);

            RenderImGui();

            ImGui.End();

            Position = Vector3.Zero;
            Size     = c.CurrentTarget.Size;
            if (!open)
            {
                Parent?.RemoveChild(this);
                return(false);
            }

            if (_textureFb?.ColorAttachment == null)
            {
                return(true);                                     // Disposed or uninitialized fb
            }
            if (_currentAssetTexture == null)
            {
                return(true);
            }

            _textureFb.ColorAttachment.Smooth = false;
            c.RenderToAndClear(_textureFb);
            c.RenderSprite(Vector3.Zero, _currentAssetTexture.Size, _currentAssetTexture);

            // Render meta overlay on the spritesheet texture.
            if (_currentAsset != null)
            {
                AnimatedSprite             currentFileContext = _currentAsset.Content !;
                SpriteAnimationFrameSource frameSource        = currentFileContext.FrameSource;
                if (frameSource != null)
                {
                    for (var i = 0; i < frameSource.GetFrameCount(); i++)
                    {
                        Rectangle frameUv = frameSource.GetFrameUV(i);
                        c.RenderOutline(frameUv, _selectedFrame == i ? Color.Green : Color.Red);

                        if (_showFrameIdx && frameSource is SpriteArrayFrameSource)
                        {
                            Vector3           stringPos = frameUv.Position.ToVec3();
                            DrawableFontAtlas atlas     = _debugFont.GetAtlas(20);
                            c.RenderString(stringPos + new Vector3(1), Color.Black, i.ToString(), atlas);
                            c.RenderString(stringPos, Color.Red, i.ToString(), atlas);
                        }
                    }
                }
            }

            c.RenderTo(null);

            RenderAnimationPreview(c);

            return(true);
        }
예제 #8
0
        public void VerifyFontRendering()
        {
            var fonts = new[]
            {
                "Junction-Bold.otf",   // Cff
                "CaslonOS.otf",        // Cff 2 (covers other cases)
                "1980XX.ttf",          // Ttf
                "LatoWeb-Regular.ttf", // Composite
                "Junction-Bold.otf",   // 14 font size
                "Junction-Bold.otf"    // 11 font size
            };

            var names = new[]
            {
                "Junction-Bold",
                "CaslonOS-Regular",
                "1980XX",
                "Lato Regular",
                "Junction-Bold",
                "Junction-Bold"
            };

            var unitsPerEm = new[]
            {
                1000,
                1000,
                1024,
                2000,
                1000,
                1000
            };

            int[] descender =
            {
                -250,
                -360,
                -128,
                -426,
                -250,
                -250
            };

            var ascender = new[]
            {
                750,
                840,
                682,
                1974,
                750,
                750
            };

            var glyphs = new[]
            {
                270,
                279,
                141,
                2164,
                270,
                270
            };

            string[] cachedRender =
            {
                ResultDb.EmotionCffAtlas,
                "",
                ResultDb.EmotionTtAtlas,
                ResultDb.EmotionCompositeAtlas,
                "",
                ""
            };

            int[] fontSizes =
            {
                17,
                17,
                17,
                17,
                14,
                11
            };

            FrameBuffer b = null;

            for (var i = 0; i < fonts.Length; i++)
            {
                Engine.Log.Info($"Running font {fonts[i]} ({i})...", TestRunnerLogger.TestRunnerSrc);
                ReadOnlyMemory <byte> data = Engine.AssetLoader.Get <OtherAsset>($"Fonts/{fonts[i]}")?.Content ?? ReadOnlyMemory <byte> .Empty;
                var f = new Font(data);

                // Verify basic font data.
                Assert.True(f.Valid);
                Assert.True(f.FullName == names[i]);
                Assert.True(f.UnitsPerEm == unitsPerEm[i]);
                Assert.True(f.Descender == descender[i]);
                Assert.True(f.Ascender == ascender[i]);
                Assert.True(f.CharToGlyph.Count == glyphs[i]);

                // Get atlases.
                int fontSize     = fontSizes[i];
                var emotionAtlas = new StbDrawableFontAtlas(f, fontSize, false);
                Runner.ExecuteAsLoop(_ =>
                {
                    var str = "";
                    for (uint j = emotionAtlas.Font.FirstCharIndex; j < emotionAtlas.Font.LastCharIndex; j++)
                    {
                        str += (char)j;
                    }

                    emotionAtlas.CacheGlyphs(str);
                }).WaitOne();
                DrawableFontAtlas packedStbAtlas = RenderFontStbPacked(data.ToArray(), fontSize, emotionAtlas.Texture.Size * 3, (int)f.LastCharIndex + 1, f, out StbTrueType.stbtt_fontinfo stbFont);

                // Compare glyph parsing.
                CompareMetricsWithStb(f, emotionAtlas, stbFont);

                // Compare render metrics.
                foreach (KeyValuePair <char, DrawableGlyph> g in emotionAtlas.Glyphs)
                {
                    DrawableGlyph glyph = packedStbAtlas.Glyphs[g.Key];
                    Assert.Equal(glyph.XAdvance, g.Value.XAdvance);

                    var fontGlyph = g.Value.FontGlyph;
                    int width     = (int)(MathF.Ceiling(fontGlyph.Max.X * emotionAtlas.RenderScale) - MathF.Floor(fontGlyph.Min.X * emotionAtlas.RenderScale));
                    int height    = (int)(MathF.Ceiling(-fontGlyph.Min.Y * emotionAtlas.RenderScale) - MathF.Floor(-fontGlyph.Max.Y * emotionAtlas.RenderScale));

                    Assert.Equal(glyph.Width, width);
                    Assert.Equal(glyph.Height, height);
                }

                // Check if there's a verified render.
                if (string.IsNullOrEmpty(cachedRender[i]))
                {
                    continue;
                }

                // Compare with cached render.
                // ReSharper disable AccessToModifiedClosure

                Runner.ExecuteAsLoop(_ =>
                {
                    if (b == null)
                    {
                        b = new FrameBuffer(emotionAtlas.Texture.Size).WithColor();
                    }
                    else
                    {
                        b.Resize(emotionAtlas.Texture.Size, true);
                    }

                    RenderComposer composer = Engine.Renderer.StartFrame();
                    composer.RenderToAndClear(b);
                    composer.RenderSprite(Vector3.Zero, emotionAtlas.Texture.Size, Color.White, emotionAtlas.Texture);
                    composer.RenderTo(null);
                    Engine.Renderer.EndFrame();
                    Runner.VerifyScreenshot(cachedRender[i], b);
                }).WaitOne();
            }
        }