holodepth

Three.js · Işık · Konik odak

SpotLight: Sahne ışığı ve dramatik odak

Karanlık ile aydınlık arasındaki keskin geçişi sen yönetirsin

SpotLight, tek bir noktadan doğan ancak PointLight’ın aksine yalnızca belirli bir konik alan içinde yayılan ışık türüdür. Işığın sınırlarını net görebildiğin, karanlık ile aydınlık arasındaki o geçişi kontrol edebildiğin en güçlü yer burasıdır.

Tiyatral bir atmosfer yaratmak, bir objeyi sahneye çıkarmak veya karanlığı bir el feneriyle delmek için en güçlü fırçandır.

Bağlam: DirectionalLight (paralel güneş), PointLight (tam küre), Materyal Giriş.

Zihin modeli: ışık konisi

Ampul değil — karanlığı belirli bir açıyla süpüren koni

  • Kaynak: Tek bir koordinat noktasıdır.
  • Yayılım: Konik — açıyla sınırlanmış bir hacim.
  • Yönelim: SpotLight yönünü position ile target.position arasındaki vektöre göre belirler.
  • Amaç: Sahne spotları, el fenerleri, araba farları ve odak noktası oluşturma.

Apex ve hedef: koninin omurgası

Spot geometrisini düşünürken zihninde tepe noktası (apex) ile hedef arasında tek bir eksen çiz: koni bu eksen etrafında döner. position apex’i, target.position ise koninin “baktığı” dünya noktasını taşır; ikisi aynı hizada değilse koni eğilir ve gölge frustum’u beklediğin hacmi kapsamayabilir. Bu yüzden hedefi bir Object3D üzerinden animasyonla taşımak, sahnede “takip eden sahne ışığı” kurmanın en doğrudan yoludur.

Point’ten sonra gelen kesim

PointLight tüm küreyi besler; SpotLight ise aynı enerjiyi önce konik bir hacme keser, sonra mesafe ve decay ile zayıflatır. Bu kesim, hem performans hem de dramaturji açısından “nerenin aydınlık kalacağını” açıkça seçmeni sağlar — özellikle iç mekân ve vitrin sahnelerinde vinyet hissi buradan gelir.

Kritik parametreler: açık ve yumuşaklık

SpotLight’ı “gerçekçi” kılan şey, dairesel ışık lekesinin kenarlarını nasıl yönettiğindir:

  • angle (açı): Koninin ne kadar geniş olacağını belirler. Değer radyan cinsindedir ve API’de yarı açı (half-angle) olarak tanımlanır — örneğin Math.PI / 6 yaklaşık 30° yarı açı demektir; tam açılık konik kesit kabaca 60° olur (2 × angle).
  • penumbra (yarı gölge): Işık lekesinin kenarlarının ne kadar yumuşak geçeceğini belirler. penumbra, tam sert kenar ile yumuşak geçiş arasında bir bölge oluşturur (0–1 aralığında düşün).
  • decay (sönümlenme): Fiziksel tabanlı aydınlatma kullandığında bu değer genellikle 2 olmalıdır — mesafeyle parlaklık düşüşü bu sönümle uyumludur.

Açı birimi: derece değil, radyan

API’de angle her zaman radyan cinsindedir; editör veya HUD’da derece gösteriyorsan degToRad ile çevirmeyi unutma. Açıyı daraltmak koni kesitini inceltir — aynı distance ve intensity ile bile sahne daha “sinematik” ve odaklı okunur; geniş açı ise daha çok genel dolguya yaklaşır.

angle = yarı açı (half-angle)

Three.js’te spotLight.angle koninin yarı açısıdır (eksenden koni yüzeyine kadar olan açı). Bu yüzden sezgisel “tam konik açı”yı düşünüyorsan gerçek açılık kabaca 2 × angle olur — half-angle varsayımını kaçırırsan sahneyi veya editör HUD’unu yanlış ölçeklersin (dar/geniş koni, gölge frustum’u, sahne planı).

Yoğunluk: enerji koninin içine

SpotLight’ta parlaklık fikri, enerjinin konik hacim / kesit içinde dağıtılmasıdır: angle küçüldükçe aynı intensity daha dar bir alana sıkışır — yani aynı enerji daha küçük taban üzerine yoğunlaşır ve leke merkezi görece daha parlak okunur. Geniş açıda enerji daha geniş bir tabana yayılır; bu yüzden “sadece açıyı daraltayım” dediğinde çoğu zaman intensity’yi de birlikte dengelemek gerekir.

Demodaki decay (2.38) notu

