Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Anonymous

unregistriert

1

13.07.2004, 10:35

Problem mit Geschwindigkeit/Framerate

Hallo,

ich hoffe Ihr könnt mir helfen, ich habe z.Z. ein merkwürdiges Problem mit meiner Engine was die Geschwindigkeit angeht. Zunächst einmal, so bestimmte ich die FPS:

1. Vor Start der Nachrichtenschleife und damit des Renderns "merke" ich mit die aktuelle Zeit mit timeGetTime().
2. Während der Nachrichtenschleife zähle ich nen Counter hoch, der also die Frames zählt
3. Nach der Nachrichtenschleife und damit nach dem Rendern speicher ich erneut die Zeit und ziehe die Startzeit davon ab, so habe ich die Dauer Nachrichtenschleife in Millisekunden.
4. Am Ende rechne ich einfach FPS = Anzahl der Frames / (Gemessene Zeit / 1000)
(Ich hoffe das ist soweit korrekt, sonst kann ich das folgende Problem vergessen ;)

Nun zum Problem:
Ich habe auf einem Athon XP 2 Ghz mit Radeon 9700Pro ca. 50 Frames. Und das einzige was mein Programm bei der Messung rendert ist nen einfacher Würfel mit einer Lichtquelle, die darum kreist. Zunächst dachte ich, ich hätte den ganzen Code soo schlecht geschrieben, dass die Engine eben so langsam läuft, aber bei den wenigen zu rendernden Objekten kam es mir schon komisch vor.
Dann habe ich den Würfel UND die Lichtquelle mal rausgenommen - ja ich habe quasi bis auf "BeginScene()", "EndScene()" und "Present(...)" alles aus der Renderfunktion entfernt - und siehe da, ich habe immer noch ca. 50 FRames (es schwankt ein wenig, +/- 3 Frames). Dann habe ich auch mal "BeginScene()", "EndScene()" und "Present(...)" entfernt und die Messung ergab dann irgendwas bei 3000 Frames.

Ich habe ausserdem bemerkt, dass das Drehen des Würfels (als er noch in der Renderfunktion animiert wurde) sehr un-flüssig aussah, also leichtes Stocken und Zittern, während er sich bewegt. Bei einem solchen einfachen Objekt dürfte das doch nicht wahr sein, und meine Engine hat auch keinen komplizierten Code, der das nun verursachen könnte.

Das ganze kommt mir sehr merkwürdig vor. Hat vielleicht irgendjemand eine Idee, warum das alles so langsam abläuft (denn 50 Frames auf dem angegebenen Rechner mit nur einem Würfel + Lichtquelle finde ich seehr langsam) und warum die Framerate auch bei auskommentierung des Rendercodes so gleichbleibend ist? Und warum komsumiert Present(..) so unglaublich viele Frames?


Vielen Dank für Eure Hilfe!

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

2

13.07.2004, 10:53

Ich schätze mal, Du synchronisierts mit dem Bildschirmneuaufbau des Monitors (VSync). Dies sollte man während des Spielens an haben und während Benchmarking aus.
"Games are algorithmic entertainment."

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

3

13.07.2004, 11:27

Das erklärt aber nciht das ruckeln, denn das Menschliche auge kann nur 16bilder/sec wahrnehemn, alles darüber müsste flüssig aussehen.....

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

4

13.07.2004, 12:12

Es ist sehr naheliegend, Ruckeln an der durchschnittlichen Framerate festzumachen, aber es ist völlig kontraproduktiv. Du kannst eine Framerate von konstant 25 fps haben und es sieht gut aus. Du kannst andererseits 70 fps haben und sagen wir pro Sekunde einenFframe der 1/26 Sekunde dauert. Im zweiten Fall sind also alle Frames schneller und die fps Rate immer höher. Es wird aber schlechter aussehen.

Es ist in einem 3D Spiel, d.h etwas mit interaktiven bewegten Objekten auf dem Bildschirm sehr wichtig dass die fps rate möglichst konstant ist.

Schauen wir uns mal die kommerzielle Flusi Industrie an, die haben nicht die Einschränkung daß sie auf Wald- und Wiesen-PCs laufen müssen. Simulatoren werden von der FAA (Amerikanische Luftfahrtbehörde) zertifiziert. Die sagen ganz einfach, Du musst in der rate des Monitors rendern und darfst keinen Frame auslassen! Dann ist sogar der Speicher Garbadge Collection Algorithmuss der GeForce ein Problem. Da bei manchen Sims die fps Rate nicht allzu wichtig ist, wird die Monitorfrequenz absichtlich runtergedrückt, damit es leichter ist, keinen Frame zu verlieren. Damit ergibt sich die Gefhar, dass der Monitor flimmert. Daher werden diese Sims mit Spezialmonotoren ausgeliefert, die extra lang nachleuchten. Ein anderer Trick der benuzt wird wenn die leute nicht nur SW sondern auch HW liefern, ist während der Simulation die XxY Auflösung runterzudrehen, wenn ein frame sonst zu langsam würde.

