PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OGL: Schnell(st)er Geometrietransfer


ph
2004-03-01, 12:41:21
Hiho,

Ich habe einen (durchgehenden) Strip mit 66.000 Vertices den ich mit DrawElements() rendere, wobei die Indexliste 132.000 Elemente hat. Spaßhalber habe ich das ganze auf DrawArrays() umgeschrieben, also 132.000 Vertices und keine Indices.

Und siehe da: Über einen 25 sek. testzeitraum habe ich mit DrawElements() 3100 frames (124 fps), mit DraArrays() 5400 (216 fps)! Das ist eine Steigerung um 75%!
Wie kann denn sowas sein?

Gibt es eventuell eine methode wie das ganze noch schneller geht? Alles was mit Indizes zu tun hat fällt ja offensichtlich weg, (warum eigentlich? vermutlich weil der treiber bei indizierter geometrie im Vertexbuffer kreuz und quer herumspringen muss, während bei DrawArrays kann er sich schön linear durchsaugen. Meine Schlußfolgerung.) bleibt noch MultiDrawArrays(), InterleavedArrays() und das Vertex Buffer Object-Dingi.
Was davon nimmt man am besten? Und gibt es wirklich keine Möglichkeit indizierte Geometrie schneller zur Graka zu senden?

MfG

micki
2004-03-01, 13:27:04
du hat mehrere stellen die du optimieren kannst.

1. grakas können nur 16bit indicies benutzen, also sind 65536 vertices das limit. wenn du 32bit nutzt, wird es per treiber umgestellt.
2. lokalität ist auch ein bisschen wichtig, dafür sortiert man die vertices normalerweise dann auch, bringt aber nur ein paar %.
3. indizes sind um einiges schneller als unindizierter geometri, eine graka hat einen cache für trasformierte vertices, den nutzt sie nur wenn indizes verwendet werden, der cache ist 16 einträge gross bei TnL karten und 24 einträge für vertexshader karten, wobei man 3 abziehen muss, weil diese einträge gerade geschrieben werden (die TnL einheit steht ja nicht still wenn der rasterizer aus dem cache vetices ließt).

das beantwortet deine frage jetzt nicht wirklich, weil es den geometrietransfer vom ram in die graka nicht beschleunigt, aber vielleicht ist deine frage auch nicht genau genug gestellt ;o) :
4. du kannst vertexbuffer objects benutzen, dabei werden die vertices ins ram der graka geschoben und die hollt sich die dann wenn nötig. das ist meißtens viel schneller als der AGP bus und wohl die einzige möglichkeit wie du an das transformierlimit der graka kommst.

wobei ich es gut finde dass du 28.512 MVertices durchgeschoben bekommst, wären ja immerhin 340MB (bei 3floats/vertex).

MfG
micki

zeckensack
2004-03-01, 13:30:47
Original geschrieben von ph
Hiho,

Ich habe einen (durchgehenden) Strip mit 66.000 Vertices den ich mit DrawElements() rendere, wobei die Indexliste 132.000 Elemente hat. Spaßhalber habe ich das ganze auf DrawArrays() umgeschrieben, also 132.000 Vertices und keine Indices.Das kann schonmal nicht stimmen :)
Ein Strip mit 66000 vertices kommt mit exakt 66000 Indizes aus. Das Index-Array sollte dabei linear aufsteigend alle Zahlen von 0 bis 65999 enthalten.
Auch bei DrawArrays kann da was nicht stimmen. Den strip kannst du so rendern:
glDrawArrays(GL_TRIANGLE_STRIP,0,66000);
Wie du hier auf 132000 kommst, will mir nicht einleuchten.

Würdest du den Strip in einzelne Dreiecke zerlegen (geht nur mit Indizes), hättest du nachher 65998 Dreiecke und 197994 Indizes. Das kann's also auch nicht sein.

Ich vermute mal, du hast falsch gemessen :)

Und siehe da: Über einen 25 sek. testzeitraum habe ich mit DrawElements() 3100 frames (124 fps), mit DraArrays() 5400 (216 fps)! Das ist eine Steigerung um 75%!
Wie kann denn sowas sein?