Fiziksel taban için decay = 2 sık tercih edilir; bu sayfadaki interaktif demoda ise menzil düşüşünü biraz daha hissettirmek için 2.38 kullanılır (SPOT_DECAY_DEMO). Kendi üretiminde bu değeri kopyalamadan önce sahne ölçeği ve ton eşlemesiyle birlikte A/B yap: abartılı decay, yakın nesneleri hızla karartır ve distance sürgüsünün etkisini gölgede bırakabilir.

physicallyCorrectLights ve fiziksel ölçek

Eski Three.js sürümlerinde renderer.physicallyCorrectLights = true ile intensity daha çok candela benzeri bir ölçeğe yaklaşır; SpotLight için de decay = 2 fiziksel modda beklenen taban olur. Güncel sürümlerde bu bayrak kaldırılmış / davranış varsayılanlarla birleşmiş olabilir — projende WebGLRenderer ve ışık birimleri için resmi migration notlarına bak.

Görsel gözlem: sahneyi nasıl etkiler?

  • Vinyet etkisi: Sahnenin geri kalanını karanlıkta bırakarak izleyicinin gözünü doğrudan ışığın merkezine yönlendirir.
  • Hacimsel gölgeler: Işık tek bir noktadan çıktığı için nesneler ışığa yaklaştıkça gölgeleri büyür; dramatik bir perspektif kazanır.
  • Yüzey dokusu: Işığı yüzeye dar bir açıyla (oblique lighting) gönderdiğinde pürüzler ve dokular en iyi bu ışıkla okunur.

Penumbra ve düz yüzey

penumbra yarı gölge bölgesi, özellikle düz zemin ve düz arka yüzeylerde ışık lekesinin kenarını yumuşatarak okunur; eğri ve karmaşık normallerde fark doğal olarak daha az belirgin kalır. Demodaki arka düzlem, bu farkı bilinçli olarak öne çıkarmak için eklenmiştir — üretimde benzer bir “okuma yüzeyi” (duvar, perde) koymak, sanatçı ile ışığı ayarlarken ortak dil oluşturur.

Penumbra: iç koni → dış koni

penumbra sıfıra yakınsa leke kenarı sertleşir; sıfırdan büyüdükçe Three.js modelinde iç bölge (inner / core cone) tam güce yakın kalırken, dış bölge (outer cone) kenara doğru yumuşakça söner — yani dış koni halkasında fade (geçiş) oluşur. Düz zeminde bu halkayı en net okursun; eğri yüzeylerde geçiş daha “dağılmış” görünür.

İnteraktif: küresel ampul vs. konik spot

Aynı torus knot + bloklar; sağda ek arka düzlem (biraz açık ton) ve daha koyu zemin penumbra kenarını okutmak için kontrast verir. Sol yarıda sıcak PointLight (kaynakta küçük glow küreleri); sağ yarıda aynı konumdan SpotLighttarget torus merkezinde. Sarı küre kaynak, emissive magenta hedef (hafif nabız), pembe çizgi apex→target (yön), sağda her zaman hafif yarı saydam koni hacmi (additive). Sürgüler yalnızca sağ spot için: angle, penumbra (HUD değeri demoda eğrilir), distance, intensity (×4.25). İki kutu: gölgeler (ışık ≠ gölge) ve koni tel kafesi (yalnız tel çizgileri; hacim mesh’i açık kalır). Tel kafes çekirdek three.module.js ile; üstteki satır anlık değerleri yazar.

İsteğe bağlı ses: aynı bölümde, demo kutusundan ayrı sütun genişliğinde şerit — dosya adı Spot-Light-Demo (uzantı sırasıyla denenir).

Karşılaştırma · Point vs Spot (sağ ayarlar)

Sol: aynı noktadan her yöne ışık — zemin ve bloklar daha eşit aydınlanır; kaynakta küçük glow ile “her yere yayılıyor” ipucu güçlenir. Sağ: koni dışı hızlı kararır; angle daralınca “sahne ışığı” gibi daralır. penumbra özellikle zemin ve arka duvardaki ışık lekesinin kenarında fark edilir; HUD’un alt yarısı sert bölgeyi, üst yarısı yumuşamayı hızlandırır (demoda eğri eşleme). Torus gibi ince eğride değişim doğal olarak daha azdır (normal). distance + biraz yükseltilmiş demo decay menzil düşüşünü güçlendirir. Gölgeleri kapatınca ışık kalır, gölgeler gider — aynı kavram üretimde de geçerli. Tel kafes LineSegments; yarı saydam koni ShaderMaterial (ek addons yok). PCFSoftShadowMap.

Split ekranı nasıl okumalısın?

