holodepth

Three.js · Sahne

Sahne (Scene): Three.js evreninin temeli

Three.js ile çalışırken ilk kurduğunuz yapı çoğu zaman THREE.Scene olur: mesh, ışık, grup ve yardımcı nesneler bu kökte toplanır. Sahne ekrana piksel basmaz; evrende neyin var olduğunu, nesnelerin üst–alt ilişkisini ve ortak transform kurallarını tanımlar; yani projenizin içerik ve düzen katmanıdır.

Holodepth üçlüsünde roller birbirini tamamlar: sahne yapıyı tutar, kamera hangi kesitin ekrana yansıyacağını seçer, renderer bu kesiti GPU ile çizer. Kamera ve renderer'ın ayrıntıları kamera ve renderer sayfalarında; bu metinde üçlünün sahne ayağını okuyorsunuz.

Aşağıdaki tablo üçlüyü tek bakışta özetler. Sonrasında scene graph, Object3D, eksenler, scene.traverse(), ortam özellikleri (background, fog, environment) ve sahne + kamera + renderer'ı birleştiren minimal kurulum örneğine geçilir; kamera matrisleri veya WebGL hattının içi burada tekrar anlatılmaz.

Sahne, kamera ve renderer (üçlü · hatırlatıcı)

Bileşen Teknik karşılık Ana sorumluluk
Sahne THREE.Scene Nesnelerin hiyerarşik listesini ve ortam özelliklerini (fog, background) tutmak.
Kamera THREE.PerspectiveCamera 3D uzayı matematiksel bir perspektifle 2D düzleme (ekrana) iz düşürmek.
Renderer THREE.WebGLRenderer GPU kullanarak verileri piksellere dönüştürüp canvas'a basmak.

Sahne: evrenin konteyneri ve hafızası

Sahne nedir?

Sahne, yalnızca nesnelerin bulunduğu bir kap değil; tüm 3D evrenin organizasyon ve ilişki merkezidir. THREE.Scene kök düğüm olarak mesh, ışık, grup ve yardımcı araçları aynı evrende toplar; burada kurduğunuz ilişkiler animasyon ve sahne yönetiminin omurgasıdır.

Scene graph: evrenin hiyerarşik ağacı

Sahne sadece bir liste değil, bir ebeveyn–çocuk (parent–child) ilişkisidir. Bir Group oluşturup içine üç Mesh eklerseniz, grubu hareket ettirdiğinizde içindeki nesneler kendi yerel koordinatlarını koruyarak grupla birlikte taşınır.

Kök düğüm ve graf: En üstte sahne vardır; altında Mesh, Group, Light vb. düğümler bulunur. Bir grubu döndürmek içeridekileri de döndürür; bir objeyi taşımak child’ları da taşır; bu yüzden sahne grafiği karmaşık mekanizmalar ve animasyon için hayatidir.

Object3D ve ortak transform sistemi

Three.js'te sahne dahil tüm nesneler Object3D hiyerarşisinden türetilir. Bu, hepsinin aynı temel transform arayüzünü (position, rotation, scale), üst–alt bağını (parent / children) ve sahne grafiğinde tutarlı hareket kurallarını paylaştığı anlamına gelir.

Kartezyen eksenler ve sağ el kuralı

Three.js'te evren (0, 0, 0) merkez noktasından dışarıya doğru uzanan üç hayali yol üzerine kurulur. Bu yolları (eksenleri) karıştırmamanın en pratik yolu Sağ el kuralı'dır; parmağınızı konuma göre konumlandırın:

  • X ekseni (yatay) Sağ el başparmağınız sağa baksın. Pozitif değerler sağa, negatifler sola hareket ettirir. (Kırmızı eksen)
  • Y ekseni (dikey) İşaret parmağınız gökyüzüne baksın. Pozitif değerler yukarı, negatifler aşağı (yerçekimi yönü) hareket ettirir. (Yeşil eksen)
  • Z ekseni (derinlik) Orta parmağınızı kendinize (ekranın dışına) doğru bükün. Pozitif Z size yaklaşır; negatif Z ekranın içine girip uzaklaşır. (Mavi eksen)

İpucu: Nesne ile bakış aynı noktada çakışıyorsa genelde hiçbir şey görünmez; pozisyonları Z ekseninde ayırmak sık kullanılan ilk adımdır.

Aşağıdaki mini demo, Three.js AxesHelper varsayılan renklerini gösterir; metindeki kırmızı / yeşil / mavi eşleşmesini sahne içinde doğrulayın ( OrbitControls ile döndürün).

