Wie gehe ich mit einer parametrischen Gleichung beim Raytracing um?

7

Nachdem ich mir den Mobius-Streifen angesehen hatte , bemerkte ich, dass seine Gleichung wirklich einfach ist und versuchte, ihn meinem Raytracer hinzuzufügen.

Ich habe einen "naiven" Weg versucht, indem ich einfach Naneinander befestigte Dreiecke erzeugt habe, um die gewünschte Form zu erhalten. Während dieser Ansatz funktioniert, ist das Ergebnis nicht wirklich hübsch:

IMG

(Übrigens habe ich wahrscheinlich ein Problem mit meinen Normalen, aber ich weiß nicht, woher es kommt.)

Ich habe es mit PovRay versucht und das Ergebnis war erstaunlich. Perfekt glatter Streifen, hergestellt in einer weitaus kürzeren Zeit als meiner. Ich bin mir ziemlich sicher, dass Povray gut optimiert ist, aber ich denke auch, dass es keine Dreiecke wie ich erzeugen wird.

Povray

Falls dies hilfreich sein könnte, finden Sie hier den tatsächlich verwendeten Code (C ++):

float step = .1f;
float halW = 0.5f;

_facets.clear();

auto lambda = [this] (float v, float t) {
  Vec_t p;

  float cdv = Tools::Cos(2 * v);
  float sdv = Tools::Sin(2 * v);
  float ctv = Tools::Cos(v);
  float stv = Tools::Sin(v);

  float c = 2 + t * ctv;

  p.x = c * cdv;
  p.z = c * sdv;
  p.y = t * stv;

  return p;
};

for (float v = 0.f; v < Globals::PI; v += step)
{
  if (v > Globals::PI)
    v = Globals::PI;

  for (float t = -halW; t < halW; t += step)
  {
    if (t > halW)
      t = halW;

    Vec3 p1 = lambda(v, t);
    Vec3 p2 = lambda(v + step, t);
    Vec3 p3 = lambda(v, t + step);
    Vec3 p4 = lambda(v + step, t + step);
    _facets.emplace_back(p1, p2, p3);
    _facets.emplace_back(p3, p2, p4);
  }
}

TL; DR

Wie kann ich beim Raytracing mit parametrischen Oberflächen wie dieser umgehen ?

Bearbeiten Nachdem ich den obigen Algorithmus etwa 20 Stunden lang laufen ließ, erhielt ich ein viel schöneres Ergebnis (mit 3 Torsionen anstelle von 1).

Besseres Ergebnis

Telokis
quelle
Für das im ersten Bild rot umrandete Problem müssen Sie möglicherweise überprüfen, auf welche Seite der Oberfläche Sie sich nähern, bevor Sie entscheiden, in welche Richtung die Normalen zeigen sollen. Andernfalls werden einige Bereiche falsch schattiert. Dies zeigt sich insbesondere bei einem Möbius-Streifen, da es einen Punkt geben muss, an dem die Normalen aufgrund der Verdrehung die Richtung wechseln. Es müssen einige benachbarte Dreiecke vorhanden sein, die fast entgegengesetzte normale Richtungen haben (wie die hellen und dunklen benachbarten Dreiecke im Bild).
Trichoplax
Ja, das habe ich auch gedacht, aber ich setze ein isInsideFlag in der Dreieckskreuzungsmethode. Wenn es wahr ist, negiere ich den normalen Vektor. Das Flag wird gesetzt, wenn det < 0eine Schnittmethode verwendet wird, an die ich mich
momentan
Ich benutze den Möller-Trumbore-Schnittalgorithmus
Telokis

Antworten:

6

Vor vielen Jahren habe ich an einem Raytracer gearbeitet, der parametrische Oberflächen handhabt, daher ist dies wahrscheinlich nicht der Stand der Technik, aber IIRC habe ich eine Kombination aus Intervallarithmetik mit (binärer?) Unterteilung und Newton-Rhapson verwendet.

Die Intervallarithmetik + Unterteilung konstruierte (konservative) Begrenzungsrahmen, die zur Schnittpunktunterdrückung verwendet werden könnten. Ich glaube, ich habe möglicherweise auch Intervallarithmetik für die 1. Ableitung verwendet, um festzustellen, wann der Start in Newton-Rhapson sicher war. Typischerweise konvergierten die Newton-Schritte sehr schnell.

Sie können Ihre parametrischen Oberflächen auch vorab in Würfel schneiden und in eine Beschleunigungsstruktur (Voxel-Gitter / BVH) einfügen, um den Prozess zu beschleunigen.

Diese Arbeit basiert auf / inspiriert von Daniel Toths 1985er Arbeit "On Ray Tracing Parametric Surfaces".

Simon F.
quelle
Danke für die Antwort, aber ich muss zugeben, dass ich nicht alles verstehe. Könnten Sie ein konkretes Beispiel oder einen konkreten Code angeben, damit ich bitte nicht klarer sehen kann?
Telokis
OK. Ich habe heute keine Zeit, werde aber versuchen, bald weitere Informationen hinzuzufügen (ish).
Simon F
Was Sie vorschlagen, ist, dass ich weiterhin meine Methode zum Konstruieren von Dreiecken verwende, aber dass ich einen räumlichen Unterteilungsalgorithmus verwenden sollte, um die Berechnung zu "beschleunigen"?
Telokis
Es scheint mir, dass Sie zwei grundlegende Optionen haben, obwohl beide in gewisser Hinsicht zu einem "äquivalenten" Ergebnis konvergieren können: (a) Intervallarithmetik, um Regionen auszusortieren, gefolgt von Newton-Rhapson, um nach dem Strahlschnittpunkt zu suchen, oder (b ) Würfeln (dh tessellieren) Sie Ihr Objekt in "ausreichend kleine" Dreiecke, sodass Sie keine Diskontinuitätsartefakte sehen (wie in Ihrem ersten Bild). In gewissem Sinne sind diese "ähnlich", da in (a) jede Newton-R-Iteration die Oberfläche lokal als Ebene (wie ein kleines Dreieck) approximiert. Ich vermute, dass b viel einfacher zu implementieren ist, aber schwierig, das ideale Unterteilungsniveau abzuschätzen.
Simon F
2

Wenn Sie in einem Ray Tracer parametrisch arbeiten, benötigen Sie im Allgemeinen eine Lösung für

{P.=vt+C.P.=f(u,v)

für die niedrigsten t wo f(u,v) ist Ihre parametrische Funktion C. ist die Kameraposition und v ist die Strahlrichtung.

Es gibt einige allgemeine Möglichkeiten. Wenn Sie beispielsweise feststellen können, ob sich 2 Punkte auf derselben Seite befinden oder nicht, können Sie 2 Punkte auf dem Strahl auf gegenüberliegenden Seiten nehmen und binär suchen, bis Sie die Tiefe erreicht haben. Sie können das erste Paar finden, indem Sie entlang des Strahls marschieren.

Ratschenfreak
quelle
Was meinst du mit "der gleichen Seite"? Ich kenne die allgemeine Idee, wie es geht, aber ich weiß nicht, wie es in der Praxis passiert. Povray liefert ein so genaues und hübsches Ergebnis, dass ich nicht verstehe, wie es das möglicherweise kann.
Telokis