holodepth

Three.js · PBR

MeshStandardMaterial: Gerçekçiliğin Kodlanmış Hali

Işığın yüzeyle yaptığı pazarlık

Bazı 3D modeller neden “plastik” gibi görünürken, diğerleri gerçek hayattan farksızdır? Aradaki fark, ışığın yüzeye yalnızca çarpması değil, o yüzeyle nasıl bir pazarlığa girdiğidir. Three.js dünyasında bu pazarlığın adı PBR (Physically Based Rendering), yani fiziksel temelli render modelidir. MeshStandardMaterial, bu felsefenin kalbidir. Klasik Phong’ta ayrı bir “parlak leke” rengi vardır; Standard’da ise aynı hikâye metalness · roughness · çevre ışığı üzerinden, enerji tutarlılığına yakın bir dilde anlatılır — bu yüzden glTF ve modern içerik boru hatlarıyla uyumludur.

Önkoşul: MeshPhongMaterial (stilize specular) ve MeshLambertMaterial (mat difüz); ışıksız referans MeshBasicMaterial. Cam, clearcoat ve genişletilmiş yüzey katmanları için MeshPhysicalMaterial. Kavramsal çerçeve: Materyal giriş. Üretim disiplini: HoloDepth kuralları. Sayfa sonunda özet ve komşu ders bağlantıları.

Zihin modeli: PBR nedir?

Özet

PBR kullanırken ışığı “taklit etmeye” çalışmazsınız; ışığın yüzeydeki fiziksel davranışını modellersiniz. Işık bir yüzeye çarptığında ya yansır ya emilir; PBR bu dengeyi matematiksel bir disiplinle — enerji korunumu çerçevesinde — yönetir.

Pratikte bu, sanatçıya şunu söyler: “Işığı tek tek hileyle boyamak” yerine yüzeyi iletkenlik (metal) ve mikro pürüzlülük (roughness) ile tanımlarsın; yansımaların neyi göstereceği büyük ölçüde sahnedeki ortam ve ışık düzeninden gelir. Aynı metalness / roughness çifti, farklı HDR ortamlarında tamamen farklı karakter okunabilir — bu bir hata değil, PBR’nin tasarım sözleşmesidir.

MeshStandardMaterial tek başına “fotoğraf modu” değildir; doğru ton eşlemesi, exposure ve (çoğu projede) çevre haritası ile birlikte düşünülmelidir. Aşağıdaki bölümlerde önce parametre sezgisi, sonra çevre bağımlılığı ve en sonda etkileşimli örnek üzerinden bu zinciri somutlaştırıyoruz.

Hızlı görünüm rehberi: kombinasyonlar

PBR dünyasında çoğu malzeme görünümü metalness ve roughness ikilisinin dansına bağlıdır. Sık kullanılan “tarifler”:

Metalness · roughness

Cilalı metal

metalness: 1.0
roughness: 0.1

Aynaya yakın, keskin yansımalar.

Fırçalanmış çelik

metalness: 1.0
roughness: 0.5

Mat ama metalik; pütürlü yüzey hissi.

Parlak plastik

metalness: 0.0
roughness: 0.1

Yansıtıcı ama metal olmayan; lake yüzey.

Kuru toprak / taş

metalness: 0.0
roughness: 0.9

Işığı dağıtan, pürüzlü ve mat görünüm.

Kartlardaki değerler başlangıç noktalarıdır; gerçek üretimde çoğu zaman metalnessMap, roughnessMap veya glTF içinde kanal birleştirme (ör. ORM dokusu) ile yüzey içi varyasyon taşınırsın. Bu sayfada harita ayrıntılarına girmeden bile şu ayrımı korumak yeterlidir: metalness “parlaklık sürgüsü” değil, dielectric ↔ conductor ayrımıdır; parlaklığın keskinliği ve yansıma bulanıklığı ise roughness ve çevre aydınlatmasıyla birlikte okunur.

Albedo (color / map) seçerken metal yüzeylerde renk bilgisinin çoğunun yansımada “yaşadığını” unutma: tam metalde difüz taban sık sık çevre tonlarına kayar; bu yüzden referans görselini tek bir spot altında değil, hedef ortamın ışığında değerlendirmek gerekir.

En büyük yanılgı: metalness parlaklık değildir

Yeni başlayanlar tuzağı

