برمجة ال shader باستخدام ال CG الدرس الأول

قبل ان نبدا في البرمجة علينا ان نفهم قليلا ال rendering pipeline وقد تحدث عنه مسبقا في هذا الدرس سوف افصل هنا في بعض الامور النظرية قبل ان نبدا البرمجة .

 

الخطوات التي تمر بها عملية ال rendering

 

ننقل البيانات الى ال gpu على شكل vertices تحتوي على معلومات اللون وال texture map و غيرها وايضا ترافق هذه المعلومات تعريف لطريقة تجميع هذه النقاط الى primitives geometric  ثم تنتقل هذه النقاط والبيانات الى برنامج ال vertex حيث يحولها الى احداثيات ال view port ومنها الى عملية تجميع النقاط وتحويلها الى primitives geometric ثم ننتقل الى مرحلة ال resterization حيث يحدد مواقع البكسلات التي تغطي ال primitives geometric وايضا في هذه المرحلة يتم تحديد لون متدرجا حسب لون ال vertex المرفق معه تضاف هذه البيانات لكل لكل بكسل يغطي الشكل البدائي لنحصل على fragment ثم ينتقل كل fragment الى برنامج ال fragment على التوالي قد تحتوي الشكل البدائي ذو الثلاثة نقاط على ملايين ال fragments التي تغطيها بعد الانتها من برنامج ال fragment فانه يعيد لون للبكسل يذهب الى raster operation وفيه تتم عمليات مثل ال blending and alpha test and stencil and depth test وبعدها يذهب ال pixel الى ال frame buffer .

صورة تشرح الخطوات بالرسم

 

انتقال البيانات بين مراحل ال rendering pipeline


كما هو موضح البيانات تنتقل من التطبيق الى برنامج ال vertex  في بارامترات معرفة ب semantics لتحدد استخدام كل parameter فمثلا ال POSITION semantic لتحديد احداثيات ال vertex  و ال  NORMAL semantic لتحدد المتجه العامودي على المستوى و  COLOR لون ال vertex و TXCOORD0,1,2  لل texture map
البيانات السابقة تحدد لكل vertex وهناك بيانات عامة وثابتة تشترك فيها جميع ال vertices  تسمى ب uniform وبامكانك حفظ الصورة او بعض البيانات بها ويمكن تغييرها والتحكم به برمجيا من unity هذه البيانات ثابتة وحتى وان قمت بتغييرها من خلال برنامج ال fragment فانه يعود لقيمته الحقيقية في ال fragment التالي وينطبق نفس الكلام على برنامج ال vertex .
تخرج البيانات من برنامج ال vertex على شكل semantics مثل POSITION, SV_POSITION, COLOR, TEXCOORD0, TEXCOORD1 لتذهب الى مرحلة ال rasterization وال interpolation
ملاحظة :  SV_POSITION تعني system value position وتستخدم لتحديد موقع الشكل البدائي على الشاشة وبامكانك استخدام POSITION فقط .
ملاحظة : وفي حال كان الشكل البدائي عبارة عن نقاط استخدم PSIZE sementic حجم النقطة .
المعلومات الخارجة من برنامج ال vertex وبعد معالجتها يتم اضافتها الى كل بكسل يغطي ال primitive geometric لنحصل على ال fragment
تنتقل البيانات في رحلتها الى بارامترات ال fragment program لتتم معالجتها في البرنامج ويكون ال output لبرنامج ال fragment في الغالب اما DEPTH semantic او COLOR semantic ومنه الى ال raster operation ثم الى ال frame buffer.

ملف Shader

نبدا بمثال بسيط

Shader "test/shader1"
{
	subshader
	{
		pass
		{
		}
	}
}

يبدا ملف الshader  ب Shader يتبعه اسم ال shader ثم بين قوسين مجموعة نضيف ال  subshader وقد يحتوي Shader على أكثر من subshader كل واحد منها يعمل لمصلحة نظام وهاردوير مختلف ولا يعملون سوية .
ويحتوي subshader بداخله على مجموعة passes تعمل بالتتابع pass  ثم الذي يليه وبامكانك عن طريق unity عمل draw على pass  معين ٠ او ١ الخ كل pass كانه استدعاء للامر draw فترسم الكائن من جديد في كل pass .

كود CG بسيط

Shader "test/shader1"
{
	subshader
	{
		pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			float4 vert(float4 pos:POSITION):SV_POSITION
			{
				return mul(UNITY_MATRIX_MVP,pos);
			}

			fixed4 frag(void):COLOR
			{
				return fixed4(1,1,1,1);
			}
			ENDCG
		}
	}
}

يتم كتابة كود ال cg بين CGPROGRAM و ENDCG ونبدا بتحديد برنامج ال vertex وال fragment

#pragma vertex vert
#pragma fragment frag

ثم قمنا بتعريف البرنامجين

float4 vert(float4 pos:POSITION):SV_POSITION
{
	return mul(UNITY_MATRIX_MVP,pos);
}

fixed4 frag(void):COLOR
{
	return fixed4(1,1,1,1);
}

برنامج ال vertex يستقبل موقع ال vertex ويعيد موقعه النهائي بعد ضربه بمصفوفة UNITY_MATRIX_MVP .
اما برنامج ال fragment لايستقبل شيئ ويعيد لون البكسل .