Sol yarı, aynı kaynak konumundan tam küresel yayılımı hatırlatır; sağ yarı ise aynı geometride koninin dışını hızla karartan kesilmiş hacmi gösterir. Sarı kaynak ve emissive magenta hedef yön eksenini sabitler; pembe çizgi apex→hedef ilişkisini netleştirir; sağdaki hafif koni hacmi “görünür ışık hacmi”ni destekler. Gölgeleri kapatınca yalnız aydınlanma terimi değişir — bu ayrım, üretimde “önce ışık rengi ve hacim, sonra gölge” hata ayıklama sırasını destekler.

Uygulama: tiyatral spot kurulumu

Üstteki split sahne (diagram-spot-light.js) ile aynı sabitleri burada ön harita tabloda topladık; aşağıdaki kod önce demodaki sağ SpotLight kurulumunu, ardından genel “tiyatral” örneği hatırlatır. Gölge haritası çözünürlüğü arttıkça kalite artar; GPU maliyeti de yükselir.

Tablodaki sayılar “tek doğru kurulum” değildir; amaç, HUD’daki her sürgünün arkasında hangi sabitin durduğunu ve sol/sağ sahnelerin dolgu seviyelerinin neden bilinçli olarak farklı seçildiğini göstermektir — sağda daha düşük dolgu, koni kenarının ve penumbranın zeminde okunmasına yer açar.

Ön harita tablosunu nasıl kullanırsın?

Üst bloklar ortak LIGHT_POS / TARGET_POS ve yardımcı geometrileri listeler; ortada sol PointLight referansı, altta sağ SpotLight ve renderer satırı gelir. Kod örneğindeki (A) bölümü doğrudan bu sırayla eşleştirilebilir; (B) bölümü ise genel tiyatral kurulum için kısa bir şablondur.

diagram-spot-light.js — Split Demo Sabitleri
Sahne / rol Parametre Değer
Ortak · konum / hedef Kaynak position (3.35, 5.05, 3.95) (LIGHT_POS)
target.position (0, 0.62, 0) (TARGET_POS)
Ortak zemin (her iki sahne) buildStage zemin rengi 0x263545 (kontrast; arka düzlemden ayrışır)
Görsel yardımcılar Sarı küre kaynak; sol PointLight üzerinde emissive + additive halo; hedefde emissive magenta + halo + hafif nabız; pembe Line apex→target; sağda sürekli yarı saydam koni (ShaderMaterial, additive); isteğe bağlı koni teli (LineSegments)
Arka düzlem (sağ ek geometri) Penumbra / leke kenarı için düzlem (renk ≈ 0x7588a0); merkez yaklaşık (0, 1.35, −4.85)
HUD · gölgeler / tel kafes Checkbox: tüm mesh cast/receiveShadow + renderer gölge haritası; tel kafes yalnız çekirdek three (addon yok); split iki yarıda ortak cam.aspect
Sol · PointLight (karşılaştırma) color / decay 0xffd4a8 (KEY_COLOR), 2
intensity / distance 3.45 ve 88 (sabit, sürgü yok)
Gölge mapSize 1024; near 0.2 / far 96
Dolgu Ambient 0.12 + Hemisphere 0.36 (sol sahne; sağdan daha yüksek dolgu)
Sağ · SpotLight color / demo decay KEY_COLOR, 2.38 (SPOT_DECAY_DEMO — menzil düşüşü demoda biraz abartılı)
intensity 4.25 × (sürgü 0–1) → ctor başlangıcı ~2.9, sonra applyControls
angle HUD: 18°–68° → radyan; ctor varsayılan degToRad(38)
penumbra / distance HUD 0–100 → 0–1, sonra parçalı eğri ile spot.penumbra (alt yarı ≈ 0–0.2, üst yarı 0.2→1); ctor başlangıç 0.138 (≈ HUD %35). Mesafe sürgüsü 8–72
Gölge mapSize 1024, bias, normalBias 0.028, kamera near 0.35 / far 58
Sağ dolgu Ambient 0.065 + Hemisphere 0.28 (kontrast için sola göre daha düşük)
Renderer Ton / gölge Exposure ≈1.22; PCFSoftShadowMap
// --- A) Split demo — diagram-spot-light.js (sağ Spot özeti)
const KEY_COLOR = 0xffd4a8;
const LIGHT_POS = new THREE.Vector3(3.35, 5.05, 3.95);
const TARGET_POS = new THREE.Vector3(0, 0.62, 0);
const SPOT_INTENSITY_SCALE = 4.25;
const SPOT_DECAY_DEMO = 2.38;

const angle = THREE.MathUtils.degToRad(38);
const spot = new THREE.SpotLight(KEY_COLOR, 2.9, 38, angle, 0.138, SPOT_DECAY_DEMO);
spot.position.copy(LIGHT_POS);
spot.target.position.copy(TARGET_POS);
spot.castShadow = true;
spot.shadow.mapSize.set(1024, 1024);
scene.add(spot);
scene.add(spot.target);
// Demoda: intensity = SPOT_INTENSITY_SCALE * (sürgü 0–1); angle / distance HUD’dan;
// penumbra: HUD 0–1 parçalı eşlenir (Ctor’daki 0.35 yalnız başlangıç; canlı değer applyControls’ta).

