 |
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Erni Junior JLI'ler
Anmeldedatum: 29.10.2003 Beiträge: 54
Medaillen: Keine
|
Verfasst am: 29.10.2003, 01:58 Titel: surface locken, gehen zuviele Resourcen verloren? |
|
|
Hi, ich probiere mich gerade im 2. Buch von CR am surface locken. Da wollte ich meine Klasse eine methode schreiben, die genaue RGB werte auslesen kann, um Staaten auf einer strategischen Karte zu erkennen. Schreibe bis jetzt alles noch in die WM_PAINT message und lasse WM_PAINT per SetTimer 1000/30 mal pro Sekunde aufrufen.
An einer Stelle las ich, dass das locken von surfaces sehr viel Resourcen in Anspruch nimmt, bei meiner Funktion wird alle 30ms ein lock und unlock durchgeführt, ist das zuviel und gibts dort elegantere wege? Ich habe mal folgende Funktion geschrieben, zuerst die Deklaration der Maps in einer header für globals
Code: |
//globals.h
map<char*,D3DCOLOR> mCountriesRGB;
map<char*,D3DCOLOR>::iterator mCountriesRGB_iterator;
//in WinApi werden 3 mCountriesRGB zum Test initialisiert
//hab eine karte gezeichnet wo jeder staat/Fluss eine bestimmte RGB FARBE hat
mCountriesRGB["Deutschland"] = D3DCOLOR_XRGB(0,0,0);
mCountriesRGB["Frankreich"] = D3DCOLOR_XRGB(21,32,182);
mCountriesRGB["Rhein"] = D3DCOLOR_XRGB(139,144,202);
/*das ist die Klassenmethode, um einen Pixel genau zu erkennen und in einen char* puffer den NAmen des Staates zu schreiben*/
bool cD3D::SurfacePixelScan(map<char*,D3DCOLOR> mCountryRGB,map<char*,D3DCOLOR>::iterator iter, int x, int y, char *buffer)
{
D3DLOCKED_RECT rect;
int nPitch;
m_lpdsurface->LockRect(&rect, 0,0);
nPitch = rect.Pitch / 4;
D3DCOLOR *Pixels = (D3DCOLOR*)rect.pBits;
for(iter = mCountryRGB.begin();iter!=mCountryRGB.end();iter++)
{
if(Pixels[y * nPitch + x]==iter->second)
{
sprintf(buffer, "%s", iter->first);
m_lpdsurface->UnlockRect();
return true;
}
}
m_lpdsurface->UnlockRect();
return false;
}
/*in WM_MOUSEMOVE speicher ich die statischen variablen mouse_x und mouse_y mit lo und hiword lparam, die werte übergebe ich der funktion(intx, int y) */
// in WM_PAINT siehts dann so aus
Direct3D.BeginScene();
Direct3D.DrawSurface(0,0,SCREEN_WIDTH, SCREEN_HEIGHT);
sprintf(buffer, "mouse_x: %d mouse_y: %d", mouse_x, mouse_y);
Direct3D.DrawText(buffer, 815,748,TextColor2);
if(Direct3D.SurfacePixelScan(mCountriesRGB, mCountriesRGB_iterator,
mouse_x, mouse_y, buffer))
{
Direct3D.DrawText(buffer, 815,730,TextColor2);
}
Direct3D.EndScene();
|
Tja, bei jedem Aufruf wird halt lock und unlock gemacht, weiss nich ob das bei grösseren Projekten zu problemen führt? Wüsste jemand was besseres?(ich vermute mal Pixelgenau kollisiionserkennung wird mich weiterbringen, aber da bin ich nich nicht )
noch eine zweite frage, warum kann ich eine map nicht global initialisieren?? Krieg jedenfalls ne menge error meldungen wenn ichs global versuch, erst ab WINAPI gehts, warum?
Danke
Erni[/code] |
|
Nach oben |
|
 |
Fallen JLI MVP


Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 29.10.2003, 09:04 Titel: |
|
|
Das locken dürfte eigentlich nicht alzuviel kosten ich selber Locke und Unlocke (zwar keine Surfaces) mehrere male pro Frame. Das kannst du aber auch verhindern indem du dir jedesmal wenn sich dein Bild verändert eine Kopie des Bildes irgendwo in den Speicher ablegst und dann auf das Speicherabbild zugreifst. Das geht natürlich nur wenn du lesen möchtest welche Farbe der bestimmte Bildpunkt hat. _________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
 |
