Seite 1 von 1

richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 01.05.2024, 15:10
von RedGuy
Hallo zusammen !

War schon lange nicht mehr hier...

Nun zum Thema:
Ich arbeite gerade an einem Projekt, bei dem ich farbige Pixel auf den Bildschirm unter windows forms zeichnen möchte.
Und zwar möchte ich ganze Flächen ausfüllen.

Das berechnen der Pixel geht schnell. Das anschließende Zeichnen mit einem System.Drawing.Graphics Objekt läuft zu langsam ab
(im Bereich von 10 Sekunden).

Also habe ich mir gedacht, verwende ich Hardware - Beschleunigung. Dies müsste doch die Lösung sein, oder?
Versuche Direct3d zu verwenden. Das habe ich allerdings noch nie gemacht. Irgendwann ist immer das erste Mal...

Jetzt ist das Problem die richtigen DLLs zu beschaffen und in mein Projekt einzubinden.
Ich will C# unter dem aktuellen .NET 8 und Visual Studio 2022 verwenden.

Konkret: Wenn ich jetzt allerdings D3d12.dll, welche ich bei meinem Laptop unter Windows10 im system32 - Ordner gefunden habe, referenzieren möchte kommt die Fehlermeldung: The reference is invalid or unsupported.

Bei stackOverflow kommt der Post:
The Microsoft.DirectX, Direct3DX, DirectDraw, and DirectSound components are the legacy deprecated Managed DX 1.1 assemblies. They have not been updated since ~2006 and were written for .NET 1.1.
Aber das wäre ja fatal. Gibt es keine neue API DLL, welche ich unter .NET 8 einbinden kann ?!

Auf meinem richtigen Rechner habe ich übrigens Windows11 und das genannte Visual Studio 2022 mit .NET 8.
Habe übrigens das Windows SDK installiert. In der Installationsanleitung und dem Installationsordner war übrigens keine Spur von Direct3d.
Die genannte D3d12.dll habe ich wie schon erwähnt stattdessen im windows\system32 Ordner gefunden :-(...

Freue mich schon auf Eure Antworten...

Liebe Grüsse!

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 01.05.2024, 15:28
von gombolo
"C++ ist die einzige unterstützte Sprache für die Direct3D 12-Entwicklung, C# und andere .NET-Sprachen werden nicht unterstützt."

https://learn.microsoft.com/de-de/windo ... ent-set-up

vielleicht damit:

https://github.com/sharpdx/SharpDX

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 01.05.2024, 17:21
von RedGuy
Hi !

Ok, danke!

Dann werd ich mich mal, denke ich, in diese
SharpDX managed DirectX API
einarbeiten ;-)...

Ich möchte unbedingt bei C# bleiben.

Vielen Dank!

Gut wieder zurück im Forum zu sein!

Grüsse
RedGuy

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 01.05.2024, 20:36
von TomasRiker
Es kommt mir merkwürdig vor, dass deine ursprüngliche Implementierung 10 Sekunden braucht, um eine Fläche zu füllen. Magst du vielleicht mal den relevanten Code zeigen? Direct3D ist möglicherweise Overkill.

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 04.05.2024, 08:09
von RedGuy
Hi !

@TomasRiker:
Aber gern doch !

Hier der wesentliche Code:

Code: Alles auswählen

namespace GraphicsTest
{
	public struct ColorD
	{
		public	bool	transparent	= true;
		public	Color	color;

		public	ColorD(Color COLOR, bool Transparent)
		{
			color		= COLOR;
			transparent	= Transparent;
		}
	}

	public partial class FormMain : Form
	{
		private Graphics m_pWorld;

		private void m_pButtonCreateVG_Click(object sender, EventArgs e)
		{
			m_pWorld					= m_pPanelWorld.CreateGraphics();

.
.
.

			ColorD[,] aaPointMatrix = pStoredGraphic.RasterizedPixels;	// array index = Koordinate

			int xWorld;
			int yWorld;

			int			pictureSizeX= aaPointMatrix.GetLength(0);
			int			pictureSizeY= aaPointMatrix.GetLength(1);

			int			worldSizeX	= m_pPanelWorld.Width;
			int			worldSizeY	= m_pPanelWorld.Height;

			for (int x = 0; x < pictureSizeX ; x++)
			{
				xWorld				= x + pStoredGraphic.xLeft;	// pStoredGraphic.xLeft: linke Kante

				for (int y = 0; y < pictureSizeY ; y++)
				{
					yWorld			= worldSizeY - (y + pStoredGraphic.yLower);	// pStoredGraphic.yLower: y - Kante

					ColorD			sColor		= aaPointMatrix[x, y];

					if (!sColor.transparent)
					{
						if ((xWorld >= 0) && (yWorld >= 0) && (xWorld <= m_pPanelWorld.Width) && (yWorld <= m_pPanelWorld.Height))
						{
							m_pWorld.DrawRectangle(new Pen(sColor.color), xWorld, yWorld, 1, 1);
						}
					}
				}
			}
		}
	}
}
Hatte etwas übertrieben. Der Bildaufbau dauert keine 10 Sekunden, aber EINE Sekunde: Viel zu langsam.
Hab auch mal ohne debuggen ausgeführt: Kein Unterschied.

Liegts vielleicht an dem Pen Objekten, welche ich für jeden Pixel neu instanziiere ?
Man konnte unter .NET 7 zumindest nicht einen einzigen Pen verwenden, da kam ne Fehlermeldung.

Hoffe, ihr findet das heraus ;-)...

Grüsse

RedGuy

