Vertex Shader هو مرحلة قابلة للبرمجة في خط أنابيب الرسومات (graphics pipeline) تعالج كل رأس من نموذج ثلاثي الأبعاد بشكل مستقل. وفقًا Khronos Group، 2025، يستقبل shader الرؤوس سمات الرؤوس — الإحداثيات، الاتجاهات (normals)، اللون وإحداثيات النسيج — ويحولها وفق المنطق المحدد. Vertex Shader يُنفذ لكل رأس بشكل مستقل، مما يسمح بتوزيع الحسابات بكفاءة على آلاف أنوية GPU.
الخلاصة
Vertex Shader هو مرحلة قابلة للبرمجة في خط أنابيب الرسومات تعالج كل رأس من نموذج ثلاثي الأبعاد بشكل فردي. الرأس (vertex) هو نقطة في الفضاء ثلاثي الأبعاد تحتوي على سمات: إحداثيات xyz، الاتجاهات (normals)، اللون وإحداثيات النسيج UV.
على عكس خط الأنابيب ذي الوظائف الثابتة (fixed-function pipeline) حيث كانت التحويلات تُنفذ وفق خوارزمية صلبة، يمنح Vertex Shader المطور تحكمًا كاملاً في تحويل الرؤوس. يتيح ذلك تنفيذ الرسوم المتحركة الإجرائية، تشويه النماذج، skinning الهيكلي وأي تحويلات رياضية على جانب GPU.
يشمل خط أنابيب الرسومات في OpenGL ES سلسلة من المراحل من بيانات الإدخال إلى الصورة النهائية. Vertex Shader يقع بعد مرحلة تجميع الرؤوس (vertex assembly) وقبل مرحلة التنقيط (rasterization). كل رأس يُرسل من CPU عبر مخزن الرؤوس يمر عبر Vertex Shader مرة واحدة بالضبط، وتُنقل النتيجة إلى المرحلة التالية لتجميع البدائيات.
| مرحلة خط الأنابيب | الغرض |
|---|---|
| Vertex Specification | نقل بيانات الرؤوس والسمات من VBO |
| Vertex Shader | معالجة كل رأس، تحويل الإحداثيات |
| Tessellation | تقسيم اختياري للهندسة إلى بدائيات فرعية |
| Geometry Shader | توليد أو إزالة اختيارية للبدائيات |
| Rasterization | تحويل البدائيات إلى أجزاء (fragments) للتعبئة |
Vertex Shader يستقبل سمات الرؤوس من مخزن الرؤوس (VBO) عبر مؤشرات سمات الرؤوس (vertex attribute pointers) المكونة في كود CPU. يكتب المطور كود shader بلغة GLSL (OpenGL Shading Language) أو لغة مكافئة، والتي يترجمها برنامج تشغيل GPU إلى تعليمات آلية للرقاقة المحددة.
لكل رأس، ينفذ Vertex Shader ثلاث عمليات بالتسلسل: قراءة سمات الإدخال — تطبيق التحويلات المحددة من قبل المطور — كتابة النتائج في متغيرات الإخراج. الحد الأدنى المطلوب للإخراج هو موضع الرأس في مساحة القص (clip space) (gl_Position). تُدرج جميع بيانات الإخراج الأخرى (اللون، الاتجاهات، إحداثيات النسيج) وتُنقل إلى المرحلة التالية — Fragment Shader.
#version 300 es
in vec3 aPosition;
in vec2 aTexCoord;
uniform mat4 uMVP;
out vec2 vTexCoord;
void main() {
gl_Position = uMVP * vec4(aPosition, 1.0);
vTexCoord = aTexCoord;
}
Vertex Shader يحل مجموعة واسعة من مهام خط أنابيب الرسومات المتعلقة بتحويل الهندسة. تُنفذ كل مهمة من خلال عمليات رياضية على المتجهات والمصفوفات، تُنفذ بالتوازي لآلاف الرؤوس في وقت واحد.
المهمة الأساسية والأكثر شيوعًا هي ضرب إحداثيات الرؤوس في مصفوفات model و view و projection (MVP). مصفوفة MVP تحول الرأس من مساحة النموذج المحلية إلى مساحة القص (clip space)، والتي تُطبع وتُحول إلى إحداثيات الشاشة في المراحل التلقائية لخط الأنابيب.
للشخصيات المتحركة، ينفذ Vertex Shader الرسوم المتحركة الهيكلية (skinning). كل رأس مرتبط بعدة عظام بأوزان محددة. Vertex blending — مجموع موزون للتحويلات من العظام المرتبطة — يسمح بتشويه جلد الشخصية بسلاسة عند حركة الهيكل العظمي.
يستطيع Vertex Shader تعديل الهندسة بناءً على الوقت أو معاملات uniform أخرى دون مشاركة CPU. Wave deformation، إزاحة ضوضاء Perlin وتأثيرات تموج الماء — جميع هذه التأثيرات تُنفذ في shader الرؤوس دون إعادة تحميل الهندسة من RAM.
على الرغم من أن كلا النوعين من shaders هما مرحلتان قابلتان للبرمجة في خط أنابيب الرسومات، إلا أن Vertex Shader و Fragment Shader يحلان مهام مختلفة جوهريًا ويعملان في مراحل مختلفة من معالجة الصور.
| الخاصية | Vertex Shader | Fragment Shader |
|---|---|---|
| بيانات الإدخال | سمات الرؤوس من VBO | بيانات مُدرجة من VS |
| عدد الاستدعاءات | عدد الرؤوس | عدد الأجزاء (fragments) |
| المهمة الرئيسية | تحويل الهندسة | حساب لون البكسل |
| الحمل الحسابي | تعقيد الهندسة | دقة الشاشة |
| الوصول إلى النسيج | محدود (عبر texture lookup) | وصول كامل |
الفرق الرئيسي هو تكرار الاستدعاء. يُستدعى Vertex Shader مرة واحدة لكل رأس، بينما يُستدعى Fragment Shader لكل جزء (بكسل). في مشهد عالي الدقة، يتجاوز عدد استدعاءات Fragment Shader عدد استدعاءات Vertex Shader بآلاف المرات، مما يجعل تحسين shaders البكسل أكثر أهمية.
أداء Vertex Shader مهم جدًا للتطبيقات في الوقت الفعلي، خاصة في تطوير التطبيقات المحمولة مع استهلاك محدود للطاقة. عوامل الأداء الرئيسية هي عدد الرؤوس، تعقيد كود shader وعرض النطاق الترددي لذاكرة GPU.
لتقليل الحمل على Vertex Shader، تُستخدم الأساليب التالية. Level of Detail (LOD) — التبديل إلى إصدارات مبسطة من النماذج عند ابتعاد الكاميرا عن الجسم. Instancing — رسم نفس الهندسة عدة مرات بمصفوفات تحويل مختلفة في استدعاء رسم واحد (draw call).
// Vertex Shader مع دعم instancing
in vec3 aPosition;
in mat4 aInstanceMatrix;
uniform mat4 uViewProjection;
void main() {
vec4 worldPos = aInstanceMatrix * vec4(aPosition, 1.0);
gl_Position = uViewProjection * worldPos;
}
Vertex Shader في واجهات برمجة الرسومات المختلفة له منطق مماثل، لكن بناء جملة واتفاقيات تسمية مختلفة. لنلقِ نظرة على تنفيذ shader رؤوس أساسي في GLSL لـ OpenGL ES 3.0 وفي Metal Shading Language لـ iOS و macOS.
#version 300 es
in vec4 position;
in vec3 normal;
in vec2 texcoord;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
out vec3 vNormal;
out vec2 vTexCoord;
out vec3 vPosition;
void main() {
vec4 mvPosition = modelViewMatrix * position;
vPosition = mvPosition.xyz;
vNormal = normalMatrix * normal;
vTexCoord = texcoord;
gl_Position = projectionMatrix * mvPosition;
}
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
};
struct VertexOut {
float4 position [[position]];
float3 worldNormal;
};
vertex VertexOut
vertexMain(VertexIn in [[stage_in]],
constant float4x4& mvp [[buffer(1)]]) {
VertexOut out;
out.position = mvp * float4(in.position, 1.0);
out.worldNormal = in.normal;
return out;
}
الأسئلة الشائعة
Vertex Shader هو برنامج على GPU يعالج كل رأس من نموذج 3D ويحول إحداثياته إلى إحداثيات شاشة. تخيل النموذج كشبكة من النقاط؛ shader الرؤوس يحرك هذه النقاط وفق قواعد رياضية محددة.
Vertex Shader يعالج الرؤوس ويتولى الهندسة، بينما Fragment Shader يحدد لون كل بكسل. الأول يُستدعى لكل رأس (آلاف)، والثاني لكل بكسل (ملايين).
يُكتب Vertex Shader بلغة تتوافق مع واجهة برمجة الرسومات: GLSL لـ OpenGL ES، Metal Shading Language لـ Metal API على iOS/macOS، HLSL لـ Direct3D. من الناحية المفاهيمية، تؤدي جميعها نفس العمليات على الرؤوس.
يؤثر تعقيد shader الرؤوس مباشرة على FPS: تعليمات أكثر لكل رأس = وقت معالجة أطول. التحسين يشمل تقليل عدد الرؤوس عبر LOD، استخدام instancing وتقليل الفروع الشرطية في كود shader.
المهام الرئيسية في الألعاب: تحويل الإحداثيات عبر مصفوفات MVP، skinning الشخصيات المتحركة، تشويه إجرائي للملابس والشعر، morphing بين تعابير الوجه وتأثيرات الجسيمات مع الرسوم المتحركة على GPU.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا