holodepth

Three.js · Kamera türleri

ArrayCamera (dizi kamera)

ArrayCamera; tek render, çoklu kamera görünümü

Yarış simülasyonunda dikiz aynası, dört oyunculu bölünmüş ekran veya güvenlik odasındaki dörtlü monitör; hepsi aynı tuvalde birden fazla bakış ister. İzleyici tek pencerede kalır; her bölge farklı kamera konumu, FOV veya kadrajla çizilir. Bu, çevreyi küp dokusuna yazan CubeCamera veya tek kadrajlı ana oyun kamerasından farklı bir ihtiyaçtır: amaç aynı karede, yan yana okunabilir görünümler.

Three.js'te bunu ArrayCamera ile kurarsınız: önceden tanımlı alt kameralar (PerspectiveCamera veya gerektiğinde OrthographicCamera) ve her birine bağlı viewport ile ekranın hangi dikdörtgeninin kime ait olduğunu belirlersiniz. Uygulama tarafında çoğu zaman tek renderer.render(scene, arrayCamera) çağrısı yeterlidir; dört ayrı döngü ve elle senkron yerine motor, aynı sahneyi bölgelere sırayla işler. Tek bakışlı kadraj ve FOV için PerspectiveCamera; canlı yansıma / küp haritası için CubeCamera.

Bu sayfa ArrayCamera'ya özeldir: split-screen mantığı, alt kamera + viewport anatomisi, etkileşimli demo, dörtlü monitör örneği, teknik tablo ve sınırlar (iç döngü, post-process). View / projection dili için Kamera giriş sayfasına dönün.

Çoklu bakış açısı ve split-screen mantığı

ArrayCamera, ekranın belirli bölgelerini farklı alt kameralara tahsis eder. Her alt kamera (sub-camera), yalnızca kendisine ayrılan viewport dikdörtgeni içinde sahneyi görür; böylece dört oyunculu bölünme, izleme monitörü veya dikiz aynası düzeni tek sahne üzerinde birleşir.

Kullanım senaryoları; ortak ihtiyaç: aynı sahne grafiği, farklı kadrajlar; her bölge kendi viewport ve alt kamera parametreleriyle çizilir.

  • Yarış ve simülasyon: Ana bakış ön camdan, küçük dikdörtgen dikiz veya yan ayna — farklı konum ve FOV ile aynı karede. Cockpit içi ek ekranlar (radar, harita düzlemi) bazen ortografik alt kamera, ana yol perspektif kalır. Ayrı render() döngüleri yerine tek çağrıda senkron kalır; alt kamera aspect’i kendi viewport genişliğine göre ayarlanmalıdır (anatomi ve demo).
  • Çok oyunculu split-screen: İki veya dört oyuncu aynı dünyada, ekran çeyrek veya yarım bölünür; her oyuncunun kamerası farklı pozisyon ve giriş cihazıyla güncellenir. UI katmanı genelde HTML/CSS’te kalır; 3B görünüm bölgeleri ArrayCamera ile paylaşılır. Klasik yerel çok oyunculu modun tipik desenidir — çevrim içi çoklu istemcide her istemcide tek bakış daha yaygındır.
  • Güvenlik ve gözetim: Tek monitörde dört köşe canlı önizleme; her alt kamera farklı sanal “güvenlik kamerası” konumunu temsil eder. Sahne aynıdır, viewport dörtlü ızgaradır; operatör tüm akışları bir bakışta izler. Üretimde düşük çözünürlüklü alt görünüm veya seyrek güncelleme tercih edilebilir — maliyet görünüm sayısıyla ölçeklenir (aşağıdaki callout).
  • VR ve çoklu ekran prototipleri: Geliştirme aşamasında tuvali bölgelere ayırıp stereo / çift göz düzenini veya ikinci monitör önizlemesini denemek için kullanılır; tam WebXR oturumu ayrı API ile yürür. Callout’taki çok bölgeli, çok bakışlı okuma burada köken alır — split-screen ve izleme panelinde aynı mantık yeterlidir.

