Wie gehe ich mit Schnittpunkten um, die näher am Auge liegen als die nahe Schnittebene?

13

Ich rolle meine eigene 3D-Engine in JavaScript und verwende nur Zeichenfläche, kein WebGL. Dies ist ein weiterer Minecraft-Klon. Ich liebe Kisten, verurteile mich nicht.

Bisher funktioniert alles wunderbar, bis auf eines: Wenn in 3D einige Scheitelpunkte hinter der nahen Schnittebene liegen, kommt ihre Projektion auf dem Bildschirm merkwürdig heraus (vorausgesetzt, andere Scheitelpunkte, die zum Verfolgen einer Ebene verwendet werden, sind vorne).

Ich habe versucht, diese Punkte auszuschneiden, aber dann kann ich durch die Oberflächen sehen, die diese Scheitelpunkte verwenden. In WebGL / OpenGL kümmert sich die Grafikkarte um diese Punkte und die Ebene wird korrekt gerendert, aber ich habe keinen Zugriff auf Hardware, daher muss ich diese selbst codieren.

Ich bin mir nicht ganz sicher, was ich davon halten soll. Derzeit ist das letzte, was mir in den Sinn gekommen ist, die Projektion von Punkten hinter der Clipping-Ebene des Spielers umzukehren, was logisch erscheint, da ich einen Punkt auf einen Bildschirm projizieren muss, der vor mir liegt des Scheitelpunkts.

Hier sind meine Gedanken:

Bildbeschreibung hier eingeben

Hier sind einige Bilder, die veranschaulichen, was passiert:

Bildbeschreibung hier eingeben

Aus der Ferne macht sich die blaue Box perfekt.

Bildbeschreibung hier eingeben

Wenn einige der Scheitelpunkte hinter der nahen Clipping-Ebene des Players liegen, mache ich eine Umkehrprojektion, aber es sieht nicht richtig aus:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

Beachten Sie, dass das graue Feld dahinter vollständig entfernt ist, da sich alle zum Zeichnen der Gesichter verwendeten Scheitelpunkte hinter dem Player befinden.

Bildbeschreibung hier eingeben

Dies ist, was passiert, wenn Sie nach oben oder unten schauen.

Ich weiß nicht, was ich mit der Mathematik dahinter anfangen soll. Ich hoffe, jemand hat bereits das gleiche Problem und kann mir helfen.

Magnet
quelle
1
Wenn die Punkte näher am Auge liegen als in der Nähe der Clip-Ebene, sollten sie abgeschnitten werden. Dadurch können Sie in der Tat ein Objekt "durchschauen". Dies ist das typische Verhalten. Kollision verhindert normalerweise dieses bestimmte visuelle Artefakt. War das die einzige Sache, die mit Ihrer Ausschnittlösung falsch ist?
@JoshPetrie: Ich verstehe, dass die Punkte abgeschnitten werden müssen, aber wenn ich das tue, verschwindet das ganze Quadrat, da ein oder zwei der Eckpunkte fehlen, durch die die Zeichenroutine verlaufen muss (in 2d) und der Spieler sehen kann durch diesen Platz. Ich möchte, dass sie sich "außerhalb" der Leinwand befinden (auf der Projektion), damit das Quadrat noch gezeichnet werden kann. Ich bin mir nicht sicher, ob ich klar genug bin.
Solenoid
Sie sind - ich sage, das ist normal und Sie möchten dies verhindern, indem Sie verhindern , dass der Spieler so nah an einen der Würfel kommt. Wenn Sie dies wirklich wollten, sollten Sie die Dreiecke (möglicherweise) ausschneiden, aber rekonstruieren. Dies wird immer noch ungewöhnlich aussehen, insbesondere wenn Sie Texturen haben. Wenn das, was ich sage, keinen Sinn ergibt, kannst du uns im Chat beitreten, damit wir keinen wirklich gesprächigen Kommentarthread erstellen.
Was Sie sagen, ist sinnvoll. Die Rekonstruktion dauert zu lange. Das ist also nicht die Lösung. Ich hoffte, dass es eine Möglichkeit gab, den Scheitelpunkt in der 2d-Ebene , der sich hinter dem Player befand, zu zeichnen, sodass die lineTo(x,y)Funktion weiterhin aufgerufen werden konnte. Ich weiß nur nicht, wie sie sich verhält. Es ist eine bizarre Dimension, da stimme ich zu.
Solenoid

