amerkoleci / Vortice.Windows

.NET bindings for Direct3D12, Direct3D11, WIC, Direct2D1, XInput, XAudio, X3DAudio, DXC, Direct3D9 and DirectInput.
MIT License
1.01k stars 73 forks source link

Linear Gradient Brush in Direct2D breaks after version 2.1.41 #388

Closed Dovencio closed 1 year ago

Dovencio commented 1 year ago

I'm using:

C# .NET 6 Core DirectX 12.1 NVIDIA GeForce GTX 4070 Ti

Description:

Attempting to draw with a linear gradient brush after version 2.1.41 causes unexpected results. I'm using the following method below with all set to true to create the factories.

private void RegenerateDX(bool all = false)
{
    if (all)
    { 
        writeFactory?.Release();
        direct2DFactory?.Release();
        hwndRenderTarget?.Release();
    }
    textFormat?.Release();
    defaultBrush?.Release();

    if (all)
    {
        writeFactory = DWrite.DWriteCreateFactory<IDWriteFactory>(Vortice.DirectWrite.FactoryType.Isolated);
        direct2DFactory = D2D1.D2D1CreateFactory<ID2D1Factory>(Vortice.Direct2D1.FactoryType.MultiThreaded);
    }
    textFormat = writeFactory.CreateTextFormat(Font.Name, Font.Size); 
    IDWriteTextLayout layout = writeFactory.CreateTextLayout("█", textFormat, Width, Height);
    tileSize = new(layout.ClusterMetrics[0].Width, layout.LineMetrics[0].Height);
    layout.Release();

    textFormat.TextAlignment = TextAlignment.Leading;
    textFormat.ParagraphAlignment = ParagraphAlignment.Near;
    textFormat.SetLineSpacing(LineSpacingMethod.Default, 0, 0);
    RenderTargetProperties renderTargetProperties = new RenderTargetProperties()
    {
        DpiX = DeviceDpi,
        DpiY = DeviceDpi,
        Type = RenderTargetType.Hardware,
        Usage = RenderTargetUsage.None,
    };
    HwndRenderTargetProperties hwndRenderTargetProperties = new()
    {
        Hwnd = Handle,
        PixelSize = new SizeI(Right - Left, Bottom - Top),
        PresentOptions = PresentOptions.None
    };

    if (all)
    {
        hwndRenderTarget = direct2DFactory.CreateHwndRenderTarget(renderTargetProperties, hwndRenderTargetProperties); 
    }
    defaultBrush = hwndRenderTarget.CreateSolidColorBrush(System.Drawing.Color.HotPink.ToColor4());
    Invalidate();
}

Then I use this method to draw the gradient:

ID2D1GradientStopCollection stopCollection = hwndRenderTarget.CreateGradientStopCollection(gradientStops, ExtendMode.Wrap);
ID2D1LinearGradientBrush GradBrush = hwndRenderTarget.CreateLinearGradientBrush(new(new(0, 0), new(100, 100)), stopCollection);
hwndRenderTarget.BeginDraw();
hwndRenderTarget.Clear(base.BackColor.ToColor());
hwndRenderTarget.FillRectangle(new Rect(0, 0, 500, 500), GradBrush);
hwndRenderTarget.EndDraw();

Expected Result:

In version 2.1.41: image

Actual Result:

In version 2.2.0+: image

amerkoleci commented 1 year ago

Can you provide an example repo so I can try and run a demo?

manju-summoner commented 1 year ago

There seems to be some confusion between new Color(float r, float g, float b, float a); and new Color(byte r, byte g, byte b, byte a);. The first constructor takes values 0.0 - 1.0 and the second takes values 0 - 255.

Dovencio commented 1 year ago

Here is one that I made quickly using VS 2022 that should reflect the error. If the error pattern is hard to see you can change userControl1.BackColor = System.Drawing.Color.Black https://github.com/Dovencio/GradTest

amerkoleci commented 1 year ago

Here is one that I made quickly using VS 2022 that should reflect the error. If the error pattern is hard to see you can change userControl1.BackColor = System.Drawing.Color.Black https://github.com/Dovencio/GradTest

Versione3.0.1-beta fixes this, please check and report any issues.

Dovencio commented 1 year ago

Verified fixed on V. 3.0.1-beta image