holodepth

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 BufferGeometry kuruyorsanız uv2 özniteliğinin varlığını mutlaka doğrulayın — yoksa aoMap sessizce 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.

Mini demo · prosedürel aoMap · düşük yönlü ışık · harici dosya yok

AO kapalı → nesne yüzüyor. AO açık (yoğunluk ↑) → nesne zemine oturur.

Sahne

4,74 / 5

Mod

Hızlı seçim
Yaygın hatalar

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, uv2 eksik
  • data-ao-demo-intensity0…5 (adım 0,05); uygulanan aoMapIntensity = 5 × √(slider / 5) (eşik ≤ 0,0150)
diagram-ambient-occlusion-demo.js — Demo Sabitleri (ambient-acclusion.html)
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.0150; 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.0640 · 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 mapAO kapanışı ile birlikte düşünüldüğünde, biri görünen silueti kaldırırken diğeri temas okumasını derinleştirir.