Nesneyi “parlatmak” için metalness değerini artırmak — yaygın ama yanlış bir refleks.

Gerçek: metalness yalnızca yüzeyin iletkenlik / metal karakterini belirler.

  • Parlaklık (brightness): Işık kaynağının gücü ve albedo ile ilişkilidir.
  • Bulanıklık (blur): roughness ile kontrol edilir.
  • Yansıma: Sahnede çevre haritası (env map) yoksa, metaliklik çoğu zaman kendini yalnızca koyu, cansız bir alan olarak gösterir.

Doğru refleks şudur: önce çevreyi ve kamera exposure’unu oturt, sonra roughness ile yansımanın keskinliğini ayarla; metalness’i yalnızca malzeme gerçekten iletken/metal davranışı istediğinde yükselt. Dielectric bir yüzeyi “parlak” hissettirmek için çoğu zaman düşük roughness + güçlü ortam yeterlidir — metalness’i tırmalamadan.

Bu yanılgı, Phong alışkanlığından gelir: orada parlaklık ayrı bir specular rengiyle modellenirdi. Standard’da ise parlaklığın büyük kısmı BRDF + ortam konvolüsyonu üzerinden gelir; bu yüzden “aynı slider hissi” yoktur ve ilk gün kafa karıştırıcıdır — ama tutarlılık ödülü, farklı sahneler arasında taşınabilir malzeme dilidir.

Gerçekçiliğin sırrı: ortam (environment map)

PBR ve çevre

PBR materyalin en önemli içgörüsü şudur: Yansıtacak bir dünya yoksa, metal tam anlamıyla çalışmaz. Metalik yüzeyler doğası gereği çevreyi yansıtır. scene.environment veya materyalin envMap özelliği boşsa, ayarları ne kadar ince ayarlasanız da yüzey sık sık koyu ve cansız kalır. MeshStandardMaterial, etrafındaki dünyadan beslenen bir aynadır.

Three.js tarafında çevre genelde PMREMGenerator ile ön işlenmiş bir kübik doku olarak gelir; bu, speküler lobların farklı genişliklerde doğru bulanıklaşmasına yardım eder. scene.environment sahneye yayılır; istenirse tek nesneye özel envMap da verilebilir — ikinci yol, varyasyon için güçlü olsa da bellek ve tutarlılık maliyetini artırır.

Aşağıdaki etkileşimli örnekte prosedürel bir ortam kullanıldığı için harici HDR dosyası yoktur; yine de “IBL kapatılınca metalin neden solgunlaştığı” dersi aynen geçerlidir. Sayısal ayrıntılar figür altındaki özetle birlikte demo sabitleri tablosunda toplanır; burada odak iş akışıdır: önce ortamı doğrula, sonra metalness / roughness ile formu şekillendir.

İnteraktif: “PBR facet gem”

Bu sahnede sol taraftaki facet’li gövde tam PBR parametreleriyle güncellenir; sağdaki küçük küre ise dielectric bir referans baseline olarak sabit kalır — böylece metalness / roughness oynatırken “tamamen metal mi, yoksa parlak dielectric mi?” ayrımını gözle karşılaştırabilirsiniz. Üstteki onay kutusu scene.environment’ı açıp kapatır; bu tek hareket, bir önceki bölümdeki “çevresiz metal” uyarısını sahada anında gösterir.

Readout satırı anlık değerleri kısaltır; ışık yerleşimi, IBL yoğunluğu ve spot açısı gibi ince ayarlar figür altındaki açıklamada — metinleri üst üste binmeden okumak için önce sürgüleri deneyip sonra alt yazıyı tarayın. Tüm sayısal ölçüler demo sabitleri tablosunda diagram-standard-material.js ile eşlenir.

Premium sahne · MeshStandardMaterial

Sol: dodecahedron — sürgülerle PBR; sağ: küçük referans küre (metalness 0, roughness 0.5), metal olmayan dielectric baseline. scene.environmentIntensity ~2 ile IBL daha hissedilir; PMREM içinde parlak nokta + küçük emissive küre ve daha düşük blur (sigma) ile çevrede keskin bir “hotspot”; sahnede dar cone SpotLight + accent nokta ışık spec’i netleştirir. Ana gövde rengi soğuk nötr gri taban. IBL kapatınca yine aynı öğreti. Harici HDR/doku URL yok.

Demo sabitleri tablosu (PBR facet gem)