Gibt es eventuell eine methode wie das ganze noch schneller geht? Alles was mit Indizes zu tun hat fällt ja offensichtlich weg, (warum eigentlich? vermutlich weil der treiber bei indizierter geometrie im Vertexbuffer kreuz und quer herumspringen muss, während bei DrawArrays kann er sich schön linear durchsaugen. Meine Schlußfolgerung.) bleibt noch MultiDrawArrays(), InterleavedArrays() und das Vertex Buffer Object-Dingi.
Was davon nimmt man am besten? Und gibt es wirklich keine Möglichkeit indizierte Geometrie schneller zur Graka zu senden?

MfG Indizes kosten selbst im Optimalfall (linear aufsteigend) Bandbreite. Wenn möglich, sollte man sie sich schenken. Und ja, "verstreute" Indizes senken die effektive Bandbreite zwischen AGP/Grafik-Speicher und dem Chip (bursts ahoi).

Eine zumeist schnellere Variante von glDrawElements ist glDrawRangeElementsEXT.
Bei glMultDrawArrays konnte ich bisher weder bei ATI noch bei NV irgendeinen Performance-Gewinn feststellen.

InterleavedArrays ist ja nur eine Abkürzung für die Spezifikation des Vertex-Layouts, man kann die exakt gleiche Funktionalität auch mit den gl*Pointer- und den gl{Enable|Disable}ClientState-Funktionen erreichen.
Aber grundsätzlich ja, ein verschachteltes Vertex-Layout ist in 99% der Fälle besser.

VBO ist dagegen nur ein Container für Geometrie. Es ist natürlich schwer zu empfehlen das zu benutzen (ist auch auf einigen Software-T&L-Karten verfügbar und durchaus sinnvoll). VBO definiert btw auch einen Container für Index-Arrays, das kannst du mal ausprobieren.

Eine weitere (sehr alte) Möglichkeit sind display lists. Dabei kann man aber so dermassen viel falsch machen, dass ich das nicht grundsätzlich empfehlen kann.

Noch was:
Viele Karten (uA alle Geforces <=Geforce 4Ti) "mögen" keine UNSIGNED_INTs als Indizes. Sie sind nur mit UNSIGNED_SHORT wirklich schnell. Wenn du ein Umbauen der Index-Arrays innerhalb des Treibers aus deinen Messungen heraushalten willst, solltest du UNSIGNED_SHORT benutzen (wobei du natürlich maximal das Element #65535 adressieren kannst).
In "echten" Anwendungen lohnt das nicht, aber um den "besten" Transfermodus zu ermitteln, sollte man das schon machen.

ph
2004-03-01, 13:53:31
Original geschrieben von zeckensack
Das kann schonmal nicht stimmen :)
Ein Strip mit 66000 vertices kommt mit exakt 66000 Indizes aus. Das Index-Array sollte dabei linear aufsteigend alle Zahlen von 0 bis 65999 enthalten.
Auch bei DrawArrays kann da was nicht stimmen. Den strip kannst du so rendern:
glDrawArrays(GL_TRIANGLE_STRIP,0,66000);
Wie du hier auf 132000 kommst, will mir nicht einleuchten.


Um aus den Vertices den Strip zu formen muss ich in meinem Fall einige (ok: fast jeden) Vertex doppelt verwenden. Dann gibts noch degenerierte beim um die Ecke biegen...Aber ich habe das ganze natürlich falsch formuliert: Ich habe 66.000 Vertices, und aus diesen mache ich einen Strip mit 132.000 Elementen. So müsstes stimmen :)

Original geschrieben von zeckensack
Würdest du den Strip in einzelne Dreiecke zerlegen (geht nur mit Indizes), hättest du nachher 65998 Dreiecke und 197994 Indizes. Das kann's also auch nicht sein.

Ich vermute mal, du hast falsch gemessen :)

s.o.

Original geschrieben von zeckensack
Indizes kosten selbst im Optimalfall (linear aufsteigend) Bandbreite. Wenn möglich, sollte man sie sich schenken. Und ja, "verstreute" Indizes senken die effektive Bandbreite zwischen AGP/Grafik-Speicher und dem Chip (bursts ahoi).

Eine zumeist schnellere Variante von glDrawElements ist glDrawRangeElementsEXT.
Bei glMultDrawArrays konnte ich bisher weder bei ATI noch bei NV irgendeinen Performance-Gewinn feststellen.