Kritik nüans: tek render() çağrısı, içeride birden çok geçiş

ArrayCamera ile yaptığınız tek renderer.render(scene, arrayCamera) çağrısı, uygulama düzeyinde “tek draw” anlamına gelmez. WebGLRenderer içinde her alt kamera için sırayla viewport ayarlanır ve çizim listesi o bakış açısıyla yeniden işlenir; yani motor tarafında internal bir döngü vardır. Kazanç çoğunlukla API ve akış sadeleşmesi (tek çağrı, aynı kare zamanı, daha az el yapımı senkron) ve doğru ayarlandığında daha tutarlı pencerelemedir; “GPU yükü görünüm sayısıyla çarpılır” satırıyla da örtüşür.

Bu desen WebXR stereo mantığına da yakındır: her göz için ayrı projeksiyon ve dikdörtgen, tek kare ömründe eşleştirilir; ArrayCamera köken itibarıyla bu tür çok bölgeli, çok bakışlı düzenlere dayanır; VR dışında split-screen ve izleme panelinde aynı okuma geçerlidir.

Yapısal anatomi: alt kameralar ve viewport

ArrayCamera, bir dizi PerspectiveCamera (nadiren OrthographicCamera) nesnesini bir arada tutan bir kapsayıcı kameradır. En kritik parça, her alt kameranın tuval üzerindeki yerini belirleyen viewport ayarıdır.

  • Viewport: Her alt kamerada viewport (veya renderer yolunda eşdeğeri), tuval üzerindeki (x, y, genişlik, yükseklik) dörtlüsüdür — GPU’ya “projeksiyonu bu dikdörtgene yay” der. WebGL’de koordinat kökeni çoğu zaman sol alttır; aşağıdaki paragraf CSS alışkanlığından farkı anlatır. Bu sayfadaki canlı demo ve üretim örneği piksel viewport kullanır; resize’ta genişlik / yükseklik yeniden hesaplanmalıdır. Kritik eşleşme: alt kameranın aspect değeri, viewport’un genişlik / yükseklik oranına eşit olmalıdır — aksi halde görüntü ezilir (demo ipuçları ve uygulama kodu). Komşu panele taşmayı kesmek için makas (scissor) çoğu zaman viewport ile birlikte düşünülür; ayrıntı alttaki mor callout’tadır.
  • Senkronizasyon: Tüm alt kameralar aynı Scene grafiğini paylaşır — ayrı sahne kopyası veya dört bağımsız render() döngüsü gerekmez. Her alt kamera yine bir Object3D: kendi position, rotation, fov / near / far (veya ortografik sınırları) ile farklı kadraj üretir; animasyon ve fizik bir kez güncellenir, dört panel aynı kare anını gösterir. Oyuncu A ile oyuncu B’nin kamerası aynı dünyada farklı noktalardaysa bu bağımsızlık sayesinde mümkündür — CubeCamera gibi çevre dokusu üretmez, doğrudan ekrana bölünmüş bakış çizer.

Normalize tuval koordinatları (WebGL): Viewport genelde tuvale göre 0–1 arası ifade edilir; (0, 0) köşe sol alt, (1, 1) sağ üsttür (y ekseni yukarı doğru büyür). CSS ile üst/sol köşeden konumlandırma alışkanlığı olanlar için bu fark önemlidir: aynı “üstteki panel” WebGL’de yüksek y değerine karşılık gelir.

İleri: viewport ve scissor

Viewport: Projeksiyonu bu dikdörtgene sığdırır; yani “kamera görüntüsü hangi piksel alanına yayılacak?”

Scissor (makas) testi: Çizimin yazılacağı piksel alanını kırpar; çoklu alt render’da genelde viewport ile birlikte kullanılır ki bir alt görünüm komşu bölgelere taşmasın. Three.js çoklu bakış yollarında bu ikisi pratikte sık yan yana gelir.