initStandardDemo · prosedürel ortam PMREMGenerator.fromScene ile üretilir; ana sahnede ızgara, dodecahedron + referans küre, çoklu ışık ve IBL aç/kapa ile doldurma güçlendirme (fillLow / fillBoost). Gölge haritası yok.

initStandardDemo · PBR facet gem lab
Sahne / rol Parametre Değer Tür
Renderer WebGLRenderer antialias: true · alpha: false · powerPreference: high-performance · setPixelRatio(min(dpr, 2)) · SRGBColorSpace · arka plan 0x070910 · ACESFilmicToneMapping · exposure 1.06 · gölge yok 🔒 Sabit
PMREM ortam üretimi fromScene σ (blur) 0.022 · iç sahne: BoxGeometry(48,48,48) arka yüz 0x1a1528 roughness 0.92 · ışıklar: 0xffdcc8 3.6 · 0x9ec4ff 3.2 · beyaz 4.4 · nokta 52 @ (8.5,6.2,7) · emissive küre emissiveIntensity 6 @ (6.8,5.5,9.2) 🔒 Sabit
Sahne · IBL açık scene.environment PMREM dokusu · environmentIntensity (destekleniyorsa) 2.05 · arka plan 0x070910 🔒 + ↔ UI
Sahne · IBL kapalı scene.environment null · environmentIntensity 1 · arka plan 0x121a28 · dolgu ışıkları fillBoost (ambient 0.48, key 1.55, rim 0.72, accent 1.45, spot 2.95) 🔒 + ↔ UI
Izgara GridHelper boyut 14 · bölüm 28 · renkler 0x3a4a6a / 0x1a2030 · y = -0.52 🔒 Sabit
Doldurma (IBL açık) AmbientLight / DirectionalLight ×2 · PointLight · SpotLight ambient 0xffffff 0.2 · key 1.2 konum (4.5, 6.2, 3.5) · rim 0xb8c8ff 0.5 konum (-4, 2.5, -3.5) · accent 0xfff2dd 1.15 mesafe 14 decay 1.6 konum (2.1, 2.35, 2.2) · spot 2.35 mesafe 22 açı 13° penumbra 0.38 decay 1.15 konum (3.05, 3.45, 2.65) hedef (-0.48, 0.82, 0) 🔒 + ↔ UI
Ana gövde MeshStandardMaterial / DodecahedronGeometry renk 0xb2bac4 · başlangıç metalness 0.65 roughness 0.28 · envMapIntensity 1.22 · geometri (1.1, 0) · konum (-0.5, 0.82, 0) · dönüş (0.22, 0.55, 0.12) 🔒 + ↔ UI
Referans küre MeshStandardMaterial / SphereGeometry renk 0xa8c4e8 · metalness 0 · roughness 0.5 · envMapIntensity 1.05 · yarıçap 0.32 · segment 36 · konum (1.48, 0.56, 0.18) 🔒 Sabit
Kamera PerspectiveCamera FOV 40 · yakın/uzak 0.08 / 80 · konum (0.32, 0.9, 3.25) · lookAt(0.06, 0.68, 0.06) 🔒 Sabit
OrbitControls damping / mesafe enableDamping · 0.06 · hedef (0.06, 0.68, 0.06) · mesafe 2.05…12 🔒 Sabit
HTML · Metalness type="range" 0…1 · adım 0.01 · varsayılan 0.65 🔒 + ↔ UI
HTML · Roughness type="range" 0…1 · adım 0.01 · varsayılan 0.28 🔒 + ↔ UI
HTML · IBL checkbox data-standard-demo-env · varsayılan işaretli (scene.environment açık) 🔒 + ↔ UI

Önemli kod kesiti

apply() sürgülerden metalness ve roughness okur; IBL kapalıyken ortamı kaldırıp dolgu ışıklarını güçlendirir — böylece “karanlık metal” yerine kontrollü bir sahnede aynı karşılaştırma okunabilir kalır.