// --- B) Genel tiyatral örnek (sayfa anlatımı)
const spotLight = new THREE.SpotLight(0xffffff, 2.0, 30, Math.PI / 6, 0.5, 2);
spotLight.position.set(5, 10, 5);
spotLight.target.position.set(0, 0, 0);
spotLight.castShadow = true;
spotLight.shadow.mapSize.set(1024, 1024);
scene.add(spotLight);
scene.add(spotLight.target); // Hedefi sahneye eklemeyi unutma!

API tarafında hatırlatma

new THREE.SpotLight(color, intensity, distance, angle, penumbra, decay) altı parametreyi tek satırda toplar; target ayrı bir nesne olduğu için scene.add(spot.target) adımı atlanmamalıdır. Gölge açıkken spot frustum’u angle ve distance ile birlikte büyür — koni genişledikçe gölge haritasında piksel başına düşen detay azalabilir; bu durumda önce açıyı daraltıp sonra mapSize artırmak daha dengeli bir sıradır.

Yaygın hata: hedefi (target) unutmak

Yönü olmayan spot

Hata: SpotLight yönlü bir ışıktır. Yalnızca position’ı değiştirip target’ı sahneye eklemezsen veya konumunu güncellemezsen koninin baktığı yer beklediğinle örtüşmeyebilir.

Çözüm: scene.add(spotLight.target) ile hedefi her zaman sahneye ekle ve ışığın takip etmesi gereken noktayı orada tut (veya hedefi başka bir Object3D’ye bağlayıp onu hareket ettir).

Bazı projelerde hedef kökte sabit kalırken spot position ile hareket eder; bazı projelerde tersi yapılır — ikisi de geçerli, yeter ki matris güncellemesi ve sahne grafiği tutarlı olsun. Hedefi unuttuğunda koni beklenmedik bir yöne bakabilir veya frustum tamamen sahne dışına kayar; bu yüzden geliştirme aşamasında SpotLightHelper veya demodaki tel kafes gibi görsel ipuçları zaman kazandırır.

Hedef hareket ediyorsa matris: target konumunu her kare elle set ediyorsan veya grafik dışı özel bir akışta güncelliyorsan, ışığın dünya uzayındaki yönü için spotLight.target.updateMatrixWorld() çağrısının güncel olduğundan emin ol — aksi halde spot, bir önceki kareden kalma matrixWorld ile yanlış eksene bakabilir. Normal Object3D hiyerarşisi ve standart render döngüsünde çoğu projede bu ekstra adım gerekmez; “hedef takip” kodunda ise sık karşılaşılır.

Holodepth ilkesi

Dikkat yönetimi aracı

SpotLight genel aydınlatma değil, odak aracıdır. Her yeri aydınlatmak yerine izleyicinin görmesini istediğin kritik bölgeleri vurgula.

Holodepth çizgisinde spot, çoğu zaman DirectionalLight ile kurulan genel güneşin üstüne ince bir dram katmanıdır: vitrin, boss fight alanı veya tiyatro sahnesi gibi. Bir sonraki dosyada dikdörtgen alan ışığı ( RectAreaLight ) ile yumuşak stüdyo paneli düşüncesine geçilir — orada da yön ve alan kontrolü vardır fakat konik kesim yerine yüzey alanı baskındır.

Production notu: gölge frustum ve hata ayıklama

Gölge haritası üretimi açısından kabaca maliyet sıralaması (tipik kurulum, tek harita yönü başına):

Işık Gölge maliyeti (yaklaşık)
DirectionalLight 1 (tek yönlü harita)
SpotLight 1 (tek perspektif frustum)
PointLight 6 (küp harita — altı yüz)

DirectionalLight’tan farklı olarak SpotLight gölgesi tipik olarak perspektif bir kamera frustum’u ile üretilir. Gölgeler kesik veya eksik görünüyorsa spotLight.shadow.camera alanını (ör. yakın/uzak düzlemler, fov) ve harita çözünürlüğünü gözden geçir; çoğu kurulumda konu açısı (angle) ile uyum tutulur.

Görsel hata ayıklama için SpotLightHelper kullan (three/addons/helpers/SpotLightHelper.js): koniyi ve sınırları canlı görmek saatler kazandırır.

Özet kutusundan sıradaki dosyaya geçerek alan ışığı kavramına devam edebilirsin; spot ile rect arasındaki seçim çoğu zaman konik odak mı, dikdörtgen yumuşak panel mi sorusuna indirgenir.