GUI Design gut?
-
Ich meinte natürlich das Code-, Klassen- oder sonstnochwasdesign. Und Anforderungsmäßig eher wie im ersten Screen
-
Für sowas einfaches würd ich gar keine "GUI Klassen" schreiben. Sind ja nur ein paar Texte und Rahmen drumrum.
-
Was schon mal klar ist deine GUI wird so sehr Grafikkartenhungrig werden. Keine Ahnung ob das bei dir eine Rolle spielt. Wenn man aber mit dieser Rechteckklasse seinen Hintergrund mit 8x8 Pixel kachelt, dann wird die Framerate wohl schonmal einbrechen.
-
TGGC schrieb:
Was schon mal klar ist deine GUI wird so sehr Grafikkartenhungrig werden. Keine Ahnung ob das bei dir eine Rolle spielt. Wenn man aber mit dieser Rechteckklasse seinen Hintergrund mit 8x8 Pixel kachelt, dann wird die Framerate wohl schonmal einbrechen.
Naja, so Grafikhungrig wirds wohl auch nicht werden, die paar Vektoren schafft auch ne alte Grafikkarte.
Aber wie würdest da das ganze denn machen?
-
GUIFreak schrieb:
Naja, so Grafikhungrig wirds wohl auch nicht werden, die paar Vektoren schafft auch ne alte Grafikkarte.
Warum fragst du ueberhaupt, wenn du es ehh schon besser weisst?
-
Weil ich der Meinung bin, dass die 129600 Vektoren bei 8x8 Vierecken und einer Auflösung 1920x1080 Pixel,
1. Nicht übermäßig viele sind
2. Die Dimension zumindestens für mein klein Spielchen viel zu übertrieben
3. Ich dennoch immer andere Alternativen einbeziehen will, da es immer eine bessere Lösung gibt
-
120k Vektoren mögen "nicht viel" sein, aber 30k Render-Calls sind definitiv viel. Zu viel wenn du mich fragst.
p.S.: einen Vertex-Buffer für 4 Vektoren kann man sich denke ich sparen, DrawPrimitiveUP tut's da vermutlich auch.
-
GUIFreak schrieb:
Weil ich der Meinung bin, dass die 129600 Vektoren bei 8x8 Vierecken und einer Auflösung 1920x1080 Pixel,
1. Nicht übermäßig viele sind
2. Die Dimension zumindestens für mein klein Spielchen viel zu übertrieben
3. Ich dennoch immer andere Alternativen einbeziehen will, da es immer eine bessere Lösung gibtEben. Du hast keine Ahnung. Ich hab Ahnung. So lange du das nicht kapierst, habe ich keinen weiteren Grund fuer Kommunikation mit dir.
-
Die Performance hängt nicht einzig und allein von der Anzahl der Dreiecke ab, die Spielt da heutzutage bei weitem keine Hauptrolle. Ob 32400 Dreiecke viel sind oder nicht hängt von sehr sehr vielen Faktoren ab. Aber wenn du jedes Dreieck einzeln mit einem eigenen Aufruf von DrawPrimitive() malst dann sind, ungeachtet alles anderen, 32400 Dreiecke verdammt viel. Weil nämlich die CPU ihre ganze Zeit damit verbringt tonnenweise mikroskopisch kleine Renderaufträge an die GPU zu schicken welche mit ihrer Winzigkeit die GPU dermaßen unterfordern dass selbige praktisch nichts tut als auf Renderaufträge zu warten.
Du kannsts aber auch einfach mal ausprobieren wenn du uns nicht glaubst
-
TGGC schrieb:
Eben. Du hast keine Ahnung. Ich hab Ahnung. So lange du das nicht kapierst, habe ich keinen weiteren Grund fuer Kommunikation mit dir.
Wenn ich denken würde du hättest keine Ahnung hätte ich gar nicht erst gefragt, aber mir soll recht sein.
dot schrieb:
Du kannsts aber auch einfach mal ausprobieren wenn du uns nicht glaubst
Glauben tu ich euch schon, aber ich habs trotzdem mal ausprobiert, und ich hab mit VSync bei mir eine CPU und GraKa auslastung von nahezu 0% und ohne VSync FPS um die 2000 (mit einer Timerklasse und Fraps getetstet). Deswegen auch meine Aussage.
Aber wie kann ich denn die Renderalls verringern, wenn ich will, dass jedes Element im GUI "dynamisch" bleibt, ich es also auf Events reagieren lassen kann, oder rumschieben kann?
-
GUIFreak schrieb:
Glauben tu ich euch schon, aber ich habs trotzdem mal ausprobiert, und ich hab mit VSync bei mir eine CPU und GraKa auslastung von nahezu 0% und ohne VSync FPS um die 2000 (mit einer Timerklasse und Fraps getetstet). Deswegen auch meine Aussage.
Und das bei 32400 Rechtecken?
-
Ähm nein
Sorry, ich hab jetzt die Dimensionen von meiner Anwendung genommen und da sind es 1280x720 * 10x10 = 9216 Rechtecke.
-
OK das wundert mich trotzdem noch ein wenig aber versuchs mal mit 32400
-
Hmm, GraKa immernoch bei 0%, der Prozessor springt jetzt aber immer zwischen 0 und 30% rum, was natürlich nicht so dolle ist
In einem anderen Thread wurde es ja schon angesprochen, was gibt es da für Lösungansätze?
-
EDIT:
Hab gerade die Antwort von dot im anderen Thread gelesen. Ich werds mal ausprobieren
-
GUIFreak schrieb:
Hmm, GraKa immernoch bei 0%, der Prozessor springt jetzt aber immer zwischen 0 und 30% rum, was natürlich nicht so dolle ist
In einem anderen Thread wurde es ja schon angesprochen, was gibt es da für Lösungansätze?Aber nicht bei deaktiviertem vsync. Wäre ziemlich unlogisch, wenn da weder CPU noch GPU limitieren würde - was wird sonst nämlich in der restlichen Zeit gemacht?
(P.S. beim ermitteln der CPU-Auslastung daran denken sich für jeden Kern ein eigenes Diagramm anzeigen zu lassen)
-
Ich hab es jetzt so geändert, dass einfach Vektoren in einen Vertexbuffer gesteckt werden, und dieser dann über einen einzigen Rendercall als TRIANGLELIST gerendert wird. Ich habe zwar immernoch eine Menge Vektoren, jedoch nurnoch einen einzigen rendercall
Was mich aber jetzt stört, ist dass ich wegen TRIANGLELIST für jedes Viereck 6 Vektoren brauche. Gibt es da eine möglichkeit TRIANGLELIST und TRIANGLESTRIP zu kombinieren, dass ich nurnoch 4 Vektoren für ein Viereck brauche?
-
Öhm. Erstmal kann man auch mit indizierten Vertices rendern. In D3D heissen die entsprechenden Funktionen DrawIndexedPrimitive(UP), OpenGL weiss ich nicht.
Und dann kann man natürlich auch einen Triangle-Strip verwenden. Und zwar indem man, wenn man z.B. vom Ende einer Zeile zum Anfang der nächsten wechseln muss, degenerierte Dummy-Dreiecke verwendet. Also welche wo zwei Punkte die gleichen Koordinaten haben. Die gehen dann zwar quer über den Bildschirm, nur da sie "unendlich dünn" sind, wird auch kein einziger Pixel für sie gerendert.
-
So, habe jetzt einen neuen Ansatz.
Header:class GUI { public: GUI(); void Init(LPDIRECT3DDEVICE9 d3dd, int width, int height); void Add(float x, float y, float width, float height, DWORD color); void Draw(); private: std::vector<FORMATEDVERTEX> vertices; std::vector<short> indices; LPDIRECT3DDEVICE9 d3dd; LPDIRECT3DVERTEXBUFFER9 vBuffer; LPDIRECT3DINDEXBUFFER9 iBuffer; int count; };
CPP:
GUI::GUI() : vertices(), indices(), d3dd(0), vBuffer(0), iBuffer(0), count(0) {}; void GUI::Init(LPDIRECT3DDEVICE9 _d3dd, int width, int height) { d3dd = _d3dd; HRESULT result = d3dd->CreateVertexBuffer(sizeof(FORMATEDVERTEX), 0, FORMATEDFVF, D3DPOOL_MANAGED, &vBuffer, 0); if(FAILED(result)) std::cerr << result << std::endl; result = d3dd->CreateIndexBuffer(sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &iBuffer, 0); if(FAILED(result)) std::cerr << result << std::endl; }; void GUI::Add(float x, float y, float width, float height, DWORD color) { FORMATEDVERTEX v1 = FORMATEDVERTEX(x, y, color); FORMATEDVERTEX v2 = FORMATEDVERTEX(x + width, y, color); FORMATEDVERTEX v3 = FORMATEDVERTEX(x, y + height, color); FORMATEDVERTEX v4 = FORMATEDVERTEX(x + width, y + height, color); indices.resize(indices.size() + 6); std::vector<FORMATEDVERTEX>::iterator it; it = std::find(vertices.begin(), vertices.end(), v1); if (it == vertices.end()) { vertices.push_back(v1); indices[indices.size() - 6] = vertices.size() - 1; } else { indices[indices.size() - 6] = it - vertices.begin(); } it = std::find(vertices.begin(), vertices.end(), v2); if (it == vertices.end()) { vertices.push_back(v2); indices[indices.size() - 5] = vertices.size() - 1; indices[indices.size() - 3] = vertices.size() - 1; } else { indices[indices.size() - 5] = it - vertices.begin(); indices[indices.size() - 3] = it - vertices.begin(); } it = std::find(vertices.begin(), vertices.end(), v3); if (it == vertices.end()) { vertices.push_back(v3); indices[indices.size() - 4] = vertices.size() - 1; indices[indices.size() - 1] = vertices.size() - 1; } else { indices[indices.size() - 4] = it - vertices.begin(); indices[indices.size() - 1] = it - vertices.begin(); } it = std::find(vertices.begin(), vertices.end(), v4); if (it == vertices.end()) { vertices.push_back(v4); indices[indices.size() - 2] = vertices.size() - 1; } else { indices[indices.size() - 2] = it - vertices.begin(); } vBuffer->Release(); iBuffer->Release(); d3dd->CreateVertexBuffer(sizeof(FORMATEDVERTEX) * vertices.size(), 0, FORMATEDFVF, D3DPOOL_MANAGED, &vBuffer, 0); d3dd->CreateIndexBuffer(sizeof(short) * indices.size(), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &iBuffer, 0); void* pvoid = 0; vBuffer->Lock(0, 0, &pvoid, 0); std::memcpy(pvoid, &vertices[0], sizeof(FORMATEDVERTEX) * vertices.size()); vBuffer->Unlock(); pvoid = 0; iBuffer->Lock(0, 0, &pvoid, 0); std::memcpy(pvoid, &indices[0], sizeof(int) * indices.size()); iBuffer->Unlock(); count += 2; }; void GUI::Draw() { d3dd->SetFVF(FORMATEDFVF); d3dd->SetStreamSource(0, vBuffer, 0, sizeof(FORMATEDVERTEX)); d3dd->SetIndices(iBuffer); d3dd->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertices.size(), 0, count); };
Das ganze ist bisher nur ganz primitiv für Rechtecke gemacht.
Jedoch gefallen mir hier 2 Sachen nicht.
1. Die komplette Objektorientierung ist weg, ich habe keine Informationen über einzelne Primitive
2. Ab einer bestimmten Menge an Vektoren wird der Heap beschädigt
Was kann man da noch besser machen?
-
http://archive.gamedev.net/reference/programming/features/gui/
Da wird das ganze Thema nahezu vollständig erklärt