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.
Mod
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ükseknormalScale, yeşil tersi, displacement
| 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
NoColorSpacekuralını unutma (bölüm 2). - Işığı kontrol et: Garip yönlerde kırılım varsa önce G kanalı / DX–GL 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:
normalScaleile 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ışı).