InterleavedArrays ist ja nur eine Abkürzung für die Spezifikation des Vertex-Layouts, man kann die exakt gleiche Funktionalität auch mit den gl*Pointer- und den gl{Enable|Disable}ClientState-Funktionen erreichen.
Aber grundsätzlich ja, ein verschachteltes Vertex-Layout ist in 99% der Fälle besser.

Ich vermute mit "sich schenken" meinst du "pfeif auf indizes, wozu gibts DrawArrays", ja? :)

Hö? Wieso ist denn verschachteltes Layout auf einmal besser?
Ansonsten danke für die Erlärungen.
Original geschrieben von zeckensack
VBO ist dagegen nur ein Container für Geometrie. Es ist natürlich schwer zu empfehlen das zu benutzen (ist auch auf einigen Software-T&L-Karten verfügbar und durchaus sinnvoll). VBO definiert btw auch einen Container für Index-Arrays, das kannst du mal ausprobieren.

Eine weitere (sehr alte) Möglichkeit sind display lists. Dabei kann man aber so dermassen viel falsch machen, dass ich das nicht grundsätzlich empfehlen kann.

Noch was:
Viele Karten (uA alle Geforces <=Geforce 4Ti) "mögen" keine UNSIGNED_INTs als Indizes. Sie sind nur mit UNSIGNED_SHORT wirklich schnell. Wenn du ein Umbauen der Index-Arrays innerhalb des Treibers aus deinen Messungen heraushalten willst, solltest du UNSIGNED_SHORT benutzen (wobei du natürlich maximal das Element #65535 adressieren kannst).
In "echten" Anwendungen lohnt das nicht, aber um den "besten" Transfermodus zu ermitteln, sollte man das schon machen.

Ja, den VBO werd ich mir mal anlachen...
Haben ATI Karten (R300) auch diese "Abneigung" gegen UnsignedInts? Woher kommt dieses höchst eigentümliche Verhalten?

MfG

ph
2004-03-01, 14:02:15
Original geschrieben von micki
du hat mehrere stellen die du optimieren kannst.

1. grakas können nur 16bit indicies benutzen, also sind 65536 vertices das limit. wenn du 32bit nutzt, wird es per treiber umgestellt.
2. lokalität ist auch ein bisschen wichtig, dafür sortiert man die vertices normalerweise dann auch, bringt aber nur ein paar %.
3. indizes sind um einiges schneller als unindizierter geometri, eine graka hat einen cache für trasformierte vertices, den nutzt sie nur wenn indizes verwendet werden, der cache ist 16 einträge gross bei TnL karten und 24 einträge für vertexshader karten, wobei man 3 abziehen muss, weil diese einträge gerade geschrieben werden (die TnL einheit steht ja nicht still wenn der rasterizer aus dem cache vetices ließt).

4. du kannst vertexbuffer objects benutzen, dabei werden die vertices ins ram der graka geschoben und die hollt sich die dann wenn nötig. das ist meißtens viel schneller als der AGP bus und wohl die einzige möglichkeit wie du an das transformierlimit der graka kommst.

wobei ich es gut finde dass du 28.512 MVertices durchgeschoben bekommst, wären ja immerhin 340MB (bei 3floats/vertex).

MfG
micki

1. Das mit den 16-32 bit erklärt vermutlich die "Abneigung" gegen unsigned_ints, die zeckensack erwähnt hat.

3. Wieso sind denn Indizes jetzt schneller? Es kann sein dass du mit "unindizierter Geometrie" was anderes meinst als ich aber bei mir waren die Indices langsamer.

das beantwortet deine frage jetzt nicht wirklich, ... aber vielleicht ist deine frage auch nicht genau genug gestellt ;o) :

Alles was ich hier lese hilft mir weiter, auch dir ein Dankeschön :)


MfG

zeckensack
2004-03-01, 14:23:58
Micki und ich sind uns wohl nicht ganz einig, was die Indizes betrifft.

Wenn du deinen Strip um die Ecke faltest, also tatsächlich Elemente wiederholst, dann sind Indizes gut. In deinem Fall wäre es so, dass du - wenn du die Indizes weglassen würdest - vertices doppelt speichern müsstest. Das ist natürlich noch schlechter als "unnütze" Indizes, also einfach so lassen.

Wo ich Micki wiedersprechen muss, ist die Sache mit dem PTVC. Wenn man strips und fans zeichnet, kann der Chip die bereits transformierten vertices auch ohne Indizes aus dem Cache fischen. Das zeigen jedenfalls meine eigenen Messungen (auf NV20, R200, R300, RV280).

