Irrlicht engine, zwei fragen



  • Hallo, ich habe gestern mit 3D Gaming Programmierung angefangen mit der Library Irrlicht, davor war ich immer mit 2 dimensionale Programmierung beschäftigt.

    Dazu hätte ich zwei fragen:

    1 ) Im 2D Bereich brauchte ich Bilder, die ich mehrfach benutzen wollte nur einmal zu laden, ich konnte die Bilder einfach an die Position setzen und Rendern und das an mehreren stellen (gleichzeitig!). Geht das auch mir Irrlicht? Ein Objekt an mehreren Stellen gleichzeitig zu Projizieren um vll fps zu sparen? (Im Notfall kann ich meine kleine Klasse die dazu geschrieben habe Posten... wenn es hilft)

    2 ) Beim Erstellen von IrrlichtDevice kann man zwischen mehreren Optionen wählen, damit meine ich OpenGl oder DirectX8 / 9 zum Beispiel. Warum sollte ich DirectX nehmen wenn doch OpenGL (so glaube ich) Cross Platform ist, ich denke das ist so das optional Beste was ich an dieser Stelle nehmen kann oder sehe ich das falsch?



  • MrSpaghettiCode schrieb:

    1 ) Im 2D Bereich brauchte ich Bilder, die ich mehrfach benutzen wollte nur einmal zu laden, ich konnte die Bilder einfach an die Position setzen und Rendern und das an mehreren stellen (gleichzeitig!). Geht das auch mir Irrlicht? Ein Objekt an mehreren Stellen gleichzeitig zu Projizieren um vll fps zu sparen? (Im Notfall kann ich meine kleine Klasse die dazu geschrieben habe Posten... wenn es hilft)

    getTexture und draw2DImage? Ist aber die falsche Anlaufstelle eigentlich hier.

    Ich habe aber vor einigen Monaten mal in den Irrlicht-Quellcode reingeschaut und gemerkt, dass Irrlicht nicht wirklich intelligent vorgeht, was das Einladen von Dateien eingeht. Die verwenden einfache Streams. Sprich, du hast immer eine Kopie der Datei im Arbeitsspeicher. Die hat aber dein Kernel schon (nennt sich I/O-Cache), und der weiß in der Regel besser, welche Dateien er im Speicher halten will. Ich habe dann damals manuell Texturen eingemappt ( CreateFileMapping unter Windows/ mmap unter Linux) und über createMemoryReadFile und getTexture ein Handle auf die Texturen bekommen. Das hat damals nur ein paar Tausend Cycles eingespart beim Einladen. Wenn du also nicht wirklich verhungerst, was den VRAM angeht - Texturen werden dort gehalten - dann lädst du die Dateien ein, bevor du in deine Render-Loop gehst, und dann sparst du da eh nix mehr an FPS. Höchstens die Ladezeiten verbesserst du minimal, weil keine Kopie deiner Datei vom Mapping erstellt wird.

    Ist den Aufwand einfach nicht wert. Vor allem, weil du dich dann auf eine Plattform beschränkst (Mapping ist SEHR plattformspezifisch). Oder du schreibst dir einen Mapping-Wrapper. Das habe ich gemacht. Aber sowas ordentlich hinzubekommen und abstrahieren ist nicht leicht. Deswegen vertrau mal besser Irrlicht und nimm einfach getTexture .

    Wenn du dir noch Draw Calls einsparen willst, kannst du, wenn du eine große Textur aus einem sich immer wieder wiederholendem Bild aufbauen willst, IImage verwenden. Die Klasse erlaubt dir, dein Bild im Arbeitsspeicher zu bauen, dann in den VRAM zu laden und nur einmal draw2DImage für das große Bild aufzurufen. Das könnte tatsächlich Einfluss auf die FPS haben - wenn du halt sonst sehr viele Draw Calls hättest. Verbraucht natürlich viel mehr Arbeitsspeicher. Aber du hast entsprechend weniger Kontextwechsel.

    EDIT: Und vermutlich geht es auch viel einfacher. Dafür kenne ich mich aber nicht genug in Irrlicht aus.

    MrSpaghettiCode schrieb:

    2 ) Beim Erstellen von IrrlichtDevice kann man zwischen mehreren Optionen wählen, damit meine ich OpenGl oder DirectX8 / 9 zum Beispiel. Warum sollte ich DirectX nehmen wenn doch OpenGL (so glaube ich) Cross Platform ist, ich denke das ist so das optional Beste was ich an dieser Stelle nehmen kann oder sehe ich das falsch?

    Musst du testen. Vor einigen Jahren, als ich mir Irrlicht angeschaut habe, habe ich auf Windows bessere Performance mit DirectX gehabt, OpenGL war so 60% langsamer als DirectX. Aber das ist lange her, und andere Leute berichten, dass DirectX langsamer ist. Im Zweifel würde ich dir daher einfach raten, "irrlicht OpenGL DirectX" zu googlen, das zeigt dir Leute, die bereits darüber geschrieben haben und viel mehr Ahnung haben als ich. 🙂



  • Danke dachschaden, es waren sehr nützliche Informationen. Da mein Projekt nicht so der Performensfresser sein wird, werde ich bei OpenGL bleiben.
    Ich denke, dass ich die Frage 1 etwas schlecht formuliert habe.
    Deswegen würde ich es gerne erneut Versuchen.

    1 ) Mit ...
    scene::ISceneNode * MyNode = SceneM_Old->addMeshSceneNode(SceneM_Old->getMesh(PhatObject.c_str()));
    ... erstelle ich ein Node Objekt indem ich ein .3ds datei lade. Dieses Objekt kommt an mehreren Stellen gleichzeitig vor, sagen wir ein Stein in der Landschaft zum Beispiel.
    Der plumpste Gedanke währe wahrscheinlich einfach für jeden Stein in der Welt einen Node zu erstellen, mit clone() oder so.
    Der Code wird dadurch aber unübersichtlicher und auch andere dinge wie die fps leidet darunter.
    Ich denke jedoch das es eine bessere Lösung geben muss, die ich nur noch nicht kenne.

    Im 2D Raum mit SDL2 z.B.:

    rect.x = 50;
    rect.y = 50;
    SDL_RenderCopy(renderer, Stone, &crop, &rect);

    rect.x = 550;
    rect.y = 550;
    SDL_RenderCopy(renderer, Stone, &crop, &rect);

    Dasselbe Bild wurde jetzt nur einmal geladen und an zwei stellen gerendert.



  • Auf diesem Gebiet kann ich nicht mit Autorität reden, aber ein wenig eingelesen habe ich mich:

    In der Regel versuchen Treiber, so viel wie möglich zu buffern, bevor wirklich an die Grafikkarte gesendet wird. Einfach deswegen, weil das Kontextwechsel benötigt. Darüber kann man streiten, aber in der Realität ist es einfach so, dass es Treiberprogrammierern noch mehr um Schnelligkeit als um Genauigkeit geht.

    Deswegen wird in der Regel nichts zur Karte gesendet, bevor nicht wirklich muss.

    So wie ich mir das vorstelle, lädst du also einmal dein Stein-Mesh in den VRAM, sagst dem Treiber, dass er den Stein an zwei Positionen erstellen lassen soll, und um den Rest kümmert sich der Treiber dann.

    Mit getMesh machst du genau das, du lädst den Stein in den VRAM. Das tun nach meinem Verständnis alle getXXX -Funktionen von Irrlicht, zumindest in diesem Kontext. Der VRAM hält dann einfach deinen Stein beim Szenenaufbau. Für jeden Frame. Aber den Stein in den VRAM zu laden wird nur beim ersten Frame gemacht, danach ist er ja schon drin, und die Grafikkarte sieht dann nur den Befehl, die Steine (Plural) anzuzeigen.

    Aber wie gesagt, ich bin überhaupt kein Experte auf dem Gebiet.


Anmelden zum Antworten