holodepth

Three.js · Doku · PBR

Texture türleri: Normal Map (detay illüzyonu)

Performans, poligon sayısını düşük tutmakla ilgilidir; gerçekçilik ise çoğu zaman yüzeydeki mikro girinti–çıkıntıda gizlidir. Normal map, geometriyi çoğaltmadan piksel başına yüzey yönünü değiştirerek ışığın kırılımını yönetir ve sahte bir derinlik algısı üretir — silüeti ise değiştirmez.

Bu doku bir «tablo resmi» değil; yöneyi kodlayan veridır. Doğru renk uzayı (NoColorSpace) ve tangent space (TBN çatısı) olmadan aydınlatma hızla tutarsızlaşır.

Bağlam: Albedo / Base Color, Doku temelleri, Renk uzayı, UV mapping, Materyal girişi.

Normal map omurgası: hızlı harita

Konu Soru Bölüm
Tanım Geometriyi büyütmeden neyi değiştirir? 1
RGB = yön Mor–mavi dokuda kanallar ne taşır? 2
Tangent space Döndürünce detay neden «yapışık» kalır? 3
DX / OpenGL Yeşil kanal ters mi, çıkıntı neden çukur görünür? 4
Bump / displacement Hangisi gerçek geometri iter? 5
Three.js normalMap ve normalScale ne işe yarar? 6
Mini demo Panel modları hangi hatayı gösterir? 7
HoloDepth Üretimde hızlı kontrol listesi 8

Normal map nedir? (Yüzey normalleri)

Her yüzeyin dışa bakan, ışığın yansıma açısını belirleyen bir yönü vardır; buna normal (yüzey normali) denir. Düz bir plakada normaller genelde paraleldir; yüzey düz okunur.

Normal map, bu yön bilgisini bir görüntünün RGB kanallarına kodlar. Işık çarptığında geometride fiziksel bir çıkıntı yokmuş gibi parlaklık ve gölgelenme yine de oluşur; göz, detayı hacim sanır.

Önemli sınır: bu illüzyon göz hattı ve gölge sınırında kırılır — çünkü silüet ve gerçek örtüşme hâlâ düşük poligon geometrisine bağlıdır. İnce çizik, vida başı, panel olukları gibi mikro detay için ideal; büyük formu «bükmek» için displacement veya model topolojisi gerekir.

RGB kanallarının gizli dili

Bu dokuların neden çoğu zaman mor–mavi tonlarında göründüğünü merak eden çoktur: burada klasik bir «tablo resmi» değil, yöney vektörleri saklanır (genelde tangent space’te, bileşenler −1…+1 aralığından 0…255’e ölçeklenir). Piksel rengi «güzel görünmek» için değil; shader’ın dot product ile ışığı eğmesi için vardır.

Kanalların yorumu

  • Kırmızı (R): X doğrultusundaki eğim (tipik olarak teğet eksenine göre sağ–sol).
  • Yeşil (G): Y doğrultusundaki eğim (yukarı–aşağı; OpenGL / Three.js tarafında genelde yukarı pozitif).
  • Mavi (B): Z (yüzeyden dışa, yaklaşık normal yönü) bileşeni — bu yüzden haritalar genelde mavimsi kalır.

HoloDepth kritik uyarı

Normal map bir veri dokusudur. Three.js’te yüklerken renk uzayı mutlaka THREE.NoColorSpace (doğrusal / veri) olmalıdır. Yanlışlıkla SRGBColorSpace uygulanırsa yönler bozulur; ışık ve yansımalar yüzeyde saçma açılara kayar.

myNormalTexture.colorSpace = THREE.NoColorSpace;

Tangent space: yerel koordinat sistemi

Haritaların çoğu tangent space’te çalışır: doku pikselindeki yön, dünya uzayına göre değil; yüzeyin teğet düzlemi ve UV akışı ile tanımlanan yerel çatıya (TBN: teğet, bitangent, normal) göre ifade edilir.

Böylece nesne döndüğünde veya iskeletle büküldüğünde bile, haritadaki detay yüzeye yapışık ve tutarlı kalır; aydınlatma hesabı her karede bu çatı üzerinden yeniden kurulur. Dünya uzayı (world space) veya nesne uzayı haritaları da vardır; fakat karakter zırhı, organik yüzey gibi deforme edilen ağlarda tangent haritası endüstri standardıdır.

Pratik not: UV adası keskin dönüşleri veya aşırı gerilmiş bölgeleri UV mapping sayfasında anlattığımız gibi ele almazsanız, aynı doku yüzeyde «kayar» veya tangent bazında tutarsız görünebilir.