Warum die unsigned ints langsamer sind, ist wohl ein Betriebsgeheimnis ;)
Ich würde mal vermuten, dass hier ein paar Multiplikatoren im Speichercontroller des Chips nur mit 16 Bit-Inputs umgehen können.
Die finale Addresse für ein Vertex-Attribut errechnet sich aus

//vorgegeben durch gl*Pointer
int* base_pointer; //Beginn der Daten für dieses Attribut
int attrib_stride; //Entfernung "zwischen" den Elementen

int index=get_index(); //vorgegeben durch Index-Array
int* element_attrib; //wird gesucht


element_attrib=base_pointer+index*attrib_stride;



Ein verschachteltes Layout ist deswegen besser, weil der Chip nur einen "stream" linear durchackern muss, anstatt für jeden Vertex die Attribute von zwei (drei, vier, blablub) Positionen einzusammeln. Vielleicht verstehen wir uns auch nicht richtig, mit dem verschachtelten Layout meinte ich zB das, was man mit InterleavedArrays bekommt.


//interleaved
struct Vertex
{
float x,y,z;
ubyte r,g,b,a;
float s,t;
};

Vertex vertex_array[1024];
__________________________

//disjoint
struct Position
{
float x,y,z;
};
struct Texcoord
{
float s,t;
};
struct Color
{
ubyte r,g,b,a;
};

Position position_array[1024];
Texcoord texcoord_array[1024];
Color color_array[1024];

micki
2004-03-01, 14:55:43
[SIZE=1]Original geschrieben von zeckensack
Wo ich Micki wiedersprechen muss, ist die Sache mit dem PTVC. Wenn man strips und fans zeichnet, kann der Chip die bereits transformierten vertices auch ohne Indizes aus dem Cache fischen. Das zeigen jedenfalls meine eigenen Messungen (auf NV20, R200, R300, RV280).


du wiedersprichst nicht mir, sondern ati und nvidia, aus deren papern hab ich das. da stand dass nur bei indizierten vertices ein cachereuse festgestellt werden kann :-/

es ist aber selbsterklärend dass man bei einem reinem strip oder fan keine zusätzlichen vertices aus dem cache nutzt als eh schon durch diese besondere meshtopologie genutzt werden (im gegensatz zu GL_TRIANGLES bzw D3DTRIANGLELIST).

es ist aber selten der fall dass man nur ein riesen mesh zeichnet dass aus einem fan oder strip besteht, oft jedoch kommt es vor dass man viele kleine strips zeichnet, deswegen sollte man dann (laut NVIDIA), indizes nutzen um strips zu erzeugen die mit degenerierten vertices zusammengehalten werden. in dem paper stand zudem, dass die hardware die indizierten degenerierten triangles schon in der transformationsebene rauswirft, wogegen unindizierte strips noch durch den rasterizer laufen, was für indizies spricht.

wenn also die rechenleistung der limitierende factor ist, dann sollte man lieber cachoptimierte strips erzeugen die den transformationscache nutzen und mittels degenerierten polys zusammengehalten werden anstatt lange strips bei denen jedes neue vertex transformiert werden muss.

die 32 bit sind deswegen langsammer weil der treiber versucht diese auf 16bit umzustellen und wenn das trivial nicht möglich ist, dann wird ein normales trianglestrip daraus generiert.

MfG
micki

http://developer.nvidia.com/attach/3442 seite 22/25 ganz unten steht die nvidia behauptung sie würden nur mit indizes die caches nutzen... ich hab das noch irgendwo anders mal gelesen, aber so auf die schnelle nur das jetzt gefunden.

Matti
2004-03-01, 15:54:20
Original geschrieben von zeckensack
Eine weitere (sehr alte) Möglichkeit sind display lists. Dabei kann man aber so dermassen viel falsch machen, dass ich das nicht grundsätzlich empfehlen kann.

...was kann man denn falsch machen?? :kratz2:
Ich verwende nämlich gerne Display-Lists...

ph
2004-03-01, 18:08:07
Original geschrieben von micki
du wiedersprichst nicht mir, sondern ati und nvidia, aus deren papern hab ich das. da stand dass nur bei indizierten vertices ein cachereuse festgestellt werden kann :-/

