Three.js · Gelişmiş PBR
MeshPhysicalMaterial: PBR'ın Ötesinde Bir Katman
Cam, kadife, cila — Standart'ın çözdüğünden fazlası
Gerçekçi bir metal yüzey yapmak artık standarttır. Peki ya kristal bir kadeh? Kadife bir koltuk? Ya da yeni cilalanmış, derinliği olan bir spor araba boyası? Bu soruların ortak noktası: ışığın yüzeyde tek bir olay olarak bitmemesi — üst cila, iç hacim veya kenar parlması gibi ikinci ve üçüncü olayların devreye girmesi.
Standart PBR modelleri ışığın yüzeyle olan tek seferlik etkileşimine odaklanır. Oysa gerçek
dünyada ışık bazen yüzeyin üstündeki ince bir vernik tabakasından seker, bazen de malzemenin
içine girip kırılarak yoluna devam eder. MeshPhysicalMaterial, Standart
PBR'ın yetmediği ileri düzey fiziksel detayları yönetmek için tasarlanmış bir mühendislik
harikasıdır.
Aynı sahne grafiğinde Standard ile yan yana durduğunda, Physical’ın işi “daha fazla parametre”
değil; doğru problemi doğru katmanda çözmek olarak özetlenebilir.
Önkoşul: MeshStandardMaterial (metalness · roughness · ortam), MeshPhongMaterial (klasik specular referansı). Stilize gölgeler için MeshToonMaterial. Kavramsal çerçeve: Materyal giriş. Performans çerçevesi: LOD ve transmission. Sayfa sonunda özet ve komşu ders bağlantıları.
Zihin modeli: katmanlı yapı
Physical materyali tek bir yüzey gibi değil, soğan gibi katmanlı bir yapı olarak düşünmelisiniz:
Üç katman
- Alt katman: Malzemenin ana rengi ve dokusu (albedo).
- Üst katman: Üzerindeki vernik, cila veya mikro tüyler
(
clearcoat/sheen). - İç hacim: Işığın malzemenin içinden geçerken izlediği yol
(
transmission/thickness).
Bu soğan metaforu, shader tarafında da hissedilir: her katman için ayrı bir “sözleşme”
vardır ve sıra önemlidir — örneğin cam hissi için çoğu zaman önce çevre ve
IOR oturur, sonra thickness ile iç yol uzunluğu ayarlanır; en son
üstteki cilayı clearcoat ile inceltirsiniz. Hepsini aynı anda maksimuma çekmek
hem sanatsal hem teknik olarak nadir olarak gereklidir.
MeshStandardMaterial ile paylaştığınız albedo / roughness / metalness tabanı
korunur; Physical ekleri bu tabanın üstüne bindirilen davranışlardır. Bu
ayrım, mevcut PBR varlıklarınızı “bir üst sınıfa” taşırken yeniden boyamadan ilerlemenize
yardım eder.
Hangi katman, hangi problemi çözer?
Standart bir yüzeyi fiziksel bir başyapıya yaklaştırmak için şu ekstra güçleri kullanırız:
Özellik özeti
Clearcoat
Nesnenin üzerine ikinci bir yansıma katmanı ekler. Alt katman mat olsa bile nesne epoksi kaplama gibi camın içindeymiş gibi parlayabilir.
Sheen
Işığın yüzeyin kenarlarında yumuşakça parlamasını sağlar; kumaşların dokunulası yumuşaklığını bu katmanla yakalarsınız.
Iridescence
Işığın ince filmlerde kırılmasıyla oluşan gökkuşağı etkisi; sabun köpüğü, CD yüzeyi gibi.
Transmission
Işığın yalnızca geçmesini değil, kırılarak objenin içine nüfuz etmesini sağlar.
Kartlar tek başına bir “reçete listesi” değil, hangi görsel şikâyete hangi anahtarın cevap verdiği haritasıdır: parlak ama metal olmayan üst tabaka düşünüyorsanız clearcoat; ışığın kumaşta tüy gibi dağıldığı yumuşak rim hissi için sheen; ince film interferansı için iridescence; içten geçen, kırılan ışık için transmission. Aynı nesnede birden fazlasını açmak mümkündür; maliyet ve ayar karmaşıklığı genelde hızla artar — bu yüzden üretimde önce tek bir dominant efekt seçmek disiplin kazandırır.
glTF tarafında bu kavramların çoğu uzantılar veya belirli harita / kanal kombinasyonlarıyla gelir; Three.js’te doğrudan özellik adlarıyla oynuyorsunuz. İçerik boru hattınız glTF odaklıysa, Physical parametrelerini “motor içi ince ayar” olarak düşünmek, dışa aktarım sürprizlerini azaltır.
Kritik fark: cam neden opacity değildir?
Yaygın hata
Cam yapmak için yalnızca opacity (saydamlık) değerini düşürmek — yanıltıcıdır.
Opacity: Nesnenin görünürlüğünü azaltır. Arka planı kırılma olmadan, olduğu gibi gösterir; sonuç sık sık hayaletimsi bir görüntüdür.
Transmission: Işığı fiziksel olarak büker. Arka plandaki görüntü, kalınlık ve IOR (kırılma indisi) ile şekil değiştirir. Gerçek cam hissi veren şey bu bükülmedir.
opacity ile saydamlık hâlâ meşru araçtır: örneğin düz bir UI paneli, hafif
fade veya stencil öncesi basit karışım için. Cam, sıvı veya kalın cam tabakada ise
izleyici beklentisi lens davranışıdır — bu da transmission + IOR +
thickness üçlüsünün alanıdır. Opacity tabanlı “cam” genelde arka planı kırılmadan ve IOR ile
ilişkilendirilmeden gösterdiği
için ürün görselinde inandırıcılığı kaybeder.
Üretimde karar ağacı şöyle sadeleşir: arka plan kırılmadan görülecekse transmission düşün; yalnızca örtüşme / hafif karartma yeterliyse opacity veya alpha haritası yeterli olabilir. İkisini aynı anda “güçlü” kullanmak çoğu zaman gereksiz belirsizlik ve sıralama (render order) riski doğurur.
Ortam olmadan Physical çalışmaz
IBL / HDR
Bu materyal, Standart materyalden bile daha fazla environment map bağımlıdır. Physical materyal tek başına bir renk değildir; çevresini içine alan ve yansıtan bir sistemdir.
Zorunluluk: Sahnede scene.environment (HDR / IBL) yoksa cam
materyaliniz ya koyu bir leke gibi durur ya da sahneye kaybolur.
Gerçekçilik denklemi: Environment + IOR + transmission → kusursuza yakın cam.
Physical özelliklerinin çoğu, Standart’tan daha agresif biçimde speküler ve transmisyon örneklemesine bağlıdır; bu örneklemeyi besleyecek kübik ortam yoksa sonuç “boş stüdyoda çekilmiş cam” gibi düzleşir veya tersine kontrolsüz parlama üretir. Bu yüzden ekip içi kural olarak önce HDR/IBL’i kilitlemek, sonra IOR ve thickness ile formu bulmak daha az döngülü bir iş akışıdır.
Three.js’te PMREMGenerator ile ön işlenmiş ortam yaygın desendir; demo da
harici dosya olmadan aynı fikri gösterir. Renderer tarafında transmisyon çözünürlüğü gibi
ayarlar (ör. transmissionResolutionScale) kalite–hız dengesini oynatır —
ayrıntı
figür altındaki özetle sınırlı tutuldu; burada mesaj, Physical’ın yalnızca materyal
değil sahne–renderer sözleşmesi olduğudur.
Tam sayı listesi
bölüm 5 demo sabitleri
tablosunda toplanır.
İnteraktif: “Katmanlı cam”
Bu sahne, transmission / IOR / thickness ilişkisini tek bir kompozisyonda okutmak için tasarlandı: öndeki lathe profili arkasındaki ikosahedronu “camdan” okutur; IBL kapatıldığında aynı parametrelerin neden cansızlaştığını bir önceki bölümle birlikte görürsünüz. Ghost mode ise geometri–ışık ilişkisini sadeleştirerek iç kırılmayı gözlemlemeyi kolaylaştırır — amaç görsel efekt şovu değil, parametrelerin birbirini nasıl bastırdığını hissettirmek.
Üstteki readout anlık değerleri kısaltır; Lathe vs. ikosahedron,
PMREM ve grid davranışı figür altındaki açıklamada. Metinleri üst üste binmeden okumak için
önce sürgüleri ve onay kutularını deneyin, sonra alt yazıyı tarayın. Ölçüler
demo sabitleri
tablosunda diagram-physical-material.js ile eşlenir.
Bu demo yalnızca Physical sayfasına özel bir kompozisyon: önde
LatheGeometry ile döndürülmüş ince gövdeli cam kadeh
profili (MeshPhysicalMaterial), arkada camdan okunan turkuaz
ikosahedron — torus / küre / koni demosundan ayrı bir form dili.
IBL kapalıyken dolgu ışık yükselir; yansıma yine yok. Ghost
mode grid’i kapatır, iç kristali büyütür. IBL yine
PMREMGenerator ile; harici HDR URL yok. thickness kırılma
gücünü değiştirir.
Demo sabitleri tablosu (Katmanlı cam)
initPhysicalDemo · prosedürel IBL (PMREMGenerator.fromScene),
Lathe cam gövdesi, arkada MeshStandardMaterial ikosahedron, ızgara + yönlü
dolgu ışıkları; IBL kapalıyken fillBoost, ghost modunda grid gizli ve iç
kristal ölçeği 1.3.
| Sahne / rol | Parametre | Değer | Tür |
|---|---|---|---|
| Renderer | WebGLRenderer |
antialias: true · alpha: false ·
powerPreference: high-performance ·
setPixelRatio(min(dpr, 2)) · SRGBColorSpace · arka
plan
0x080a12 · ACESFilmicToneMapping · exposure
1.05 · shadowMap.enabled false
|
🔒 Sabit |
| PMREM ortam üretimi | fromScene |
σ 0.045 · kutu oda 48³ · renk 0x1c2436
roughness 0.95 · ışıklar: 0xb8d4ff 3.2 @
(-6,8,10) · 0xffc9a8 2.1 @
(8,3,-6)
|
🔒 Sabit |
| Sahne · IBL açık | scene.environment |
PMREM dokusu · arka plan 0x080a12 · dolgu
fillLow: ambient 0.22 · key 1.35 · rim
0.55
|
🔒 + ↔ UI |
| Sahne · IBL kapalı | scene.environment |
null · arka plan 0x101522 ·
fillBoost: ambient 0.5 · key 1.62 · rim
0.78
|
🔒 + ↔ UI |
| Izgara | GridHelper |
boyut 14 · bölüm 28 · renkler
0x3a4a6a / 0x1a2030 · y = -0.55 ·
ghost’ta visible false
|
🔒 + ↔ UI |
| İkosahedron (arka) | MeshStandardMaterial |
yarıçap 0.68 · detay 0 · renk 0x00d4b8 ·
roughness 0.34 · metalness 0.28 · emissive
0x04221c · emissiveIntensity 0.48 · konum
(0.06, 0.64, -0.92) · dönüş (0.45, 0.72, 0.22) ·
ghost ölçek 1.3
|
🔒 + ↔ UI |
| Cam kadeh | MeshPhysicalMaterial / LatheGeometry |
color 0xffffff · metalness 0 · roughness
0.05 · başlangıç transmission 0.88 · thickness
0.62 · IOR 1.5 · transparent true ·
DoubleSide · attenuationColor 0xd8ecff ·
attenuationDistance 1.85 · specularIntensity 1.22 ·
envMapIntensity 1.58 · clearcoat 1 ·
clearcoatRoughness 0.05 · lathe kesit 8 nokta ·
segment 56 · konum (0, 0.08, 0.46) · dönüş
(-0.12, 0.38, 0.04)
|
🔒 + ↔ UI |
| Kamera | PerspectiveCamera |
FOV 42 · yakın/uzak 0.08 / 80 · konum
(0.48, 0.88, 4.05) · lookAt(0.02, 0.58, -0.12)
|
🔒 Sabit |
| OrbitControls | damping / mesafe | enableDamping · 0.06 · hedef
(0.02, 0.58, -0.12) · mesafe 2.6…14
|
🔒 Sabit |
| HTML · Transmission | type="range" |
0…1 · adım 0.01 · varsayılan 0.88 |
🔒 + ↔ UI |
| HTML · IOR | type="range" |
1…2.45 · adım 0.01 · varsayılan 1.5 |
🔒 + ↔ UI |
| HTML · Thickness | type="range" |
0.05…2.4 · adım 0.02 · varsayılan 0.62
|
🔒 + ↔ UI |
| HTML · IBL | checkbox |
data-physical-demo-env · varsayılan işaretli |
🔒 + ↔ UI |
| HTML · Ghost | checkbox |
data-physical-demo-ghost · varsayılan kapalı |
🔒 + ↔ UI |
Önemli kod kesiti
apply() sürgülerden transmission, IOR ve thickness okur; IBL kutusu ortamı ve
dolgu ışıklarını değiştirir; ghost kutusu ızgarayı ve iç kristal ölçeğini günceller.
function apply() {
const t = trans ? Number(trans.value) : 0.88;
glassMat.transmission = Math.max(0, Math.min(1, t));
const i = ior ? Number(ior.value) : 1.5;
glassMat.ior = Math.max(1, Math.min(2.45, i));
const th = thick ? Number(thick.value) : 0.62;
glassMat.thickness = Math.max(0.05, Math.min(2.4, th));
const envOn = !!(envCb && envCb.checked);
scene.environment = envOn ? envMap : null;
const boost = !envOn;
ambient.intensity = boost ? fillBoost.amb : fillLow.amb;
key.intensity = boost ? fillBoost.key : fillLow.key;
rim.intensity = boost ? fillBoost.rim : fillLow.rim;
scene.background = new THREE.Color(boost ? fillBoost.bg : fillLow.bg);
const ghost = !!(ghostCb && ghostCb.checked);
grid.visible = !ghost;
const ghostScale = ghost ? 1.3 : 1;
innerCrystal.scale.set(ghostScale, ghostScale, ghostScale);
glassMat.needsUpdate = true;
if (readout) {
const envMsg = envOn
? "IBL açık — yansıma + transmission."
: "IBL kapalı → yansıma yok; cam yansıtacak/kırılacak ortam (IBL) bulamaz. Dolgu ışık formu okutur.";
const ghostMsg = ghost
? " Ghost: grid kapalı, ikosahedron %30 büyük — kırılma daha belirgin."
: "";
readout.textContent = `${envMsg}${ghostMsg} · trans ${glassMat.transmission.toFixed(
2
)} · IOR ${glassMat.ior.toFixed(2)} · thick ${glassMat.thickness.toFixed(2)}.`;
}
}
Uygulama: ileri düzey cam konfigürasyonu
Aşağıdaki örnek, “tam cam” hissi için tipik bir yüksek transmission tabanı
ve üzerine ince bir clearcoat katmanı koyar. Gerçek ürünlerde cam genelde
hafif renk sapması, iç yüzey pürüzlülüğü ve çevre yansıması gerektirir; burada yalnızca API
şekli ve birlikte düşünülmesi gereken bayraklar gösterilir.
Çift yüzlü geometride (Side seçenekleri) veya içi boş mesh’lerde thickness
yorumunun değişebileceğini unutmayın; aksi halde IOR doğru olsa bile “cam kalınlığı”
beklenenden farklı okunur.
const glassMaterial = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
roughness: 0, // Pürüzsüz yüzey
transmission: 1.0, // Işığın içeri girmesine izin ver
ior: 1.5, // Standart cam kırılma indisi
thickness: 0.5, // Işığın içinde yol alacağı hacim
specularIntensity: 1, // Yansıma gücü
clearcoat: 1.0, // Ekstra dış yüzey parlaklığı
clearcoatRoughness: 0.1 // Ciladaki mikro kusurlar
});
// Uretim kurali: Bu materyal "GPU canavaridir". Yalnizca ana odak (hero) nesnelerinde kullanin.
// Arka plandaki siseler icin MeshStandardMaterial cogu zaman yeterlidir.
Üretimde bu materyali sahneye eklemeden önce: ortam haritası, ton eşlemesi ve (varsa)
transmisyon çözünürlüğü ayarlarını birlikte doğrulayın; tek başına materyal kodu ile
“kırık” görünümler çoğu zaman renderer veya IBL yapılandırmasından kaynaklanır. Kullanım
bittikinde geçici ortam üreticilerini ve büyük dokuları dispose etmek mobil
bellek baskısını azaltır.
Performans ve strateji
MeshPhysicalMaterial, Three.js tarafında en ağır sınıflardan biridir: GPU her
karede geçiş, kırılma ve katmanlar arası etkileşimi hesaplar.
LOD stratejisi
Kamera yakındayken Physical, uzaktayken MeshStandardMaterial ile değiştirmek, profesyonel projelerde performansı koruyan akıllıca bir hamledir.
Transmission maliyeti
transmission açıkken GPU arka planı doku olarak yakalayıp nesneye
giydirir; mobilde FPS düşüşüne yol açabilir — dikkatli kullanın.
Özet strateji: hero’da Physical, mesafede Standard veya Lambert; transmisyon açık nesneleri aynı karede toplu sınırlamak, profil çıkarmayı kolaylaştırır. Takım içinde “Physical onayı” gibi hafif bir kontrol listesi (IBL var mı, IOR referansı net mi, mobilde kapatılacak varyant hazır mı) kaliteyi stabilize eder.
Bir sonraki adımda stilize gölgelere geçiyorsanız MeshToonMaterial ile PBR’nin bilinçli olarak sadeleştirildiği bir dil; Physical ile aynı sahneye karıştırırken ışık ve tonlama hedefinin farklı olduğunu açıkça ayırmak gerekir.