3D-Grafik OpenGL FPS Einbruch

Network

Top Contributor
Hi,

ab wievielen zu zeichnenden Punkten ist es denn so ca. "üblich" dass die FPS-Rate in den Keller geht?
Ich weiss eine sehr abstrakte Frage in der sehr viele Faktoren eine Rolle spielen.

Ich arbeite derzeit mit LWJGL. Die Standardfpsrate sollte eigentlich bei 60 liegen.
Es wird immer wieder das selbe Viereck mit 4 Polygonen gezeichnet mit GL_TRIANGLE_STRIP.
Die Textur des Vierecks ändert sich bei jedem zeichnen.

Wenn es dann 6500 mal gezeichnet wird (Das entspräche ja dann 6500*4 = 26000Punkten), brechen die ersten FPS ein, dann geht es auch schon relativ zügig in den Keller.
Meine Grafikkarte gehört zu den "ATI HD 5700 Series" Desktop Grafikkarten... sehr leistungsstark auf jedenfall.

Ich mache mir aber sorgen, denn 26000 hört sich nicht gerade viel an.
Ich habe versucht mit einem Profiler herauszufinden woran es liegen könnte um herauszufinden ob es am eigenen Code irgendetwas verlangsamendes gibt oder es an OpenGL liegt.
- Naja sagen wir so, ich bin auf der Suche nach einem Profiler gescheitert, VMVisual will nicht und der Rest spart sich offenbar eine Installationsanleitung.

Deshalb frage ich jetzt euch: ab 26000Punkten - FPS sinkt unter 60. Normal?

[EDIT]
Die Daten scheinen sich ständig zu verändern.
Ich habe jetzt mal alle Hintergrundprogramme abgeschaltet die ein normaler User wahrscheinlich sonst nicht laufen haben würde und den Test nochmals ein paar mal gestartet, das beste Ergebniss bis jetzt:
Ab 15000 Vierecken: <60FPS
Bei 30000 Vierecken: =40FPS
Bei 90000 Vierecken: =10FPS
[/EDIT]

Gruß
Net
 
Zuletzt bearbeitet:
S

Spacerat

Gast
Also die Zahlen sind keineswegs normal...
Kann es sein, das du die VOBs oder was auch immer du erstellst in jedem Frame mit "new" instanzierst, was in jedem Frame dann auch zwangsläufig Kopiervorgänge (ob auf Graka oder im Hauptspeicher) nach sich zieht? Irgendwann schiesst du damit nämlich den GC ab, der mit dem Abräumen von "non escapable Objects" nicht mehr hinterherkommt.
 
Zuletzt bearbeitet von einem Moderator:
T

tröööt

Gast
naja ... ob man jetzt ne AMD HD 5700 als "sehr leistungsstark" bezeichnen kann wäre jetzt ne frage die man mal so in einen raum voller gaming-nerds werfen könnte ... aber auch für heutige technologien sollte es ein model sein mit dem man noch gut dabei ist ...

natürlich ist es immer wichtig auch den richtigen treiber zu installieren ...

zwar hat Win 7 mit WDDM1.1 für moderne AMD und nVidia schon "standard-treiber" dabei die halt suspend-to-ram und aero ermöglichen ... aber will man richtige 3D power reicht das lange nicht mehr aus ... da müssen die passenden treiber von AMD bzw nVidia geladen und installiert werden ...
ist gerade bei OEM systemen beliebter fehler wenn sich z.b. medion mal wieder denkt : ach wir verpacken einfach WDDM1.1 schick und sperren die möglichkeit den "echten" treiber zu installieren ... wobei medion eh der größte bullshit ist ...
auch muss man bei modellen im höheren preissegment sowie high-end sicherstellen das diese vom netzteil auch mit genug strom versorgt werden um die gpu's richtig auf leistung zu fahren ... ist das psu zu schwach auf der brust oder leidet das ganze system an "strom-mangel" kann das auch starke leistungs-einbußen zur folge haben ...

was ich eigentlich damit sagen will : es kann noch ganz andere gründe als schlechten code geben das eine 3D anwendung selbst auf einer relativ guten graka fps-mäßig einfach nur im keller rumdümpelt ...