Mini demo · sağ el · RGB eksenler OrbitControls · sürükle / tekerlek

AxesHelper köken noktasından çıkan üç ok: Three.js dünya uzayında X kırmızı, Y yeşil, Z mavidir; sağ el kuralıyla aynı kod renkleri. Izgara yalnızca derinlik sezgisi içindir; eksenler asıl referanstır. Sahne editöründeki renkli oklarla bire bir aynı sözdizimi değildir; amaç «hangi eksen hangi renk»i görmek ve kamerayı serbestçe çevirmektir.

Traversal (gezinme)

Sahnedeki tüm nesneler üzerinde işlem için scene.traverse() kullanılır; büyük sahnelerde hata ayıklama ve toplu ayarlar için kritiktir.

// Örnek: sahne ağacında tüm Mesh'leri bul
let meshCount = 0;
scene.traverse((object) => {
  if (object.isMesh) meshCount += 1;
});
console.log('Mesh sayısı:', meshCount);

Sahne = global atmosfer katmanı

Scene yalnızca nesne listesi değildir: background, fog ve environment gibi ortam kararları kökte toplanır. Ayrıntılı kod ve HDR notu için görünüm ayarları alt başlığına bakın; ışık türleri ve PBR dolgu mantığı ışık konularında kalır.

Temel metotlar ve modern teknikler

Sahne yönetiminde sık kullanılan metotlar ve optimizasyon ipuçları aşağıda özetlenir. Hepsi sahne ve sahne grafiği düzeyinde kalır: nesne ekleme/çıkarma, ortam görünümü, debug override ve traverse ile toplu bayrak. Kamera matrisleri, WebGL renderer hattı, gölge haritası kalitesi veya ışık türleri ilgili sayfalarda işlenir; burada yalnızca hangi API’nin nerede devreye girdiği gösterilir.

Nesne yönetimi (add, remove, clear)

Sahneye nesne eklemek, kaldırmak veya tüm kök altını tek seferde boşaltmak için üç temel metot yeterlidir. clear() sonrası paylaşılan geometri/materyal referanslarını gerekiyorsa ayrıca dispose() etmeyi unutmayın.

const cube = new THREE.Mesh(geometry, material);
scene.add(cube);       // Nesne ekle
scene.remove(cube);    // Nesne kaldır
scene.clear();         // Tüm sahneyi temizle (dispose ayrıca gerekebilir)

Görünüm ayarları (background, fog, environment)

Bunlar Scene özellikleridir: tek renk veya doku arka planı, sis ve (PBR projelerinde) HDR tabanlı ortam yansıması. Işık nesneleri sahneye add edilir; scene.environment materyallere yansıyan ortam terimini besler; ışık türleri ve dolgu mantığı ışık konularında ayrı işlenir.

scene.background = new THREE.Color(0x111122);   // Koyu mavi arka plan
scene.fog = new THREE.FogExp2(0x111122, 0.02); // Hafif sis
// scene.environment = hdrTexture; // HDR / PMREM — materyal ve IBL konularında ayrıntı

Hata ayıklama (overrideMaterial)

Tüm sahneyi geçici olarak tek malzeme ile çizer; geometri hacmini veya draw yoğunluğunu materyal karmaşası olmadan görmek için kullanılır. İş bitince mutlaka null yapın.

scene.overrideMaterial = new THREE.MeshStandardMaterial({
  color: 0xff0000,
  transparent: true,
  opacity: 0.5,
});
// … inceleme …
scene.overrideMaterial = null;

Optimizasyon teknikleri

  • Frustum culling (doğuştan) Kameranın görüş hacmi dışındaki nesneler varsayılan olarak çizilmez; sahne tarafında ekstra kod gerekmez — kamera sayfasında frustum mantığı anlatılır.
  • LOD (Level of Detail) Uzaklığa göre daha düşük poligonlu mesh’e geçiş; ayrıntı Geometry Optimization konusunda.
  • Instancing Binlerce kopya için InstancedMesh — tek draw call ailesi; Instancing sayfasına bakın.
  • Katmanlar (object.layers) Nesneleri katmanlara ayırıp hangi kameranın neyi göreceğini seçersiniz; UI / ana sahne ayrımı için sık kullanılır (kamera katman API’si kamera bağlamında tamamlanır).
uiObject.layers.set(1);
camera.layers.disable(1);
uiCamera.layers.enable(1);
uiCamera.layers.disable(0);