Viewport + scissor birlikte: Viewport, NDC’den ekrana projeksiyonun hangi dikdörtgende ölçekleneceğini söyler; scissor ise raster aşamasında renk ve derinlik yazımını hangi piksel alt kümesine kısıtlar. Döngülü render() yazarken ikisini çoğu zaman aynı piksel dikdörtgeninde eşleştirmek, komşu panele taşmayı ve “hayalet” fragment’leri kesmek için en güvenli kalıptır.

Derinlik tamponu (tek hedef): Varsayılan çerçeve tamponunda tipik olarak tek bir depth buffer paylaşılır; her alt geçiş yalnızca kendi viewport alanındaki piksellere yazar. Paneller birbirinden ayrık olduğu sürece bir panelin derinlik değeri komşunun piksellerini budamaz; bu, çoklu bakışta doğruluk için önemlidir. Aynı panel içinde üst üste binen yüzeylerde z-fighting algısı yine oluşabilir; çoklu bakış bunu tek başına çözmez.

Etkileşimli demo: tek sahne, dört bakış

Aşağıda aynı sahne ortak: zemin ızgarası, merkezde anker küp (biraz daha büyük; yüz tonları + hafif emissive, belirgin kenar), köşede eksen okları (X/Y/Z). Dört alt kamera öğretici set: Front / Right / Top / Free (Türkçe: ön · sağ · üst · serbest orbit). Ön / sağ hafif yukarı, üst tam tepe değil (ufak X/Z offset); blueprint düzü yerine 3B derinlik okunur. Renkli küre ve sahnedeki görüş çizgileri hangi alt kameranın ankere baktığını gösterir; köşe etiketinin üzerine gelince hem etiket hem çizgi hem de tuval kenarında viewport glow ile eşleşme güçlenir.

Üstteki şema, 2×2 Front / Right / Top / Free düzenini özetler (kavramsal). Alttaki canlı demo aynı mantıkla tuvali viewport’lara böler; köşe yazıları WebGL normalize düzlemde (0,0) sol alt, (1,1) sağ üst köşesine karşılık gelir.

Tek sahne · çoklu bakış — FPS

Tek render(); ArrayCamera; her alt kamerada çizim tamponu pikseli viewport.

Görünüm sayısı
Front (Ön) Konum (0, 1.2, 4) · +Z ön · anker küp
Right (Sağ) Konum (4, 1.2, 0) · +X sağ · anker
Top (Üst) Konum (0, 5, 0.01) · neredeyse tepe, hafif tilt
Free (Serbest) Orbit · dönen bakış

Bu demo yalnızca ArrayCamera + tek render() yolunu gösterir: aynı sahne, alt kameraların her birinde tanımlı piksel viewport ile tek çağrıda çizilir. Üretimde alternatif olarak her kamera için döngüde setViewport / setScissor + ayrı render() da kullanılabilir; bu sayfa o kalıbı teoride anlatır, arayüzde ise yalnızca ArrayCamera vardır.

Görünüm sayısı 1 / 2 / 4 olarak değiştikçe hem viewport düzeni hem de aktif alt kamera sayısı güncellenir. GPU, kaç panel olursa olsun sahneyi her görünüm için yeniden rasterize eder; ArrayCamera’nın pratik kazancı çoğu projede tek çağrı ve daha sade senkronizasyon tarafındadır. İlk yüklemede tek görünüm seçilidir; 2 veya 4 paneli radyo ile açarak düzeni inceleyebilirsiniz.

Aynı karede çoklu bakış: Tek render() ile tüm alt kameralar aynı zaman damgasında işlendiği için çoklu viewport düzenleri genelde stabil ve okunaklı kalır. Hizasız küp veya ızgara çoğu zaman aspect / projeksiyon ile viewport pikselinin uyuşmamasıdır; doğrulama ve ince ayar için Son karar (doğrulama ve demo kapsamı) bölümüne bakın.

İpucu: Az sayıda viewport ve statik sahnelerde fark küçük olabilir; ancak kamera sayısı arttıkça ArrayCamera avantajı daha belirgin hale gelir. Özellikle dört panelde küp veya ızgara hizası “biraz kaymış” görünüyorsa önce viewport ile aspect / projeksiyon eşleşmesine bakın (aşağıdaki tablo, notlar ve kontrol listesi).