allerdings sollte man folgendes nicht vergessen : auch wenn LWJGL native-lib's zur anbindung nutzt geht doch gerade dort die meiste performance verloren ... denn auf dem weg vom VM-code zum GPU liegen so manche stolpersteine im weg ...
man sollte die leistung des systems also generell mal mit benchmark-tools prüfen ... dann kann man sich immer noch an code-optimierung ran machen
 

Marco13

Top Contributor
Spacerat hat von VBOs geredet... aber ... irgendwie deucht mir, dass bei dir im Code gelegentlich sowas wie glBegin/glEnd und ein paar glVertex3f dazwischen vorkommen - richtig?
 
S

Spacerat

Gast
@Marco13: Ich meinte so ein was auch immer... und ich glaube kaum, das sich jemand die Mühe macht 6500 mal glVertex3f oder ähnliches zu schreiben. Ich denke mal, dass ich dieses Problem damals auch hatte, da lag es nicht an glVertex3f, sondern an einem float-Array, welches ich in einer Schleife ständig mit new neu instanzierte, statt eine einzige Instanz öfters zu verwenden.
 

Marco13

Top Contributor
Man muss ja nicht jeden Aufruf ausschreiben - trotzdem kann er ja DA sein. Sowas wie
Java:
glBegin(GL_TRIANGLES);
for (int i=0; i<10000; i++)
{
    glVertex3f(x[i], y[i], z[i]);
}
glEnd();
ist auf jeden Fall deutlich langsamer, als ein einzelner Aufruf, um den Inhalt eines VBOs zu rendern.
 

Network

Top Contributor
Okay also ist diese Leistung nicht "normal". Das ist schonmal gut zu wissen. Also eigentlich verwende ich die OpenGL 4 standards... hoffe ich jedenfalls. Mit einem VAO mit VBOs.

Fals noch wer Lust zum raten hat: :D
So sieht das zeichnen der Quadrate aus - Bei jedem FPS ruft jedes dieser Quadrate diese Methode auf.
Java:
private void drawImage(int image, float x, float y, float w, float h,
			float angle) {

	m4fModel = new Matrix4f();
			
	Matrix4f.translate(new Vector3f(x, y, 0), m4fModel, m4fModel);
	Matrix4f.rotate(angle, new Vector3f(0, 0, 1), m4fModel, m4fModel);
	Matrix4f.scale(new Vector3f(w, h, 0), m4fModel, m4fModel);

	// Draw
	GL13.glActiveTexture(GL13.GL_TEXTURE0);
	GL11.glBindTexture(GL11.GL_TEXTURE_2D, image);

	m4fModel.store(fbMatrices);
	fbMatrices.flip();

	GL20.glUniformMatrix4(quadID[9], false, fbMatrices); // quadID[9] = ModelMatrix-ID
	GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 4);

}
Ansonsten gibt es noch den Fragment- und Vertexshader die machen aber eigentlich nur das:
Code:
VertexShader:
     gl_Position = projectionMatrix * modelMatrix * in_Position;
FragmentShader:
     out_Color = texture2D(texture_diffuse, pass_TextureCoord);
Ich kann fals notwendig natürlich noch den Rest des Codes senden. Jetzt hier alles zu senden würde in Unübersichtlichkeit und folgender Desinteresse enden. ;)

@tröööt das ist natürlich wahr, meine Grafikkarte befindet sich aber mit ziemlicher Sicherheit auf ihrer Standardleistung.
Der Windowsbenchmark gibt 7.0 von 7.9 an. Im mitgelieferten Testprogramm liefert die Grafikkarte "Leistung: 1.0" und auch in der Praxis läuft Battlefield 3 auf allen Grafikeinstellungen mit Ultra flüssig (Bis auf 16xAA, dieses "wichtige" Feature scheinen nur NVidia Karten zu können).
Treiber werden monatlich automatisch auf den neuesten Stand gebracht.
Die unterstützte Treiber-OpenGL-Version ist 4.2.
Das alles brachte mich zu der Aussage "sehr leistungsstark" ;)

@Spacerat Alle Quadrate wurden extrem schnell hintereinander in einer while(true)-Schleife instanziert mit "new" in einem seperaten Thread. Könnte das dazu geführt haben?
(Also die Quadrate als Objekt an sich, nicht das QuadratVBO, wie man im Code sieht wird für alle immer das selbe QuadratVBO verwendet)
-> Edit: Ich habe einfach mal nur einen bestimmten Prozentsatz tatsächlich gezeichnet. Das verbesserte die Leistung um den eben jeweiligen Prozentfaktor, also nehme ich wirklich an es handelt sich um ein Problem beim zeichnen.

