Designfrage



  • KN4CK3R schrieb:

    Ist ein ITexture Interface, dass Methoden zum Bearbeiten von Bitmapdaten anbietet kein vernünftige Abstraktion?

    Die Tatsache dass du diesen Downcast in RenderTexture brauchst, schreit doch nach Designfehler.

    Was genau ist es, das deine Anwendung tut und warum muss es dabei unbedingt Renderer->RenderTexture() sein und nicht z.B. Texture->Render() ?



  • den Downcast brauche ich, damit ich an das eigentliche LPDIRECT3DTEXTURE9 Objekt (in D3D9Texture) komme, das mir das IDirect3DDevice9 (in D3D9Renderer) dann zeichnet.

    class D3D9Renderer : public IRenderer
    {
    public:
    	virtual void RenderTexture(shared_ptr<ITexture> texture)
    	{
    		shared_ptr<D3D9Texture> temp = static_pointer_cast<D3D9Texture>(texture);
    
    		device->SetTexture(0, temp->GetTexture());
    
    		//ob ich hier jetzt in D3D9Texture oder einen Schritt später GetTexture() in LPDIRECT3DTEXTURE9 caste, ist ja egal...
    
    		AddVertex(x, y, 0.0f, 0.0f);
    		AddVertex(x + w, y, 1.0f, 0.0f);
    		AddVertex(x, y + h, 0.0f, 1.0f);
    		AddVertex(x + w, y, 1.0f, 0.0f);
    		AddVertex(x + w, y + h, 1.0f, 1.0f);
    		AddVertex(x, y + h, 0.0f, 1.0f);
    
    		device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, verticesNum / 3, &vertices[0], sizeof(Vertex2D));
    	}
    };
    

    Die ganze Vertex Verwaltung hat in der Textur nichts zu suchen. IDirect3DDevice9 rendert ja die Textur und nicht umgekehrt. Aus diesem Grund gibt es auch keine Textur->Render() Funktion (klar, sorum wäre das ganze absolut unproblematisch)

    greetz KN4CK3R



  • Ich greife nochmal meinen Code auf:

    virtual void render(d3d9_texture texture)
        {
            device->SetTexture(0, texture->GetTexture()); //kein cast
            AddVertex(x, y, 0.0f, 0.0f);
            AddVertex(x + w, y, 1.0f, 0.0f);
            AddVertex(x, y + h, 0.0f, 1.0f);
            AddVertex(x + w, y, 1.0f, 0.0f);
            AddVertex(x + w, y + h, 1.0f, 1.0f);
            AddVertex(x, y + h, 0.0f, 1.0f);
    
            device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, verticesNum / 3, &vertices[0], sizeof(Vertex2D));         
        }
    


  • den cast für eine Renderer Klasse einzusparen, die für jeden beliebigen Texturtyp eine RenderMethode bereitstellt, halte ich für etwas fragwürdig. Wenn eine neue Grafik-API dazukommt, muss jeder Renderer (oder nur der BaseRenderer, falls er nicht mehr virtuel gemacht wird) geändert werden, nur um in der Funktionen eine "gibts net" Exception zu werfen. Das kann unmöglich ein gutes Design sein.

    greetz KN4CK3R



  • KN4CK3R schrieb:

    den cast für eine Renderer Klasse einzusparen, die für jeden beliebigen Texturtyp eine RenderMethode bereitstellt, halte ich für etwas fragwürdig. Wenn eine neue Grafik-API dazukommt, muss jeder Renderer (oder nur der BaseRenderer, falls er nicht mehr virtuel gemacht wird) geändert werden, nur um in der Funktionen eine "gibts net" Exception zu werfen. Das kann unmöglich ein gutes Design sein.

    greetz KN4CK3R

    Doch ist es. Denn jeder neue Renderer und die dazu gehörenden Texuren ist unterschiedlich, und das wird dadruch ausgedrückt. Du hingegen versuchst die ganze Zeit, Unterscheide auf "Teufel komm raus" gleich zu biegen. Und das ist scheiss Design. Zu mal die Anzahl der möglichen Renderer vermutlich eher begrenzt sein wird.



  • der Unterschied zwischen OpenGL und D3D Textur tritt im entsprechenden Renderer auf, vorher existiert kein Unterschied. Und der Renderer weiß, was er vor sich hat.

    Ein Autohändler stellt ja auch nur ein Schild "kaufe Kraftfahrzeuge" und nicht "kaufe PKWs", "kaufe Motorräder", "kaufe LKWs" vor sein Geschäft und sagt dem LKW Fahrer dann "ich kaufe ihren LKW aber nicht ihren PKW und auch nicht ihr Motorrad" eben weil der LKW Fahrer nur einen LKW hat.

    greetz KN4CK3R



  • KN4CK3R schrieb:

    den Downcast brauche ich, damit ich an das eigentliche LPDIRECT3DTEXTURE9 Objekt (in D3D9Texture) komme, das mir das IDirect3DDevice9 (in D3D9Renderer) dann zeichnet.

    Mir ist klar warum du den Cast brauchst. Das Problem liegt ja eben genau in der Natur dieses Designs, das den Cast erst notwendig macht. Der Cast ist nur Symptom. Worum es geht ist, mal festzustellen, dass hier ein Designfehler vorliegt.

    KN4CK3R schrieb:

    Die ganze Vertex Verwaltung hat in der Textur nichts zu suchen. IDirect3DDevice9 rendert ja die Textur und nicht umgekehrt. Aus diesem Grund gibt es auch keine Textur->Render() Funktion (klar, sorum wäre das ganze absolut unproblematisch)

    Und was interessiert das die Anwendung, dass es intern ein ID3Direct3DDevice9 gibt, das die Textur rendert? Warum muss deine Abstraktionsschicht unbedingt das Interface der zugrundeliegenden Grafik-API widerspiegeln? In D3D11 hast du plötzlich keinen Device mehr, der rendert, sondern einen DeviceContext. Deine D3D11 Implementierung möchte vielleicht multithreaded Rendering einsetzen. Wie löst du das? Ich vermute mal, deine Anwendung will einfach nur 2D Bildchen malen!? Dann bau ein Interface, dass es erlaubt, 2D Bildchen zu malen. Und zwar so wie die Anwendung es will und nicht so wie die Grafik-API es will.



  • ja macht die Anwendung doch?! Die Anwendung ruft beim Renderer RenderTexture auf, alles was danach passiert, ist Sache der Grafik-API und interessiert die Anwendung nicht. Die Anwendung kann sich ja auch gar nicht dafür interessieren, weil sie nicht weiß, auf welcher Grafik-API sie überhaupt ausgeführt wird.

    greetz KN4CK3R



  • Warum genau muss die Anwendung ihre Texturen selbst rendern. Sollte das Rendern nicht vielleicht Aufgabe des Renderers sein? Wenn es sich da um einen Sprite Renderer handelt (was ich mal schwer vermute), dann wirst du früher oder später nicht eine Textur pro Bild haben, sondern mehrere Bilder in eine Textur packen wollen, um möglichst viele Sprites in einem Drawcall zu rendern. Wie löst du das?



  • Wieso sollte sie sich nicht selbst zeichnen?
    Die PictureBox bekommt quasi per WM_PAINT einen IRenderer* geschickt und ruft dann renderer->RenderTexture(mein anzuzeigendes Bild); auf. Woher sollte der Renderer wissen, wie eine PictureBox aussieht.

    Eine Textur beinhaltet nur ein Bild (außer die animierte ;)) und dadran wird sich auch nichts ändern. Dass alles auf einer Textur ist und nur gezeichnete Ausschnitt verschoben wird, ist nicht geplant und auch nicht gewollt.

    greetz KN4CK3R



  • KN4CK3R schrieb:

    Ein Autohändler stellt ja auch nur ein Schild "kaufe Kraftfahrzeuge" und nicht "kaufe PKWs", "kaufe Motorräder", "kaufe LKWs" vor sein Geschäft und sagt dem LKW Fahrer dann "ich kaufe ihren LKW aber nicht ihren PKW und auch nicht ihr Motorrad" eben weil der LKW Fahrer nur einen LKW hat.

    Ein PKW Händler stellt aber das Schild auf "Kaufe PKW" und ein LKW Händler stellt das Schild auf "Kaufe LKW". Denn ein PKW Händler will nur PKW haben und ein LKW Händler nur LKW. Ein Kraftfahrzeugshandel ist ein abstraktes Gebilde, genau wie ein Kraftfahrzeug. Wenn es kein generelles Konzept gibt, dass jeder Kraftfahrzeughandel ein beliebiges Kraftfahrzeug kaufen kann, dann gibt es kein Schild "Kaufe Kraftfahrzeug", dass vor jedem Kraftfahrzeughandel steht.

    Es ist das gleiche wie hier, eine Verletzung des LSP. Das Schild "Kaufe Kraftfahrzeuge" ist für den PKW Handel mit einer zusätzlichen Bedingung versehen, der PKW Händler sagt "Ätsch.. kaufe gar nicht alle Kraftfahrzeuge, ich kaufe nur PKW". Du kannst dem PKW Händler nicht einfach statt einem PKW ein Motorrad verkaufen (Substitution), da wird es irgendwo Ärger geben.


Anmelden zum Antworten