Ich muss alle (blauen) Dreiecke unabhängig voneinander mit dem Vertex-Shader versetzen. Um das Dreieck als Ganzes zu bearbeiten, habe ich benutzerdefinierte (vec3) Attribute für jeden Scheitelpunkt (rot) erstellt, der die nach links (lila) und rechts (grün) benachbarten Scheitelpunkte darstellt. Daraus muss ich den orangefarbenen Punkt in gleichem Abstand (im Bildschirmbereich ) von beiden angrenzenden Kanten ableiten . Mit drei solchen orangefarbenen Punkten, die von jedem Dreieck abgeleitet sind, wird das verarbeitete (orangefarbene) Dreieck an den Fragment-Shader weitergeleitet.
Im Idealfall wird das Dreieck ausgesondert (wie bei Backfacing / nicht gerendert), wenn die Offsets den verfügbaren Platz innerhalb des Dreiecks negieren, z. B. im zweiten Dreieck im zweiten Bild.
Ich verwende THREE.BufferGeometry () als meine Datenstruktur.
Hier ist ein Screenshot des Effekts, den ich anstrebe:
Antworten:
Wenn das Dreieck ▲ ABC gegeben ist, halbieren wir den Winkel ∠BAC mit der Linie AD, abgeleitet mit dem Satz der Winkelhalbierenden :
BA / BD = CA / CD Punkt E repräsentiert unsere objektiv verfeinerte Position auf dem gewünschten resultierenden eingefügten Dreieck. Da es auf der Winkelhalbierenden AD liegt, ist es von den Seiten BA und CA gleich weit entfernt und bildet identische rechtwinklige Dreiecke ▲ AFE & ▲ AGE. Wir können jetzt Sinus für rechte Dreiecke verwenden , um die Länge von AE zu ermitteln:
AE = EG / Sin (∠EAG)
Das ist alles, was wir brauchen, also lasst uns GLSL kochen!
Wir beginnen mit allen typischen Attributen: Positions-, Normal- und Transformationsmatrizen. Da der Scheitelpunkt-Shader jedoch nur für einen einzelnen Scheitelpunkt funktioniert, müssen wir die benachbarten Scheitelpunkte als zusätzliche Attribute hinzufügen. Auf diese Weise findet jeder Scheitelpunkt seinen eigenen "Punkt E", wodurch das resultierende eingefügte Dreieck erzeugt wird. (Hinweis: Ich nenne sie hier nicht "B" und "C", da sie sich noch nicht im Bildschirmbereich befinden .)
Apropos Bildschirmbereich, ich beziehe auch das Seitenverhältnis des Displays ein (und mache es einheitlich, falls die Fenstergröße geändert wird).
Nachdem wir verschiedene Normalen für den Fragment-Shader vorbereitet und das Gesicht in einen Clipping-Bereich umgewandelt haben, können wir uns der Anwendung der obigen Mathematik widmen:
Dieser Code gibt uns die folgenden Ergebnisse.
Beachten Sie, dass es einige Randfälle gibt, die damit zu tun haben, dass durch diesen Prozess fast rückseitig ausgesuchte Dreiecke umgedreht werden, und ich begann, dies im Code zu behandeln, entschied mich jedoch, diese Fälle vorerst einfach zu vermeiden. Vielleicht werde ich es noch einmal besuchen, wenn ich dieses Projekt fertig habe.
quelle
Dies kann ohne trigonometrische Funktionen erreicht werden , indem die Verkleinerung incircle des Dreiecks.
incircle()
berechnet den Kreis des durch die Eckpunkte gebildeten DreiecksA,B,C
und gibt Mittelpunkt und Radius als zurückvec4
. Die EckpunkteX=A,B,C
werden dann um den Bruchteil ihres Abstands zum Kreismittelpunkt (Q-X
) nach innen bewegt , der dem Verhältnis des gewünschten Randes zum Kreisradius (m/Q.w
) entspricht.quelle