es ist aber selbsterklärend dass man bei einem reinem strip oder fan keine zusätzlichen vertices aus dem cache nutzt als eh schon durch diese besondere meshtopologie genutzt werden (im gegensatz zu GL_TRIANGLES bzw D3DTRIANGLELIST).

es ist aber selten der fall dass man nur ein riesen mesh zeichnet dass aus einem fan oder strip besteht, oft jedoch kommt es vor dass man viele kleine strips zeichnet, deswegen sollte man dann (laut NVIDIA), indizes nutzen um strips zu erzeugen die mit degenerierten vertices zusammengehalten werden. in dem paper stand zudem, dass die hardware die indizierten degenerierten triangles schon in der transformationsebene rauswirft, wogegen unindizierte strips noch durch den rasterizer laufen, was für indizies spricht.

wenn also die rechenleistung der limitierende factor ist, dann sollte man lieber cachoptimierte strips erzeugen die den transformationscache nutzen und mittels degenerierten polys zusammengehalten werden anstatt lange strips bei denen jedes neue vertex transformiert werden muss.

die 32 bit sind deswegen langsammer weil der treiber versucht diese auf 16bit umzustellen und wenn das trivial nicht möglich ist, dann wird ein normales trianglestrip daraus generiert.

MfG
micki

http://developer.nvidia.com/attach/3442 seite 22/25 ganz unten steht die nvidia behauptung sie würden nur mit indizes die caches nutzen... ich hab das noch irgendwo anders mal gelesen, aber so auf die schnelle nur das jetzt gefunden.

Hm, bei mir ist genau das der Fall: Ich habe einen riesengroßen Mesh der aus einem einzigen Strip besteht. Und der limitierende Faktor sollte tatsächlich die rechenleistung sein, die Menge an Vertices ist groß genug und alles andere hab ich abgeschaltet.

Dass trotzdem die Lösung ohne Indizes signifikant schneller ist liegt whrscheinlich daran dass nur alle 600 Elemente ein degeneriertes poly vorkommt, d.h. der Nutzen aus dem Cachereuse trägt fast nichts zur Gesamtleistung bei. Ofensichtlich ist es wichtiger dass der Treiber das ganze Array linear durchrendern kann, als das er hin und wieder eine transformation durch den PostT&L Cache einspart.

MfG

ph
2004-03-01, 18:17:47
Original geschrieben von zeckensack
Warum die unsigned ints langsamer sind, ist wohl ein Betriebsgeheimnis ;)
Ich würde mal vermuten, dass hier ein paar Multiplikatoren im Speichercontroller des Chips nur mit 16 Bit-Inputs umgehen können.
Die finale Addresse für ein Vertex-Attribut errechnet sich aus

...


Ein verschachteltes Layout ist deswegen besser, weil der Chip nur einen "stream" linear durchackern muss, anstatt für jeden Vertex die Attribute von zwei (drei, vier, blablub) Positionen einzusammeln. Vielleicht verstehen wir uns auch nicht richtig, mit dem verschachtelten Layout meinte ich zB das, was man mit InterleavedArrays bekommt.


...


Ja das mit den verschachtelten Arrays ist mir klar. Mal sehen wieviel Mehrleistung das noch bringt.

Ansonsten:
Interessant. Danke sehr&copy

MfG :)

marco42
2004-03-02, 01:16:09
Original geschrieben von ph
Hm, bei mir ist genau das der Fall: Ich habe einen riesengroßen Mesh der aus einem einzigen Strip besteht. Und der limitierende Faktor sollte tatsächlich die rechenleistung sein, die Menge an Vertices ist groß genug und alles andere hab ich abgeschaltet.

Dass trotzdem die Lösung ohne Indizes signifikant schneller ist liegt whrscheinlich daran dass nur alle 600 Elemente ein degeneriertes poly vorkommt, d.h. der Nutzen aus dem Cachereuse trägt fast nichts zur Gesamtleistung bei. Ofensichtlich ist es wichtiger dass der Treiber das ganze Array linear durchrendern kann, als das er hin und wieder eine transformation durch den PostT&L Cache einspart.

MfG

Hast du mal versucht das umzuformen? NV hat da NVTriangleStrip. Waere interessant ob das was bringt. Ich habe das bisher nie gebraucht, da ich immer Fuellraten limitiert war.

