Reputation: 11
This is my first time using a sharpdx to draw a ellipse in screen and i have this code right here(Using c# .net framework windows forms), i dont know why, there a two several problems:
Also i want to optimize my code as much as i can!
Here is my code:
private WindowRenderTarget _renderTarget;
private Ellipse el;
private Stopwatch _stopwatch = new Stopwatch();
private int _frameCount;
private string _gpuDescription;
public Form1()
{
InitializeComponent();
InitializeDirect2D();
el = new Ellipse
{
RadiusX = 50,
RadiusY = 50,
Point = new RawVector2(ClientSize.Width / 2.0f, ClientSize.Height / 2.0f)
};
using (var factory = new SharpDX.DXGI.Factory1())
{
using (var adapter = factory.GetAdapter1(0))
{
_gpuDescription = adapter.Description.Description;
}
}
this.Text = _gpuDescription;
}
private void InitializeDirect2D()
{
var dpi = this.CreateGraphics().DpiX;
var properties = new HwndRenderTargetProperties
{
Hwnd = this.Handle,
PixelSize = new Size2(this.ClientSize.Width, this.ClientSize.Height),
PresentOptions = PresentOptions.None
};
var renderTargetProperties = new RenderTargetProperties
{
DpiX = dpi,
DpiY = dpi,
Type = RenderTargetType.Hardware,
Usage = RenderTargetUsage.GdiCompatible,
PixelFormat = new PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Premultiplied)
};
_renderTarget = new WindowRenderTarget(new SharpDX.Direct2D1.Factory(), renderTargetProperties, properties);
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
SolidColorBrush brush = new SolidColorBrush(_renderTarget, new RawColor4(1.0f, 0.0f, 0.0f, 1.0f));
_renderTarget.BeginDraw();
_renderTarget.Clear(new RawColor4(0, 0, 0, 1));
_renderTarget.FillEllipse(el, brush);
_renderTarget.EndDraw();
}
private void Form1_Resize(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
_frameCount++;
if (_stopwatch.ElapsedMilliseconds >= 1000)
{
this.Text = $"FPS: {_frameCount}, GPU: {_gpuDescription}";
_frameCount = 0;
_stopwatch.Restart();
}
}
I hope for someone to help me fix those problems, i really appreciate!
I have another code wchich basically moves the ellipse, but it dont work. Of course the coordinates are changing but the ellipse is not showing up
Code:
private WindowRenderTarget _renderTarget;
private Ellipse el;
private Stopwatch _stopwatch = new Stopwatch();
private int _frameCount;
private string _gpuDescription;
private float ellipseXPosition = 100; // Starting x-coordinate
private const float MovementSpeed = 2f;
public Form1()
{
InitializeComponent();
InitializeDirect2D();
el = new Ellipse
{
RadiusX = 50,
RadiusY = 50,
Point = new RawVector2(100, 100)
};
using (var factory = new SharpDX.DXGI.Factory1())
{
using (var adapter = factory.GetAdapter1(0))
{
_gpuDescription = adapter.Description.Description;
}
}
_stopwatch.Start();
// Force a repaint
this.Invalidate();
}
private void InitializeDirect2D()
{
var dpi = this.CreateGraphics().DpiX;
var properties = new HwndRenderTargetProperties
{
Hwnd = this.Handle,
PixelSize = new Size2(this.ClientSize.Width, this.ClientSize.Height),
PresentOptions = PresentOptions.None
};
var renderTargetProperties = new RenderTargetProperties
{
DpiX = dpi,
DpiY = dpi,
Type = RenderTargetType.Hardware,
Usage = RenderTargetUsage.GdiCompatible,
PixelFormat = new PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Premultiplied)
};
_renderTarget = new WindowRenderTarget(new SharpDX.Direct2D1.Factory(), renderTargetProperties, properties);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Console.WriteLine("Form1_Paint method called");
SolidColorBrush brush = new SolidColorBrush(_renderTarget, new RawColor4(1.0f, 0.0f, 0.0f, 1.0f));
_renderTarget.BeginDraw();
_renderTarget.Clear(new RawColor4(0, 0, 0, 1));
// Update the position of the ellipse
el.Point = new RawVector2(ellipseXPosition, 100); // Y-coordinate remains the same
// Rysowanie elipsy
_renderTarget.FillEllipse(el, brush);
_renderTarget.EndDraw();
// Move the ellipse to the right for the next frame
ellipseXPosition += MovementSpeed;
// Check if the ellipse reaches the right boundary and reset its position
if (ellipseXPosition > this.ClientSize.Width)
{
ellipseXPosition = -el.RadiusX; // Reset to the left side of the window
}
}
private void Form1_Resize(object sender, EventArgs e)
{
if (_renderTarget != null)
{
_renderTarget.Resize(new Size2(ClientSize.Width, ClientSize.Height));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
_frameCount++;
if (_stopwatch.ElapsedMilliseconds >= 1000)
{
this.Text = $"FPS: {_frameCount}, GPU: {_gpuDescription}";
_frameCount = 0;
_stopwatch.Restart();
}
}
And i have a question, if there is any document of how can i use the sharpDx 2d in c#?
Upvotes: 0
Views: 220
Reputation: 138776
Your stopwatch is not started, so you can add something like this in constructor:
public Form1()
{
InitializeComponent();
InitializeDirect2D();
_stopwatch.Start();
...
}
Also you must resize the render target if the window is resized, like this on form's resize event:
private void Form1_Resize(object sender, EventArgs e)
{
_renderTarget.Resize(new Size2(ClientSize.Width, ClientSize.Height));
}
As for measuring FPS, you must use a Timer with a tick interval lower or equal yo your monitor frequency (this is far from being perfect as it also depends on other factors but at least it should you something more useful) so add this in the constructor too:
timer1.Interval = 16; // ~16ms or lower if your monitor is 60hz
As for the second code, since your drawing happens in Paint
method, you must call Invalidate()
each time you change its state, and you should't change the state in the Paint
method, so
Start the timer somewhere:
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
Move the update state code in timer's tick handler (remove it from Paint
) and call Invalidate
in there (if you don't do this, resizing will cause unexpected moving effects):
private void timer1_Tick(object sender, EventArgs e)
{
_frameCount++;
if (_stopwatch.ElapsedMilliseconds >= 1000)
{
this.Text = $"FPS: {_frameCount}, GPU: {_gpuDescription}";
_frameCount = 0;
_stopwatch.Restart();
}
// update state
ellipseXPosition += MovementSpeed;
if (ellipseXPosition > this.ClientSize.Width)
{
ellipseXPosition = -el.RadiusX; // Reset to the left side of the window
}
// ask for repaint
Invalidate();
}
Add this line to constructor:
SetStyle(ControlStyles.Opaque, true);
To ask Winforms not to erase background since you're already doing this in your renderTarget.Clear
code.
Also last but not least, add a using
on SolidColorBrush
usage (or keep it aside render target so you don't create it each time) as it's a disposble resource:
using (var brush = new SolidColorBrush(_renderTarget, new RawColor4(1.0f, 0.0f, 0.0f, 1.0f)))
{
...
}
Upvotes: 1