Bağlantı: Her köşe etiketi, aynı renkteki alt kamera küresi ve ankere giden çizgi ile eşleşir. Fareyi etiketin veya o paneldeki sahnenin üzerine getirince vurgu artar; hangi viewport’un hangi bakışa ait olduğunu bir bakışta kapatırsınız.


Üstteki etkileşimli sahne (diagram-array-camera.js, kök data-array-camera-demo) ile aynı sayıları ön harita tabloda topladık; aşağıdaki kod özeti demodaki anker, klip düzlemleri, alt kamera yerleşimi ve viewportNorm → piksel dönüşümünü hatırlatır. Ara yüzde değişenler HUD satırında; kalan satırlar dosyadaki sabitlerdir. Tür sütunu: ekran kontrolleri ile kaynak koddaki değerleri ayırır.

diagram-array-camera.js — Sayfa Demosu Sabitleri (array-camera.html playground)
Sahne / rol Parametre Değer Tür
Ortak · renderer WebGLRenderer antialias: true, alpha: false, powerPreference: "high-performance" 🔒 Sabit
Piksel oranı / renk min(devicePixelRatio, 2) · çıkış SRGBColorSpace (destekleniyorsa) · setClearColor(0x05060c) 🔒 Sabit
Ortak · sahne Scene.background 0x05060c 🔒 Sabit
Işıklar AmbientLight 0xffffff, yoğunluk 0.42 🔒 Sabit
DirectionalLight 0xffffff · 1.15; konum (4, 9, 6) 🔒 Sabit
Zemin GridHelper Boyut 16, bölüm 32; renkler 0x3a4a6a / 0x1a2030; position.y = -0.6 🔒 Sabit
Anker küp BoxGeometry / çoklu yüz Kenar 1.32; merkez yaklaşık y = 0.35 · MeshStandardMaterial (yüz başına ton + hafif emissive) 🔒 Sabit
Çerçeve + eksen EdgesGeometry · AxesHelper Kenar opaklık 0.88; eksen uzunluk 1.58 (küp ile hizalı) 🔒 Sabit
Alt kamera · ortak PerspectiveCamera FOV 40°, clip 0.0880 🔒 Sabit
Renk kodları · COLORS front 0x5ec8ff · side 0xc86bff · top 0x7dff9a · orbit 0xff9f6e 🔒 Sabit
viewportNorm → piksel · resize / updateAspects 0–1 yerleşim userData.viewportNorm; çizim tamponu canvas.width / height ile subCamera.viewport ve aspect = pw/ph 🔒 Sabit
Dört panel yerleşimi · normalize (x,y,w,h) Örn. 4 görünüm: üst sıra (0,0.5,0.5,0.5), (0.5,0.5,0.5,0.5); alt sıra (0,0,0.5,0.5), (0.5,0,0.5,0.5) — WebGL sol alt köşe 🔒 Sabit
Yardımcı + çizgi · küre · Line Küre yarıçap 0.17; çizgi opaklığı taban 0.28 (hover’da artar) 🔒 Sabit
Front / Right / Top position + lookAt(origin) (0, 1.2, 4) · (4, 1.2, 0) · (0, 5, 0.01); origin = (0, 0.35, 0) 🔒 Sabit
Free (orbit) dairesel yörünge Yarıçap 6.15; açı += dt×0.058; dikey y ≈ 1.48 + sin×0.34; lookAt(origin) 🔒 Sabit
HUD Görünüm sayısı ArrayCamera + tek render() · 1 / 2 / 4 panel 🔧 HUD
// diagram-array-camera.js — Sayfa Demosu Sabitleri (üstteki tablo ile; özet)

const COLORS = {
  front: 0x5ec8ff,
  side: 0xc86bff,
  top: 0x7dff9a,
  orbit: 0xff9f6e,
};

const NEAR = 0.08;
const FAR = 80;
const CUBE_SIZE = 1.32;
const ORIGIN = new THREE.Vector3(0, 0.35, 0); // anker (küp merkezi)