Gruß
Net
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Ähm. Wenn dieser Code für jedes der x0000 Quadrate aufgerufen wird, wundert es mich nicht. Das wäre ja, wie wenn man den Code von
Java:
glBegin(GL_TRIANGLES);
for (int i=0; i<10000; i++)
{
    glVertex3f(x[i], y[i], z[i]);
}
glEnd();
ändern würde zu
Java:
//glBegin(GL_TRIANGLES);
for (int i=0; i<10000/3; i++)
{
    drawVboForOneTriangle();
}
//glEnd();
(d.h. genau das IST es, wenn ich das richtig verstanden habe).

VBOs dienen ja nicht zuletzt dem Zweck, die ganzen Zustandsänderungen und Aufrufe an GL zu vermeiden.

Wie die geeingetste Lösung aussehen würde, ist schwer zu sagen. Eigentlich einfach: Pack' die Koordinaten von allen Vierecken in EIN VBO. Aber dort werden ja (zumindest potentiell) unterschiedliche Texturen verwendet. Soweit ich weiß gibt es (auf OpenGL aufsetzende, Sezengraphbasierende) Rendering-Bibliotheken, die genau wegen so etwas die Objekte quasi "nach ihren Materialien sortieren", so dass erst alle mit Material 1 gerendert werden, dann alle mit Material 2 usw...
 
S

Spacerat

Gast
Also bei mir sah es damals wie folgt aus und das mal unabhängig davon, was für Objekte instanziert und wie sie verwendet werden. Bei Network nehme ich an, dass es die Vector3fs sind.
Java:
for(int n = 0; n < vertices.size(); n++) {
  float[] fv = vertices.get(n); // diese Methode instanzierte ständig neue float-Arrays
  glVertex3fv(fv);
}
Das konnte ich mit folgendem bereinigen:
Java:
float[] fv = null;
for(int n = 0; n < vertices.size(); n++) {
  fv = vertices.get(n, fv); // diese Methode instanzierte nur dann ein float-Array
  // wenn die Daten nicht in das übergebene passten oder es null war.
  glVertex3fv(fv);
}
Das Ganze heisst Objekt-Reuse und hat mein FPS-Problem dazumal behoben.
Und wie Marco schon bemerkt hat... [IRONIE]wenn du nur ein Dreieck ins VBO packst, kannst auch gleich wieder glVertex3f nehmen ;).[/IRONIE]
 
Zuletzt bearbeitet von einem Moderator:

Marco13

Top Contributor
Erstens war das nicht ironisch, und zweitens (OT: ) das Object-Reuse könnte/sollte durch die verbesserte Escape Analysis von Java >= 7 obsolet (oder zumindest weniger wichtig) werden. Hier ist das Problem wohl wirklich, dass "viel" gemacht werden muss, um viele (verschwindend kleine) VBOs an die GraKa zu schicken.
 

Network

Top Contributor
Mir ist gerade nicht bewusst wo ich das VBO ständig an die Graka schicke? Irgendwie sehe ich das jetzt nicht in meinem geposteten Code. Ich dachte eigentlich ich schicke es einmal an die Graka, danach bevor ich anfange alles zu zeichnen registriere ich die ID des VBO bei der Grafikkarte.
Java:
// Steht vor der Zeichenschleife
GL20.glEnableVertexAttribArray(0);
Das war jedenfalls meine Vorstellung. Jetzt weiss ich nicht ganz was ich ändern sollte, ausser das es in Zukunft wahrscheinlich einfach besser ist eine vorgefertigte Engine zu verwenden. ;)

Nichts desto trotz werde ich Spacerats Tipp nachgehen. Eigentlich denke ich auch dass das in Java mittlerweile vernachlässigbar ist, aber vieleicht hilft es praktisch ja tatsächlich insbesondere wegen der Schilderung der eigenen Erfahrung. :)

[EDIT]
Okay wobei ich jetzt natürlich verstehe, dass es selbstverständlich einen Unterschied darstellt ob man ein großes kompliziertes Objekt darstellt mit 200.000Punkten (Mir fällt nicht mehr das Wort dafür ein) oder ganz viele kleine mit insgesammt 200.000Punkten.
Da ständig die Matrix dazu an die Grafikkarte übertragen werden muss.