marco42
2004-03-02, 01:18:55
Original geschrieben von zeckensack
VBO ist dagegen nur ein Container für Geometrie. Es ist natürlich schwer zu empfehlen das zu benutzen (ist auch auf einigen Software-T&L-Karten verfügbar und durchaus sinnvoll). VBO definiert btw auch einen Container für Index-Arrays, das kannst du mal ausprobieren.

Na, eigentlich ist es doch nur Speicher, irgendwo. Ich hoffe, es gibt bald PBO's. Ich frage mich sowieso, weshalb sie es nicht nur einfach Buffer Objects genannt haben.

ph
2004-03-02, 13:33:39
Original geschrieben von marco42
Hast du mal versucht das umzuformen? NV hat da NVTriangleStrip. Waere interessant ob das was bringt. Ich habe das bisher nie gebraucht, da ich immer Fuellraten limitiert war.

Indizes sind wohl in meinem Fall sowieso nicht die ideale Lösung denn ich habe nur alle 600 Elemente einen Index der wiederverwendet wird.

MfG

micki
2004-03-02, 19:00:35
du zeichnest nicht zufälilg ein terrain oder so?

MfG
micki

ph
2004-03-02, 21:26:31
Original geschrieben von micki
du zeichnest nicht zufälilg ein terrain oder so?

MfG
micki

Wie hast du das nur erraten? ;)

MfG

marco42
2004-03-04, 17:07:57
Original geschrieben von ph
Wie hast du das nur erraten? ;)

MfG

Aber da muesstest du doch eine massive Wiederverwendung von Punkten haben? Du benutzt doch triangle strips? Oder gehts du die linear durch?

ph
2004-03-04, 18:19:38
Original geschrieben von marco42
Aber da muesstest du doch eine massive Wiederverwendung von Punkten haben? Du benutzt doch triangle strips? Oder gehts du die linear durch?

Natürlich verwende ich jeden Vertex öfter, aber der Post T&L Cache ist viel zu klein. Im Durchschnitt kommt derselbe Vertex alle 300 250 Elemente vor. Nur alle 500 Elemente hab ich ein degenerate wo Indizes etwas bringen würden.

IIRC hat Demirug mal etwas von einer Cacheoptimierten Art das Terrain zu rendern erzählt, das ging ungefähr so:


--->|
v
<---- .
| .
v--->|>--.
||
<---v^--<
| |
v--->--->


Da würden Indizes wirklich etwas bringen. Aber einen Algorithmus dafür nmöchte ich mir nicht überlegen :D

MfG

marco42
2004-03-05, 03:37:10
Original geschrieben von ph
Natürlich verwende ich jeden Vertex öfter, aber der Post T&L Cache ist viel zu klein. Im Durchschnitt kommt derselbe Vertex alle 300 250 Elemente vor. Nur alle 500 Elemente hab ich ein degenerate wo Indizes etwas bringen würden.

IIRC hat Demirug mal etwas von einer Cacheoptimierten Art das Terrain zu rendern erzählt, das ging ungefähr so:


--->|
v
<---- .
| .
v--->|>--.
||
<---v^--<
| |
v--->--->


Da würden Indizes wirklich etwas bringen. Aber einen Algorithmus dafür nmöchte ich mir nicht überlegen :D

MfG

AFAIK macht das NVtriStrip oder schau mal in Real Time Rendering, da steht der Code drin, schoen erklaert. Bei NVtriStrip(ist eine C++ class) gibst du noch die Cache groesse an.

ph
2004-03-05, 21:03:43
Original geschrieben von marco42
AFAIK macht das NVtriStrip oder schau mal in Real Time Rendering, da steht der Code drin, schoen erklaert. Bei NVtriStrip(ist eine C++ class) gibst du noch die Cache groesse an.

Cachegröße angeben und das wars? :o
Kaum zu glauben.

Gibts das Real Time Rendering (ich nehm an das ist ein Buch) irgendwo zum "gratisnachschauen"?

MfG

marco42
2004-03-05, 22:30:42
Original geschrieben von ph
Cachegröße angeben und das wars? :o
Kaum zu glauben.

Gibts das Real Time Rendering (ich nehm an das ist ein Buch) irgendwo zum "gratisnachschauen"?

MfG

In deiner gut sortierten Uni Bibliothek? Nimma ber die zweite Auflage. Ansonst nein. Schau mal unter www.realtimerendering.com