// Alt kamera şablonu: FOV 40° — viewport pikseli resize’ta userData.viewportNorm’dan
// aspect = (norm.z * bufW) / (norm.w * bufH); updateProjectionMatrix()

// Bakış konumları (lookAt → ORIGIN)
// Front (0, 1.2, 4) · Right (4, 1.2, 0) · Top (0, 5, 0.01)
// Free: orbit yarıçap 6.15; orbitAng += dt * 0.058; y = 1.48 + sin(orbitAng * 0.38) * 0.34

// ArrayCamera: new THREE.ArrayCamera(subCameras.slice(0, viewCount));
// renderer.render(scene, arrayCamera); // 1 panel: doğrudan subCameras[0]

“Sahne yok” gibi; ne zaman endişe?

ArrayCamera yolunda yalnızca köşe yazıları görünüp 3B içerik boş hissediliyorsa, bu çoğu zaman “sahne yok” değil; tek render() içinde viewport / projeksiyon / bakış vektörü zinciri tam oturmamış demektir. Aynı sahneyi hata ayıklamak için döngüde her kamera için ayrı render() denemek de yaygındır; bu demoda yalnızca ArrayCamera yolu gösterilir.

Kontrol listesi (üretimde de aynı):

  • Viewport (r170, WebGLRenderer + ArrayCamera) Alt kameranın viewport değeri bu yolda çizim tamponu pikseli olarak gl.viewport’a iletilir; 0–1 normalize bırakırsanız pratikte birkaç piksel alanına sıkışır ve sahne “yok” görünür. Bu demoda yerleşim userData.viewportNorm (0–1, sol alt orijin) olarak tutulur; resize sonrası subCamera.viewport.set(nx*bufW, ny*bufH, nw*bufW, nh*bufH) ile piksele çevrilir. Çoklu render() döngüsünde setViewport / makas ile aynı ölçeği koruyun.
  • Aspect + matris Her alt görünüm için aspect = o panelin viewport piksel eni ÷ boyu; ardından updateProjectionMatrix()atlanırsa veya viewport ile uyumsuzsa küp/ızgara “kaymış” veya sıkışmış görünür. Çoklu render() döngüsünde her iterasyonda setViewport / setScissor ile aynı w, h üzerinden hesaplayın.
  • Bakış position + lookAt (veya eşdeğeri) sahneye kilitlenmezse “boş” veya tek renk alan hissi oluşur.

Viewport, aspect ve (alternatif) döngüde çoklu render()

Dört görünümde bazı panellerde küpün hafif yan kaymış veya ızgaranın tam oturmamış görünmesi çoğu zaman “kamera kötü” değil, genişlik ÷ yükseklik ile çizim alanının uyuşmamasıdır: yani camera.aspect güncellenmeden viewport değişmiş demektir. Bu demoda resize sonrası her alt kamera için aspect = viewportGenişliği / viewportYüksekliği ve updateProjectionMatrix() uygulanır.

Çoklu render() kullanırken (genel kural): her alt görünüm için, o pass’ten hemen önce sırayla şunların tutarlı olması gerekir:

  • renderer.setViewport(x, y, w, h) ve gerekiyorsa renderer.setScissor(x, y, w, h) ile aynı dikdörtgen; setScissorTest(true) komşu bölgelere taşmayı keser.
  • camera.aspect = w / h ardından camera.updateProjectionMatrix() — atlanırsa projeksiyon yanlış en-boy oranında kalır ve sahne “kaymış” görünür.

Bu tür algı farkları eğitim ve keşif içeriğinde genelde sorun teşkil etmez; ürün veya stüdyo demosunda ise son ince ayar (tam senkron pipeline, sabit zaman adımı vb.) tercih edilebilir. Bu sayfadaki dört bakış (ön, sağ, hafif tilt üst, orbit) üretim tarafında da tutarlı, okunaklı bir set olarak düşünülebilir.

Son karar: doğrulama, ince hizalama ve demo kapsamı

