Three.js · Doku · PBR
Texture türleri: Ambient Occlusion (AO)
Bir 3D sahneyi «render edilmiş gibi değil de, gerçek bir fotoğraf gibi» hissettiren şey genellikle en parlak ışıklar değil, en karanlık köşelerdir. Ambient Occlusion (AO), yönlü ışığın anlık gölgesi değil; dolaylı / yarı küresel ışığın yüzeyin kendi kıvrımlarında nerede zayıfladığını anlatan, çoğu pipeline’da önceden bake edilmiş bir maskedir. Bu yüzden shadow map ile karıştırılmamalıdır — biri sahne dinamiği, diğeri çoğu zaman varlık içi okuma.
AO, ışık kaynağının anlık konumundan bağımsız, yüzeyin kendi formuna
bağlı statik dolaylı gölge bilgisini taşır; doğru yerde kullanıldığında
nesneleri zemine veya birbirine «oturtur». glTF’te aynı veri
occlusionTexture olarak gelir; occlusionStrength
ile sahneye göre kısılır — Three.js tarafında karşılığı çoğu zaman aoMap +
aoMapIntensity birleşimidir.
Bağlam: Albedo, Normal map, Roughness map, Metalness map, UV mapping, Renk uzayı, MeshStandardMaterial.
Ortam kapanışı (Ambient Occlusion) mantığı
Gerçek dünyada ışık her yönden gelir (ambient / dolaylı bileşen). Ancak iki yüzey birbirine çok yaklaştığında — örneğin bir duvar köşesi veya bir karakterin koltuk altı — bu her yönden gelen dolaylı ışığın o bölgeye ulaşması zorlaşır.
- Statik gölge: AO, ışık kaynağının nerede olduğundan bağımsızdır. Işıklar değişse bile objenin kendi formundan gelen o «dip gölgeleri» haritada kodlanmış kalır.
- Derinlik algısı: AO olmadan nesneler bazen sahnede «yüzer» gibi görünür. Harita, yüzeylerin birbirine temas ettiği bölgeleri karartarak onları zemine veya birbirine oturtur.
Motorlar bunu genelde difüz / dolaylı bileşene uygular; metal yüzeylerde yansıma hikâyesi çoğu zaman roughness ve çevre ile yürür. Bu yüzden AO’yu «her şeyi karartan genel gölge» sanmamak gerekir — rolü kapanım okumasıdır.
AO haritası nasıl okunur?
AO haritaları tipik olarak gri tonlu görsellerdir (çoğu iş akışında tek kanal mantığıyla düşünülür):
- Beyaz (≈ 1): Açık alanlar — dolaylı ışığın rahatça ulaşabildiği bölgeler; materyalin rengi tam okunur.
- Siyah (≈ 0): Kapalı alanlar — ışığın zor girdiği derin çatlaklar ve köşeler; bu bölgeler albedo’yu karartarak derinlik illüzyonu yaratır.
- Gri ara tonlar: Geçiş bölgeleri — engellenmenin kademeli olduğu yumuşak gölgeler.
glTF metal–rough paketinde oklüzyon sık sık ORM (Occlusion–Roughness–Metallic) dokusunun kırmızı kanalında taşınır; dosyayı yalnızca gri görüntü sanmayın — doğru kanalı ayırmak içerik üretiminde kritiktir.
Three.js ve ikinci UV kanalı (uv2)
Holodepth için kritik teknik detay: Three.js’te
MeshStandardMaterial üzerinde
aoMap kullanırken AO örneklemesi genellikle
uv2 üzerinden yapılır.
- Neden? Albedo veya normal map sık sık tiling (tekrar) ile kullanılır; AO ise çoğu pipeline’da objeye özel, benzersiz bir «gölge tablosu» olduğu için ayrı bir UV düzeniyle gelir.
- Pratik: glTF genelde doğru kanalları getirir;
elle
BufferGeometrykuruyorsanızuv2özniteliğinin varlığını mutlaka doğrulayın — yoksaaoMapsessizce etkisiz kalabilir.
İkinci UV seti, genelde dikişsiz (non-overlapping)
bir açılım anlamına gelir; böylece albedo’da agresif
tiling yapılırken oklüzyon tek parça halinde kalır. Ayrıntılı
kırılım için UV mapping sayfasına dönün — burada mesele, aoMap
örnekleyicisinin hangi koordinat kanalına bağlandığıdır.
// Örnek: uv2 yoksa ve tile etmeyecekseniz geçici olarak uv kopyalanabilir (üretimde genelde ayrı unwrap)
geometry.setAttribute("uv2", geometry.attributes.uv);
material.aoMap = aoTexture;
material.aoMapIntensity = 1.0; // Dip gölgelerin dramı
HoloDepth ipucu
uv ile uv2’yi her zaman körlemesine eşitlemek her model için doğru
değildir; fakat «AO hiç uygulanmıyor» teşhisinde ilk kontrol
edilecek yerdir.
Teknik kurallar ve renk uzayı
AO haritası bir veri dokusudur; dolaylı ışığın yoğunluğu ile albedo’yu çarpan bir maskeleme rolündedir.
THREE.NoColorSpace: sRGB gama ile yüklenirse köşeler fazla koyu veya fazla soluk kalır; fiziksel okuma bozulur.
Dışa aktarımda «fotoğraf» olarak kaydetmek, özellikle JPEG ile, maske kenarlarında istemeden blok üretir; bu da dip kapanışını «kirli halka» gibi gösterir. Üretimde PNG / EXR gibi kayıplı olmayan veya kontrollü sıkıştırma tercih edin.
const aoTexture = new THREE.TextureLoader().load("ao.jpg");
aoTexture.colorSpace = THREE.NoColorSpace;
aoMapIntensity çoğu sürümde 1 civarı «doğal» kabul edilir;
değeri yükseltmek dramı artırır, düşürmek ise haritayı neredeyse nötrler. Bu sayfadaki
etkileşimli demo öğretim için kasıtlı güçlü bir aralık kullanır — üretimde
aynı uç değerleri kopyalamak zorunda değilsiniz.
AO ve Albedo ilişkisi
Albedo bölümündeki kuralı hatırlayın: Albedo içinde gölge barındırmamalıdır.
Doğru yöntem: Gölgeleri albedo’ya boyamak yerine AO olarak ayrı dokuda tutmak. Böylece sahne aydınlatması değiştikçe dip gölgeler albedo ile matematiksel olarak tutarlı harmanlanır; yüzey «kirli» değil, hacimli kalır.
Metalness
veya roughness
haritası yüzeyin yansıma karakterini seçer; AO ise
çoğu zaman difüz tarafı inceltir. Albedo’ya hem bake gölge hem ayrı
aoMap bindirirseniz çift kararma riski doğar — birini «hikâye anlatıcı»,
diğerini
«teknik maske» olarak netleştirin.
Performans: AO ve gerçek zamanlı gölgeler
Gerçek zamanlı shadow map’ler GPU için pahalıdır. Baked AO ise:
- Performans dostu: Genelde önceden üretilmiş bir dokudur; çalışma anında çoğu zaman çarpma düzeyinde kalır.
- Sınırı: Hareketli objelerin birbirine düşürdüğü temas gölgelerini hesaplamaz; bunun için SSAO, GTAO gibi ekran uzayı teknikleri gerekir. Klasik AO dokusu, objenin kendi iç geometrisindeki statik derinliği güçlendirir.
Ekran uzayı oklüzyon, her karede maliyet öder; bake AO ise dosya boyası olarak gelir. Web ürün vizyonunda ikisi bazen birlikte kullanılır — o zaman «hangi karanlık nereden geliyor?» sorusunu sahne tasarımcılarıyla netleştirmek gerekir.
Gölge haritası temelleri için: Shadow map.
Etkileşimli AO demosu
Aşağıdaki sahne harici doku veya HDRI indirmez:
AO maskeleri tarayıcıda Canvas ile üretilir. Güçlü çevre
ışığı AO farkını yutabileceği için demo çok düşük
yönlü ışık (≈0,08) kullanır; ortam (ambient)
ışığı yoktur — böylece temas kapanışı ve harita hataları daha net okunur.
Yoğunluk için 0–5 slider (varsayılan 4,5) verilir;
uygulanan aoMapIntensity √(slider/5) ile ölçeklenir
(düşükte bile belirgin «tick»). Üretimde değerler genelde daha muhafazakârdır.
Sahne: «Temas» küre + düzlem; «Oyuk» torus + düzlem.
Modlar: slider ile canlı yoğunluk, kapalı, albedo’ya gömülü AO, yanlış sRGB, uv2 eksikliği.
Bu sahne, renk
uzayı ve roughness
demosundaki «yanlış sRGB» dersini AO
maskesi üzerinden tekrarlar; fark burada kapanışın difüz temas okumasına
etkisidir. Yoğunluk uçları öğretim içindir — üretimde daha düşük aoMapIntensity
ile başlamak genelde daha güvenlidir.
AO kapalı → nesne yüzüyor. AO açık (yoğunluk ↑) → nesne zemine oturur.
Sahne
Mod
Checklist: AO kapalıyken nesne zeminde mi ama
temas hattı «kopuk» mu? Açıkken dip kapanış albedo’yu kirletmeden mi geliyor?
uv2 modunda harita varken etki neden kayboluyor?
HDRI yok; yönlü ışık
çok düşük (≈0,08). Küre + düzlemde ince «temas diski» yalnızca AO
açıkken (öğreti için) — telif ve ağ riski taşıyan doku indirimi
yapılmaz.
Aşağıdaki tablo diagram-ambient-occlusion-demo.js içinde bu demo için
gerçekten kullanılan sabitleri özetler; «öneri» değil, dosyadaki değer
kaydıdır. Tür sütunu: radyo ve slider dışındakiler kodda sabittir.
Bu demo’da kontrol edilenler
ao-demo-scene→ küre + düzlem (contact) veya torus + düzlem (cavity)ao-demo-mode→ yoğunluk kapalı, slider’lı AO, albedo gömülü, yanlış sRGB,uv2eksikdata-ao-demo-intensity→0…5(adım0,05); uygulananaoMapIntensity=5 × √(slider / 5)(eşik≤ 0,015→0)
| Sahne / rol | Parametre | Değer | Tür |
|---|---|---|---|
Sabitler (const) |
SLIDER_MAX / SLIDER_DEFAULT |
5 / 4.5 (HTML value="4.5" ile uyumlu)
|
🔒 Sabit |
mapSliderToAoIntensity |
slider ≤ 0.015 → 0; aksi
5 × √(clamp(slider/5,0,1))
|
🔒 Sabit (kod) | |
| Renderer | Temiz renk / ton | setClearColor(0x060810) · ACESFilmicToneMapping ·
exposure 1.34 · SRGBColorSpace çıkış |
🔒 Sabit |
| Gölge haritası / piksel oranı | shadowMap.enabled = false ·
Math.min(window.devicePixelRatio || 1, 2)
|
🔒 Sabit | |
| Sahne | scene.background |
THREE.Color(0x060810) |
🔒 Sabit |
| Işık | DirectionalLight |
0xffffff, yoğunluk 0.08 · konum
(2.2, 3.4, 1.8) — ortam ışığı yok
|
🔒 Sabit |
| Geometri | Düzlem | PlaneGeometry(5.5, 5.5, 80, 80) ·
rotation.x = -Math.PI / 2
|
🔒 Sabit |
| Küre / torus | SphereGeometry(0.22, 56, 40) · konum (0, 0.22, 0) ·
TorusGeometry(0.3, 0.095, 32, 112) ·
rotation.x = -Math.PI / 2
· konum (0, 0.095, 0)
|
🔒 Sabit | |
Temas diski (MeshBasicMaterial) |
CircleGeometry(0.2, 64) · y = 0.0025 ·
opacity 0.52 · renderOrder 1 (koşullu görünür)
|
🔒 Sabit (kod) | |
MeshStandardMaterial |
Temiz renk / pürüzlülük | color 0xb8c2d4 · düzlem roughness 0.93 ·
kahraman 0.91 · metalness 0 |
🔒 Sabit |
| Albedo gömülü mod | color 0x6a707a · aoMap kapalı |
🔄 Mod (wrong_baked) |
|
Prosedürel aoMap kanvasları |
Düzlem / küre / torus | Çoğunlukla 512×512 · NoColorSpace · düzlem-küre
ClampToEdge · torus RepeatWrapping
|
🔒 Sabit (kod) |
Temas diski alphaMap |
128×128 · radyal gradyan (merkez → kenar) |
🔒 Sabit (kod) | |
| Kamera | PerspectiveCamera |
FOV 36 · clip 0.06–40 · pozisyon
(0.32, 0.5, 1.72) · lookAt(-0.04, 0.11, 0)
|
🔒 Sabit |
| HUD | Sahne / mod / slider | ao-demo-scene · ao-demo-mode · aralık
0…5 adım 0.05
|
🔄 Dinamik (HUD) |
// diagram-ambient-occlusion-demo.js — özet (detay tabloda)
const SLIDER_MAX = 5;
const SLIDER_DEFAULT = 4.5;
// aoMapIntensity = slider <= 0.015 ? 0 : SLIDER_MAX * Math.sqrt(clamp(slider / SLIDER_MAX, 0, 1));
renderer.setClearColor(0x060810);
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.34;
renderer.shadowMap.enabled = false;
scene.background = new THREE.Color(0x060810);
const dir = new THREE.DirectionalLight(0xffffff, 0.08);
dir.position.set(2.2, 3.4, 1.8);
const planeGeo = new THREE.PlaneGeometry(5.5, 5.5, 80, 80);
const sphereGeo = new THREE.SphereGeometry(0.22, 56, 40);
const torusGeo = new THREE.TorusGeometry(0.3, 0.095, 32, 112);
const cleanColor = 0xb8c2d4;
const muddyColor = 0x6a707a;
const cam = new THREE.PerspectiveCamera(36, 1, 0.06, 40);
cam.position.set(0.32, 0.5, 1.72);
cam.lookAt(-0.04, 0.11, 0);
HoloDepth «AO» checkpoint’i
Özet
Ambient Occlusion, projeyi «hobi» görüntüsünden çıkarıp prodüksiyon hissine taşıyan sessiz ama güçlü katmanlardan biridir. Doğru kullanıldığında izleyici nedenini tam adlandırmasa da «bu nesne sahnenin parçası» hissini alır; yanlış kullanıldığında ise her köşe yanmış siyah çerçeve gibi görünür.
HoloDepth özet stratejisi
UV2 kontrolü
aoMap ekledin ama etki yoksa geometride
uv2 özniteliğini doğrula.
aoMapIntensity
Dramı sahneye göre ayarla; abartılı AO «kirli siyah çerçeve» üretir. Şüphede bu sayfadaki slider’lı modu referans al, üretimde aynı uç değeri kopyalama.
Doğrusal kural
Veri haritası: NoColorSpace; şüphede
yanlış sRGB demo modunu aç.
Modelleme
AO’yu genelde DCC’de bake ederek üret (Blender, Substance Painter vb.).
Sonraki durak: geometrik yüksekliği gerçekten oynatan Height / Displacement map — AO kapanışı ile birlikte düşünüldüğünde, biri görünen silueti kaldırırken diğeri temas okumasını derinleştirir.