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 .)
attribute vec3 left; //vertex to the left of this vertex
attribute vec3 right; //vertex to the right of this vertex
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:
attribute vec3 left; //vertex to the left of this vertex
attribute vec3 right; //vertex to the right of this vertex
uniform float aspect;
varying vec3 vNormal;
varying vec2 vUv;
void main() {
vNormal = normal;
vUv = uv;
mat4 xform= projectionMatrix * modelViewMatrix;
vec4 A = xform * vec4( position, 1.0 );
vec4 B = xform * vec4( left, 1.0 );
vec4 C = xform * vec4( right, 1.0 );
vec3 CB = C.xyz - B.xyz;
vec2 BA = B.xy - A.xy;
vec2 CA = C.xy - A.xy;
float lengthBA = length(BA);
float lengthCA = length(CA);
float ratio = lengthBA / ( lengthBA + lengthCA );
vec3 D = B.xyz + ratio * CB.xyz;
vec3 AD = D - A.xyz;
vec3 bisect = normalize(AD);
float theta = acos( dot(BA, CA) / (lengthBA * lengthCA) ) / 2.0;
float AE = 1.0/(sin(theta)*aspect);
newPos.z += AE/length(AD) * (D.z - A.z);
newPos.x += bisect.x*AE;
newPos.y += bisect.y*AE;
gl_Position = newPos;
}
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.