Kalan fark ne? Viewport / aspect düzeltmelerinden sonra görüntü belirgin şekilde daha stabil; bariz bir hata kalmaması beklenir. Motor ve sürüme göre viewport piksel yuvarlaması veya kayan nokta hassasiyeti kaynaklı çok ince farklar görülebilir; bu tür durumlar çoğu eğitim demosunda pratik sorun teşkil etmez. Bu bir bug değildir; “piksel mükemmel” hizalama gerekiyorsa ek doğrulama ve sabit çözünürlük senaryoları düşünülür.

Sistem doğru mu? Pratik doğrulama: 1 görünümde tek panel tutarlı; 2 görünümde düzen simetrik; 4 görünümde her bakış doğru eksen / açıdan okunuyorsa, kamera dönüşümü + projeksiyon hattı tutarlı demektir. Ön bakış net ve ankere kilitli; sağ eksen okunabilir; üst tam düz değil, hafif tilt; derinlik için doğru tercih; serbest orbit dinamik bakış hissi verir. Bu set salt “tutorial” değil; ürün / eğitim içeriğinde rahatlıkla kullanılabilecek düzeyde okunaklıdır.

Ek model gerekir mi? Hayır; bu demodaki amaç zengin sahne göstermek değil, viewport + ArrayCamera render hattını okunaklı göstermektir. Fazla obje dikkati dağıtır; mevcut sade küp + ızgara + eksen bu hedef için uygun seçimdir.

İsteğe bağlı “bir üst seviye” dokunuşlar (hiçbiri zorunlu değildir): aktif viewport’ta hafif vurgu, hover’da kamera → küp çizgisinin güçlenmesi, köşe etiketlerinde kısa giriş animasyonu. Canlı demoda fareyle panel / sahne üzerinde glow ve çizgi opaklığı zaten güncellenir; ekstra animasyon tamamen tercihe bağlıdır.

Uygulama: dörtlü bölünme kurulumu

Aşağıdaki örnek, ekranı dört eşit panele böler; her alt kamera farklı bir konumdan sahneye bakar. Üretimde pencere oranı değişince her alt kameranın aspect ve viewport değerlerini güncellemeyi unutmayın. Canlı demodaki (diagram-array-camera.js) yerleşim ve hata ayıklama notları için bölüm 3’teki kontrol listesine bakın.

// diagram-array-camera.js ile aynı fikir:
// — yerleşimi 0–1 (sol alt) userData.viewportNorm’da tut
// — ArrayCamera yolunda subCamera.viewport = çizim tamponu pikseli + aspect = pw/ph

const subCameras = [];
const origin = new THREE.Vector3(0, 0.35, 0); // anker (demodaki küp merkezi)

const layoutsNorm = [
  new THREE.Vector4(0, 0.5, 0.5, 0.5),
  new THREE.Vector4(0.5, 0.5, 0.5, 0.5),
  new THREE.Vector4(0, 0, 0.5, 0.5),
  new THREE.Vector4(0.5, 0, 0.5, 0.5),
];

const positions = [
  new THREE.Vector3(0, 1.2, 4),
  new THREE.Vector3(4, 1.2, 0),
  new THREE.Vector3(0, 5, 0.01),
  new THREE.Vector3(3.5, 1.5, 3.5), // Free: demoda orbit; burada örnek sabit bakış
];

function applyViewportPixels(subCamera, norm, bufW, bufH) {
  subCamera.userData.viewportNorm = norm.clone();
  const pw = norm.z * bufW;
  const ph = norm.w * bufH;
  subCamera.aspect = pw / Math.max(1, ph);
  subCamera.updateProjectionMatrix();
  subCamera.viewport.set(norm.x * bufW, norm.y * bufH, pw, ph);
}

for (let i = 0; i < 4; i++) {
  const subCamera = new THREE.PerspectiveCamera(40, 1, 0.08, 80);
  subCamera.position.copy(positions[i]);
  subCamera.lookAt(origin);
  const canvas = renderer.domElement;
  applyViewportPixels(subCamera, layoutsNorm[i], canvas.width, canvas.height);
  subCameras.push(subCamera);
}

// Her resize / setSize sonrası: layoutsNorm[i] ile applyViewportPixels(...) tekrar

