3D Model Formatları · glTF / GLB · Dosya Yapısı
Accessor Mantığı: Ham Veriye Anlam Kazandırma
Dosya yapısı serisinde zincir şu ana kadar şöyle ilerledi: JSON yapısı sahneyi organize etti; binary buffer ham veriyi depoladı. Bu sayfa anatominin «aha!» noktasıdır buffer’ın içinde yalnızca baytlar varken, onların ne anlama geldiğini kim söyler?
Cevap: Accessor. Vertex attribute düzeni,
BufferAttribute API’si, geometri sayfaları, POSITION /
NORMAL / UV kanallarının detayı veya
bufferView dilimleme mekaniği bu sayfada
işlenmez
her biri ayrı konudur. Odak tek soruda: «Accessor, buffer’daki kör baytlara nasıl
anlam kazandırır?»
Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «Buffer’ın içinde sadece baytlar vardır; accessor, bu baytların ne anlama geldiğini söyleyen yorumlama katmanıdır.»
Accessor Nedir?
Accessor, glTF JSON’undaki accessors tablosunun bir
kaydıdır. Görevi veri taşımak değil veriyi okuma talimatı vermektir.
Binary buffer
kördür: içinde yalnızca ardışık baytlar vardır; dosyanın «ağır yükü» orada durur,
fakat o yükün ne olduğu buffer’ın işi değildir.
10110110 00111010 11100111 ...
Bu akışa bakınca doğal soru şudur: «Bu veri nedir?» Bir vertex koordinatı mı? Bir UV çifti mi? Animasyon zaman damgası mı? Üçgen indeksi mi? Buffer bu soruya cevap veremez cevap vermesi de beklenmez. Buffer depodur; accessor yorum rehberidir.
Talimat kaydı, veri kapsülü değil
Binary
buffer sayfasında buffer’ın «ham veri deposu» olduğunu gördük: gerçek sayılar orada,
sıkıştırılmış bayt blokları halinde. accessors tablosu ise tam tersi bir
karaktere sahiptir kayıtlar metin tabanlı JSON nesneleridir, içlerinde
float veya integer değer listesi taşımazlar. Bir accessor kaydı «şu kadar eleman var, her
eleman şu biçimde, şu bayt aralığından okunacak» gibi okuma kurallarını
yazar; kuralların uygulanacağı ham malzeme binary tarafta kalır.
Bu ayrımı kaçırmak sık karşılaşılan bir kafa karışıklığına yol açar: «Accessor position
verisini mi tutuyor?» Hayır position değerleri buffer’da; accessor yalnızca o
değerlerin nasıl okunacağını tarif eder. Dosyayı elle açtığınızda
accessors dizisinde gördüğünüz şey bir veri tablosu değil, loader’a verilen
talimat setidir.
Kör akış, açık soru
Buffer’ın bilmediği şeyler listesinde tip, eleman sayısı ve anlam yoktur yalnızca sürekli bir octet şeridi vardır. Aynı bayt dizisi, farklı yorumlama kurallarıyla farklı «şeyler» olabilir: bir blok mesh koordinatları, başka bir blok indeks listesi, üçüncüsü animasyon zaman damgaları. Buffer hepsini aynı biçimde saklar: ardışık bayt. Fark, dosyada accessor kayıtlarında tanımlanır.
Pratik sonuç: hex editörde veya bellek dökümünde gördüğünüz akış size «burada ne var?» sorusunu sormaya zorlar; cevap buffer’ın içinde değil, JSON’daki ilgili accessor kaydındadır. Bu sayfa tam olarak bu boşluğu doldurur buffer ile anlam arasındaki yorumlama katmanını tanımlar.
Primitive’in indeks dili
glTF organizasyonu indekslerle konuşur. Bir mesh primitive kaydı, kanallarını
doğrudan sayılarla değil, accessor numaralarıyla bağlar. Tipik bir ifade
şöyle okunur: «position için accessor #0, normal için accessor #1, indices için accessor
#2.» Buradaki 0, 1, 2 gerçek koordinat veya indeks değerleri değildir
accessors
dizisindeki sıra numaralarıdır, tıpkı materials veya
nodes tablolarına referans vermek gibi.
Loader bu numarayı görünce şunu yapar: «accessors[0] kaydını aç, oradaki
kurallara göre binary’den oku, sonucu bir sonraki pipeline adımına ilet.» Gerçek float veya
integer değerleri buffer’da durur; JSON tarafı yalnızca hangi talimatın hangi
amaçla çağrıldığını bağlar. Kanal adı (POSITION,
NORMAL
vb.) ile accessor’ın tarif ettiği veri biçimi bilinçli olarak ayrı yerlerde tutulur bu
ayrım 10. bölümde ayrıca
vurgulanır; burada yalnızca «sayılar organizasyon dilidir» noktası önemlidir.
Depo ile rehber: tek sorumluluk
İki katmanı yan yana düşünün:
- Buffer (depo): Bayt taşır; «içeride ne var?» sorusuna cevap vermez. JSON yapısı sayfasındaki «organizasyon vs ham veri» ayrımının sayısal uç noktasıdır.
- Accessor (rehber): Bayt taşımaz; «bu baytları nasıl okuyacağım?» sorusuna cevap verir. Talimat JSON’da kalır, uygulama binary okuma sırasında yapılır.
glTF bu ikisini birleştirmek yerine zincir halinde bağlar: önce organizasyon katmanı «şu accessor’ı kullan» der, accessor «şu kurallarla oku» der, buffer «işte baytlar» der. Kuralların kendisi JSON’da, uygulanacak malzeme binary’de bu bölünme formatın temel tasarım kararıdır ve sonraki bölümlerde «çevirmen» metaforu, anlam formülü ve loader pipeline’ı bu iskelet üzerine oturur.
Neden ayrı bir accessors
tablosu?
«Okuma kuralları zaten primitive içinde yazılamaz mı?» sorusu doğaldır. glTF bunu bilinçli
olarak ayırır çünkü aynı bayt bloğu birden fazla yerden farklı biçimlerde
okunabilir; ayrıca bir talimat seti tekrar kullanılabilir. Merkezi bir
accessors
dizisi, loader’a tek bir yerden «tüm yorumlama kayıtları burada» der indeks dili tutarlı
kalır, validasyon ve hata mesajları öngörülebilir olur.
Özet cümle: Buffer’da yalnızca baytlar vardır; accessor, bu baytların ne anlama geldiğini söyleyen yorumlama katmanının JSON’daki kayıtlarıdır. Bir sonraki bölümde bu talimat kaydının içinde hangi alanların bulunduğuna ve «çevirmen» metaforuna geçilir; bufferView dilimleme mekaniği ise bufferView sayfasında ele alınır.
Accessor Bir Veri Tercümanıdır
1. bölümde accessor’ın «talimat kaydı» olduğunu ve buffer’ın kör depo olduğunu gördük. Bu bölüm aynı fikri daha somut bir metaforla sabitler: accessor bir çevirmendir. Buffer tarafında ham bayt dizisi vardır «kaynak metin» gibi, anlamı kendi başına taşımaz; accessor tarafında «bu baytları şöyle oku» talimatı vardır «çeviri kuralları» gibi. Çevirmen orijinal metni taşımaz; okuma kurallarını taşır.
Metafor neden «çevirmen»?
glTF’de buffer ile accessor arasındaki ilişki, dil bilimindeki çeviriye benzer bir yapı kurar. Ham bayt akışı «yabancı dilde yazılmış metin» gibidir: karakterler (octet’ler) vardır, fakat okuyucu onları hangi gramerle parçalayacağını bilmeden anlamlı cümleler çıkaramaz. Accessor tam bu noktada devreye girer «her kelime üç heceli», «her hece float», «toplam 1024 kelime» gibi kurallar yazar. Kurallar uygulandığında kör bayt dizisi, loader’ın anlayabileceği yapılandırılmış bir okumaya dönüşür.
Diğer metaforlar da iş görür («rehber», «etiket», «gözlük»), fakat çevirmen özellikle şu yüzden sağlamdır: çevirmen kaynak metni kopyalamaz, onu yorumlar. glTF’de de accessor buffer’ı kopyalamaz binary veri olduğu yerde kalır; yalnızca «nasıl okunacağı» JSON’da tanımlanır. Bu, 7. bölümdeki «accessor kopya üretmez» fikrinin de temelidir.
İki taraf: ham malzeme ve okuma kuralı
Çevirmen metaforunu glTF katmanlarına oturtursak:
- Kaynak (buffer): Sürekli octet şeridi «metin» burada, fakat henüz parçalanmamış, tiplenmemiş, sayılmamış.
- Çeviri talimatı (accessor): «Kaç blok okuyacağım? Her blok kaç bileşen? Her bileşen hangi tip?» «gramer kitabı» burada.
- Çıktı (loader tarafı): Typed array veya eşdeğer yapı «hedef dilde okunabilir metin». Bu sayfanın dışında; burada yalnızca talimatın varlığı önemlidir.
Önemli sınır: accessor «kaynak metni» buffer’dan almak için
bufferView referansına ihtiyaç duyar çevirmenin eline hangi sayfaların
verileceğini söyleyen ara katman. Dilimleme mekaniği
bufferView
sayfasında; bu bölümde yalnızca «çevirmen tek başına metne ulaşamaz, önce doğru
sayfaları ister» notu yeterlidir.
Örnek kayıt: kuralların JSON’daki hali
Soyut metaforu somutlaştırmak için tipik bir accessor kaydına bakın. Alanların tam spec detayı ve WebGL eşlemesi bu sayfanın dışındadır; burada yalnızca «çevirmen ne tarif ediyor?» sorusu yanıtlanır:
{
"bufferView": 0,
"componentType": 5126,
"count": 1024,
"type": "VEC3"
}
Bu dört satır, loader’a şu «çeviri sözleşmesini» verir:
bufferView: 0«Kaynak metnin şu bölümünü al» (sayfa seçimi; mekanik ayrı konu).componentType: 5126«Her bileşeni float olarak oku» (tip kuralı).type: "VEC3"«Her mantıksal kayıt üç bileşenli bir vektör» (şekil kuralı).count: 1024«Bu kuralı 1024 kez tekrarla» (uzunluk kuralı).
Hepsi birleşince cümle şudur: «Seçilen bayt aralığından 1024 adet VEC3 float oku.» Loader artık buffer’a bakıp «bu position benzeri bir float×3 dizisi olabilir mi?» diye tahmin yürütmez accessor bunu açıkça tarif eder. Tahmin ile tarif arasındaki fark, 3. bölümde aynı baytların farklı yorumlarla farklı sayılara dönüşmesiyle somutlaştırılır.
Biçim tarifi, rol tarifi değil
Çevirmen metaforunda accessor «cümle yapısını» söyler, «konuyu» söylemez. Yukarıdaki kayıt
«1024 VEC3 float» der «position verisi» demez. Position, normal veya UV ayrımı mesh
primitive’inin attributes haritasında yapılır: aynı biçimdeki accessor farklı
kanal adlarıyla çağrılabilir. Bu bilinçli ayrım, veri biçiminin (shape) kullanım amacından
(role) kopmasını sağlar; detay
10. bölümde ve
4. bölümdeki tabloda ayrıca
vurgulanır.
Pratik sonuç: bir accessor kaydını okurken «bu ne işe yarıyor?» sorusunun cevabını kaydın kendisinde aramayın cevap, o kaydı çağıran JSON bağlamındadır (primitive, animation sampler vb.). Accessor yalnızca «nasıl okuyacağını» söyler; «neden okuduğunu» üst katman belirler.
Loader ile accessor arasındaki sözleşme
glTF spec’i accessor kayıtlarını, loader ile binary arasında standart bir okuma
sözleşmesi olarak tanımlar. Her uyumlu loader aynı kuralları uygular: aynı
componentType aynı byte genişliğini, aynı type aynı bileşen
sayısını, aynı count aynı eleman adedini garanti eder. Bu öngörülebilirlik,
farklı export araçlarından gelen dosyaların aynı okuma mantığıyla işlenmesini sağlar
çevirmen metaforunda «aynı gramer kitabı, farklı yazarların metinleri» gibi düşünülebilir.
Sözleşme ihlali örneğin count ile gerçek bayt uzunluğunun uyuşmaması
loader’ın hata vermesine veya geçersiz okumaya yol açar; accessor bu yüzden yalnızca
«yorum» değil, doğrulanabilir bir talimatdır. Bir sonraki bölüm, accessor
olmadan buffer’ın neden anlamsız kaldığını ve «veri + yorumlama = anlam» formülünü açar.
Accessor Olmadan Buffer Anlamsızdır
2. bölümde accessor’ın «çevirmen» olduğunu ve loader’ın tahmin yürütmeden okuduğunu gördük. Bu bölüm aynı fikrin sonucuna odaklanır: çevirmen yoksa metin yalnızca karakter yığınıdır buffer yalnızca octet yığınıdır. glTF’de anlam, binary’nin içine gömülü değildir; okuma anında accessor kuralları uygulanarak üretilir.
Dört bayt, sıfır anlam
Somut bir örnek: 00 00 80 3F. Hex editörde veya bellek dökümünde gördüğünüz
şey yalnızca dört ardışık octettir ne float ne integer ne koordinat
etiketi vardır. İnsan gözü «1.0 gibi duruyor» diyebilir; fakat bu sezgidir, dosyanın
taşıdığı bilgi değildir. Buffer seviyesinde kayıtlı olan tek gerçek: «byte0=0x00,
byte1=0x00, byte2=0x80, byte3=0x3F».
Binary buffer · buffer kördür ifadesinin bayt düzeyindeki kanıtı budur: depo doludur, etiket yoktur. Anlamı «içeriden» okumaya çalışmak, kapalı konteynerin ağırlığından yükün ne olduğunu çıkarmaya benzer mümkün değildir; plan (accessor) gelmeden yük «sadece ağırlık»tır.
Aynı veri, farklı anlam
Accessor devreye girince aynı dört bayt farklı sayılara dönüşebilir çünkü dönüşüm kuralı değişmiştir, baytlar değil:
- Accessor «tip: float, bileşen: 1 (
SCALAR)» derse okuyucu 1.0 float görür. - Farklı bir kayıt «tip: unsigned int, bileşen: 1» deseydi aynı octet’ler 1065353216 tamsayı olarak okunurdu.
Veri aynı, anlam farklı bu cümle glTF’nin buffer–accessor ayrımının özüdür. Yanlış accessor uygulanırsa sahne bozulur: koordinatlar anlamsız uç değerlere, indeksler geçersiz üçgenlere dönüşebilir; hata «baytların bozuk olmasından» değil, yanlış gözlükle bakılmasından kaynaklanır. Doğru yorumlama kuralının dosyada açık yazılması bu yüzden zorunludur.
Not: aynı bayt bloğu type değişince de farklı «şeyler» olur örneğin sekiz
bayt tek bir MAT2 matrisi veya iki ayrı VEC2 vektörü olarak
gruplanabilir. Parçalama kuralı accessor’dadır; buffer yalnızca ham malzemeyi sunar.
Anlam formülü: veri + yorumlama
Bu gözlemler tek bir formülde toplanır:
Veri + yorumlama = anlam
«Veri» tek başına anlamlı değildir; «yorumlama» tek başına uygulanacak malzemeye sahip değildir. İkisi birleştiğinde loader anlamlı bir yapı üretir typed array, indeks dizisi, animasyon örneği veya benzeri tüketilebilir girdi. Formüldeki üç terim glTF katmanlarına bire bir oturur:
- Veri → binary buffer (bayt havuzu). Veri havuzu sayfasında gördüğünüz gibi tek şerit halinde durur; içinde tip veya kanal adı yoktur.
- Yorumlama → accessor (+ bayt aralığını seçen bufferView dilimi dilimleme mekaniği bufferView sayfasında). Accessor «nasıl oku» der; bufferView «nereden oku» der ikisi birlikte gözlüğü takar.
- Anlam → loader’ın ürettiği typed array / geometri girdisi / animasyon örneği. Bu çıktının GPU veya sahne grafiğine nasıl bağlandığı geometry, pipeline ve vertex attribute sayfalarında; burada yalnızca «anlamın accessor uygulamasının ürünü olduğu» sabitlenir.
Anlam depolanmaz, türetilir
JSON’da «position = 1.0, 2.0, 3.0» satırları yazmak yerine glTF baytları buffer’a yazar, anlamı accessor ile okuma anında türetir. Bu tasarım kararı iki sonuç doğurur:
- Dosya boyutu: Milyonlarca float JSON’da metin olarak durmaz; yoğun binary + seyrek talimat kayıtları kalır.
- Tek kaynak: Aynı bayt bloğu birden fazla accessor ile farklı «gözlüklerden» okunabilir (6. bölüm); anlam kopyalanmaz, yorum tekrarlanır.
Binary buffer · anlam sonradan yüklenir bölümünde zincirin özeti verilmişti: JSON accessor sorar, accessor bufferView sorar, bufferView buffer’dan bayt getirir. Bu sayfanın vurgusu zincirin mekaniği değil zincir tamamlanmadan buffer’ın hiçbir halkasında anlam üretilememesi.
Demo paraleli: seçim = yorum
Binary
Memory Explorer demosunda buffer şeridinden bir segment seçtiğinizde küpün farklı
katmanları vurgulanır position, normal veya indeks «gibi» görünür. Fakat buffer’ın kendisi
hâlâ kördür: vurguyu sizin seçiminiz (yorum katmanınız) belirler.
Accessor Lens demosu aynı octet
bloğunu sabit tutup yalnızca accessor kuralını değiştirerek aynı dersi görselleştirir
tıpkı 00 00 80 3F örneğinde float 1.0 ile uint 1065353216 ayrımı gibi.
Gerçek glTF dosyasında yorum rastgele değildir her mantıksal veri parçası için spec uyumlu accessor kaydı vardır. İkisi de aynı sonuca varır: ham bayt tek başına sahne kurmaya yetmez.
Accessor olmadan ne kalır?
accessors dizisi boş veya eksik olsaydı loader elindeki buffer ile ne
yapacağını
bilemez: kaç byte bir eleman? Kaç eleman var? Float mı short mu? Primitive kayıtları
accessor indeksleri olmadan anlamsız referanslara dönüşür. Validasyon araçları bu durumu
yakalar; uyumlu loader’lar genelde erken hata verir.
Özet: buffer glTF’nin ham malzemesidir, accessor ise malzemeye anlam kazandıran zorunlu yorum katmanıdır. Bir sonraki bölüm, bu yorum katmanının loader’a hangi somut soruları yanıtladığını tablo halinde listeler.
Accessor Hangi Soruları Cevaplar?
3. bölümde «veri + yorumlama = anlam» formülünü gördük; yorumlama katmanının somut hali accessor kaydıdır. Loader binary’ye elini uzatmadan önce bir dizi yapılandırılmış soru sorar cevaplar accessor alanlarında yazar. Bu bölüm o soruları görev odaklı listeler: «loader bu kayıtla ne öğrenir?» Spec’teki tam enum listeleri, byteOffset/byteStride hesabı veya WebGL attribute eşlemesi burada işlenmez; amaç accessor’ın hangi boşlukları doldurduğunu netleştirmektir.
Okuma öncesi: buffer’a dokunmadan
Ham bayt akışına doğrudan bakmak, tip ve uzunluk bilgisi olmadan anlamsızdır (3. bölüm · dört bayt). Loader bu yüzden sırayı tersine çevirmez: önce accessor kaydını açar, soruları yanıtlar, ancak ondan sonra buffer’dan okur. Bu sıra, tahmin yürütmeyi ortadan kaldırır 2. bölümdeki «çeviri sözleşmesi» tam olarak bu yanıtların toplamıdır.
Aşağıdaki tablo beş temel soruyu özetler. Her satır bir accessor alanına karşılık gelir; alan adları JSON’da göründüğü haliyle bırakılmıştır ki dosyayı açtığınızda doğrudan eşleştirebilesiniz.
| Soru | Accessor cevabı (özet) |
|---|---|
| Veri tipi nedir? | componentType örn. float, unsigned short, unsigned int |
| Kaç eleman var? | count dizideki mantıksal kayıt sayısı |
| Her eleman kaç bileşen? | type SCALAR, VEC2, VEC3, VEC4, MAT4 … |
| Baytlara nereden ulaşılır? | bufferView indeksi dilimleme sonraki sayfada |
| Sıkıştırılmış mı? | İsteğe bağlı extension bu sayfada detay yok |
Tablodaki sorular neden ayrı ayrı?
Beş satır birbirinin yerine geçmez loader’ın typed okuma yapabilmesi için hepsinin birlikte yanıtlanması gerekir:
componentType(tip): Her bileşen kaç bayt ve hangi yorumla okunacak? Aynı dört octet float veya uint olabilir; tip seçimi sayısal sonucu belirler. Bu soru olmadan loader baytları kesemez.type(şekil): Ardışık bileşenler nasıl gruplanır? Üç float arka arkaya tek birVEC3mü, yoksa bağımsız üçSCALARmı? Gruplama kuralı stride ve vertex düzenini etkiler; detay geometry sayfalarında, burada yalnızca «şekil tarifi accessor’da» notu yeterlidir.count(uzunluk): Bu gruplama kuralı kaç kez tekrarlanır? «1024 vertex» ifadesinin sayısal karşılığıdır. Count ile gerçek bayt hacmi uyuşmazsa okuma ya erken biter ya taşar validasyon bu satırı kontrol eder.bufferView(adres): Yukarıdaki üç cevap «nasıl oku» der; bufferView «hangi bayt aralığından oku» der. Accessor tek başına buffer içindeki ofseti bilmez bu bilinçli ayrım bufferView sayfasının konusudur; burada yalnızca sorunun accessor tarafında indeksle yanıtlandığı sabitlenir.- Sıkıştırma (extension): Baytlar sıkıştırılmışsa okuma kuralı değişir; accessor extension bayrakları «önce çöz, sonra yukarıdaki kuralları uygula» der. Bu sayfada mekanik yok; satır yalnızca «beşinci soru bazen gerekir» diye tabloda durur.
Accessor’ın cevaplamadığı sorular
Tablo loader’a biçim ve erişim hakkında bilgi verir; aşağıdaki sorular başka katmanlara aittir accessor kaydında aramayın:
- «Bu veri sahnede ne işe yarar?» Position mu, normal mi, UV mi?
Cevap mesh primitive’in
attributesharitasında; accessor yalnızca biçim tarif eder (10. bölüm). - «GPU’da hangi attribute slot’una gider?» WebGL/WebGPU eşlemesi loader ve motor katmanında; spec’in accessor tanımının dışındadır.
- «Buffer içinde tam ofset kaç?» bufferView + isteğe bağlı
byteOffsetalanı; dilimleme sonraki sayfada. - «Vertex’ler interleaved mi, ayrı mı?» bufferView
byteStrideve export düzeni; yine bufferView/geometry konusu.
Bu sınırı net tutmak önemlidir: accessor «1024 adet VEC3 float oku» der «bu position verisidir» demez. Kullanım amacı ile veri biçimi bilinçli olarak ayrılır; aksi halde aynı float×3 biçimi normal, tangent veya morph target için tekrar tanımlanamazdı.
Yanıtlar birleşince: okuma cümlesi
Tablodaki cevaplar tek tek anlamsız değildir; birleşince loader için tek bir «okuma cümlesi»
oluşur. Örneğin tip + şekil + count üçlüsü «1024 adet VEC3 float» der; bufferView eklendiğinde cümle «bufferView #0’daki baytlardan 1024 adet VEC3
float oku» haline gelir. İşte bu cümle,
3. bölümdeki «yorumlama»
teriminin somut ifadesidir buffer’a uygulanacak gözlük tanımı.
İsteğe bağlı alanlar (min, max, sparse, normalizasyon
bayrakları) tabloda yer almaz; bunlar okumayı mümkün kılmak için zorunlu değil, sahne
optimizasyonu veya özel dağılım için ek bilgidir. Temel beş soru yanıtlandığında loader
typed array üretmeye hazırdır runtime hattının geri kalanı
8. bölümde, buffer’a fiziksel
ulaşım ise 5. bölümde
zincirle açılır.
Accessor ve Buffer İlişkisi
4. bölümde tablo yanıtları birleşince «bufferView #0’daki baytlardan 1024 VEC3 float oku» cümlesi oluştu. Bu bölüm o cümlenin buffer’a nasıl ulaştığını zincir üzerinden sabitler. Accessor verinin kendisini içermez; binary baytlara ulaşmak için alt katmanlara referans verir. glTF’de tipik yol üç halkalıdır bu sayfada yalnızca accessor’ın zincirdeki yeri netleştirilir; bufferView nasıl dilimler, ofset ve stride nasıl hesaplanır soruları bufferView sistemleri sayfasına bırakılır.
İçerik değil, referans taşır
Bir accessor kaydı megabyte’larca buffer verisini JSON’a taşımaz birkaç alan ve bir
bufferView indeksi taşır. Bu tasarım
7. bölümde «kopya üretmez» temasıyla
örtüşür: talimat küçük kalır, ham malzeme binary’de kalır. İlişki «içerme» değil
«işaret etme»dir primitive «accessor #2’yi kullan» der, accessor
«bufferView #1’i şu kurallarla oku» der, bufferView (sonraki sayfa) «buffer #0’ın şu
aralığı» der, buffer «işte octet’ler» der.
Dosyayı açtığınızda accessors dizisinde buffer URI’si veya base64 bloğu
aramayın; doğrudan buffer referansı accessor’da yoktur. Bu bilinçli bir ara katman
kararıdır: aynı buffer şeridinden birden fazla dilim alınabilir, aynı dilim farklı
accessor kurallarıyla okunabilir esneklik, doğrudan buffer bağlantısından gelir.
Üç halka, üç ayrı soru
Şemadaki her halka tek bir soruya cevap verir; görevler üst üste binmez:
- Accessor (bu sayfa): «Baytları nasıl okuyacağım?»
componentType,type,countve hangibufferViewindeksinin kullanılacağı. Yorum katmanının JSON tarafındaki giriş kapısıdır. - BufferView (sonraki sayfa): «Buffer’ın hangi bayt aralığını alacağım?» ofset, uzunluk, isteğe bağlı stride. Dilimleme mekaniği orada; burada yalnızca accessor’ın buffer’a doğrudan değil, bufferView üzerinden ulaştığı sabitlenir.
- Buffer (binary buffer): «Ham malzeme nerede?» sürekli octet havuzu; tip, kanal adı veya vertex kavramı yoktur.
Okuma yönü yukarıdan aşağıya iner: organizasyon katmanı accessor’ı seçer, accessor bufferView’i işaret eder, bufferView buffer’dan dilim getirir, accessor kuralları o dilime uygulanır. Verinin kendisi en alttaki halkadadır; anlam en üstteki talimatla birleşir (3. bölüm · formül).
Neden arada bufferView var?
«Accessor doğrudan buffer’a işaret etse olmaz mı?» sorusu doğaldır. glTF bufferView’i ara katman olarak koyar çünkü depo ile yorum ayrı ihtiyaçlara hizmet eder:
- Buffer tek havuzdur: Position, normal, UV ve indeks verisi aynı şeritte yan yana durabilir (veri havuzu). BufferView «şu ofsetten şu uzunluğa kadar» der fiziksel adresleme.
- Accessor yorum tarifidir: «O aralıktaki baytları VEC3 float olarak oku» der mantıksal okuma. Aynı dilim teorik olarak farklı accessor’larla farklı biçimde yorumlanabilir; pratikte her kanal kendi çiftine sahiptir (6. bölüm).
İki katman birlikte «nereden + nasıl» sorusunu çözer. Accessor tek başına «nereden»yi bilmez; bufferView tek başına «nasıl»ı bilmez ikisi birleşince loader okumaya hazırlanır.
Eksik halka: accessor tek başına yetmez
3. bölümde buffer’ın
körlüğünü gördük; accessor da tek başına hex dump’ı anlamlı kılmaz. Tip ve count bilgisi
vardır, fakat hangi bayt aralığına uygulanacağı
bufferView olmadan belirsiz kalır tüm buffer’a mı, ortasındaki bir bloğa mı?
Geçersiz veya eksik bufferView indeksi zinciri kırar; loader erken hata verir
veya validasyon başarısız olur.
Ters yönde de geçerlidir: bufferView dilimi vardır, accessor yoksa loader «bu baytlar ne?» sorusuna cevapsız kalır. Zincirin her halkası zorunludur; bu sayfa accessor halkasının buffer’a referans yoluyla bağlandığını vurgular veriyi taşımadan, bir sonraki halkayı çağırarak.
Liman analojisi: etiket, bölüm, konteyner
Binary buffer · liman analojisinde üç rol net ayrılır: buffer konteyner (kapalı yük); bufferView konteynerin şu bölümü (hangi bölme); accessor içerik tipi etiketi (float×3, uint indeks vb.). Limanda plan gelmeden yük ağırlıktan ibarettir; glTF’de de buffer octet’ten ibarettir plan accessor + bufferView zinciridir.
Analoji bilinçli olarak yüzeysel bırakılır: limanda gümrük ve manifest detayı yoktur; glTF’de ofset/stride hesabı bufferView sayfasındadır. Buradan alınacak ders tek cümle: accessor buffer’ın kapısını açmaz doğru bufferView’e yönlendirir; kapı orada açılır.
Loader’ın zincir boyunca adımları
Soyut şema, runtime’da kabaca şu sıraya dönüşür (GPU upload ve geometri detayı yok):
- Primitive veya animation sampler «accessor #N kullan» der.
- Loader
accessors[N]kaydını açar tip, count, type, bufferView indeksini okur. bufferViews[…]kaydına geçilir buffer indeksi ve bayt aralığı çözülür (mekanik sonraki sayfa).- İlgili
buffers[…]binary’si belleğe alınmışsa, dilim üzerine accessor kuralları uygulanır. - Sonuç typed array veya eşdeğer görünüm 8. bölüm bu hattın devamını gösterir.
Accessor bu listede 2. adımda devreye girer: buffer’a henüz dokunulmamışken okuma sözleşmesi kurulur. Bir sonraki bölüm, aynı buffer havuzundan birden fazla accessor ile nasıl farklı yorumlar üretildiğini somutlaştırır.
Aynı Buffer’dan Birden Fazla Accessor
5. bölümde buffer’ın tek havuz, accessor’ın yorum tarifi olduğunu gördük. Bu bölüm o yapının doğal sonucunu somutlaştırır: gerçek modellerde tek bir buffer şeridi position, normal, UV, indeks ve hatta animasyon örneklerini yan yana taşır her mantıksal parça için ayrı bir accessor kaydı tanımlanır. Depo tektir; yorumlar çoğulur.
Tipik bir mesh primitive’i düşünün. Aynı veri havuzundan okunan kanallar kabaca şöyle ayrılır sayılar örnektir, export aracına göre değişir:
- Accessor A «şu dilimde VEC3 float, count=N» → position yorumu
- Accessor B «başka dilimde VEC3 float, count=N» → normal yorumu
- Accessor C «başka dilimde VEC2 float, count=N» → UV yorumu
- Accessor D «ayrı dilimde unsigned int, count=M» → üçgen indeks yorumu (tip ve count genelde vertex kanallarından farklıdır)
Kritik fikir: bir buffer, birden fazla yorum. Ham octet’ler bir kez yazılır; JSON tarafında her kanal için küçük bir talimat kaydı eklenir. Loader primitive’i okurken «position için #0, normal için #1…» der her numara aynı buffer havuzuna giden farklı bir gözlük takar.
Tek havuz, birden fazla «pencere»
Buffer’ı uzun bir bellek şeridi olarak düşünün. BufferView (sonraki sayfa) şeridin
fiziksel pencerelerini tanımlar; accessor her pencereye «içeriği şu
biçimde oku» der. Position penceresi ile normal penceresi çoğu zaman bitişik
bloklardır aynı vertex sayısına sahip VEC3 float dizileri yan yana durur.
UV penceresi daha kısa olabilir (VEC2); indeks penceresi tamamen farklı tip
ve uzunlukta olabilir.
Önemli olan: buffer bu kanalları «position/normal/UV» diye etiketlemez. Etiketler
primitive’in attributes haritasındadır; accessor yalnızca her pencere için
okuma kuralını yazar. Aynı VEC3 float biçimi position ve normal için iki kez kullanılabilir
biçim aynı, bufferView dilimleri ve primitive bağlantıları farklıdır.
Neden tek accessor yetmez?
«Tüm mesh verisini tek accessor’da birleştirsek?» pratikte işlemez çünkü kanallar farklı okuma sözleşmeleri gerektirir:
- Farklı
type: Position/normalVEC3, UVVEC2, indeks çoğu zamanSCALARunsigned int. - Farklı
componentType: Vertex kanalları float, indeksler genelde unsigned short veya unsigned int bayt genişliği değişir. - Farklı
count: İndeks sayısı vertex sayısından farklıdır (üçgen başına üç indeks). - Farklı
bufferView: Her kanal havuzda farklı aralıkta tek accessor tüm aralıkları tarif edemez.
Merkezi accessors dizisi bu çeşitliliği tekrar kullanılabilir
kayıtlarla yönetir: aynı biçimdeki iki kanal aynı accessor’ı paylaşabilir mi?
Spec izin verir; pratikte position ve normal ayrı kayıtlar kullanır çünkü dilimler ve
primitive bağlantıları farklıdır. Paylaşım daha çok instancing veya morph target gibi özel
durumlarda görülür detay başka konularda.
Aynı dilim, farklı yorum (nadir)
Format teorik olarak aynı bayt aralığına farklı accessor kuralları bağlanmasına izin verir örneğin aynı dilim bir kez float dizisi, başka bir senaryoda farklı gruplamayla okunabilir. Bu günlük export’ta nadirdir; çoğu araç her kanal için ayrı dilim yazar. Yine de fikir önemlidir: buffer’daki octet’ler sabittir, anlam accessor seçimine bağlıdır (3. bölüm · aynı veri, farklı anlam).
Pratikte «bir buffer, birden fazla yorum» ifadesi bu nadir durumdan çok yan yana
dilimler için kullanılır: position bloğu, normal bloğu, UV bloğu hepsi aynı
buffers[0] şeridinde, her biri kendi accessor + bufferView çiftiyle okunur.
Export: bir kez yaz, çok kez tarif et
DCC ve optimizasyon araçları bellek tekrarını önlemek için veriyi buffer’a bir kez yazar, JSON’da birçok accessor ile «gözlük» takar. Dosya boyutu açısından kazanç nettir: megabyte binary + kilobyte talimat kayıtları; her kanal için ayrı buffer dosyası veya JSON’da float listesi taşınmaz.
Runtime’da da ideal senaryo benzerdir: buffer bir kez belleğe alınır, her accessor farklı offset/length ile typed görünüm üretir yeni bir octet kopyası şart değildir (7. bölüm). «Bir buffer, birden fazla accessor» hem disk hem bellek tasarımının temel desenidir.
Mesh dışında da aynı desen
Çoklu accessor deseni yalnızca mesh vertex kanallarına özgü değildir. Animasyon sampler’ları zaman damgası ve değer dizileri için ayrı accessor’lar referans eder; skin inverse bind matrix dizileri tek buffer’da, tek accessor tarifinde durabilir. Ortak payda aynıdır: tek binary havuz, ihtiyaç kadar accessor talimatı. Organizasyon katmanı hangi accessor’ın hangi amaçla çağrıldığını söyler; accessor biçimi tarif eder ikisi birleşince anlam oluşur.
Özet: glTF’de buffer «depo», accessor «gözlük koleksiyonu»dur. Bir mesh onlarca accessor indeksi kullanabilir; hepsi aynı veya birkaç buffer havuzuna bağlanır. Bir sonraki bölüm, accessor’ın bu gözlükleri oluştururken veriyi neden kopyalamadığını netleştirir.
Accessor Bir Kopya Üretmez
6. bölümde export’ın veriyi buffer’a bir kez yazıp birçok accessor ile tarif ettiğini gördük. Bu bölüm o desenin neden mümkün olduğunu netleştirir: accessor verinin kopyası değildir yalnızca okuma talimatıdır. Sık karışan nokta: accessor’ın buffer’daki veriyi «içermesi» veya «kopyalaması» sanılır. Oysa accessor JSON’da küçük bir metadata kaydıdır birkaç sayı ve indeks. Dosyada megabyte buffer varken accessor satırı birkaç yüz byte bile olmayabilir.
Yanlış model: accessor = veri kutusu
Yeni başlayanlar bazen accessors dizisini «vertex listesi» veya «position
tablosu» sanır tıpkı JSON’da float dizisi beklemek gibi. Dosyayı açınca hayal kırıklığı
gelir: kayıtlar kısa, sayılar az, gerçek koordinatlar binary’de. Doğru model:
accessor talimat kartıdır; ağır yük buffer’dadır
(1. bölüm).
2. bölümdeki çevirmen metaforu da aynı noktayı vurgular: çevirmen orijinal metni cebinde taşımaz. glTF’de accessor buffer’ı JSON’a gömmez binary kanalda bırakır, JSON’a yalnızca «nasıl oku» yazar.
Üç kural: taşımaz, kopyalamaz, tarif eder
Accessor’ın buffer ile ilişkisini tek cümlede toparlamak için üç ayrım yeterlidir:
- Accessor veriyi taşımaz Koordinatlar, indeksler ve animasyon örnekleri binary’de durur. JSON’daki accessor satırı onları temsil etmez; yalnızca onlara giden yolu tarif eder.
- Accessor veriyi kopyalamaz Dosya yazılırken veya parse edilirken accessor kaydı oluşturmak buffer’dan yeni bir octet bloğu üretmez. «On accessor = on kopya buffer» diye bir kural yoktur.
- Accessor veriyi tarif eder «Şu bufferView diliminden, şu tip ve count ile oku» der. Anlam 3. bölümdeki formülde «yorumlama» teriminin dosyadaki karşılığıdır.
Bu üçlü, accessor’ın «kopya üretmez» iddiasının özüdür: ne diskte ne JSON’da verinin ikinci bir kopyasını taşımak accessor’ın işi değildir.
Dosyada: megabyte binary, byte’larca talimat
Boyut farkı pratikte şöyle hissedilir: orta ölçekli bir modelde buffers[0]
megabyte mertebesinde olabilir; aynı mesh’e bağlı on accessor kaydı toplamda kilobyte
altında kalabilir. Talimatların küçük kalması formatın hibrit mimarisinin
sonucudur ağır yük binary’de, seyrek metadata JSON’da
(JSON vs
binary).
On accessor tanımlamak buffer’ı on kat büyütmez; yalnızca JSON’a on küçük kayıt ekler. Bellek tekrarını önleyen desen burada somutlaşır: veri bir kez, talimat ihtiyaç kadar.
Runtime: görünüm ≠ kopya
Tarayıcıda loader binary chunk’ı okuduğunda elinde bir ArrayBuffer vardır
(binary buffer
· runtime). Accessor kuralları uygulandığında motor çoğu zaman
Float32Array (veya uygun typed array) gibi bir görünüm
oluşturur bu görünüm yeni bir octet havuzu olmak zorunda değildir; aynı
ArrayBuffer üzerinde byteOffset ve length ile
tanımlanabilir.
«Görünüm» ile «kopya»yı ayırmak önemlidir: görünüm aynı bellek bloğuna farklı tipten bakmaktır; kopya ise baytların başka bir adrese yazılmasıdır. Accessor yalnızca görünümün nasıl parametreleneceğini söyler (tip, eleman sayısı, bileşen düzeni) bellek tahsis stratejisi loader’a aittir.
6. bölümdeki «tek havuz, çok pencere» deseni runtime’da tam olarak budur: buffer bir kez RAM’de, her accessor farklı offset/length ile aynı bloğa bakar her kanal için ayrı megabyte buffer gerekmez.
Peki kopya ne zaman olur?
Accessor «asla kopya yok» demez; «kopya benim işim değil» der. Kopyalama ihtiyacı başka katmanlarda doğabilir:
- GPU upload: Donanım bazen CPU belleğindeki düzenle farklı bir paket ister; motor vertex verisini VRAM’e taşırken kopyalayabilir. Bu accessor talimatından bağımsız bir upload adımıdır VAO/VBO detayı geometry sayfalarında.
- Interleaved unpack: Vertex kanalları tek şeritte iç içe paketlenmişse loader ayrı attribute buffer’ları için geçici kopya oluşturabilir. Karar export düzenine ve motor stratejisine bağlıdır; accessor yalnızca kaynak şeridi tarif eder.
- Endianness / normalizasyon: Nadir dönüşüm adımları loader içinde yapılabilir; yine accessor’ın JSON kaydı değil, runtime implementasyonunun işidir.
Ortak payda: kopyanın ne zaman ve neden yapıldığı loader ile GPU pipeline’ının sorusudur. Accessor dosyada sabitlenmiş okuma sözleşmesidir kopyalama planı değil. Bu ayrım, 8. bölümdeki runtime hattını okurken de işinize yarar: accessor adımı binary’yi anlamlandırır; sonraki adımlar motorun tercihidir.
Runtime’da Accessor Ne İşe Yarar?
7. bölümde accessor’ın kopya değil okuma sözleşmesi olduğunu gördük. Bu bölüm o sözleşmenin tarayıcıda ne zaman devreye girdiğini sorar: diskten bayt geldikten, JSON organizasyonu okunduktan sonra loader hâlâ «bu octet’ler ne?» sorusuna accessor olmadan cevap veremez. Runtime’da accessor, binary ile anlamlı veri yapıları arasındaki yorum hattının giriş kapısıdır.
Tam yüklemenin neresindeyiz?
glTF yüklemesi birkaç paralel hattı bir araya getirir. Binary buffer
· runtime sayfası disk / ağ → ham chunk → ArrayBuffer zincirini
anlatır «baytlar belleğe geldi» noktasına kadar. Bu bölüm bir sonraki parçayı kapsar:
bellekteki baytlar accessor kurallarıyla okunduğunda ne olur?
5. bölümdeki zincir yürüyüşünde primitive «accessor #N» dediğinde loader JSON’dan ilgili kayda geçer; bufferView ile buffer dilimi çözülür (mekanik ayrı sayfada). Aşağıdaki şema o noktadan itibaren accessor odaklı dört adımı özetler geometri, materyal ve sahne grafiği yok, yalnızca veri akışı:
-
Loader accessor kaydını okur
-
Tip, count, type, bufferView çözülür
-
TypedArray görünümü oluşturulur
-
Motor geometri / attribute nesnelerine bağlar (detay başka sayfalar)
Şemadaki dört adım ne yapar?
Diyagramdaki her adım accessor’ın runtime’daki somut karşılığıdır; sıra değiştirilmeden uygulanır:
- Accessor kaydına giriş: Organizasyon katmanı (primitive, animation
sampler, skin vb.) bir accessor indeksi verir. Loader
accessorsdizisinden ilgili JSON nesnesini alır henüz typed veri yoktur, yalnızca talimat. - Sözleşme çözümü:
componentType,type,countvebufferViewbirleşerek «kaç bayt, kaç eleman, hangi tip» sorusu yanıtlanır. bufferView üzerinden buffer dilimine ulaşılır. Alanların görev listesi 4. bölümde; burada önemli olan çıktı: uygulanabilir bir okuma planı. - Typed görünüm: Bellekteki
ArrayBufferüzerinde uygun typed array oluşturulur örneğin VEC3 float içinFloat32Array, indeks içinUint16ArrayveyaUint32Array. Bu adım 3. bölümdeki «anlam» teriminin runtime karşılığına yaklaşır: kör bayt artık sayısal dizi gibi okunabilir. - Motor bağlantısı: Loader typed veriyi motorun geometri veya attribute
API’sine iletir.
BufferAttribute, interleaved düzen, shader attribute eşlemesi bu sayfanın dışındadır accessor hattı burada «binary’den anlamlı diziye» kadar gider.
İki hat birleşince: disk → anlam
Dosya yapısı serisinde runtime’ı ikiye bölmek faydalıdır:
- Binary buffer hattı: Dosyadan ham chunk çıkar, RAM’de tek
ArrayBufferolur hâlâ etiketsiz octet. - Accessor hattı (bu bölüm): Her ihtiyaç duyulan kanal için accessor
uygulanır; aynı
ArrayBufferüzerinde bir veya birden fazla typed görünüm doğar (6. bölüm).
İkisi birleşince «glTF dosyasındaki position verisi» ifadesi teknik olarak şuna dönüşür: «Şu accessor kaydı, şu buffer dilimindeki baytları VEC3 float olarak oku.» Kullanıcı sahneyi görür; arka planda yorum hattı bu adımlardan geçmiştir.
Loader sizin adınıza yürütür
Three.js GLTFLoader ve benzeri
implementasyonlar
yukarıdaki dört adımı otomatik yapar elle accessors[0] açıp typed array
oluşturmanız gerekmez. Yine de hata ayıklarken veya özel loader yazarken şema yol
haritasıdır: «position neden undefined?» sorusunda zincir accessor adımında mı kırılıyor,
bufferView diliminde mi, yoksa buffer hiç yüklenmedi mi diye ayrıştırırsınız.
Accessor adımı başarılı olsa bile sonraki motor adımları başarısız olabilir (GPU upload, materyal, node transform). Bu bölüm yalnızca veri yorumlama hattını kapsar; sahne runtime’ı için glTF pipeline ayrı kanaldadır.
Bu hattın sınırı
Bilinçli olarak işlenmeyen konular accessor sayfasının runtime sınırı: vertex attribute düzeni, VAO/VBO, compute morph, Draco decode sonrası okuma, WebGL/WebGPU attribute location ataması. Hepsi accessor’dan sonra gelir; accessor yalnızca «buffer’daki baytları şu sözleşmeyle oku» der.
Özet: Runtime’da accessor, bellekteki ham binary ile loader’ın kullanabileceği typed veri arasındaki zorunlu köprüdür. Binary buffer sayfası baytların belleğe gelişini; bu bölüm baytların anlama dönüşümünü tamamlar. Bir sonraki bölüm accessor katmanının format tasarımındaki «neden»ini mühendislik kazanımlarıyla özetler.
Neden Accessor Katmanı Var?
8. bölümde accessor’ın runtime’da binary ile typed veri arasındaki köprü olduğunu gördük. Bu bölüm bir adım geriye çekilir ve format tasarımına sorar: «Bu katman neden var?» Cevap yalnızca spec cümlesi değildir accessor, glTF’nin hibrit mimarisinin (JSON organizasyon + binary depo) tamamlayıcı mühendislik parçasıdır.
Formalite değil, bilinçli ayrım
Accessor kayıtları «spec’in doldurulması gereken alanları» gibi görünebilir; fakat
1. bölümde gördüğünüz
gibi merkezi bir accessors tablosu tekrar kullanım, validasyon ve tutarlı
indeks dili için bilinçli seçilmiştir. Buffer kördür; anlamı her loader’ın kendi tahminiyle
üretmesi kaos olurdu. Accessor katmanı bu boşluğu standart bir okuma
sözleşmesiyle
doldurur formalite değil, öngörülebilirlik aracıdır.
Özetle mühendislik kazanımları şu başlıklarda toplanır:
- Aynı buffer, farklı okuma biçimleri: Aynı bayt aralığı farklı type ile yorumlanabilir (nadir); farklı aralıklar aynı buffer’da yan yana durabilir (yaygın).
- Bellek tekrarını önler: Veri bir kez yazılır; çok accessor referans verir.
- Dosya boyutu: Yorumlama metadata’sı JSON’da küçük; ağır yük binary’de kalır.
- Standartlaştırılmış runtime: Tüm loader’lar aynı accessor sözleşmesini uygular platform bağımsızlık.
- GPU hazırlığı: Tip ve count bilgisi, attribute upload planını öngörülebilir kılar (VAO/VBO detayı ayrı).
Esnek okuma, tek depo
Tek bir buffer havuzu mesh’in tüm kanallarını taşıyabilir; her kanal farklı accessor ile
okunur (6. bölüm). Yaygın desen:
yan yana dilimler, farklı type ve componentType kombinasyonları.
Nadir senaryoda aynı dilim farklı yorumlarla bağlanabilir format buna izin verir; pratik
export çoğu zaman kanalları ayırır.
Kazanç: depo birleşik kalır, yorumlar modüler kalır. Yeni bir kanal eklemek buffer’ı baştan yazmak değil, yeni bir accessor (+ bufferView) kaydı eklemek anlamına gelir organizasyon esnekliği.
Bellek ve disk verimliliği
Veri bir kez binary’de durur; on accessor tanımı buffer’ı on kat büyütmez
(7. bölüm). Runtime’da ideal
senaryoda aynı ArrayBuffer üzerinde birden fazla typed görünüm oluşturulur
her kanal için ayrı megabyte kopya gerekmez.
Bu desen hem dosya hem RAM tasarımında tekrar eder: ağır yük paylaşılır, hafif talimatlar çoğalır. Export araçları ve web loader’ları aynı felsefeyi paylaşır.
Küçük JSON, büyük binary
glTF’nin hibrit yapısında JSON insan ve araçlar için okunabilir organizasyon taşır; accessor kayıtları bu katmanda kalır birkaç yüz byte’lık talimatlar. Koordinat ve indeks gibi yoğun sayılar JSON’a gömülmez (JSON vs binary).
Accessor olmadan ya tüm yorumlama kuralları primitive içine gömülür (tekrar, validasyon zorluğu) ya da buffer anlamsız kalır. Ayrı tablo, metadata ile payload’ı temiz biçimde ayırır.
Platform bağımsız sözleşme
2. bölümdeki loader
sözleşmesi burada «neden»e dönüşür: Blender’dan export, tarayıcıda Three.js, mobilde farklı
motor hepsi aynı componentType, type, count
kurallarını uygular. Tahmin yok; spec’te yazılı okuma.
Validasyon araçları, dönüştürücüler ve test suite’ler de aynı accessor semantiğine dayanır. Katman sayesinde «dosya bozuk mu?» sorusu binary hex dump yerine JSON talimatları üzerinden de sorulabilir.
GPU yolunu önceden planlama
Accessor tip ve count bilgisi, loader’a «kaç byte okuyacağım, kaç eleman üreteceğim» cevabını verir GPU upload öncesi buffer boyutu ve attribute düzeni kabaca öngörülebilir. VAO/VBO oluşturma, interleaved unpack ve shader location ataması geometry pipeline’ında; burada yalnızca planlanabilir girdi sağlandığı not edilir.
Accessor olmasaydı motor her buffer diliminde «float mı, short mu, kaç bileşen?» diye keşif yapmak zorunda kalırdı upload stratejisi dosyadan dosyaya değişirdi.
Accessor olmasaydı ne olurdu?
JSON organizasyonu + binary depo + accessor yorumu birlikte glTF’nin hibrit mimarisini tamamlar. Accessor katmanını çıkarsanız buffer kalır octet hâlâ orada fakat loader her seferinde «1024 VEC3 float mu, 3072 scalar mı?» sorusuna cevap arar (2. bölüm · 3. bölüm). Anlam tahmine kalır; sahne tutarlılığı düşer.
bufferView katmanı «hangi aralık» sorusunu çözer; accessor «nasıl oku» sorusunu. İkisi
birlikte
buffer körlüğünü giderir bufferView detayı
sonraki
sayfada. Son bölümde accessor’ın bir etiket
(POSITION vb.) olmadığı, yalnızca biçim tarifi olduğu netleştirilir.
Accessor Bir Etiket Değildir
Yeni başlayanların sık yaptığı hata: «POSITION = accessor» sanmak.
Oysa primitive’te gördüğünüz:
"attributes": {
"POSITION": 0,
"NORMAL": 1
}
burada POSITION ve NORMAL kullanım amacı
etiketleridir
(semantic / attribute adı). 0 ve 1 ise accessors
tablosundaki indekslerdir yani veri biçimi tarifine gider. İki ayrım:
- Semantic (
POSITION,NORMAL, …): «Bu veri sahnede ne işe yarar?» mesh primitive bağlamında. - Accessor kaydı: «Baytlar hangi tipte, kaç eleman, kaç bileşen?» biçim tarifi.
Aynı accessor biçimi farklı semantic’lere atanabilir mi? Spec kurallarına bağlıdır; pratikte position ve normal farklı accessor kayıtları kullanır. Önemli olan: accessor isim taşımaz, indeksle referanslanır; isim primitive’in attribute haritasındadır. Vertex attribute sistemi ve shader eşlemesi başka sayfalarda; burada sabitlenen: accessor = biçim, POSITION = amaç.
Demo · Accessor Lens
Metin «accessor ne yapar?» sorusunu cevaplar; bu laboratuvar aynı veri, farklı yorum hissini yaşatır. Soldaki ham buffer bayt bayt sabit kalır değişen yalnızca ortadaki accessor lensidir (tip, bileşen, count). Sağda yorumlanmış sonuç ve Three.js sahnesi birlikte güncellenir: POSITION lensi köşe konumları, UV lensi renk haritası, indeks lensi wireframe, misread lensi yanlış tip okumasını gösterir.
componentType alanını FLOAT → UNSIGNED_INT yapın: octet’ler aynı, listedeki
sayılar tamamen değişir. Bu, sayfanın öz cümlesidir:
veri değişmedi yalnızca yorum değişti. JSON Anatomy Explorer
organizasyonu,
Binary Memory Explorer ham havuzu öğretti; bu demo aradaki yorum katmanını tamamlar.
Sonraki bufferView Scanner demosu: «Accessor tam
olarak buffer’ın hangi kısmını okuyor?»
Lens seçin veya accessor alanlarını değiştirin · buffer sabit kalır
Ham buffer · sabit
Baytlar değişmez vurgu okunan aralığı gösterir.
Accessor lens · kurallar
Yorumlanmış sonuç
Bu demo ne hissettirir? Buffer ne olduğunu bilmez; accessor ona anlam verir. Lens değiştirmek veriyi değil yorumu değiştirir glTF dosya yapısı serisinde JSON → buffer → accessor zincirinin «aha!» noktası. Sırada bufferView: accessor’ın okuduğu bayt aralığını kim dilimler?