Bu, Matriks Tidak Diperlukan
(enkimute.github.io)- Ini adalah eksperimen untuk menerapkan Euclidean PGA secara menyeluruh pada forward renderer yang kompatibel dengan glTF, sebagai pengganti matriks 4x4 yang selama ini digunakan hampir seperti kebiasaan dalam grafika 3D
- Rotasi dan translasi direpresentasikan dengan PGA motor berisi 8 float, dan komposisi motor umum diproses dengan 48 perkalian dan 40 penjumlahan, lebih sedikit daripada perkalian matriks 4x4 yang membutuhkan 64 perkalian dan 48 penjumlahan
- Transformasi titik lebih mahal daripada matriks jika diekspansi secara langsung, tetapi dengan sandwich product yang memanfaatkan kondisi normalisasi, biayanya dapat dikurangi menjadi 21 perkalian dan 18 penjumlahan; transformasi arah dan arah basis bahkan lebih murah
- Dalam tangent space normal mapping, normal dan tangent diganti dengan tangentRotor, sehingga data vertex berkurang dari 12 float menjadi 9 float, sementara biaya transformasi world-space juga disesuaikan ke kisaran 47 perkalian dan 38 penjumlahan, mirip dengan metode matriks
- Agar dapat bekerja dengan konten glTF nyata, matriks perlu diubah menjadi motor saat pemuatan, uniform scale harus dilacak sebagai float terpisah, dan non-uniform scale memerlukan penanganan terbatas atau jalur pengganti berbasis matriks 4x4
Forward Renderer Tanpa Matriks yang Dibuat dengan PGA
- Proyek ini bernama Look, Ma, No Matrices, dengan tujuan mengimplementasikan forward renderer tanpa matriks
- Setelah SIGGRAPH 2019, Geometric Algebra, khususnya Euclidean PGA, mendapat perhatian dari komunitas grafika dan machine learning, tetapi dalam grafika 3D tradisional banyak kasus hanya berhenti pada menyebut ulang dual quaternion sebagai PGA motor
- Implementasi ini mengintegrasikan PGA algebra ke dalam engine 3D yang kompatibel dengan glTF, bukan sekadar mengganti nama aljabar, melainkan menyusun ulang berbagai bagian pipeline grafika dengan pendekatan PGA
- Implementasi acuannya adalah Khronos glTF viewer, dan ini lebih dekat ke eksperimen untuk mengganti matriks tanpa kompromi daripada implementasi performa optimal
- Pada akhirnya, kemungkinan besar hybrid solution akan menjadi pilihan yang lebih baik
Alasan Meragukan Matriks 4x4
- Matriks 4x4 telah lama memainkan peran sentral dalam API grafika dan pipeline fixed-function GPU, dan masih menjadi alat dasar dalam forward rendering umum
- GPU modern makin menyerupai prosesor skalar yang dapat diprogram daripada pipeline fixed-function, sehingga representasi yang berpusat pada matriks tidak selalu diperlukan
- Dalam engine 3D nyata, banyak matriks sebenarnya adalah matriks ortogonal yang hanya memuat rotasi dan translasi
- Manifold PGA motor merepresentasikan seluruh Euclidean motion dengan biaya komputasi dan memori yang lebih rendah, serta dapat mencakup quaternion dan dual quaternion tanpa konversi
Representasi Data PGA dan Operasi Dasar
- PGA algebra dibangkitkan dari empat vektor basis
e0hinggae3e1,e2,e3masing-masing bersesuaian dengan bidangx=0,y=0,z=0- Vektor degenerate khusus
e0merepresentasikan bidang di tak hingga
- Di shader, tipe bawaan GLSL digunakan untuk memanfaatkan penjumlahan, pengurangan, dan perkalian skalar tanpa operator overloading
motor mat2x4line mat2x3point vec3direction vec3
- Komposisi PGA motor umum dilakukan dengan geometric product
- Perkalian matriks 4x4: 64 perkalian, 48 penjumlahan
- Komposisi motor umum
gp_mm: 48 perkalian, 40 penjumlahan
- Pada kombinasi transformasi khusus, operasi yang lebih murah dimungkinkan
gp_rr: 16 perkalian, 12 penjumlahangp_tt: 0 perkalian, 3 penjumlahangp_rt/gp_tr: 12 perkalian, 8 penjumlahangp_rm/gp_mr: 32 perkalian, 24 penjumlahangp_tm/gp_mt: 12 perkalian, 12 penjumlahan
Optimasi Transformasi Titik dan Arah
- Dalam PGA, saat mengubah titik
pdengan motorM, digunakan sandwich productM p M̃ - Ekspansi langsung membutuhkan 33 perkalian dan 29 penjumlahan, lebih besar daripada perkalian matriks-vektor yang membutuhkan 16 perkalian dan 12 penjumlahan
- Dengan memanfaatkan fakta bahwa motor ternormalisasi memenuhi
M M̃ = 1, rumusnya dapat diubah sehingga transformasi titik berkurang menjadi 21 perkalian dan 18 penjumlahan - Arah, yaitu titik di tak hingga, lebih murah karena koefisien implied
e123bernilai 0- Transformasi arah umum: 18 perkalian, 12 penjumlahan
- Transformasi basis direction, misalnya transformasi sumbu x, dapat diturunkan hingga 6 perkalian dan 4 penjumlahan
- Optimasi basis direction ini kemudian menjadi dasar yang menggoyahkan anggapan bahwa matriks selalu paling cepat dalam pemrosesan tangent frame
Normalisasi, Akar Kuadrat, serta Peta Eksponensial dan Logaritma
- Squared pseudonorm dari PGA motor berbentuk Study Number
M M̃ = a + b e0123 - Normalisasi bukan sekadar normalisasi vektor, melainkan prosedur yang memastikan motor hasilnya menjadi orthonormal transformation
- Biaya implementasi normalisasi motor umum: 21 perkalian, 5 penjumlahan
- Untuk translation atau rotation murni, versi yang lebih efisien dapat digunakan
- Rigid transformation antara dua titik, dua garis, atau dua bidang
a,bdirepresentasikan sebagaiM = sqrt(b / a)- Geometric product
bauntuk dua elemen berjenis sama menghasilkan motor yang setara dengan dua kali transformasi dariakeb sqrt M = normalize(1 + M)dapat digunakan untuk menghitungnya
- Geometric product
- Logarithm dari PGA motor adalah scaled line, dan scaled line dapat menghasilkan motor rotasi melalui exponentiation
- Exponential map dari matriks 4x4 umum mahal secara numerik, tetapi pada manifold PGA motor, closed form yang efisien dimungkinkan
Invers dan Factorization Motor
- Geometric Algebra dapat menghitung invers objek ternormalisasi secara efisien
- plane inverse: dirinya sendiri
- line inverse: pembalikan tanda
- point inverse: pembalikan tanda
- motor inverse: reversion
- Ketika bivector umum tidak memenuhi Plücker condition sehingga tidak merepresentasikan satu line, invers dihitung menggunakan Study Number inverse
- Implementasi rendering menggunakan dua jenis factorization
- Euclidean factorization: menguraikan motor menjadi rotation di sekitar origin lalu translation
- Invariant factorization: menguraikan motor menjadi translation dan rotation yang saling commuting; di 3D bentuk ini dikenal sebagai Mozzi-Chasles theorem
- Saat mengomposisikan tangent frame dan object-to-world motor, Euclidean factorization berguna karena sifat frame yang invariant terhadap translation
Penanganan Matriks glTF dan Scale
- Agar interoperabel dengan konten glTF yang sudah ada, matriks harus dikonversi menjadi PGA motor pada saat pemuatan
- Matriks ortogonal 4x4 dikonversi menjadi motor dengan memanfaatkan isomorfisme dengan quaternion
- Semua matrix dan transformation yang diimpor dikonversi saat load time
- PGA motor menangani rigid body transformation, sehingga tidak mencakup scaling
- Uniform scaling bersifat invariant terhadap rotation dan translation, sehingga dilacak sebagai satu float per node
- Total scale setiap elemen dihitung sebagai hasil kali scale miliknya dan scale parent
- Total scale diterapkan pada vertex saat load time atau pada tahap pertama vertex shader
- Parent scale diterapkan pada translation saat load time dan ketika animation update
- Dari sampel sekitar 400 file glTF acak, kasus dengan scale animation kurang dari 0,5%, sementara fixed uniform scale cukup banyak ditemukan
- Non-uniform scaling lebih rumit karena tidak invariant terhadap rotation
- Penanganan non-uniform scale secara umum tidak dapat menghindari jalur pengganti berbasis matrix 4x4
- Dalam sampel glTF, ditemukan kasus non-uniform scale hanya diterapkan pada leaf node; dalam kasus ini scale diterapkan secara terpisah sebelum transformasi lainnya, tanpa memengaruhi animation key
Pengganti Model-View-Projection
- Forward renderer mengubah mesh geometry dari object space ke screen space, lalu menentukan pixel yang dicakup oleh setiap triangle
- Dari model, view, dan projection matrix pada pipeline umum, model dan view diganti dengan PGA motor
- Vertex position menggunakan
sw_mp - Arah normal dan tangent menggunakan
sw_md
- Vertex position menggunakan
- Projection matrix umumnya hanya memiliki 5 entry non-zero, sehingga tidak dipaksakan diubah ke PGA dan digunakan projection expression secara langsung
- Pembaruan hierarchy scene graph di sisi CPU menggunakan komposisi motor alih-alih komposisi matrix, sehingga jumlah komputasi berkurang
- Transformasi vertex di sisi GPU tampak merugikan motor jika hanya dibandingkan secara sederhana, tetapi hasilnya berubah ketika representasi tangent frame diganti
Optimasi Tangent Space Normal Mapping
- Vertex shader untuk mesh tangent space normal-mapped umum harus mentransformasi position, normal, dan tangent
- Normal, tangent, dan bitangent membentuk orthonormal frame, sehingga dalam PGA dapat direpresentasikan sebagai tangentRotor yang membawa canonical basis frame ke tangent frame yang diinginkan
- Pendekatan ini mengurangi vertex descriptor
- Konvensional: position 3 + normal 3 + tangent 4 + uv 2 = 12 floats
- Pendekatan PGA: position 3 + tangentRotor 4 + uv 2 = 9 floats
- Jumlah float per vertex berkurang 25%
- tangentRotor memiliki double cover, dan sign dari scalar coefficient disesuaikan dengan classical handedness flag untuk membedakan even/odd k-reflection
- Bergantung pada signed zero, dan handedness diekstrak di vertex shader dengan
sign(1/tangentRotor.x)
- Bergantung pada signed zero, dan handedness diekstrak di vertex shader dengan
- Jika position, normal, dan tangent ditransformasi dengan matrix 4x4, totalnya membutuhkan 48 perkalian dan 36 penjumlahan
- Pendekatan PGA mengubah seluruh tangent frame sekaligus, lalu mengekstrak normal dan tangent
- Komposisi tangent frame: 16 perkalian, 12 penjumlahan
- Ekstraksi normal/tangent: 9 perkalian, 8 penjumlahan
- Transformasi position: 21 perkalian, 18 penjumlahan
- 1 perkalian untuk ekstraksi handedness
- Total 47 perkalian, 38 penjumlahan
- Biaya transformasi vertex hampir sama dengan metode matriks, sementara penyimpanan transform berkurang dari 32 floats menjadi 8 floats
Fragment Shader dan Batasan Baked Texture
- Untuk memuat konten yang sudah ada, pada tahap fragment shader tetap diperlukan TBN matrix
- Baking tool membuat tangent space normal texture dengan menginterpolasi vertex normal dan tangent di atas triangle face selama proses membakar high-detail mesh ke low-detail mesh, lalu membentuk matrix TBN ortogonal pada setiap fragment
- Interpolasi basis vector menimbulkan error khas metode matriks, dan error itu sudah baked ke dalam texture
- Karena itu, implementasi ini mengekstrak normal dan tangent vector secara eksplisit dari tangentRotor
- Jika baking tool juga dapat dikendalikan, tangentRotor dapat diteruskan apa adanya ke fragment shader, lalu dinormalisasi dan digunakan untuk transformasi sampled normal
- Tidak perlu membuat TBN matrix
- Ekstraksi normal/tangent di vertex shader tidak diperlukan
- Satu varying parameter dapat dikurangi
- Orthogonalization yang mahal di fragment shader juga dapat dihapus
Motor Skinning dan Animation Blending
- PGA motor isomorfik dengan dual quaternion, sehingga dapat diterapkan secara alami pada skinning
- Setelah inverse bind matrix dikonversi menjadi motor, bone motor di-blend dengan pola yang sama seperti dual quaternion skinning
- Transformation yang di-blend diselaraskan tandanya agar mengikuti shortest arc, lalu transformation hasilnya dinormalisasi kembali
- Animation blending juga dilakukan dengan cara yang sama: PGA motor di-blend langsung di CPU, lalu dinormalisasi
Hasil Eksperimen Pengganti Matriks
- Implementasi yang mengganti matriks sepenuhnya dengan PGA dalam forward renderer kompatibel glTF terbukti memungkinkan
- Perkiraan bahwa biaya transformasi akan lebih mahal menjadi tidak sesederhana itu setelah representasi tangent frame dan optimasi sandwich product diterapkan
- Pada kasus umum tangent space normal mapping, metode PGA motor mempertahankan biaya vertex shader hampir sama dengan metode matriks sambil secara signifikan mengurangi jejak memori vertex
- Peningkatan memori yang memungkinkan penyimpanan sekitar 33% lebih banyak vertices dalam storage yang sama menjadi keuntungan yang sangat besar
- Teknik ini dapat diterapkan pada engine 3D yang sudah ada sebagai drop-in replacement tanpa banyak menambah biaya vertex shader dan tanpa mengubah bagian pipeline lainnya
1 komentar
Komentar Hacker News
Salah satu kreator YouTube matematika/grafis favorit saya, Freya Holmér, beberapa waktu lalu membuat video pengantar aljabar geometri yang sangat bagus: https://www.youtube.com/watch?v=htYh-Tq7ZBI&ab_channel=Freya...
Jika Anda tertarik pada grafis 3D, khususnya spline/kurva Bézier, semua videonya layak ditonton
Secara pribadi, aljabar linear selalu terasa sulit bagi saya, tetapi pendekatan aljabar Clifford seperti ini terasa jauh lebih intuitif
Library ini dibuat oleh enkimute, penulis artikel asli, dan cukup mengagumkan: meski berupa skrip satu file tanpa build, ia menyediakan dukungan untuk aljabar N-dimensi dan rendering
Misalnya ada penjelasan yang cukup baik tentang bagian yang dilewati agak cepat atau dihilangkan oleh Freya, seperti ketidakkomutatifan perkalian
Aljabar geometri sempat benar-benar menjadi misteri bagi saya, tetapi akhirnya terbuka setelah memahaminya seperti ini: itu hanyalah perkalian polinomial, hanya saja ada besaran yang urutan perkaliannya penting dan tabel perkaliannya aneh. Misalnya
i*i = 1,i*j = -j*iSebagian besar materi pengantar membuat hasil kali geometri dari dua vektor
(x1*i + y1*j) * (x2*i + y2*j)tampak dalam dan misterius, tetapi sebenarnya sama seperti ekspansi FOIL yang dipelajari di aljabar mahasiswa baru:(x1*i + y1*i)(x2*i+y2*j) = x1*x2*i*i + x1*y2*i*j + y1*x2*j*i + y1*y2*j*j = (x1*x2 + y1*y2) + (x1*y2 - y2*x1)*i*jNilai dalam kurung pertama adalah hasil kali dalam yang sudah dikenal, sedangkan nilai dalam kurung kedua setara dengan hasil kali silang yang sudah dikenal, tetapi diekspresikan sebagai basis dimensi baru bernama
i*j. Dan tidak seperti hasil kali silang, ini dapat digeneralisasi ke dimensi arbitrer; dalam aljabar geometri ini disebut wedge productSetelah memahami ini, hal seperti penurunan rumus rotasi pun menjadi mudah. Sebab teknik yang dipelajari dalam aljabar bisa langsung diterapkan untuk memecahkan masalah geometri
Jika hasil perkalian sebuah vektor dengan dirinya sendiri didefinisikan sebagai kuadrat panjang vektor tersebut, sisanya semuanya mengikuti dari perkalian polinomial sederhana. Cukup indah
“Bagaimana cara kerjanya?” dan “Mengapa itu bekerja?” adalah dua pertanyaan yang harus diseimbangkan guru matematika, dan sulit untuk selalu menjawab keduanya dengan baik dalam satu mata kuliah
Hasil kali silang dua vektor 3 dimensi adalah vektor lain yang tegak lurus terhadap bidang yang dibentuk oleh kedua vektor tersebut. Sebaliknya, hasil kali aljabar eksterior adalah 2-vektor, yaitu bivector, yang menyapu jajaran genjang di antara kedua vektor dan berada pada bidang tempat kedua vektor itu berada. Dalam 3 dimensi, vektor hasil kali silang tegak lurus terhadap bidang bivector ini
Khususnya, untuk mendefinisikan hasil kali bilinear
m:V x V -> Vpada ruang vektorV, itu persis sama dengan menentukanmhanya untuk pasangan vektor basis. Kalau ini disebut “sifat universal dari hasil kali tensor”, mungkin orang hanya akan berkata “oh begitu”Untuk interpolasi rotasi, menarik bahwa ada berbagai pendekatan seperti aljabar geometri, quaternion, bahkan interpolasi seluruh matriks: https://www.gamedev.net/tutorials/programming/math-and-physi...
Namun setelah kodenya dioptimalkan secara manual, kode akhirnya hampir sama pada sebagian besar pendekatan. Perbedaannya ada pada bagaimana kita memahami aturan dan kemungkinannya
Sepanjang yang saya tahu, aljabar geometri tampak sebagai pendekatan yang paling konsisten dan mumpuni. Ia asing dan cukup berat untuk diterima pada awalnya, tetapi orang yang berhasil melewati hambatan itu menyukainya
Sebaliknya, semua orang memakai quaternion tetapi mengeluh tidak memahaminya, dan katanya perlu satu buku penuh untuk memvisualisasikannya. Misalnya buku 『Visualizing Quaternions』 karya Andrew J. Hanson dan Steve Cunningham
Aljabar geometri itu menyenangkan, quaternion tidak. Saya merasa memahami aljabar geometri, sedangkan untuk quaternion, meski mengikuti kuliah dan mengerjakan soal, yang jelas hanya bahwa saya tidak memahaminya. Sekarang setelah sedikit tahu aljabar geometri, akhirnya saya merasa sedikit memahami quaternion juga
https://www.goodreads.com/en/book/show/4419538
Jika tertarik pada topik ini, ada slide bagus yang mengulas konsep Grassman/Clifford/aljabar geometri: http://www.terathon.com/gdc12_lengyel.pdf
Ada juga situs bagus lainnya: https://mattferraro.dev/posts/geometric-algebra
Video luar biasa dari Sudgy, “A swift introduction to projective geometric algebra”, juga tidak boleh dilewatkan: https://www.youtube.com/watch?v=0i3ocLhbxJ4
Dan situs referensi utamanya adalah https://bivector.net
Anda juga bisa bergabung dengan Discord bivector yang beranggotakan lebih dari 1.000 profesor, peneliti, dan penggemar: https://discord.gg/vGY6pPk
Sejujurnya, saya kurang suka cara aljabar geometrik menghasilkan berbagai macam elemen campuran kalau kita tidak hati-hati soal apa yang dikalikan dengan apa
Fakta bahwa untuk sesuatu yang tadinya ruang berdimensi n bisa dibutuhkan hingga
2^nsuku juga terasa sulit ditanganiRasanya ia seharusnya bisa menangani geometri, yakni hasil kali dalam, dengan lebih baik, tetapi saya belum melihat penjelasan yang meyakinkan kenapa kita tidak cukup memakai hasil kali wedge dan operator bintang Hodge atau isomorfisme musikal
“Keajaiban” seperti mengubah bivektor
u^vmenjadi rotasie^(u^v)tpada bidang itu, pada dasarnya juga menggunakan isomorfisme musikal untuk mengubah 2-formu^vmenjadi automorfisme linear, sehinggae^(u^v)tdipahami sebagai eksponensial matriksContoh lain yang sering muncul adalah bahwa persamaan Maxwell bisa dijadikan satu persamaan, tetapi dengan bentuk diferensial kita sudah bisa meringkasnya menjadi dua persamaan yang berlaku karena alasan yang berbeda, jadi saya tidak paham manfaat menggabungkannya menjadi satu
2^nsuku” kadang merupakan ilusi penghematanMisalnya, vektor normal bertransformasi berbeda dari vektor posisi. Keduanya bisa direpresentasikan dengan struktur data yang sama, tetapi kita harus melacak jenis vektor apa yang ada di dalamnya dan memasukkan kasus-kasus khusus di berbagai bagian kode untuk menanganinya secara berbeda
Aljabar geometrik menghadapinya secara langsung: untuk vektor ia memakai basis
(i,j,k), dan untuk jenis lain ia memakai basis terpisah(j*k, k*i, i*j)Dalam arti bahwa satu persamaan lebih baik daripada dua atau empat, ini menjadi contoh bagus di mana ruang berdimensi lebih tinggi justru lebih ekonomis dari sisi penyimpanan dibanding ruang berdimensi lebih rendah
Medan listrik berbeda dari medan magnet dengan cara yang cukup mirip seperti vektor berbeda dari bivektor. Medan listrik dan medan magnet bisa ditangani sebagai kasus khusus dengan persamaan terpisah, atau bisa ditangani secara seragam dengan satu cara
Quaternion dengan
w=1, x,y,z=0adalah identitas, dan quaternion sepertiw=0, x=1atauw=0, x=y=0.7hanya sesuai dengan rotasi 180 derajatJika ingin rotasi sembarang, diperlukan kombinasi keduanya. Artinya mencampur “sedikit rotasi 180 derajat di sekitar garis ini, dan sedikit rotasi 0 derajat/identitas”. Inilah makna memiliki skalar dan bivektor sekaligus
Kalau Anda mencoba menghindari pencampuran “dengan hati-hati” memakai hasil kali wedge dan hasil kali dalam, berarti Anda menggunakannya secara keliru. Hasil kali geometrik adalah pemeran utamanya, dan ia menghasilkan pencampuran yang sangat bagus
Misalnya, jika menangani normal, Anda setidaknya harus melacak dua ruang berdimensi n yang bertransformasi cukup berbeda satu sama lain
Merepresentasikan titik, bidang, garis, normal, translasi, dan rotasi semuanya dengan satu tipe multivector dan aturan yang konsisten terasa cukup membebaskan setelah dipahami. Meski saya sendiri juga masih mempelajarinya
Interpolasi animasi di bagian bawah benar-benar keren, tetapi saya berharap model-model di bagian lain halaman itu sedikit kurang aktif
Matematika sudah cukup sulit tanpa pemandu sorak gajah kecil
Kalau penulisnya membaca ini, saya berharap singkatan PGA didefinisikan saat pertama kali dipakai
Ia menambahkan satu vektor basis nol ke vektor-vektor basis ruang tempat kita bekerja. Dengan begitu, objek geometris yang tidak melalui titik asal pun bisa direpresentasikan secara aljabar
Apakah algoritma seperti ini efisien bahkan jika mempertimbangkan GPU?
Saya punya kesan samar bahwa GPU sangat cocok untuk operasi matriks, jadi saya penasaran apakah dengan memakai formulasi aljabar geometrik kita kehilangan keunggulan itu dan pada praktiknya tidak benar-benar lebih unggul
Ini hanya dugaan dari ketidaktahuan, jadi silakan koreksi kalau saya salah
Pada kenyataannya, seluruh shader core sudah berupa SIMD, jadi hal itu tidak selalu bisa dilakukan. Sebagian GPU melakukannya, sebagian tidak
PGA memang cukup membebani untuk dipahami, tetapi merupakan cara yang sangat baik untuk menangani yang pertama. Bagaimanapun, biasanya lebih baik mencoba cara yang paling sederhana dan paling mudah diimplementasikan terlebih dahulu
Implementasi yang diperoleh dengan menyelesaikan yang pertama memakai PGA sudah cukup untuk membuat prototipe bagian program lainnya dan melakukan benchmark agar menemukan bottleneck yang sebenarnya. Untungnya, dalam kebanyakan kasus itu adalah metode perhitungan tercepat, atau cukup cepat sehingga tidak menjadi bottleneck
Bahkan jika menjadi bottleneck, ia memberi pemahaman mendalam tentang masalah yang ingin diselesaikan. Menurut saya lebih baik memiliki pemahaman itu sebelum mulai memangkas cycle dengan harapan membuatnya cukup cepat
Ini terlihat seperti pertarungan selisih tipis di ujung kemajuan
Fakta bahwa animasi skeletal 3D masih memakai matriks 4x4 di GPU berarti matematika yang dikembangkan untuk keperluan ini di CPU sekitar masa Half-Life 1 masih berada di garis depan. Dari 1998 sampai 2024, itu 26 tahun
Seribu tahun lagi pun animasi 3D akan tetap seperti itu
Tulisan ini di luar jangkauan pemahaman saya, tetapi judulnya mengingatkan pada eksperimen saat membuat renderer 3D sederhana
Setelah beberapa kali gagal mempelajari aljabar linear, saat mandi saya terpikir bahwa rotasi 3D hanyalah tiga rotasi 2D, dan itu sudah saya ketahui. Sekitar satu jam kemudian, saya sudah membuat renderer 3D wireframe lengkap dengan perspektif
Saya menyarankan semua orang untuk mencobanya