// 2. ArrayCamera
const camera = new THREE.ArrayCamera(subCameras);

// 3. Render döngüsünde tek çağrı
renderer.render(scene, camera);

Teknik tablo: ArrayCamera avantajları

Özellik Geleneksel çoklu render ArrayCamera yaklaşımı
GPU / çağrı düzeni Her görünüm için ayrı render döngüsü veya manuel viewport yönetimi Tek render() içinde çoklu görünüm; viewport atamaları çerçevelenmiş akış
CPU / JS gecikmesi Döngüde birden çok .render() — senkronizasyon zorlaşabilir Tek çağrı; tüm alt görünümler aynı kare zamanında planlanır
Senkronizasyon Kareler arasında mikro kaymalar olabilir Aynı sahne anı; bakışlar tutarlı güncellenir
Kod karmaşıklığı Manuel viewport, makaslama ve temizleme sırası Alt kameralara viewport bağlama; ArrayCamera ile toplu kullanım
GPU yükü (netleştirme) Her alt görünüm için geometri ve piksel işi yapılır — yani sahne karmaşıklığı görünüm sayısıyla çarpılır. Kazanç, çoğunlukla tek render pipeline / tek çağrı düzeni ve daha iyi senkronizasyondadır; “bedava dört kamera” değildir.

Post-processing ve tam ekran geçişler

Hazır post zincirleri (ör. bloom, SSAO, TAA, tonemap) çoğu zaman tek tam ekran dikdörtgeni ve tek kamera projeksiyonu üzerinden tasarlanır. ArrayCamera ile birlikte kullanmak, bu geçişleri her alt görünüm için ayrı hedef / ayrı rect düşünmeyi gerektirir; aksi halde efekt yanlış bölgeye uygulanır veya birleştirme (kompozit) adımı eksik kalır. Yoğun post için çoklu bakışı genelde ikinci bir tampon, düşük çözünürlüklü ortak geçiş veya son kompozitör katmanıyla planlamak gerekir; bu yüzden bölüm 6’daki “post-processing zorlaşır” uyarısı pratikte “pipeline’ı baştan bölersiniz” anlamına gelir.

Döngülü render() ve clear / autoClear

Bu sayfadaki canlı demo yalnızca ArrayCamera yolunu gösterir; üretimde ise klasik desen olarak her bakış için setViewport ve çoğu zaman setScissorTest(true) ile döngüde birden fazla render() yazılabilir. Bu kalıpta hangi adımda renk veya derinlik temizlediğiniz doğrudan sonucu belirler: örneğin kare başında bir kez tam ekran clear, sonraki panellerde yalnızca clearDepth; veya ara geçişlerde autoClear’i kapatıp yalnızca ihtiyaç duyulan bölgeleri temizlemek. Sıra, makas ve viewport hizası; bir panelde “sahne yok” veya garip üst üste binme hissinin sık nedenlerindendir.

Sınırlar, ne zaman kullanılmaz ve dikkat