Christian Rousselle Site Admin

Alter: 48 Anmeldedatum: 19.07.2002 Beiträge: 1630
Medaillen: Keine
|
Verfasst am: 29.10.2003, 09:44 Titel: |
|
|
Man kann schlecht erkennen, ob du das Surface im Grafikkarten-Speicher ist. Wenn dies so ist, solltest du besser eine zweite Kopie im Hauptspeicher anlegen und diese Locken und dort testen, das geht viel schneller.
Außerdem übergibst du die map per Value, wenn ich es richtig sehen, dadurch wird die map jedes mal kopiert, besser wäre es einen Zeiger auf die map zu übergeben. Den Iterator musst du auch nicht übergeben, sondern kann ihn in der Fkt deklarieren.
C. |
|
Nach oben |
|
 |
Erni Junior JLI'ler
Anmeldedatum: 29.10.2003 Beiträge: 54
Medaillen: Keine
|
Verfasst am: 29.10.2003, 13:36 Titel: |
|
|
hi, erstmal danke für die schnellen Antworten .
Hab da eine Frage, wie genau kopiere ich ein Surface und warum ist das dann schneller? Auf dem quell-surface(lpdsurface), wo ich jedes Pixel auslesen will hab ich mit D3DPOOL_DEFAULT angelegt, und mein Ansatz ,um eine Kopie im sysmem anzulegen ist bis jetzzt der:
Code: |
bool cD3D::SurfacePixelScan(map<char*,D3DCOLOR> *mCountryRGB,
int x, int y, char *buffer)
{
//wenn die Kopie noch nicht angelegt wurde
if(!m_lpdsysmemsurface)
{
D3DSURFACE_DESC desc;
//hole eigenschaften vom quellsurface
if(FAILED(m_lpdsurface->GetDesc(&desc)))
0;
//lege Kopier im SYSTEMMEM an
if(FAILED(m_lpd3ddevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &m_lpdsysmemsurface,0)))
return 0;
//Kopiere lpdsurface nach lpdsysmemsurface
if(FAILED(m_lpd3ddevice->UpdateSurface(m_lpdsurface, 0, m_lpdsysmemsurface, 0)))
return 0;
}
map<char*,D3DCOLOR>::iterator iter;
D3DLOCKED_RECT rect;
int nPitch;
m_lpdsysmemsurface->LockRect(&rect, 0,0);
nPitch = rect.Pitch / 4;
D3DCOLOR *Pixels = (D3DCOLOR*)rect.pBits;
for(iter = mCountryRGB->begin();iter!=mCountryRGB->end();iter++)
{
if(Pixels[y * nPitch + x]==iter->second)
{
sprintf(buffer, "%s", iter->first);
m_lpdsysmemsurface->UnlockRect();
return true;
}
}
m_lpdsysmemsurface->UnlockRect();
return false;
}
|
NUn habe ich gelesen, dass es bei UpdateSurface Restriktionen gibt, u.a. dass das Quellsurface als D3DPOOL_SYSTEMMEM und das Zielsurface als D3DPOOL_DEFAULT erstellt werden muss, also dass mit dieser Funktion nur das Kopieren von Arbeisspeicher-Surfaces in Default-Surfaces möglich ist.
In meinem Fall ists ja genau umgekehrt .
Was muss ich machen? Etwa am Ende der Funktion nochmal UpdateSurface um zurückzukopieren?? Übrigens so funktioniert die FKT nicht, kriege keinen Namen eines staates mehr angezeigt.
Gruss
Erni[/code] |
|
Nach oben |
|
 |
Christian Rousselle Site Admin

Alter: 48 Anmeldedatum: 19.07.2002 Beiträge: 1630
Medaillen: Keine
|
Verfasst am: 29.10.2003, 14:31 Titel: |
|
|
Ändert sich die Landkarte häufig? Oder eher gar nicht? Wenn es sich nicht ändert, dann erstellst du ein Surface im Systemspeicher und einen im Videospeicher und testest mit dem im Hauptspeicher. Wenn sie die Karte selten (also nicht 50 mal pro Sekunde) ändert, dann kannst du die Landkarte noch kompeltter Ändernung von Systemspeicher in den Vidoespeicher mit UpdateSurface kopieren.
C. |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|