function apply() {
  const m = metal ? Number(metal.value) : 0.65;
  mat.metalness = Math.max(0, Math.min(1, m));
  const r = rough ? Number(rough.value) : 0.28;
  mat.roughness = Math.max(0, Math.min(1, r));
  mat.needsUpdate = true;

  const envOn = !!(envCb && envCb.checked);
  scene.environment = envOn ? envMap : null;
  if ("environmentIntensity" in scene) {
    scene.environmentIntensity = envOn ? 2.05 : 1;
  }
  const boost = !envOn;
  ambient.intensity = boost ? fillBoost.amb : fillLow.amb;
  key.intensity = boost ? fillBoost.key : fillLow.key;
  rim.intensity = boost ? fillBoost.rim : fillLow.rim;
  accent.intensity = boost ? fillBoost.accent : fillLow.accent;
  spot.intensity = boost ? fillBoost.spot : fillLow.spot;
  scene.background = new THREE.Color(boost ? fillBoost.bg : fillLow.bg);

  if (readout) {
    const envMsg = envOn
      ? "IBL güçlü (scene.environmentIntensity ~2) — metal vs mat küre kıyasını izle."
      : "IBL kapalı — metal ‘boşluğa’ bakar; sağdaki küre zaten metal değil (0/0.5).";
    readout.textContent = `${envMsg} Ana: metalness ${mat.metalness.toFixed(
      2
    )} · roughness ${mat.roughness.toFixed(2)}.`;
  }
}

Uygulama: profesyonel kurulum

Tipik bir PBR kurulumu, glTF ile uyumlu düşünüldüğünde aynı parametreler başka motorlarda da tutarlı kalır. Üretimde sıradaki adım genelde aoMap, normalMap, roughnessMap ve metalnessMap (veya birleşik ORM) ile yüzey detayını eklemektir; aşağıdaki örnek yalnızca çekirdek API’yi gösterir.

Renderer tarafında tone mapping ve doğru renk uzayı seçimi, PBR’nin “doğal” görünmesi için ayrı bir sıradır; demo scriptinde bu yüzden filmik tonlama ve sRGB çıkışı kullanılır — koddaki tek satırlık materyal örneği, bu bağlamın yer tutucusudur.

// 1. Standart PBR kurulumu
const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,      // Albedo (taban renk)
    metalness: 1.0,       // Tam metal karakteri
    roughness: 0.2        // Hafif mikro pürüzlülük
});

// 2. Neden glTF bu materyali kullanır?
// glTF/GLB formatları motor bağımsızdır (Unreal, Unity, Three.js).
// PBR sayesinde modeliniz her platformda aynı tutarlılıkla görünür.
const textureLoader = new THREE.TextureLoader();
material.normalMap = textureLoader.load('/textures/surface_detail_normal.jpg');

const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

Doku yüklerken colorSpace ve flipY bayraklarını hedef formatına (ör. glTF içe aktarımda beklenen renk uzayı ve doku yönü kuralları için) göre ayarlamayı unutmayın; yanlış uzay, PBR’de “her şey yağlı” veya “her şey tozlu” gibi sistematik hatalara dönüşür. Ortam haritası ürettiğinizde PMREMGenerator çıktısını ve geçici sahne nesnelerini kullanım sonrası dispose etmek bellek basıncını azaltır.

Holodepth üretim kuralları

A Performans dengesi

PBR materyaller GPU için maliyetlidir; her pikselde karmaşık BRDF hesapları çalışır. Sahnede binlerce PBR nesnesi, özellikle mobilde cihazı zorlar.

B Altın kural: hero vs. arka plan

Hero: Kullanıcının yakından baktığı, etkileşime girdiği modellerde MeshStandardMaterial kullanın.

Arka plan: Uzak binalar, ikincil objeler veya LOD ile küçültülmüş mesh’lerde MeshLambertMaterial veya MeshBasicMaterial ile GPU’ya nefes aldırın.

Bu ayrım “kalite düşürmek” değil, dikkat bütçesini yönetmektir: izleyici nereye bakıyorsa orada tam BRDF, periphery’de ise daha ucuz shading ile kare başına maliyet sabitlenir. İçerik takımında bunu netleştirmek, sanat ile mühendislik arasındaki en sık çatışmayı erken kapatır.

Son kontrol listesi: hero mesh için ortam + temel ışık düzeni, LOD geçişinde materyal ailesi (Standard → Lambert / Basic), mobilde doku çözünürlüğü ve roughness/metalness haritalarının gereksiz yüksek frekans taşımadığından emin olma. Bir sonraki derste MeshPhysicalMaterial ile cam, transmisyon ve clearcoat gibi Standard’ın üstüne çıkan katmanları ele alıyoruz.