ArrayCamera kullanışlıdır; yine de sınırları vardır. Aşağıdaki üç başlık, bölüm 2 anatomisi ve bölüm 1’deki iç döngü uyarısıyla birlikte okunmalıdır; çoğu üretim hatası burada toplanır.

  • Homojen türler: Split-screen ve gözetimde dizinin tamamı PerspectiveCamera olması en sorunsuz yoldur: aynı projeksiyon güncelleme kalıbı (aspect, updateProjectionMatrix()) her panele uygulanır. Bölüm 1’deki gibi ana bakış perspektif, küçük panel ortografik (harita / dikiz düzlemi) karışımı mümkündür; o zaman her alt kamera türüne göre ayrı parametre seti ve test gerekir — motor “hepsi aynı sınıf” varsayımıyla daha az sürpriz verir. CubeCamera veya render hedefi üreten kameraları bu diziye karıştırmayın; amaç ekrana bölünmüş bakıştır.
  • Dinamik boyutlandırma: Pencere resize olduğunda yalnızca ana kameranın aspect’ini güncellemek yetmez: her alt kameranın viewport piksel dikdörtgeni (veya normalize yerleşimden türetilmiş hali) ve aspect = panelGenişliği / panelYüksekliği değeri döngüyle yeniden yazılmalı, ardından updateProjectionMatrix(). renderer.setSize ile tuval boyutu senkron kalmazsa paneller kayar veya ezilir — demodaki 1 / 2 / 4 görünüm düzeni de aynı hesabı tetikler. Tam kalıp dörtlü kurulum örneğinde; “sahne yok” hissi çoğu zaman viewport / aspect uyumsuzluğudur (bölüm 3 kontrol listesi).
  • Gölge ve ışık: Işıklar ve gölge haritaları sahne için ortaktır — dört ayrı sahne ışığı kurmazsınız. Buna rağmen her alt geçişte geometri ve gölgelenebilir malzemeler yeniden çizilir; dört panel kabaca dört kez geometri maliyeti demektir (iç döngü). Gölge haritası çözünürlüğü ve ışık sayısı tek bakışa göre aynı kalsa bile toplam kare süresi artar; mobilde küçük panellerde gölgeyi kapatmak veya alt kamera sayısını düşürmek yaygındır. Profil çıkarırken 1 panel ile 4 paneli aynı sahnede karşılaştırın — API sadeleşmesi GPU’yu otomatik ucuzlatmaz.

Ne zaman (genelde) tercih etmeyin? Çoklu bakış ürün gereksinimi değilse basit yol daha az hata ve daha düşük maliyet bırakır; aşağıdakiler tipik “geri dön” işaretleridir.

  • Tek bakış yeterliyse: Tek oyunculu gezinti, ürün turu veya sinematik kamera yalnızca bir kadraj ister — PerspectiveCamera ve tek render() yeterlidir. Çevrim içi çok oyuncuda her istemci zaten kendi ekranını çizer; sunucu tarafında dörtlü split nadirdir. ArrayCamera ekler: viewport döngüsü, resize senkronu, panel başına aspect testi ve “boş köşe” hata ayıklama — ihtiyaç yoksa bu yükü almayın.
  • Mobil ve düşük güç: Dört çeyrek ekran telefonda okunaksızdır; parmak ve UI üst üste biner. İç döngü nedeniyle GPU maliyeti panel sayısıyla ölçeklenir; gölge ve yüksek çözünürlük küçük panellerde daha da acıtır (yukarıdaki ışık maddesi). Kalite menüsünde split-screen’i kapatmak, en fazla 2 panel veya düşük görünüm sayısı (demo 1 / 2 / 4) yaygın çözümdür — masaüstü monitör hedefliyorsanız planlayın.
  • Yoğun post-processing zinciri: EffectComposer ve bloom, SSAO, renk düzeltme gibi geçişler çoğu zaman tam tuval varsayar. ArrayCamera ile ham sahne bölgelere bölünür; efekt zinciri otomatik uyum sağlamaz. Seçenekler: her panel için ayrı render hedefi (RT) + kompozit, önce tüm panelleri ortak bir tampona birleştirip sonra tek fullscreen pass, veya post-process’i yalnızca ana panele uygulayıp küçük panelleri ham bırakmak. Sayfa girişinde de belirtildiği gibi bu sınır, split-screen kararında erken düşünülmelidir — sonradan eklemek mimari maliyetlidir.

Holodepth notu: neden viewport?

Varsayılan olarak renderer tüm tuvali boyar. ArrayCamera kullanırken her alt kameraya bir çizim alanı (viewport) vermezseniz, görünümler üst üste binebilir veya yalnızca son ayar öne çıkabilir. Viewport, GPU’ya şunu söyler: “Bu kameranın çıktısını tuvale yalnızca şu koordinatlar arasına yaz.”; split-screen ve çoklu monitör düzeninin teknik karşılığı budur.

Pratik hata ayıklama için bölüm 3’teki “Sahne yok” kontrol listesine bakın; özellikle normalize mi piksel mi ve aspect güncellemesi çoğu “boş panel” vakasını çözer.