Nebenbei habe ich jetzt auch einen Fog eingebaut, sodass Objekte die sich weit weg befinden oder von denen man ausgehen kann, nicht gerade im Sichtbereich zu liegen nicht mehr gezeichnet werden.
Das erhöht die gesammte Leistung natürlich nochmals, sofern man nicht gerade auf eine Ansammlung von tausenden Objekten schaut.
[/EDIT]
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Hui, so gesehen ... stimmt eigentlich .. :reflect: Ich würde jetzt sagen, dass das eigentliche Rüberschicken erst bei glDrawArrays passiert, aber OB das so ist (und wie es bei mehrfachem Aufruf mit schon gebundenen Daten ist) wird hier bestenfalls Fancy aus dem Stegreif sagen können...

Unabhängig davon ist aber, dass es keinen Sinn macht, mit dem gegebenen Code viele Objekte zu zeichnen. Wobei man dann vorher nochmal relativ leicht (durch wechselseitiges Auskommentieren einmal der Matrix-Sachen und einmal der GL-Sachen) prüfen könnte, ob die Zeit nun bei GL oder bei den Matrixoperationen flöten geht - die dürften in dieser Form auch nicht ganz billig sein, und könnten ggf. wegoptimiert oder beschleunigt werden....
 
S

Spacerat

Gast
@Marco13: Aber ich meinte das ironisch. Würde nie jemandem den Tipp geben glVertex3f zu verwenden.

Aber davon mal ab... wenn in einem Anweisungsblock Objektinstanzen erstellt und zurückgegeben werden, merkt diese Analyse in Java7 sofort, dass es Escapeable-Objects (ich bemerke grad' meinen Irrtum oben... :oops:) sind, weswegen sie auf dem Heap landen, wo sich später der GC drum kümmern muss. Nur deswegen macht Objekt-Reuse auch in Java7-Zeiten noch Sinn.
 

Marco13

Top Contributor
Ahso...
[ot]
Bzgl. Escape Analysis ... da gibt's ein paar Papers und Technical Reports drüber, und ... ich habe vielleicht nicht ALLE gelesen ( :joke: ) aber tatsächlich kommt da auch noch Method Inlining dazu. Sowas wie
Java:
float x,y,z;

void consume(float array[])
{
    x = array[0];
    y = array[1];
    z = array[2];
}

void doSomething()
{
    for (int i=0; i<100; i++)
    {
        float array[] = new float[] {i,i,i};
        consume(array);
    }
}
wird in einem ersten Schritt zu
Java:
float x,y,z;

void doSomething()
{
    for (int i=0; i<100; i++)
    {
        float array[] = new float[] {i,i,i};
        x = array[0];
        y = array[1];
        z = array[2];
    }
}
geinlinet, und dann escapt da eben nichts mehr.

Aaaaaber... Spätestens, wenn der Array an eine native Methode übergeben wird, beißt das natürlich auf Granit (obwohl ich meine, im Hinterkopf zu haben, dass ex Fälle gibt, wo sogar nativer Code beim Inlining berücksichtigt werden kann, aber davon kann man wohl (hier) nicht ausgehen...)
[/ot]
 
S

Spacerat

Gast
@Marco13: Warum OT? Ich denke, genau das ist das Pit in das man fällt.
Es geht eben darum, dass zu viele Objekte innerhalb eines Anweisungsblocks erstellt werden. Bei deinem Beispielcode würde die EA als erstes noch was ganz anderes optimieren, sie würde nämlich Platz für genau 12 Byte (3 Floats) auf dem Stack des Anweisungsblocks schaffen. Das sähe im Prinzip so aus.
Java:
doSomething() {
  { // virtueller Anweisungsblock für Objekte, die auf dem Stack alloziiert werden können
    float[] array = new float[3];
    for(int i=0; i<100; i++) {
      array[0] = array[1] = array[2] = i;
      //... usw.
    }
  }
}
Im Gegensatz zu deiner Version ist "array" nun genau 1 Mal in einem Anweisungsblock definiert, was zur Folge hat, dass immer die selben 12 Bytes genutzt werden, welche mit Sicherheit auch noch auf den Stack passen. So konnte man schon lange bevor irgendeiner Escape-Analyse verhindern, dass die JVM den Speicher für Objekte innerhalb eines Blocks sonstwohin (und das auch noch permanent) zuweist. Das kann man sich heutzutage sparen und so hinschreiben, wie in deinem Beispielcode.
Innerhalb meiner "getVertex()"-Methode aber ist das Array von vorne herein als Escapable einzustufen, denn es wird zurückgegeben:
Java:
float[] getVertex(index) {
  return new float[] {x, y, z}; // landet definitiv auf dem Heap, es sei denn, man sorgt einen Block
  // höher dafür, dass das nicht passiert.
}
 
Zuletzt bearbeitet von einem Moderator:
G

Guest2

Gast
Moin,

Also eigentlich verwende ich die OpenGL 4 standards... hoffe ich jedenfalls.

Du kannst das genaue Profil über die ContextAttribs beim Erzeugen des OpenGL Kontextes festlegen (z.b. [c]ContextAttribs contextAttribs = new ContextAttribs(4, 2).withProfileCore(true).withForwardCompatible(true);[/c]). Würdest Du dann trotzdem deprecated Funktionen aufrufen, wirft der Grafikkartentreiber Fehler. In die Shader gehört dann entsprechend [c]#version 420 core[/c].


[EDIT]Nebenbei habe ich jetzt auch einen Fog eingebaut, sodass Objekte die sich weit weg befinden oder von denen man ausgehen kann, nicht gerade im Sichtbereich zu liegen nicht mehr gezeichnet werden.
Das erhöht die gesammte Leistung natürlich nochmals, sofern man nicht gerade auf eine Ansammlung von tausenden Objekten schaut.
[/EDIT]

Hm, ist das CPU basiert? Oft ist das ein Anzeichen, das die Fähigkeiten der Grafikkarte nicht genutzt werden und es deshalb dann auch langsam wird. Vertexdaten gehören nicht auf die CPU. Vermutlich hat Deine Grafikkarte keine Probleme damit sehr viele Dreiecke gleichzeitig darzustellen, allerdings mögen Grafikkarten große Happen und keine kleinen Stückchen. 90000 glDrawArrays ist definitiv zu viel. (Btw. Wenn Deine Vierecke zusammenhängen ist glDrawElements viel besser.)


Wenn Du Lust hast kannst, könntest Du von Deinem Code gerne mal eine Version als KSKB online stellen. Dann würde ich mal versuchen eine schnellere Variante zu implementieren. ;)