Aussagen nach dem Motto "der Mensch kann bis zu 1/25 Sekunde sehen" sind sehr kritisch, der Wert kann je nach Messung zwischen ca 1/10 Sekunde und 1/220 Sekunde liegen:

- Das Amerikanische Militär hat Ihren Piloten kurz ein Bild auf eine Wand projeziert. Bis runter zu ca 1/220 Sekunde war es sichtbar.

- Es kommt auf den Menschen drauf an, auf die Monitoreinstellkungen, auf das Umgebungslicht, darauf mit welchem Teil des Auges man es sieht (im Augenwinkel sieht man unscharf, aber ist auf schnelle Änderungen sehr sensitiv).

- Im Film sieht 25 fps gut aus, da es ein "temporäres antialiasing" gibt, was es in Spielen praktisch nicht gibt.

- Es kommt darauf an, was gezeigt wird und auf die Bewegungen. In einem Flusi z.B. ist die beste Möglichkeit, Ruckler (nicht konstante fps) festzustellen, indem man möglichst schnell rollt und dabei den Horizon ansieht.

- Selbst in einem Film kann es unter bestimmten Umstänmden, z.B. Speichenrad einer Kutsche bei gerade der richtigen Umdrehungsgeschwindihgkeit und Speichenzahl geben, bei dem alias Effekte aufgrund der fps auftreten. Es sieht dann so aus, als ob sich das Rad rückwärts dreht.

- Etliche Spiele koppeln andere raten mit der fpsrate, z.B. Pollen der Eingabegeräte oder die Physikberechnung.

Ich könnte noch etliches schreiben, aber ich hoffe es ist schon jetzt klar dass ein X fps ist ok, X-1 zu langsam ist zu einfach
"Games are algorithmic entertainment."

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

5

13.07.2004, 12:43

Ähmm sry aber nen würfel kann man nicht mit komplexen modellen oder gar ganzen Scenen vergleichen, aber gut. De facto ruckelt es. Die framrate ist bei 50 was wohl an dem sync liegt. Aber da es 50 FPS sind und es NUR ein würfel ist, DER nicht von einem Kampfjetpilot, der schon tausende von Flugstunden hinter sich hat, betrachtet wird, muss der Fehler noch wo anderes liegen. Eine Lösung könnte sein mehrere backbuffer zu erstellen, aber das ist nur das rumdoktorieren an den symtomen.....
und bitte lass diese, in meinen Augen, mücke-elefanten vergleiche! :meinung:

P.S. das was ich schreibe lass ich doch nicht vorher auf allgeimgültikeit prüfen, sondern bezieht sich nur auf das thema!!!

Anonymous

unregistriert

6

13.07.2004, 14:29

Ok ähm, danke für die Gegenüberstellung mit Piloten, Simulationen etc... :) Aber ich hab doch nur nen armen, harmlosen Würfel...

Zu dem VSync, müsste die Framerate dann nicht so hoch sein, wie die Frequenz des Monitors? Der Läuft bei mir aber @ 85 Hertz, wieso liegt die Framerate dann bei 50... und dennoch:

Ich habe nun die PresentParameters von "D3DPRESENT_INTERVAL_DEFAULT" auf "D3DPRESENT_INTERVAL_IMMEDIATE" gesetzt, und siehe da, die Framerate liegt nun bei ca. 380 und auf dem anderen Rechner (mit der Radeon) bei 800, was sich natürlich schon um einiges besser und realistischer anhört :)

Leider hat sich nun meine Mauslook-Steuerung irgendwie verändert. Das war so ne simple Funktion die ich mir schnell mal zu Testzwecken zusammengeschustert hatte.
Ich hatte da in jedem Frame die Mausposition per GetCursorPos() abgefragt, und dann immer zwischen 2 Frames den Abstand berechnet, also quasi die relative Mausposition wie es DirectInput auch tut. Naja 1. ist die Maussteuerung durch die Änderung auf "D3DPRESENT_INTERVAL_IMMEDIATE" nun um einiges langsamer (also in-sensitiver) geworden, was ja kein Problem ist da man den Wert einfach erhöhen kann, aber 2. verhält sich die Steuerung nun auch ganz merkwürdig, dass heisst die Kamera bewegt sich ganz unregelmäßig, stockt kurz oder ist schnell, obwohl man die Maus recht konstant bewegt..

Ok, Mauslook ist jetzt Offtopic, aber irgendwie scheint es ja mit den einzelnen Frames un diesem "D3DPRESENT_INTERVAL_IMMEDIATE" zusammenzuhängen.
Kann mir jemand den Unterschied von "D3DPRESENT_INTERVAL_DEFAULT" zu "D3DPRESENT_INTERVAL_IMMEDIATE" erklären? Vielleicht hat ja auch jemand ne Erklärung dafür, warum meine Strategie mit der Mausposition zwischen 2 Frames jetzt nicht mehr so gut klappt...


Vielen Dank für Eure Hilfe!

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

