Diberi segitiga ▲ ABC, kami membagi dua sudut ∠BAC dengan garis AD, diturunkan dengan Teorema Sudut Bisektor :
BA / BD = CA / CD
Point E mewakili posisi objektif kami yang disempurnakan pada segitiga inset yang diinginkan. Karena terletak pada sudut garis-garis AD, ia berjarak sama dari sisi-sisi BA & CA, membentuk segitiga siku-siku yang identik ▲ AFE & ▲ AGE. Kita sekarang dapat menggunakan Sine untuk Segitiga Kanan untuk menemukan panjang AE:
AE = EG / Sin (∠EAG)
Itu semua matematika yang kita butuhkan, jadi mari kita memasak beberapa GLSL!
Kita mulai dengan semua atribut khas: posisi, normal, dan matriks transformasi, tetapi karena vertex shader hanya bekerja pada satu titik, kita perlu menambahkan simpul tetangga sebagai atribut tambahan. Dengan cara ini, setiap titik akan menemukan "titik E" sendiri, menciptakan segitiga inset yang dihasilkan. (Catatan: Saya tidak memanggil mereka "B" & "C" di sini, karena mereka belum di ruang layar .)
attribute vec3 left; //vertex to the left of this vertex
attribute vec3 right; //vertex to the right of this vertex
Berbicara tentang ruang layar, saya juga menyertakan rasio aspek tampilan, (dan menjadikannya seragam, jika jendelanya diubah ukurannya.)
Setelah menyiapkan berbagai normal untuk shader fragmen, dan mengubah wajah menjadi ruang kliping, kita bisa turun ke bisnis menerapkan matematika di atas:
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;
}
Kode ini memberi kita hasil di bawah ini.
Catatan, ada beberapa kasus tepi yang berkaitan dengan segitiga hampir -belakang-culled dibalik oleh proses ini, dan saya mulai membahas ini dalam kode, namun memutuskan untuk hanya menghindari kasus-kasus ini untuk saat ini. Mungkin saya akan mengunjungi lagi ketika saya menyelesaikan proyek ini.