Hallo zusammen!
Mein Problem fängt sehr ähnlich zu anderen, hier bereits
besprochenen Surface-mit-Alphakanal-darstellen Problemen an. Und zwar habe ich
ein (einmalig in der Initialisierungsphase) selbst beschriebenes Surface
welches einfach einen fließenden Überagng von Rot nach Grün zeigt (ich habe alles einmal auf das Wichtigste beschränkt):
|
Quellcode
|
1
2
3
4
5
6
7
|
CreateOffscreenPlainSurface(128, 16, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, & lpSurface, NULL);
float delta = 255.0f / 127;
for (int i = 0; i < 128; i++)
for (int j = 0; j < 16; j++)
Pixels[j * nPitch + i] = D3DCOLOR_ARGB(0xC0 ,0xFF - FS_Round(i * delta), FS_Round(i * delta), 0x00);
|
Das es nun mit den vorhandenen Funktionen, welche ein
Surface auf den Backbuffer legen, nicht möglich ist, den Alphakanal zu
berücksichtigen, habe ich mir einfach selber eine geschrieben. Dies passiert
ähnlich zu anderen (gut funktionierenden) Funktionen von mir, welche direkt auf
den Backbuffer einen Punkt eine Linie oder einen Kreis zeichnen.
Innerhalb von BeginScene und EndScene und wiederum innerhalb
der (eigenen) Funktionen BeginDrawOnBackbuffer (Lock Backbuffer) und EndDrawOnBackbuffer
(Unlock Backbuffer) finden diese Methoden jeweils ihren Aufruf.
Meine ebenfalls zwischen BeginDrawOnBackbuffer() und BeginDrawOnBackbuffer()
aufgerufene Funktion zum „Auflegen“ des Surface sieht nun folgendermaßen aus:
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
void CDirect3D::CopyRectOnBackBufferAlpha(const LPDIRECT3DSURFACE9 a_lpSourceSurface, const RECT * a_lpSourceRect,
const UINT & a_uiPosX, const UINT & a_uiPosY)
{
// Source Surface
D3DLOCKED_RECT LockedRect;
a_lpSourceSurface->LockRect(&LockedRect, 0, D3DLOCK_READONLY);
const int nPitch = LockedRect.Pitch / 4;
const D3DCOLOR * lpPixels = reinterpret_cast <D3DCOLOR*> (LockedRect.pBits);
int i = 0;
int j = 0;
// Neuen Farbwert auf BackBuffer schreiben
for (int x = a_lpSourceRect->left; x < a_lpSourceRect->right; x++)
{
for (int y = a_lpSourceRect->top; y < a_lpSourceRect->bottom; y++)
{
const int index = (a_uiPosY + j) * m_iPitch + (a_uiPosX + i);
m_lpPixelsBackBuffer[index] = CalcNewColorAlpha(lpPixels[y * nPitch + x], m_lpPixelsBackBuffer[index]);
j++;
}
i++;
j = 0;
}
a_lpSourceSurface->UnlockRect();
}
|
Die Farbwert-Berechnung:
|
Quellcode
|
1
2
3
4
5
6
7
8
9
|
inline const D3DCOLOR CDirect3D::CalcNewColorAlpha(const D3DCOLOR & a_colA, const D3DCOLOR & a_colB)
{
const DWORD A_a = a_colA >> 24 & 0xFF;
// Farbe A mit Alphakanal wird auf B gelegt
return D3DCOLOR(D3DCOLOR_XRGB(static_cast <DWORD> ((A_a / 255.0f) * (a_colA >> 16 & 0xFF) + (1 - (A_a / 255.0f)) * (a_colB >> 16 & 0xFF)),
static_cast <DWORD> ((A_a / 255.0f) * (a_colA >> 8 & 0xFF) + (1 - (A_a / 255.0f)) * (a_colB >> 8 & 0xFF)),
static_cast <DWORD> ((A_a / 255.0f) * (a_colA & 0xFF) + (1 - (A_a / 255.0f)) * (a_colB & 0xFF))));
}
|
Nun habe ich allerdings das Problem, das ein Aufruf dieser Methode zu einem extremen Performance-Einbruch (unter 30fps, von ursprünglich
konstanten 59fps bei D3DPRESENT_INTERVAL_DEFAULT) führt, was ich mir nicht weiter erklären kann, da meine anderen Zeichenfunktionen meinen Rechner Performance-technisch absolut kalt lassen (mögen es noch so viele Kreise, Linien und Punkte sein, welche da direkt auf den Backbuffer geschrieben werden). Das eigentlich verwunderliche ist jedoch die Tatsache, dass folgende (natürlich nicht zum Ziel führende) Quellcode-Änderungen keine Performance-Einbußen mit sich führen:
Anstatt
|
Quellcode
|
1
|
m_lpPixelsBackBuffer[index] = CalcNewColorAlpha(lpPixels[y * nPitch + x], m_lpPixelsBackBuffer[index]);
|
Möglichkeit 1:
|
Quellcode
|
1
|
m_lpPixelsBackBuffer[index] = 0;
|
Möglichkeit 2:
|
Quellcode
|
1
2
|
D3DCOLOR color = D3DCOLOR_XRGB(0x80, 0x80, 0x80);
m_lpPixelsBackBuffer[index] = color;
|
Möglichkeit 3:
|
Quellcode
|
1
|
D3DCOLOR color = CalcNewColorAlpha(lpPixels[y * nPitch + x], m_lpPixelsBackBuffer[index]);
|
Diese 3 Möglichkeiten machen sich in der Performance nicht bemerkbar, lediglich das Schreiben der berechneten Farbe direkt oder indirekt (mit dem Umweg über einer temporären D3DCOLOR Variable) auf den Backbuffer geht so gar nicht.
Es scheint also nichts mit meiner Funktion zur Berechnung des neuen Farbwerts unter Berücksichtigung des Alphakanals zu tun haben, geht es doch, wenn der von dieser Funktion zurückgegebene Farbwert in einer lokalen D3DCOLOR Variable gespeichert wird. Kann es sein, dass der Backbuffer hier auf nicht konstante Farben über die gesamte Schleife hinweg allergisch reagiert? Warum funktioniert die Berechnung und Zuweisung für eine lokale D3DCOLOR Variable Performance-technisch so einwandfrei?
Letztlich geht es also lediglich darum, den Backbuffer direkt mit einem Farbwert zu beschreiben, welcher aber scheinbar in Abhängigkeit dessen mal in die Knie geht und mal nicht.
Das Surfaces vielleicht nicht unbedingt die besten Lösungen mehr sind für derartige Probleme ist mir zwar klar, dennoch wäre ich in diesem Fall sehr am Hintergrund dieses Problems interessiert.
Gibt es evtl. doch noch eine (unter Umständen von DirectX selbst bereitgestellte) bessere Lösung/Funktion (mit Surfaces)?
Vielen Dank für die Hilfe!
PS: Vielleicht sind meine folgenden Einstellungen noch hilfreich:
ADAPTER = D3DADAPTER_DEFAULT;
WINDOWED = TRUE;
DEVICE_TYPE = D3DDEVTYPE_HAL;
WIDTH = 800;
HEIGHT = 600;
BACKBUFFER_FORMAT = D3DFMT_X8R8G8B8;
DEPTHSTENCILBUFFER_FORMAT = D3DFMT_D16;
VERTEXPROCESSING = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
MULTISAMPLETYPE = D3DMULTISAMPLE_NONE;
PRESENTINTERVAL = D3DPRESENT_INTERVAL_DEFAULT;