فهم Mipmaps وترشيح الخامات في Three.js (WebGL)

عند بناء تجارب ثلاثية الأبعاد للويب تكون الخامات في كل مكان. يمكن لكائن بسيط أن يحتوي على خامة لون وNormal Map وRoughness Map وMetalness Map وخامات بيئية.

لكن قد تلاحظ أحيانًا مشكلات غريبة: خامات ضبابية، كائنات بعيدة ترتعش، أنماط مشوشة، أو انخفاض الأداء لأن الخامات مكلفة. يرتبط كثير من هذه المشكلات بمفهومين مهمين: Mipmaps وترشيح الخامات. لنفهمهما ببساطة وبشكل عملي.

1. كيف يعرض WebGL الخامة؟

تخيّل صورة بحجم 1024×1024 على مكعب ثلاثي الأبعاد. عندما تكون الكاميرا قريبة، يشغل المكعب نحو 800×800 بكسل من الشاشة وكل شيء يبدو جيدًا. لكن عندما تبتعد الكاميرا، يشغل المكعب 50×50 بكسل فقط بينما ما زالت الخامة 1024×1024.

الآن يواجه WebGL مشكلة: «كيف أحوّل صورة ضخمة إلى عدد صغير جدًا من البكسلات؟» تُسمى هذه العملية أخذ عينات الخامة (Texture Sampling).

2. ما هو ترشيح الخامات؟

الترشيح هو الطريقة التي يقرر بها WebGL أي بكسلات الخامة يستخدم لكل بكسل نهائي على الشاشة. مثلًا قد يقع بكسل الشاشة بين أربعة بكسلات من الخامة، ويحتاج WebGL إلى حساب اللون النهائي. وتعطي طرق الترشيح المختلفة نتائج مختلفة.

3. ترشيح Nearest

أبسط طريقة: يختار WebGL أقرب بكسل.

texture.magFilter = THREE.NearestFilter;

سريع جدًا وينتج أسلوب البكسل آرت، لكنه يبدو مكعّبًا. استخدامات شائعة: ألعاب البكسل، والرسومات الكلاسيكية، وخامات البيانات.

4. ترشيح Linear

بدل اختيار بكسل واحد، يمزج WebGL البكسلات المجاورة — بكسل أحمر بجانب بكسل أزرق يعطي بنفسجيًا.

texture.magFilter = THREE.LinearFilter;

النتيجة أنعم، وهي عادةً ما نريده للرسومات ثلاثية الأبعاد الواقعية.

5. مشكلة الخامات البعيدة

يحل الترشيح مشكلة لكن تظهر أخرى. تخيّل جدارًا من الطوب يشغل 20 بكسلًا فقط على الشاشة بينما ما زالت وحدة معالجة الرسومات تقرأ من الخامة الأصلية 2048×2048. النتيجة: ارتعاش، وتعرّج، وأنماط مشوشة. وهنا تساعد الـ Mipmaps.

6. ما هي Mipmap؟

الـ Mipmap مجموعة من النسخ الأصغر للخامة نفسها:

Level 0: 2048 × 2048
Level 1: 1024 × 1024
Level 2:  512 × 512
Level 3:  256 × 256
Level 4:  128 × 128
Level 5:   64 × 64

فكّر فيها كامتلاك نسخ بجودات مختلفة من الصورة نفسها.

7. كيف يستخدم WebGL الـ Mipmaps؟

عندما يكون الكائن قريبًا تستخدم وحدة معالجة الرسومات مستوى 2048×2048، وعندما يكون بعيدًا تستخدم شيئًا مثل 128×128. تختار النسخة المناسبة تلقائيًا.

المزايا: ✅ جودة أفضل، ✅ عمل أقل لوحدة الرسومات، ✅ ارتعاش أقل، ✅ أداء أفضل.

8. ترشيح Mipmap في Three.js

يفعّل Three.js الـ Mipmaps تلقائيًا لمعظم الخامات:

const texture = textureLoader.load("/textures/wood.jpg");
// افتراضيًا:
texture.generateMipmaps = true;

مرشّح التصغير الافتراضي هو THREE.LinearMipmapLinearFilter، أي: استخدم الـ Mipmaps، وامزج بين مستوياتها، واصنع انتقالات ناعمة.

9. التحكم بالترشيح في Three.js

إعداد شائع:

const texture = loader.load("/textures/ground.jpg");

texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;

texture.minFilter = THREE.LinearMipmapLinearFilter;
texture.magFilter = THREE.LinearFilter;
  • يُستخدم minFilter عندما تصبح الخامة أصغر على الشاشة (كائن كبير ← كائن صغير).
  • يُستخدم magFilter عندما تصبح الخامة أكبر على الشاشة (خامة صغيرة ← كائن مكبّر).

10. متى تعطّل الـ Mipmaps؟

الـ Mipmaps رائعة لكن ليس دائمًا. الخامات الديناميكية — Canvas Texture وRender Target ومركّبات Decal وخامات الواجهة على الكائنات ثلاثية الأبعاد — قد تعاني من تسرّب لوني غير مرغوب. إذا رسمت شعارًا أحمر على خلفية بيضاء، فستمزج المستويات الأصغر البكسلات الحمراء والبيضاء وتصبح حواف الشعار ضبابية. في هذه الحالات:

texture.generateMipmaps = false;
texture.minFilter = THREE.LinearFilter;

11. مثال واقعي: Canvas Texture في Three.js

const canvas = document.createElement("canvas");
const texture = new THREE.CanvasTexture(canvas);

texture.generateMipmaps = false;
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;

مفيد للتسميات والنصوص الديناميكية والرسومات المخصصة والـ Decals.

12. قاعدة بسيطة للتذكر

لمعظم النماذج ثلاثية الأبعاد:

texture.generateMipmaps = true;
texture.minFilter = THREE.LinearMipmapLinearFilter;
texture.magFilter = THREE.LinearFilter;

للخامات الديناميكية:

texture.generateMipmaps = false;
texture.minFilter = THREE.LinearFilter;

الخلاصة

الـ Mipmaps والترشيح ليست مجرد إعدادات أداء؛ إنها تؤثر مباشرة في الجودة البصرية وأداء وحدة الرسومات ووضوح الخامات وتجربة المستخدم. في المرة القادمة التي ترى فيها خامات ترتعش أو تفاصيل ضبابية أو حوافًا غريبة، تذكّر: قد لا تكون المشكلة في نموذجك، بل في الطريقة التي يأخذ بها WebGL عينات خاماتك.