GUI Design gut?



  • 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 😉



  • Danke, allerdings hat auch da jedes Element sein eigenen Rendercall, und genau das ist ja das was ich nicht will.
    Aber mir kam gerade eine andere Idee.
    Gibt es in Direct3D schon irgendeine Implementierung von einer Zeichenfläche, die man beliebig updaten kann, und wenn man das nicht tut immer das gleiche zeichnet, es also auch immer nur ein Rendercall gibt?
    Keine Ahnung wie ich das erklären soll 😃



  • GUIFreak, hast du schonmal was von Render-Texturen gehört? 😉



  • Nope, bin noch ein ziemlicher Anfängerm hab gedacht nen GUI wäre simpler 😃
    Hast du da gute Tutorials? Bei google findet man nur render to texture 😡



  • Render Texturen sind ja Texturen auf die man rendern kann (-> render to texture) 🙂
    Sind also schon die richtigen Artikel die du da findest.

    Render Texturen sind Texturen die man einerseits als sog. "Render-Target" verwenden kann (also wo man andere Dinge mit dem 3D-Device "draufmalen" kann, also als "Ziel" verwenden kann), und die man andrerseits als Textur verwenden kann (also als "Quelle" verwenden kann).

    D.h. du erzeugst eine grosse Render-Textur. Da malst du dann deine vielen kleinen Dinge rein. Und so lange sich an den vielen kleinen Dingen nix ändert, kannst du einfach diese Textur mit einem einzigen Quad irgendwo anders draufmalen (also auf den Backbuffer oder auf ne andere Render-Textur), ohne die vielen kleinen Render-Calls zu wiederholen.

    ps: du kannst natürlich auch ohne Render-Texturen was ähnliches haben, und zwar mit D3DSWAPEFFECT_COPY. Wenn du dein Device damit initialisierst, dann wird der Back-Buffer beim Presen() nicht gelöscht, sondern es bleibt das drinnen was vorher drinnen war. Nach dem Present() kannst du dann auch nur Teile übermalen wenn nicht alles neu gezeichnet werden soll, und wieder Present() aufrufen etc. Ist IMO aber komplizierter handzuhaben. Und D3DSWAPEFFECT verschlechtert im Fullscreen Mode die Performance.



  • Danke, das klingt ja schonmal ziemlich gut. Da werd ch google mal mit quälen 😃



  • Hab noch eine Frage.
    Wenn ich die Textur erstelle ist sie imemr komplett schwrz und übermalt alles. WIe bekomme ich sie transparent?



  • Indem du entsprechende Werte in den Alphakanal schreibst und beim Rendern entsprechendes Blending verwendest?^^



  • So, nach einer kleinen Motivationspause, habe ich es mal wieder probiert, jedoch wird einfach gar nichts auf meine Textur gerendert. So wird auch das transparent machen im moment unmöglich.
    Mein Code sieht so aus, das Dreieck wird nicht gezeichnet:

    void Init() {
        //.....
    	d3dd->CreateTexture(1280, 720, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pRenderTexture, 0);
    	pRenderTexture->GetSurfaceLevel(0,&pRenderSurface);
    }
    
    void Draw() {
    	d3dd->SetFVF(FORMATEDFVF);
    	d3dd->GetRenderTarget(0,&pBackBuffer);
    	d3dd->SetRenderTarget(0,pRenderSurface);
    	//clear texture
    	d3dd->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
    	d3dd->BeginScene();
    	FORMATEDVERTEX vertices[3] = {FORMATEDVERTEX(100, 100, D3DCOLOR_ARGB(255,0,255,0)),
    									FORMATEDVERTEX(100,500,D3DCOLOR_ARGB(255,0,255,0)),
    									FORMATEDVERTEX(200,00,D3DCOLOR_ARGB(255,0,255,0))};
    	d3dd->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 1, vertices, sizeof(FORMATEDVERTEX));
    	d3dd->EndScene();
    	d3dd->SetRenderTarget(0,pBackBuffer);
    	//D3DXSaveTextureToFileW(L"test.png",D3DXIFF_PNG,pRenderTexture,0);
    	d3dd->SetFVF(FORMATEDFVF);
    	d3dd->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    	FORMATEDVERTEX vertex[4] = {FORMATEDVERTEX(0, 0, D3DCOLOR_XRGB(0,0,0)),
    								FORMATEDVERTEX(1280, 0, D3DCOLOR_XRGB(0,0,0)),
    								FORMATEDVERTEX(0, 720, D3DCOLOR_XRGB(0,0,0)),
    								FORMATEDVERTEX(1280, 720, D3DCOLOR_XRGB(0,0,0))	};
    	d3dd->SetTexture(0,pRenderTexture);
    	d3dd->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,vertex,sizeof(FORMATEDVERTEX));
    }
    

    Ich hab das ganze aus diesem Tutorial.



  • Vielleicht solltest du nicht Alpha-Blending einschalten, und dann D3DCOLOR_XRGB() für die Vertex-Farbe verwenden.



  • Das Alphablending kam noch von dem Versuch, die Textur transparent zu bekommen, hat aber nichts zur Sache getan. Da gleiche gilt auch für D3DCOLOR_ARGB() ,
    wobei das mit einem Alphawert von 255/0xff ja exakt das Selbe wie D3DCOLOR_XRGB() ist.



  • Was sagt die D3D-Debug-Runtime? (aktivieren & Trace-Level hochdrehen)



  • Im Debugger sieht alles so aus, wie es sein sollte. Ich finde aber das RanderTarget nicht...
    Und wonach soll ich denn sonst noch gucken?



  • Ich bekomms immer noch nicht hin auf eine Textur zu rendern...
    Hat irgendjemand ein funktionierendes Beispiel?





  • Genau nach dem ersten Link habe ich mich ja gerichtet, nur funkioniert da etwas nicht, und ich habe auch keine Ahnung was, der Debugger hilft da auch nicht weiter.
    2. Link bei google ist C#
    3. Link ist auch was anderes
    4. Link ist irgendwas von NVIDIA
    5. Link ist nur eine kurte Forenfrage
    6. Link ist DirectX 10
    7. Link gleicht ziemlich dem ersten
    8. Link ist was anderes zu Texturen
    9. Link ist auch was anderes zu Texturen
    10. Link ist nur ein kurzer Forenbeitrag

    Soweit dazu.


Anmelden zum Antworten