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 kameraaspect’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
ArrayCameraile 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ınaspectdeğeri, viewport’ungenişlik / yükseklikoranı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ı
Scenegrafiğini paylaşır — ayrı sahne kopyası veya dört bağımsızrender()döngüsü gerekmez. Her alt kamera yine birObject3D: kendiposition,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 —CubeCameragibi ç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 render(); ArrayCamera; her alt kamerada çizim tamponu pikseli
viewport.
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.
| 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.08 … 80 |
🔒 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
viewportdeğeri bu yolda çizim tamponu pikseli olarakgl.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şimuserData.viewportNorm(0–1, sol alt orijin) olarak tutulur;resizesonrasısubCamera.viewport.set(nx*bufW, ny*bufH, nw*bufW, nh*bufH)ile piksele çevrilir. Çoklurender()döngüsündesetViewport/ 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ındanupdateProjectionMatrix()— atlanırsa veya viewport ile uyumsuzsa küp/ızgara “kaymış” veya sıkışmış görünür. Çoklurender()döngüsünde her iterasyondasetViewport/setScissorile 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 gerekiyorsarenderer.setScissor(x, y, w, h)ile aynı dikdörtgen;setScissorTest(true)komşu bölgelere taşmayı keser.camera.aspect = w / hardındancamera.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ı
PerspectiveCameraolması 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.CubeCameraveya render hedefi üreten kameraları bu diziye karıştırmayın; amaç ekrana bölünmüş bakıştır. - Dinamik boyutlandırma: Pencere
resizeolduğunda yalnızca ana kameranınaspect’ini güncellemek yetmez: her alt kameranınviewportpiksel dikdörtgeni (veya normalize yerleşimden türetilmiş hali) veaspect = panelGenişliği / panelYüksekliğideğeri döngüyle yeniden yazılmalı, ardındanupdateProjectionMatrix().renderer.setSizeile 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 —
PerspectiveCamerave tekrender()yeterlidir. Çevrim içi çok oyuncuda her istemci zaten kendi ekranını çizer; sunucu tarafında dörtlü split nadirdir.ArrayCameraekler: 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:
EffectComposerve bloom, SSAO, renk düzeltme gibi geçişler çoğu zaman tam tuval varsayar.ArrayCameraile 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.