Saya perlu mengimbangi semua segitiga (biru), masing-masing secara independen dari yang lain, menggunakan vertex-shader. Untuk memanipulasi segitiga secara keseluruhan, saya telah membuat atribut khusus (vec3) untuk setiap simpul (merah) yang mewakili simpul tetangga sebelah kiri (ungu) dan kanan (hijau). Dari ini, saya perlu menurunkan titik oranye, berjarak sama (dalam ruang layar ) dari kedua sisi yang berdampingan. Dengan tiga titik oranye tersebut berasal dari setiap segitiga, segitiga yang diproses (oranye) diteruskan ke shader fragmen.
Idealnya, segitiga akan dimusnahkan (seperti di backfacing / tidak diberikan) jika offset meniadakan ruang yang tersedia dalam segitiga, seperti pada segitiga kedua di gambar kedua.
Saya menggunakan THREE.BufferGeometry () sebagai struktur data saya.
Ini adalah cuplikan layar dari efek yang saya inginkan:
Jawaban:
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 .)
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:
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.
sumber
Ini dapat dicapai tanpa fungsi trigonometri dengan mengurangi incircle pada segitiga.
incircle()
menghitung incircle dari segitiga yang dibentuk oleh simpulA,B,C
, ia mengembalikan pusat dan jari-jari sebagaivec4
. VerteksX=A,B,C
kemudian dipindahkan ke dalam oleh fraksi jaraknya ke pusat incircle (Q-X
) yang sama dengan rasio margin yang diinginkan dengan radius incircle (m/Q.w
).sumber