Gölge bayrakları (sahne + renderer köprüsü)

Gölge hesabı renderer (shadowMap) ve gölge atan ışık tarafında kurulur. Sahne tarafında yapılan iş, grafiği dolaşıp hangi mesh’in gölge üreteceğini / alacağını ( castShadow, receiveShadow) toplu açmaktır; gölge haritası kalitesi veya ışık türleri burada işlenmez.

// Renderer: gölge hesaplamayı aç (ayrıntı renderer sayfasında)
renderer.shadowMap.enabled = true;

// Sahne: hangi mesh gölge üretir / alır — ışık ayarı ayrı konu
scene.traverse((object) => {
  if (object.isMesh) {
    object.castShadow = true;
    object.receiveShadow = true;
  }
});

Sahne büyüdükçe traverse maliyeti ve draw call sayısı artar; sahne yönetimi yalnızca görsel düzen değil, performans mühendisliği konusudur. Renderer’ın kare başına bu sahneyi nasıl işlediği renderer giriş sayfasında kalır.

Üçlü pratikte renderer.render(scene, camera) ile birleşir; aşağıdaki örnek bu çağrıyı minimal bir kurulumda gösterir.

Tam örnek: sahne + kamera + renderer

Aşağıdaki blok, yukarıdaki bağlamı tek dosyada toplayan minimal bir kurulumdur; sahne kurulduktan sonra kamera ve renderer ile animasyon döngüsüne bağlanır.

Editor örneğinin yapısı (diyagram)
Scene Mesh (Box) DirectionalLight
PerspectiveCamera scene + camera WebGLRenderer canvas

Bu sürümde PerspectiveCamera çoğu zaman scene.add(camera) ile grafiğe eklenmez; yine de renderer.render(scene, camera) satırında ikili birlikte kullanılır. İsterseniz kamerayı da sahneye ekleyerek tek kökten traverse ile yönetebilirsiniz.

import * as THREE from 'three';

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a0c12);

const camera = new THREE.PerspectiveCamera(
  50,
  window.innerWidth / window.innerHeight,
  0.1,
  100
);
camera.position.z = 5;

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);

const mesh = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  new THREE.MeshStandardMaterial({ color: 0x5ec8ff })
);
scene.add(mesh);

const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(2, 3, 4);
scene.add(light);

function animate() {
  requestAnimationFrame(animate);
  mesh.rotation.y += 0.01;
  renderer.render(scene, camera);
}
animate();

Demo sabitleri tablosu (editor örneği)

Aşağıdaki tablo, üstteki tam editor kodundaki sayısal değerlerin ön haritasıdır. Bu sayfada canlı WebGL demosu yoktur; sabitler doğrudan gösterilen main.js bloğundan okunur. Diyagram ile birlikte kullanın.

scene-entry.html — Tam örnek editör bloğu (#box-code-editor-triad-full)
Sahne / rol Parametre Değer Tür
Scene · ortam scene.background new THREE.Color(0x0a0c12) 🔒 Sabit
PerspectiveCamera fov 50 🔒 Sabit
aspect window.innerWidth / window.innerHeight ↔ Pencereye bağlı
near / far 0.1 / 100 🔒 Sabit
camera.position z = 5 (x, y varsayılan 0) 🔒 Sabit
WebGLRenderer Oluşturucu seçenekleri { antialias: true } 🔒 Sabit
setPixelRatio Math.min(window.devicePixelRatio, 2) ↔ Cihaza bağlı (üst sınır 2)
Mesh · geometri BoxGeometry 1 × 1 × 1 🔒 Sabit
Mesh · materyal MeshStandardMaterial.color 0x5ec8ff 🔒 Sabit
DirectionalLight renk · yoğunluk · position 0xffffff · 1 · (2, 3, 4) 🔒 Sabit
Animasyon döngüsü mesh.rotation.y artışı += 0.01 / kare 🔒 Sabit
Modül import three (örnek varsayım; bundler / CDN projenize göre) ℹ Bağlam

Püf noktası: siyah ekran

Her şeyi doğru yaptığınızı düşünüyorsanız ama ekran siyah kalıyorsa: ya bakış noktası mesh'in içinde kalmıştır (Z pozisyonunu artırarak ayırın) ya da MeshStandardMaterial kullanıyorsanız sahneye yeterli ışık eklememiş olabilirsiniz; PBR malzeme ışık gerektirir.