Antworten:

1

Der Zweck der Near-Clipping-Ebene ist, dass es sich um eine Clipping-Ebene handelt . Dreiecke, die sich außerhalb einer Schnittebene befinden, werden geschnitten : Schneiden Sie sie so in Stücke, dass sich jedes verbleibende Stück innerhalb des Schnittbereichs befindet.

Sie können versuchen, den Near-Clip zu ignorieren, wenn Sie dies wünschen. In der Tat haben OpenGL und D3D Möglichkeiten, das Abschneiden in der Nähe von Ebenen zu deaktivieren (obwohl der Tiefenpuffer immer noch einen minimalen Nahwert hat). Das Problem ist nicht der nahe Clip.

Das Problem sind Scheitelpunkte, die sich hinter der Kamera befinden.

Sie können keine Dreiecke rendern, die sich hinter der Kamera befinden. Nicht mit einer perspektivischen Projektion. Solche Dreiecke sind unter den mathematischen Gesichtspunkten hinter perspektivischen Projektionen nicht sinnvoll. Darüber hinaus befinden sie sich auch außerhalb des Kegelstumpfes.

Beim Ausschalten in der Nähe von Ausschnitten wird ein Kegelstumpf zu einer Pyramide. Der Grund, warum die Pyramide an dem Punkt anhält, liegt darin, dass sich Punkte über der Pyramide hinter allen vier Seiten der Pyramide befinden. Jeder Punkt hinter der Kamera (die Spitze der Pyramide) befindet sich oberhalb, unterhalb, links und rechts des sichtbaren Bereichs des Bildschirms. Alles zur selben Zeit.

Wie gesagt: Scheitelpunkte unter einer perspektivischen Projektion, die sich hinter der Kamera befinden, ergeben keinen Sinn.

Sie müssen Clipping implementieren. Sie müssen feststellen, wann sich ein Scheitelpunkt eines Dreiecks im Clip-Raum ( vor der perspektivischen Unterteilung) hinter der Kamera befindet. Wenn dies der Fall ist, müssen Sie dieses Dreieck abschneiden und nur Dreiecke erzeugen, die sich vor der Kamera befinden.

Dies ist kein einfacher Prozess. Es handelt sich um Mathematik, die nur Sinn macht, wenn Sie die homogenen Koordinatensysteme vollständig verstehen. Alternativ können Sie jedes Dreieck auch direkt nach oben ziehen, wenn sich ein Scheitelpunkt hinter der Kamera befindet.

Nicol Bolas
quelle
Bis jetzt habe ich das ganze Dreieck ausgesucht, aber dann habe ich das Flugzeug durchgesehen (siehe Bilder oben). Ich brauchte wirklich ein Bild, um zu verstehen, warum es geometrisch keinen Sinn ergibt. Die einzige Lösung besteht darin, den Schnittpunkt zwischen Ebenen und Linien zu berechnen, wenn einer der Scheitelpunkte hinter der Schnittebene liegt, und diesen Schnittpunkt zu verwenden, um die Linie vom vorderen Scheitelpunkt aus zu verfolgen. Leider ist dies teuer.
Solenoid
0

Wenn ein Teil des Dreiecks hinter der nahen Ebene liegt, können Sie dann pro Pixel prüfen, ob die Pixelposition hinter der Beschneidungsebene liegt?

Sie können die nahe Ebene wie jede andere Schnittebene behandeln. Zum Beispiel werden Schnittebenen für Dinge wie Wasserflugzeuge (für Reflexionen und Refraktionen) verwendet. Ich würde denken, dass diese Beschneidungsebene genau wie die nahe Beschneidungsebene funktioniert und auf Pixelbasis beschneidet.

Ich weiß, wie man Clipping-Ebenen in HLSL mit DirectX handhabt, aber ihre Implementierung könnte proprietär sein. Wenn Sie sich die Informationen dafür besorgen könnten, wäre dies möglicherweise hilfreich.

Außerdem finden Sie hier einen Link, der Ihnen helfen könnte: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html

Nic Foster
quelle
Das Testen von Pixeln ist in einer interpretierten Sprache wie Javascript extrem teuer. Ich erhalte derzeit kaum akzeptable fps.
Solenoid