PS: Verzeiht mir den Umbruch-Stil, aber so programmiere ich...
Verzeiht mir auch eventuelle fehlende Kapselungen für Felder, aber die lasse ich manchmal weg...

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 04.05.2024, 08:31
von TomasRiker
RedGuy hat geschrieben: 04.05.2024, 08:09 Liegts vielleicht an dem Pen Objekten, welche ich für jeden Pixel neu instanziiere ?
Man konnte unter .NET 7 zumindest nicht einen einzigen Pen verwenden, da kam ne Fehlermeldung.
Auf jeden Fall ist das ein Grund dafür, dass es langsam ist. Dein Ansatz ist prinzipiell langsam, da du jedes Pixel als Rechteck zeichnest.
Wenn du mit Bitmaps arbeitest, kannst du Pixel setzen ohne Funktionsaufruf, indem du direkt in den Speicher des Bitmaps schreibst.
Siehe: https://learn.microsoft.com/en-us/dotne ... ew=net-8.0
Das dürfte dann so schnell sein, dass du es gar nicht mehr bemerkst.
Direct3D ist hier jedenfalls Overkill.

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 04.05.2024, 10:31
von RedGuy
Hi !

Ok ! Guter Ansatz mit Bitmaps zu arbeiten...

Am Pen liegts übrigens nicht, das habe ich grad ausprobiert.
Ich verwende jetzt einen einzigen Pen und setze das color property für jeden Pixel.

Mit Rechtecken habe ich gearbeitet, da es seltsamerweise kein DrawPixel gibt :-( - zumindest hab ich das nicht gefunden...

Werd mal Bitmaps ausprobieren!

Danke nochmals !

Grüße
RedGuy

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 04.05.2024, 10:41
von TomasRiker
SetPixel gibt es (soweit ich weiß) nicht, weil dieses Graphics-Teil so allgemein gehalten ist, dass es auch für nicht-pixelbasierte Medien funktioniert.

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 04.05.2024, 13:49
von gombolo
Wenn RedGuy die Bitmap-Klasse in C# verwendet, gibt es eine Methode namens SetPixel.
https://learn.microsoft.com/de-de/dotne ... at-ext-8.0

Der Vorschlag von TomasRiker (das direkte Schreiben in den Speicher) was meiner Meinung nach die schnellste Methode ist.

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 04.05.2024, 14:51
von RedGuy
Hi !

Genau, danke- jetzt läuft alles abrupt ;-)!

Abschließend wollte ich nochmal den code zeigen, wie ich das jetzt umgesetzt habe (lässt sich wahrscheinlich noch optimieren)...:

Code: Alles auswählen

namespace GraphicsTest
{
	public struct ColorD
	{
		public	bool	transparent	= true;
		public	Color	color;

		public	ColorD(Color COLOR, bool Transparent)
		{
			color		= COLOR;
			transparent	= Transparent;
		}
	}

	public partial class FormMain : Form
	{
		// code im Designer-Bereich:
		private PictureBox m_pPictureBox;
	
		private Bitmap m_pWorld;

		private void m_pButtonCreateVG_Click(object sender, EventArgs e)
		{
			m_pWorld		= new Bitmap(m_pPictureBox.Width, m_pPictureBox.Height);

.
.
.

			ColorD[,] aaPointMatrix = pStoredGraphic.RasterizedPixels;	// array index = Koordinate

			int xWorld;
			int yWorld;

			int			pictureSizeX= aaPointMatrix.GetLength(0);
			int			pictureSizeY= aaPointMatrix.GetLength(1);

			int			worldSizeX	= m_pPictureBox.Width;
			int			worldSizeY	= m_pPictureBox.Height;

			for (int x = 0; x < pictureSizeX ; x++)
			{
				xWorld				= x + pStoredGraphic.xLeft;

				for (int y = 0; y < pictureSizeY ; y++)
				{
					yWorld			= worldSizeY - (y + pStoredGraphic.yLower);

					ColorD			sColor		= aaPointMatrix[x, y];

					if (!sColor.transparent)
					{
						if ((xWorld >= 0) && (yWorld >= 0) && (xWorld <= m_pPictureBox.Width) && (yWorld <= m_pPictureBox.Height))
						{
							m_pWorld.SetPixel(xWorld, yWorld, sColor.color);
						}
					}
				}
			}

			m_pPictureBox.Image	= m_pWorld;
		}
	}
}
Ich benutze eine PictureBox auf der Form, schreibe eine Bitmap pixelweise und setze anschließend die Image-Eigenschaft der PictureBox.

Grüße
RedGuy

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 04.05.2024, 15:17
von gombolo
:) toll das es jetzt schneller läuft. Bei größeren Bilder könnte es trotzdem etwas länger dauern.

Was Tomas Riker meinte war direkt auf den Speicher zuzugreifen:

Also sollte es mal nicht ausreichen, dann so probieren: ;)

Code: Alles auswählen

// Direkter Zugriff auf Bitmap-Daten 
BitmapData bmpData = m_pWorld.LockBits(new Rectangle(0, 0, m_pWorld.Width, m_pWorld.Height), ImageLockMode.WriteOnly, m_pWorld.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * m_pWorld.Height;
byte[] rgbValues = new byte[bytes];

//Iteration über das Bitmap und Aktualisierung der Daten

Re: richtige DLL für Direct3d in VS2022 .NET8

Verfasst: 05.05.2024, 09:23
von RedGuy
Hi !

@gombolo
Ok interessant!

Mit IntPtr oder auch BitmapData hab ich noch nie was gemacht...

Danke für die Antwort!

@all
Danke für die Anworten. Hat mich sehr weitergebracht. Jetzt funktionierts ja =) !

Gruss
RedGuy