13.07.2004, 14:44

Zitat

Kann mir jemand den Unterschied von "D3DPRESENT_INTERVAL_DEFAULT" zu "D3DPRESENT_INTERVAL_IMMEDIATE" erklären? Vielleicht hat ja auch jemand ne Erklärung dafür, warum meine Strategie mit der Mausposition zwischen 2 Frames jetzt nicht mehr so gut klappt...


die dx sdk doku kann...

gib in den index D3DPRESENT ein
da steht alles was du wissen willst...

kurz gesagt schaltest du mit D3DPRESENT_INTERVAL_IMMEDIATE VSync aus...

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

8

13.07.2004, 15:34

Stimmt - ein Würfel sollte viel schneller rendern als eine ganze Szene und es sollte keine Ruckler geben. Aber das ist ja scheinbar nicht der Fall. Gib mal die Framezeiten in eine Log-Datei aus.

Zu der Maussteuerung:
Du bekommst ja ganzzahlige Koordinaten. Wie stark ändern die sich denn von Frame zu Frame? Ich könnte mir vorstellen, dass es bei 380 Polls pro Sekunde nur ein oder zwei Einheiten sind und man Rundungsfehler bekommt.
"Games are algorithmic entertainment."

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

13.07.2004, 15:38

Hmmm lass doch einfach mal, zu testzwecken, diesen Mauskram raus.....

Anonymous

unregistriert

10

13.07.2004, 18:37

Ja also zu testzwecken habe ich auch alles rausgelassen, auch den Mauskram. Wie auch schon gesagt, funktioniert es mit "D3DPRESENT_INTERVAL_IMMEDIATE" nun auch sehr gut, auch die Ruckler sind verschwunden, und die Framezahlen sind erwartungsgemäß hoch.

Meine Sorge ist nur, ist es "normal", dass man mit "D3DPRESENT_INTERVAL_DEFAULT" so schlechte Framewerte hat? Falls nicht, dann würde ich mir trotzdem Sorgen machen. Und wie macht ihr es in Euren Programmen, benutzt Ihr auch "D3DPRESENT_INTERVAL_IMMEDIATE"?

Zitat


Zu der Maussteuerung:
Du bekommst ja ganzzahlige Koordinaten. Wie stark ändern die sich denn von Frame zu Frame? Ich könnte mir vorstellen, dass es bei 380 Polls pro Sekunde nur ein oder zwei Einheiten sind und man Rundungsfehler bekommt.


Hm könnte natürlich sein, schwer zu sagen irgendwie. Hier ist mal der Code für die Maussteuerung, er wird einmal pro Haupt-Schleifen-Durchlauf (in der move methode) aufgerufen:

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
35
36
37
38
39
40
void mouselook(qCCamera* pCam, float fTime)
{
    GetCursorPos(&sPointNew);

    if (sPointNew.x < 10)
    {
        SetCursorPos(GetSystemMetrics(SM_CXSCREEN) - 10, sPointNew.y);
        sPointOld.x = GetSystemMetrics(SM_CXSCREEN) - 10;
        return;
    }
    
    if (sPointNew.x > GetSystemMetrics(SM_CXSCREEN) - 10)
    {
        SetCursorPos(10, sPointNew.y);
        sPointOld.x = 10;
        return;
    }

    if (sPointNew.y < 10)
    {
        SetCursorPos(sPointNew.x, GetSystemMetrics(SM_CYSCREEN) - 10);
        sPointOld.y = GetSystemMetrics(SM_CYSCREEN) - 10;
        return;
    }
    
    if (sPointNew.y > GetSystemMetrics(SM_CYSCREEN) - 10)
    {
        SetCursorPos(sPointNew.x, 10);
        sPointOld.y = 10;
        return;
    }

    float xDiff = static_cast<float>(sPointOld.x - sPointNew.x);
    float yDiff = static_cast<float>(sPointOld.y - sPointNew.y);
    sPointOld.x = sPointNew.x;
    sPointOld.y = sPointNew.y;
    
    pCam->lookUp(yDiff * 50, fTime);
    pCam->rotate(qCVector(0.0f, 1.0f, 0.0f), -(xDiff * 50 * fTime));
}


Nich hauen, das ist sicherlich total blöd gelöst :) Wie gesagt, war nur ne kurze Notlösung, damit ich mich umschauen kann. Das pCam ist eine Kamera Klasse von mir, die man quasi intuitiv bewegen kann. Die ganzen IF Blöcke überprüfen, ob der Cursor am Rand angekommen ist - ist dem so, so wird er auf die andere Seite gesetzt, so wird das "unendliche Umsehen" mit der Kamera ermöglicht.

Also jetzt im Hinterkopf, dass ich "D3DPRESENT_INTERVAL_IMMEDIATE" benutze, und auch recht viele Frames damit erreiche, könnt ihr da irgendein Problem entdecken? (wie gesagt, mit "D3DPRESENT_INTERVAL_DEFAULT" ging es wunderbar mit dem Mouselook).

Werbeanzeige