Viele Grüße,
Fancy
 

Network

Top Contributor
So unter der Woche hat ich keine Zeit mehr gehabt mich hierum zu kümmern, deshalb back in action ;)

Moin,

Du kannst das genaue Profil über die ContextAttribs beim Erzeugen des OpenGL Kontextes festlegen (z.b. [c]ContextAttribs contextAttribs = new ContextAttribs(4, 2).withProfileCore(true).withForwardCompatible(true);[/c]). Würdest Du dann trotzdem deprecated Funktionen aufrufen, wirft der Grafikkartentreiber Fehler. In die Shader gehört dann entsprechend [c]#version 420 core[/c].

Okay dann verwende ich tatsächlich OpenGL 4.2 und hoffe es nicht nur. :)
Wobei im Debugmodus immer angezeigt wird "MemoryAccessor: Unsafe" - Im entsprechenden Forum konnte mir keiner sagen was das bedeutet, ich hoffe mal das hängt nicht damit irgendwie zusammen. :)
In einem Tutorial stand man soll
Code:
#version 130 core
schreiben wenn man OpenGL 3 verwendet, deshalb hatte ich 140 core geschrieben. Also er hat es nicht angemeckert, aber ein gutes zeichen das Tutorial zu wechseln.

Hm, ist das CPU basiert? Oft ist das ein Anzeichen, das die Fähigkeiten der Grafikkarte nicht genutzt werden und es deshalb dann auch langsam wird. Vertexdaten gehören nicht auf die CPU. Vermutlich hat Deine Grafikkarte keine Probleme damit sehr viele Dreiecke gleichzeitig darzustellen, allerdings mögen Grafikkarten große Happen und keine kleinen Stückchen. 90000 glDrawArrays ist definitiv zu viel. (Btw. Wenn Deine Vierecke zusammenhängen ist glDrawElements viel besser.)

