holodepth

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.

Premium sahne · MeshPhysicalMaterial

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.

initPhysicalDemo · Katmanlı cam lab
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.