DirectX ve OpenGL (yeşil kanal uyumu)

En sık tuzaklardan biri yeşil kanal yorum farkıdır: araçlar ve motorlar Y bileşenini farklı işaretlerle bekleyebilir. Dışa aktarılan .png dosyası aynı kalsa bile, «doğru» motor farklı handedness varsayımıyla aynı pikseli ters okuyabilir.

  • OpenGL (Three.js / WebGL ekosisteminde yaygın referans): yeşil kanal çoğu zaman yukarıyı pozitif kabul edilir.
  • DirectX tarafında bazı içeriklerde yeşil eksen aşağıyı pozitif sayılır.

Sonuç: çıkıntılar çukur, çukurlar çıkıntı gibi görünüyorsa önce haritanın DX / GL üretim ayarını kontrol edin; gerekirse yeşil kanalı ters çevirin (invert G) veya normalScale.y işaretini tersleyin (sürüme ve materyale bağlı).

İş akışı ipucu: Substance Painter, Blender vb. dışa aktarımda «OpenGL normal» seçeneğini Three.js hedefi için tercih edin; şüphede kısa bir test küresi veya bu sayfadaki demo ile doğrulayın.

Bump, normal ve displacement

Üç teknik aynı «hacim» kelimesini paylaşır; fakat GPU ve sanatçı işi açısından rolleri farklıdır. Karıştırmak, özellikle gölge ve temas mesafelerinde beklentiyi bozar.

  • Bump map: Tipik olarak tek kanallı yükseklik verisi; hesap basittir, normal map kadar yönsel zenginlik sunmaz.
  • Normal map: Üç bileşenle yöneyi doğrudan kodlar; gözenek, çatlak gibi ince detaylarda verimlidır; fakat parallax hissi sınırlıdır.
  • Displacement: Geometriyi (vertexleri) fiziksel olarak iter; gölge sınırı ve silüet en doğru olanıdır fakat topoloji ve maliyet artar. Ayrıntı: Height / Displacement map.

Birçok üretimde ikisi birlikte gider: düşük poligon gövde + normal ile mikro detay; kritik silüet bölgelerinde kısıtlı displacement veya LOD ile denge.

Uygulama ve güç ayarı (Three.js)

MeshStandardMaterial ve benzeri PBR materyallerde normalMap atanıp normalScale ile etki canlı ayarlanabilir. Ölçek, dokunun «sertliğini» büyütür; aşırı değerler yapay parlama ve aliasing üretebilir.

Doku yükünde flipY (ör. GLTF kanalından gelen görsellerde) bazen beklenmedik dikey kayma yaratır; bu, normal’den ziyade UV / doku yönüyle ilgilidir — yine de ilk şüphe listesine yazın.

material.normalMap = myNormalTexture;
material.normalScale.set(1, 1); // büyüt / küçült; G tersliği için y işaretini -1 yapılabilir

İnteraktif demo: sci-fi panel (aynı geometri, aynı ışık)

Küre yerine metal panel (oluk, vida, gömme) teknik okumayı güçlendirir: göz zaten yüzeyde derinlik bekler; normal map farkı anında okunur. Albedo karşılaştırma demosunda olduğu gibi aynı geometri + aynı ışık + değişen veri kuralı korunur — yalnızca harita ve ölçekler değişir.

Aşağıdaki prosedürel yükseklikten hem normal hem (isteğe bağlı modda) displacement üretilir; harici dosya yok. «Yeşil ters» modu, DX / OpenGL uyumsuzluğunda çıkıntı–çukur duygusunun nasıl ters döndüğünü gösterir.

Mini demo · düzlem · ortografik · sabit ışık

Mod

Temel
Ölçek
Hata & geometri

Düzlem hafifçe eğilir (yalnızca sunum); ışık yönü sabittir. Displacement modunda segment sayısı yükseltilmiş düzlemde vertex itmesi görülür — gerçek projelerde maliyet ve LOD planı şarttır.

Aşağıdaki tablo diagram-normal-map-panel.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: mod radyosu dışındakiler çekirdek sahne için sabittir; mod satırlarında normalScale, ışık yoğunlukları ve displacement değerleri verilir.

Bu demo’da kontrol edilenler

  • normal-panel-mode → düz, normal, düşük/yüksek normalScale, yeşil tersi, displacement
