Objekte Zeichnen, welche Teilweise hinter dem Betrachter liegen
-
Du kannst es im Prinzip in Augkoordinaten machen, ja, ist vermutlich die einfacher verständliche Variante; die Grafikkarte macht es in projektiven Koordinaten (daher auch der name "Clipspace" ;)).
-
im Prinzip beantwortest du hier schon deine frage
ve[2] /= ve[3]; // wenn z im Bereich [0 ; 1], dann ist Punkt sichtbar
alles was <0 (und eigentlich > ve[3]) ist nicht sichtbar -> clip gegen beides.
deine umrechnung in "fenster koordinaten" kannst du eigentlich auch als matrix aufbauen und zu den oberen matritzen dazu multiplizieren. Das clipping funzt dann weiterhin noch und es spart dir den code.
[ w/2, 0, 0, -w/2, 0, h/2, 0, -h/2, 0, 1, 0, 0, 0, 0, 0, 1}
-
Ich habe nun das Clipping in Homogenen Koordinatenraum wie hier beschrieben gemacht:
http://fabiensanglard.net/polygon_codec/
Ich musste diesen C++-Quelltext nach C# übersetzen und bin sehr froh, dass es in C# keine Zeigerarithmetik gibt.
Hier ist mein aktueller Stand:
http://fs1.directupload.net/images/150322/3oxli5du.jpg
An der rechten Wand sieht man, dass es noch ein Fehler gibt. Trotzdem ist das ganze schonmal besser als vorher.
Vielleicht hat ja jemand von euch noch eine Idee, wie ich im Debugger oder so vorgehen muss, um diesen Fehler zu finden.
Eine Sache fällt mir an diesen Algorithmus noch auf:
Dort steht ja folgende Zeile:
if (previousDot * currentDot < 0)
das bedeute ja, wenn ein Punkt vom Polygon im Sichtbereich ist, und der darauffolgende oder vorhergehende Punkt nicht, dann wird geclippt. Was passiert aber, wenn alle Punkte des Polygons außerhalb des Sichtbereichs sind man aber das Polygon trotzdem sieht: Beispiel: Ich stehe ganz nah vor einer Wand. Alle 4 Eckpunkte sind außerhalb des Bildschirms.
Wie muss ich da vorgehen?
-
XMAMan schrieb:
Ich musste diesen C++-Quelltext nach C# übersetzen und bin sehr froh, dass es in C# keine Zeigerarithmetik gibt
kann ich gut verstehen, wenn ich manchmal sourcen sehe, dann bluten mir die augen und dann denke ich dass man manchen leuten die meisten werkzeuge wegnehmen sollte und sie sich nur noch mit plastikloeffeln beschaeftigen duerfen sollten
Hier ist mein aktueller Stand:
schoen dass du immer screens postest, das schaut nach spass aus :). manche stellen (z.B. rand vom tisch oder stuhlbein) sehen noch aus als haettest du ein wenig was falsch.
An der rechten Wand sieht man, dass es noch ein Fehler gibt. Trotzdem ist das ganze schonmal besser als vorher.
manchmal verwechseln manche ob wie z oder w clippen bzw auf <0 testen. check deinen source, vielleicht ist das der fehler
Vielleicht hat ja jemand von euch noch eine Idee, wie ich im Debugger oder so vorgehen muss, um diesen Fehler zu finden.
find das poly und step durch das clipping. wenn es ein 3d model ist das du laedst, loesch in deinem 3d editor einfach alle anderen triangles raus zu debug zwecken.
Eine Sache fällt mir an diesen Algorithmus noch auf:
Dort steht ja folgende Zeile:
if (previousDot * currentDot < 0)
das bedeute ja, wenn ein Punkt vom Polygon im Sichtbereich ist, und der darauffolgende oder vorhergehende Punkt nicht, dann wird geclippt. Was passiert aber, wenn alle Punkte des Polygons außerhalb des Sichtbereichs sind man aber das Polygon trotzdem sieht: Beispiel: Ich stehe ganz nah vor einer Wand. Alle 4 Eckpunkte sind außerhalb des Bildschirms.
Wie muss ich da vorgehen?
du clippst alle edges immer nur gegen ein seite/ebene und wenn dort alle punkte ausserhalb sind, dann schneidet nichts die ebene und ist somit raus.
-
Ich habe den Fehler gefunden.
Er lag in dieser Zeile hier:
intersectionFactor = (W_CLIPPING_PLANE - previousVertice.W) / (previousVertice.W - currentVertice.W);
So muss aber korrekter Weise so lauten:
intersectionFactor = (/*W_CLIPPING_PLANE -*/ previousVertice.W) / (previousVertice.W - currentVertice.W);
Der Autor von dieser Seite hier
http://fabiensanglard.net/polygon_codec/
Hat nicht direkt an der w=0 (z-Near-Ebene) geklippt sondern er wollte an der
w=0.00001-Ebene clippen, um eine Division durch 0 zu verhindern. Dummerweise hat er durch die oben genannte Zeile das Vorzeichen von previousVertice.W damit umgedreht. Hätte er stattdessen:
previousVertice.W - W_CLIPPING_PLANE
geschrieben, dann wäre das vermultlich auch OK gewesen.
Seis drum. Hier ist nun das Ergebnis von zwei Testscenen.
http://fs1.directupload.net/images/150323/39d3arza.jpg
@Rapso: Du sagtest, ich soll mich mit Texturfiltern und Antialiasing auseinder setzen. So... die Szene mit den Linien ist meine Textur-Filter-Testszene.
Ganz Rechts siehst du, wie DirectX11 Anisotroph filtert. Ich will jetzt Bilinear, Trilinear und ein Anisothropen Filter für mein CPU-Renderer und mein Raytracer implementieren. Deswegen musste vorher das Clipping gemacht werden, damit die Testszene überhaupt sichtbar ist.
Warum ist die Textur ganz hinten bei DirectX immer noch falsch? Hat der Filter eine Grenze?
So stelle ich ihn ein:
SamplerState samAnisotropic { Filter = ANISOTROPIC; MaxAnisotropy = 4; AddressU = WRAP; AddressV = WRAP; };
Ich habe es auch schon mit MaxAnisotropy = 16 probiert. Hat aber kein Unterschied gebracht.
Eine Frage noch:
Texturfilter machen die Textur schärfer
Antialiasing macht die Kanten von 3D-Objekten weicherHab ich das so richtig verstanden?
Wenn ja, dann sind Texturfilter doch viel wichtiger. Kennst du ein Beispiel, wo man die Wichtigkeit von Antialiasing sieht?
Das hier überzeugt mich nun nicht gerade:
http://media.indiedb.com/images/games/1/7/6034/AAcomp.jpg
Das Texturfilter-Beispiel find ich wiederum super hier:
-
XMAMan schrieb:
Warum ist die Textur ganz hinten bei DirectX immer noch falsch? Hat der Filter eine Grenze?
Jap, dein Stichwort lautet Mip-Mapping...
-
@dot
Versteh ich nicht ganz.
Die Mip-Maps gehen doch normalerweise runter bis auf 1x1 Pixel.
Dann müsste doch hinten alles schön einheitlich grau sein.Oder meinst du dass das Problem ist dass hier eben keine Mip-Maps verwendet wurden?
-
Ich habe das Anisotrophe Filtern so verstanden, dass man einfach nur den Farbwert des Footprints
http://de.wikipedia.org/wiki/Footprint_Assembly
Möglichst genau berechnen muss. Um so mehr Taps (Rechtecke, die man da rein legt) man nimmt, um so genauer wird also integriert.
Mip-Mapping ist lediglich ein Beschleunigungstrick, um N*N-Texel zu Addieren. Oder was will uns der Herr Dot hiermit sagen?
-
XMAMan schrieb:
Möglichst genau berechnen muss. Um so mehr Taps (Rechtecke, die man da rein legt) man nimmt, um so genauer wird also integriert.
Die Taps sind punktuelle Samples.
Und wenn man punktuelle Samples mit regelmässigen Abständen aus einem regelmässigen Muster nimmt, dann bekommt man eben manchmal solche Artefakte.Klar, wenn du unendlich viele Taps hättest, dann bräuchtest du kein Mip-Mapping mehr.
16 Taps sind da aber einfach viel zu wenig.
-
XMAMan schrieb:
Ich habe den Fehler gefunden.
Er lag in dieser Zeile hier:
intersectionFactor = (W_CLIPPING_PLANE - previousVertice.W) / (previousVertice.W - currentVertice.W);
So muss aber korrekter Weise so lauten:
intersectionFactor = (/*W_CLIPPING_PLANE -*/ previousVertice.W) / (previousVertice.W - currentVertice.W);
rapso schrieb:
manchmal verwechseln manche ob wie z oder w clippen bzw auf <0 testen. check deinen source, vielleicht ist das der fehler
wie gedacht.
Der Autor von dieser Seite hier
http://fabiensanglard.net/polygon_codec/
Hat nicht direkt an der w=0 (z-Near-Ebene) geklippt sondern er wollte an der
w=0.00001-Ebene clippen, um eine Division durch 0 zu verhindern. Dummerweise hat er durch die oben genannte Zeile das Vorzeichen von previousVertice.W damit umgedreht. Hätte er stattdessen:
previousVertice.W - W_CLIPPING_PLANE
geschrieben, dann wäre das vermultlich auch OK gewesen.
bitte nicht so.
du musst z clippen. gegen w clippen ist unsinn.@Rapso: Du sagtest, ich soll mich mit Texturfiltern und Antialiasing auseinder setzen. So... die Szene mit den Linien ist meine Textur-Filter-Testszene.
Ganz Rechts siehst du, wie DirectX11 Anisotroph filtert. Ich will jetzt Bilinear, Trilinear und ein Anisothropen Filter für mein CPU-Renderer und mein Raytracer implementieren. Deswegen musste vorher das Clipping gemacht werden, damit die Testszene überhaupt sichtbar ist.
Warum ist die Textur ganz hinten bei DirectX immer noch falsch? Hat der Filter eine Grenze?
ja, die grenze ist bei aktueller hardware meist 16 samples.
wenn du also eine 256x256 texture auf 1x1 pixel zeichnest, dann wird die hardware nur 16:65536 -> 1:4096 samples machen. eindeutig nicht genug. in software kannst du das natuerlich besser machen und da du eh tausende samples/pixel fuer deinen tracer gemacht hattest, haettest du mit leichtem jittern das aliasing problem der texturen und von der geometrie zugleich loesen koennen.
mipmaps sind an sich nur eine performance optimierung fuers anisotropische filtering (jedenfalls wurden sie damals aus diesem grund 'erfunden'). du kannst entweder 256x256 samples nehmen oder 1x1 aus der mipmap.
SamplerState samAnisotropic { Filter = ANISOTROPIC; MaxAnisotropy = 4; AddressU = WRAP; AddressV = WRAP; };
MaxAnisotropy ist das limit von dem wir sprechen.
Ich habe es auch schon mit MaxAnisotropy = 16 probiert. Hat aber kein Unterschied gebracht.
doch, hat es, aber es ist nicht die welt. du sieht lediglich dass die grenze wo noise anfaengt ein wenig nachhinten verschoben wird.
du musst fuer echtzeit dinge mipmaps verwenden.
Eine Frage noch:
Texturfilter machen die Textur schärfernicht wirklich, es kommt auf den filter an. bilinear und trilinear macht texturen eigentlich eher matschiger, aber gut angewendet vermeidest du halt texture aliasing und gerade bei bewegung siehst es dann besser aus als flimmern.
es gibt einen mipmap bias mit dem du die selektion der mipmap einstellen kannst, dann hast du die moeglichkeit es pixeliger oder vermatschter zu machen.Antialiasing macht die Kanten von 3D-Objekten weicher
weiche wuerde ich nicht sagen, eher "definierter". wenn du ein schachbrettmuster auf einem pixel hast, welche farbe sollte der pixel sein? schwarz? weiss? ... unter den meisten gesichtspunkten wuerde man eigentlich eine art grau erwarten.
Wenn ja, dann sind Texturfilter doch viel wichtiger. Kennst du ein Beispiel, wo man die Wichtigkeit von Antialiasing sieht?
Das hier überzeugt mich nun nicht gerade:
http://media.indiedb.com/images/games/1/7/6034/AAcomp.jpg
Das Texturfilter-Beispiel find ich wiederum super hier:
Es ist beides dasselbe.
Was ist eine textur? es ist eine platz sparende art und weise geometrische details abzulegen.
du kannst ein schachbrettmuster haben indem du schwarz-weisse quads nebeneinander anordnest, du kannst aber auch eine textur dafuer nutzen.
machst du ein sample pro pixel (bzw samplest immer an derselben stelle pro pixel), wird sowohl die geometrische loesung wie auch die textur loesung das gleiche bild liefern. samplest du nun pro pixel viele male an verschiedenen stellen, werden beide loesungen ebenfalls dasselbe bild liefern.. ala
http://http.developer.nvidia.com/GPUGems/elementLinks/fig25-01a.jpgwieviel antialiasing noetig ist haengt vom rauschen ab. dabei ist das rauschen fuer ein bild nicht sonderlich wichtig, viel wichtiger (weil viel mehr bemerkbar) ist das bei bewegung.
bei pixar regeln das graphiker pro szene, manchmal sind es nur 5x5 samples, manchmal 33x33 samples.