Ja der Fog ist CPU basiert. Er überprüft einfach die Koordinaten des Massepunktes XYZ der darzustellenden Objekte und gibt sie weiter an die Grafikkarte zum zeichnen wenn alles stimmt.
Ich wusste jetzt leider nicht, wie man das als Shader programmieren könnte - mein Verständnis in dem Gebiet hält sich noch sehr in Grenzen.

Okay also 90000 Aufrufe zuviel, bei meiner Grafikkarte wohl schon 6500.
(Nebenbei habe ich mal die Matrixoperationen ausgeklammert und danach die Zeichenmethode: Definitiv die eine kleine Zeichenmethode glDrawArrays)

Daraus entnehme ich aber auch: wenn ich später komplexere 3D Modelle einführe, sollte die Leistung eigentlich kaum sinken(?).
Das hier war jetzt ein Test um das ganze Programm mal auf Herz und Nieren zu prüfen und zu schauen ob es die später zu erwartende Leistung einhalten kann. Das der Grafikthread als erstes einknickt hätte ich niemals erwartet, eigentlich sollte eine preferred capacity von 16000 Darstellungen existieren.
Aber vieleicht weiss ja noch jemand wie man ein Shader-Fog hinkriegt.

Wenn Du Lust hast kannst, könntest Du von Deinem Code gerne mal eine Version als KSKB online stellen. Dann würde ich mal versuchen eine schnellere Variante zu implementieren. ;)

Viele Grüße,
Fancy

Ja an dem KSKB arbeite ich seit ich den Thread erstellt habe, mein Programm ist ein bisschen kompliziert, irgendwie will der extrahierte Code einfach nicht funktionieren. Das frustet sehr.
Wenn ich eins auf die Reihe kriege poste ich es gerne mal.

Gruß
Net

[EDIT]
Ich habe nun im Shader mal die Versionsnummer ausgetauscht von
#version 140 core
zu
#version 420 core

Die FPS-Rate bricht jetzt erst bei 22000Vierecken ein. Also das ist mehr als eine Verdreifachung der Performance. Wusste nicht dass das so einen Effekt auf die Grafikkarte hat.
[/EDIT]
 
Zuletzt bearbeitet:
S

Spacerat

Gast
Also "Unsafe" dürfte ein Hinweis aus die Java-Klasse "sun.misc.Unsafe" sein. Diese wird von der JVM in Verbindung mit DirectBuffern verwendet und deutet nur darauf hin, dass die Speicherquelle nicht der Heap, also kein durch die JVM verwalteter (deswegen "unsafe") Speicher ist. Ist also nichts weltbewegendes.
 
G

Guest2

Gast
Die Versionsnummern von GLSL wurden erst mit OpenGL 3.3 angeglichen. Dadurch ergibt sich das merkwürdige Versionsschema:

Code:
GL 2.1 = GLSL 1.20
GL 3.0 = GLSL 1.30
GL 3.1 = GLSL 1.40
GL 3.2 = GLSL 1.50
GL 3.3 = GLSL 3.30
GL 4.0 = GLSL 4.00
GL 4.1 = GLSL 4.10
usw.

Merkwürdig ist, dass die Angabe [c]#version 140 core[/c] eigentlich zu einer Fehlermeldung führen sollte, da das Core-Profil erst mit GLSL 150 spezifiziert wurde. Aber nuja, wenn es jetzt schneller läuft, einfach freuen! ;)

Ja der Fog ist CPU basiert. Er überprüft einfach die Koordinaten des Massepunktes XYZ der darzustellenden Objekte und gibt sie weiter an die Grafikkarte zum zeichnen wenn alles stimmt.
Ich wusste jetzt leider nicht, wie man das als Shader programmieren könnte - mein Verständnis in dem Gebiet hält sich noch sehr in Grenzen.

Hmm, das klingt erstmal nach einfachem Clipping und das sollte doch schon über die normale Far-Plane passieren, bzw. den Wert, den Du als maximale Entfernung in die Projektionsmatrix eingebaut hast. Evtl. könnte man das Primitiv auch schon vorher verwerfen, bin mir spontan aber nicht sicher ob das sonderlich viel bringt, dürfte von den Shadern abhängen. Aber vielleicht wird das auch klarer, wenn Du Dein KSKB hinbekommen hast.

Viele Grüße
Fancy
 

Ähnliche Java Themen

Neue Themen


Oben