diagram-normal-map-panel.js — Demo Sabitleri (normal-map.html)
Sahne / rol Parametre Değer Tür
Çekirdek sabitler MAT_BASE / LIGHT_BASE Materyal metalness 0.74, roughness 0.38 · ışık hemi 0.52 · dir 1.48 · rim 0.22 🔒 Sabit
FLAT_MAT / FLAT_LIGHT Düz mod: metalness 0.54, roughness 0.33 · hemi 0.62 · dir 1.58 · rim 0.4 🔄 Mod (flat)
Renderer Temiz renk / ton setClearColor(0x020308) · ACESFilmicToneMapping · exposure 1.07 · SRGBColorSpace çıkış 🔒 Sabit
Piksel oranı Math.min(window.devicePixelRatio || 1, 2) 🔒 Sabit
Sahne scene.background THREE.Color(0x020308) 🔒 Sabit
Işıklar (başlangıç) HemisphereLight Gökyüzü 0x8eb8e8 · zemin 0x0a0810 · yoğunluk LIGHT_BASE.hemi (moda göre değişir) 🔒 Sabit + 🔄 mod
DirectionalLight (ana) 0xffffff · LIGHT_BASE.dir · konum (2.1, 2.65, 1.55) 🔒 Sabit + 🔄 mod
DirectionalLight (rim) 0xa8c8ff · LIGHT_BASE.rim · konum (-2.4, 0.45, -1.9) 🔒 Sabit + 🔄 mod
Yükseklik → doku Izgara + gradyan gücü W = H = 256 · buildSciFiHeightField · heightToNormalCanvas(..., strength) · strength = 5.8 · flipG ile ikinci normal doku (yeşil tersi) 🔒 Sabit (kod)
Doku uzayı NoColorSpace · ClampToEdgeWrapping 🔒 Sabit
Panel geometri + materyal PlaneGeometry / dönüş 2.35 × 1.32 · segment (192, 192) · rotation.x = -0.22 🔒 Sabit
MeshStandardMaterial (taban) color 0x5c6578 · envMapIntensity 0 · modda metalness / roughness yukarıdaki tabanlardan 🔒 Sabit + 🔄 mod
Mod dalları (normal-panel-mode) normal / wrong_green normalScale (1, 1) · yeşil tersi için normalTexFlipG 🔄 Dinamik (HUD)
normal_low / normal_high normalScale (0.32, 0.32) · (2.35, 2.35) 🔄 Dinamik (HUD)
displacement displacementMap aynı height verisinden · displacementScale 0.135 · displacementBias -0.026 · normalMap açık 🔄 Dinamik (HUD)
flat Harita yok · FLAT_MAT + FLAT_LIGHT 🔄 Dinamik (HUD)
Kamera OrthographicCamera + setSize Başlangıç left/right ±1, top/bottom ±1, near 0.15, far 24 · pozisyon (0, 0.12, 3.2) · lookAt(0, 0, 0) · frustum margin 1.22 🔒 Sabit
HUD input[name="normal-panel-mode"] flat · normal (varsayılan) · normal_low · normal_high · wrong_green · displacement 🔄 Dinamik (HUD)
// diagram-normal-map-panel.js — özet (height alanı ve mod dalları tabloda)

const MAT_BASE = { metalness: 0.74, roughness: 0.38 };
const LIGHT_BASE = { hemi: 0.52, dir: 1.48, rim: 0.22 };

const W = 256;
const H = 256;
const z = buildSciFiHeightField(W, H);
const strength = 5.8;
const normalTex = heightToNormalCanvas(z, W, H, false, strength);

const geo = new THREE.PlaneGeometry(2.35, 1.32, 192, 192);
const mat = new THREE.MeshStandardMaterial({
  color: 0x5c6578,
  metalness: MAT_BASE.metalness,
  roughness: MAT_BASE.roughness,
  envMapIntensity: 0,
});

const cam = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.15, 24);
cam.position.set(0, 0.12, 3.2);
cam.lookAt(0, 0, 0);

HoloDepth «Normal» checkpoint’i

Özet

Normal map, poligon bütçesini korurken yüzey kalitesini büyüten en güçlü kartlardan biridir — yeter ki veri olarak doğru okunabilsin.

HoloDepth özet stratejisi

  • Renk uzayı ekleme: Veri dokusu olarak NoColorSpace kuralını unutma (bölüm 2).
  • Işığı kontrol et: Garip yönlerde kırılım varsa önce G kanalı / DXGL uyumunu kontrol et (bölüm 4).
  • Detay seviyesi: İnce detay → normal map; büyük form → displacement (maliyet bilinciyle; bölüm 5).
  • Ölçeklendirme: normalScale ile sertliği sahneye göre yumuşat veya güçlendir (bölüm 6).

Sonraki durak: yansımanın «matlık–parlaklık» karakterini taşıyan Roughness map (ve komşu olarak metalness akışı).