post

سخنران : بهنام آقاجانی از شرکت اسپریس پویا نما

گزارش و تدوین : مریم ثابت قدم اصفهان

ناظر علمی : بهنام آقاجانی

حقوق این گزارش برای سایت انیمیشن دیتا محفوظ است

شیدر مجموعه دستور العمل هایی است که به زبان خاصی نوشته شده و قابل اجرا بر روی سخت افزار اختصاصی با انعطاف پذیری بالا به نام GPU یا ( Graphic Processor Unit ) است تا افکت های تصویری بوجود آیند. از جمله ویژگی های این سخت افزار تعبیه ریاضیات برداری پیشرفته و Optimize شده جهت پردازش اعمال گرافیکی است.
با توجه به اشکال بالا در سمت چپ یک شیدر بسیار ساده را ملاحظه خواهید کرد در صورتیکه در سمت راست فقط با تغییر برنامه شیدر پردازش سایه، و پراکنش نور با استفاده از مکان یک منبع نور خارجی را داریم.

اطلاعات Vertex مدل ساخته شده در هر نرم افزار سه بعدی که به عنوان مفعول پردازش به چرخه رندر ارسال شده وارد Vertex Processor می شود همچنین تعدادی متغیر دلخواه که در نمودار با نام V Custom Variables نام گذاری شده اند نیز به این پردازشگر ارسال و سرانجام برنامه نوشته شده برای این واحد که Vertex Shader نامیده می شود توسط Vertex Processor اجرا گشته و خروجی در قالب یک Output structure و Vertex Position بدست می آید. Vertex Position مجددًا در Geometry Shader ممکن است مورد پردازش قرار گیرد ولی عملیات دیگری بر روی آن صورت نخواهد گرفت.( شکل زیر )

اما Output Structure به عنوان ورودی جدید Fragment Shader به Fragment Processor ارسال می شود. همچنین Texture ها و تعدادی متغیر دلخواه که در نمودار با نام P Custom Variables نام گذاری شده اند نیز وارد این پردازشگر شده. برنامه نوشته شده که Fragment Shader یا Pixel Shader نامیده می شود توسط این هسته مورد پردازش قرار خواهد گرفت و خروجی این پردازش فقط رنگی بر روی صفحه نمایش یا هر Render Target دیگری می باشد.

این شکل ، تکمیل نمودار ترسیم شده پیشین است .
یکی از قسمت های قابل برنامه نویسی شیدر ،Vertex Shader است که وظیفه آن ، نگاشت مختصات سه بعدی ورتکس ها برروی فضای دو بعدی (همان Screen ) است. اگر حرکت برگ درختی را در یک نمای سه بعدی در نظر گیرید ؛ با استفاده از Vertex Shader می توان موقعیت لحظه به لحظه Vertex را به طریقی جابه جا کرد که گویی تحت تأثیر باد حرکت می کند.

از قسمت های دیگر قابل برنامه نویسی ، Geometry Shader است که مبحث نوینی در شیدرها بشمار می آید و به جز چند بازی رایانه ای اخیر در جهان، کمتر در بازی های دیگر مورد استفاده قرار گرفته است. در حقیقت ، Geometry Shader پس از Vertex Shader قرار گرفته و وظیفه اش این است که بعد از تعیین اطلاعات ورتکس ها می توان Edge هایی را اضافه یا حذف کرد و یا به انجام برخی عملیات پردازشی که برای CPU هزینه بر است؛ پرداخت. در حقیقت ، Geometry Shader می تواند در برخی موارد عملیات سنگین بر روی CPU را حذف و آن را به خود اختصاص و با سرعتی مظاعف مورد پردازش قرار دهد.

درشکل بالای این تصویر ، ماهی را مشاهده می کنید که بطور ساده مدل سازی شده است و با Normal افکت های برجسته بر روی بدن آن بوجود آمده. اما در سمت راست آن ، بعد از پردازش در Geometry Shader ، تعدادی جزئیات ( Detail ) به بالای بدن آن افزوده شده است و خارها ی تن و دور چشم ماهی برجسته تر شده است. حتی در زیر آرواره آن ، خار نیز وجود دارد. تمام اینها بوسیله Geometry Shader و تکسچری که برجستگی را نمایان می سازد ؛ تحقق یافته است. در صورتی که تولید این مدل در فرایند ساخت سه بعدی مستلزم استفاده از مقادیر زیاد پلی گان است که نتیجه آن ، درگیر شدن CPU در فرایند دشوار و زمانبر رندرینگ برای تهیه Render Batch ها و ارسال مدل High poly به GPU برای پردازش می باشد.

در تصویر پایین سمت چپ ، هم یک مدل پیچیده و هم یک انیمیشن قابل مشاهده است که به صورت High poly درحال شکل گیری است. اگر قرار باشد چنین طرحی در 3D Studio Max ساخته شود ؛ هم هزینه مدل سازی زیادی بواسطه ایجاد شاخ و برگها در بر دارد و هم تعداد Key frame ها افزایش می یابد. در صورتی که می توان به راحتی این فرایند را در Geometry Shader انجام داد. کسانی که در مدل سازی سه بعدی فعالیت دارند ؛ می دانند که ساخت چنین Content در نرم افزار سه بعدی تا چه اندازه نیازمند پلی گان ها و انیمیشن طاقت فرسایی است.

قسمت دیگر ، Pixel Shader است و توضیح بسیار کوتاهی دارد. در واقع ، این بخش رنگ خروجی را مشخص می کند. اما همین وظیفه کوچک ، تمام تکنیک های رندرینگ را تحت تأثیر قرار می دهد.

درچند لحظه قبل، ما بخش های قابل برنامه نویسی چرخه Render را مشخص کردیم. در این بخش ، مابقی قسمت هایی را مورد توجه قرار می دهیم که غیر قابل برنامه نویسی هستند.
همانطور که بیان شد ؛ Vertex data ها به طریقی باید وارد Vertex Shader شده و از برنامه یا شبیه سازی سه بعدی خوانده شوند. لذا اطلاعات Vertex data توسط Input Assembler بر روی GPU از Application ( برنامه کاربردی ) fetch شده و وارد Vertex Shader می گردد.

Stream Output می تواند یک backup از خروجی Vertex Shader و در نهایت Geometry Shader تهیه کرده و در جایی ذخیره کند تا اینچنین تمام اطلاعات برای انجام محاسبات مجدد قابل بازگشت به حافظه باشد.

Rasterizer نتایج Vertex Shader و Geometry Shader ( در صورت موجود بودن ) را به پیکسل مبدل می کند. یعنی عملیات per-vertex به عملیات per-pixel تبدیل می شود. اصطلاحاً به این مبحث ، درون یابی (Interpolation )گویند.

اگر سه vertex در سه گوشه مثلث را مشاهده کنید ؛ درمی یابید که این سه ورتکس به رنگهای مختلف آبی، قرمز و سبز هستند؛ اما در بین این سه ورتکس ، بیشمار Pixel وجود دارد که قرار است رنگ آمیزی شود. یکی از وظایف درونیاب تعیین رنگ Pixel های مذکور است که به یک Gradient بین سه رنگ قرمز، سبز و آبی بوجود می آید.
از طرفی دیگر اگر این ورتکس ها دارای نرمال های متفاوتی باشند ؛ به این شکل هم نرمال هر پیکسل درونیابی می شود و برای سایر اطلاعات Vertex هم روش به همین شکل است.

Output Merger ، بر اساس اطلاعات Render Target Depth Stencil و خروجی های Vertex Shader ، Geometry Shader و Pixel Shader می تواند پیکسل ها را در موقعیت های مورد نظر ترسیم کند.

در تصویربالا یک نمونه کد Shader را ملاحظه می کنید. سه خط سبز اول ، همان ( V custom variable ) ها هستند که وارد شیدر شده اند. سپس یک Structure output قرار دارد که وارد Fragment Shader می شود تا پردازش Pixel shader تحقق یابد. در نهایت یک Function main وجود دارد که اطلاعات حاصل از Position ، Tangent ، Normal و Binormal و یک سری دستورالعمل هایی که بر اساس ماتریس ها دید و World و … محاسبه می کنیم ؛ در انتها Out می کند.
موقعیت این Output که با Float 4 ( رنگ زرد ) مشخص شده به Geometry Shader انتقال می یابد . اگر Geometry Shader در کار نباشد ، ادامه کار انجام می شود. اما بعد از گذشتن اطلاعات از Vertex Shader ، وارد Pixel Shader می گردد. خطوط قهوه ای ، اطلاعات مشترکی هستند که محل ارتباط اطلاعات بین Vertex Processor و Fragment Processor می باشد.
در نهایت رنگ diffuse * color + gloss * specular ، خروجی رنگ پیکسل ها را تعیین می کند.

حاصل شیدر قبلی این تصویر بالا است که با استفاده از Noise sample در تکسچری از یک فایل fetch شده و شیدر قوری که با رنگ قرمز Solid قابل مشاهده بود ؛ اکنون بدین شیوه نورپردازی می شود.

از حدود سال 2000 شیدرهایی در بازی رایانه ای بکار گرفته شد که برجستگی های روی شئ را از اطلاعات Normal map حاصل می آورد.
اما Parallax map از جمله قابلیت های نوینی است که به دلیل هزینه های سخت افزاری بسیار ، اگرچه هنوز به طور جدی در بازی های رایانه ای مورد استفاده قرار نگرفته ؛ اما می تواند تصویر دو بعدی را به نحوی نمایان سازد که کاربر گمان کند یک تصویر سه بعدی را می نگرد. بطوری که از هر زاویه به آن نگاه کنید ؛ نه یک تکسچر بلکه یک مدل را مشاهده کنید.این یک Parallax occlusion mapping است.
ساخت Parallax map چندان پیچیده نیست؛ اما از قواعد ویژه خود تبعیت می کند. در حقیقت این قابلیت ترکیبی از Normal map و Height map ( ترکیب آن در لایه آلفای Normal map ) حاصل می آید که با استفاده از شیدر مناسب می توان به قابلیت فوق دسترسی یافت.

Frame buffer ، مکانی است که اطلاعات خروجی رندر گرافیک در آن ذخیره می شود و در هر لحظه Video display می تواند به آن مراجعه کند و اطلاعات را از روی آن بخواند و بر روی صفحه نمایش ترسیم کند.
از آنجا که فریم بافر ، بطور همزمان قابل خواندن و نوشتن نیست ؛ لذا باید backup از فریم بافر در اختیار داشته باشیم تا قادر به خواندن از روی آن باشیم.
در حقیقت ، فریم بافر مکانی برای خواندن و backup بعنوان مکانی برای نوشتن مد نظر قرار می گیرند. به چنین مکانی که روی آن می نویسند، اصطلاحاً back buffer گویند.

به طور پیش فرض Render Target همان Backbuffer است؛اما می تواند یک تکسچر نیز باشد.

MRT مخفف عبارت Multiple Render Target است که در طی دو الی سه سال گذشته به عنوان یک تکنیک روز مورد توجه قرار گرفته است. بطوری که امکان رندرگیری همزمان یک صحنه بر روی چند تکسچر را برایمان فراهم می کند. اگر بخواهیم یک تصویر را چهار بار رندر کنیم ؛ باید چهار مرتبه اطلاعات ورتکس بافر را به همراه تکسچر ها fetch کرده و محاسبات شیدر ها را انجام دهیم؛ به این ترتیب Performance به شدت کاهش می یابد.
اما با تکنیک MRT می توان یک بار این عمل را انجام داد ؛ اما خروجی را به جای یک رنگ در Pixel Shader ؛ چهار رنگ را با Symbolهای Color0- Color3 ایجاد نمود

البته یکی از محدودیت های MRT این است که بیش از چهار تکسچر را نمی توان به طور همزمان به عنوان Render Target در نظر گرفت. محدودیت دیگر آن این است که هر چهار Render Target ما باید دارای یک bit size باشد. بطور مثال هر چهار تکسچر باید R8G8B8A8 یا مثلاً R16G16 یا 32 و 24 بیت باشند.

Deferred Rendering بهترین نمونه از MRT بشمار می آید. در تصویر زیر شما Deferred Rendering را در بازی Killzone2 مشاهده می کنید.

در این تصویر ، depth یا position هر پیکسل نمایش داده شده است. یک نکته قابل توجه آن است که آیا در اینجا حقیقتاً فاصله میان دو پیکسل تا ایندازه کم است که هر دو با یک gradient نمایش داده می شوند؟
Depth که شما در اینجا مشاهده می کنید ؛ float است که قابل نمایش با رنگ نیست. مابین هر Gradient ثابت ،کلی اعداد اعشاری وجود دارد که عمق های ریز تر را قابل ذخیره می سازند. تصویر depth از پیکسل ها گرفته می شود. Normal هر پیکسل در Render Targetدیگری ترسیم می شود.

تصاویر دیگر در برگیرنده اجزایی هستند که حرکت و به اصطلاح motion دارند.

یک تکسچر به اصطلاح Albedo ( بدون پردازش سایه و نور ) نیز وجود دارد که فقط ورتکس و پیکسل ها همراه با تکسچرهای آن موجود است.

و سپس با ترکیب تصاویر قبل ؛ یک composition Deferred داریم که نور و سایه های اشیاء یا به نام دیگر Shader اشیاء ( سایه ای که بر روی دیوار و یا روی زمین افتاده ؛ مد نظر نیست ) پردازش می شوند.

سپس اطلاعات blur به تصاویر قبل اضافه می شوند.

اگر دقت کنید ، شاید این پرسش به ذهن شما خطور کند که با توجه به اینکه نمی توان بیش از چهار Render Target را در اطلاعات رندرینگ بکار گرفت ؛ پس دلیل وجود شش تا هفت تکسچر موجود در این لیست از تصاویر چیست؟
علت آن را می توان در این نمایه نشان داد:

Intensity و Lighting در Render Target 0 ذخیره شده اند. بطوری که Intensity در لایه آلفا ذخیره شده و Lighting Accumulation در لایه های رنگی RGB ذخیره شده است.

Normal X و Normal Y در Render Target1 به صورت 16 بیتی ذخیره شده اند. اما Normal. z در کجا ذخیره می شود؟ اگر خط انتهای این مطلب را بخوانید ؛ در می یابید که Normal. z از یک محاسبه ریاضی ساده دبیرستان قابل دستیابی است :

Motion vector xY ، Specular power و Specular intensity در لایه آبی و آلفای Render Target 2 ذخیره می شوند.

در نهایت ، RGB تکسچرها به اسم Albedo درون Render Target 3 و Sun occlusion در آلفای آن ذخیره می شوند.

این تکنیکی بود که Kill zone 2 برای رندرینگ خود بکار برده بود.

در این تصویر ، در قسمت سمت چپ شما هشت هسته (core ) را مشاهده می کنید که هر یک دارای دو Stream Processor است. اینها همان GPU هایی هستند که محاسبات کارهای گرافیکی را بر عهده دارند.
چهار خط آدرس داریم . این یکی از دلایلی است که بواسطه آن نمی توان از بیش از چهار Render Target در تکنیک MRT بهره برد. بدیهی است اگر از هشت خط آدرس برخوردار بودیم ؛ می توانستیم از هشت Render Target نیز برخوردار شویم.

با توجه به تصویر بالا ، اگر قرار باشد تعدادی از Stream processing ها فقط ورتکس ها و تعدادی دیگر تنها پیکسل ها را پردازش کنند ؛ در اینصورت به تصویر پایین سمت چپ می رسیدیم. که در یک خط Pixel Shader ما خالی مانده و Vertex Shader پر شده است؛ این در حالی است که Performance آن عدد چهار است.
در تصویر پایینی آن که عملیات Pixel Shader بیشتر است ؛ در می یابیم که Vertex Shader خالی مانده و Pixel Shader اشغال شده است. در حالی که workload part آن عدد 8 است.
اما در تصویر راست قسمت بالا ؛ وقتی دارای Unified Shader هستیم ؛ در صورتی که نیاز به پردازش پیکسل باشد ؛ Unified Shader خود را به Pixel Shader تبدیل می کند . و اگر نیاز به پردازش ورتکس باشد ؛ خود را به Vertex Shader تبدیل می کند. و در هر حالتی، در مجموع vertex Shader و Pixel Shader ، از خانه پردازشگر و Performance برابر با 12 برخورداریم.

در این قسمت بحث سخت افزاری به پایان می رسد. اما مهمترین بخش این جلسه ، کالبد شکافی رندرینگ Pipline بازی رایانه ای call of juares و میرمهنا است.

تمام مطالبی که بازگو شد حاکی از این بود که قادر به مشاهده و ارزیابی دمو ها شده و تشخیص دهیم که یک بازی رایانه ای بسیار حرفه ای با رویکرد تکنیکی خوب به چه شیوه ای تصاویر را رندر می کند؟
اکنون می خواهیم دریابیم چگونه می توان یک بازی را ویرایش کرده و هسته رندر آن را کشف کرد؟
این کار با استفاده از ابزار PerfHUD امکان پذیر است. این ابزار منحصر به کارت گرافیکی nvidia است .
Debugging گرافیک یک بازی به این روش مستلزم کسب اجازه از سوی بازی است. درحال حاضر ، Call Of Juares این امکان را به عمد فراهم آورده تا متخصصان قادر به بررسی تکنیک های رندرینگ آن باشند.

با مشاهده تکسچر در سمت راست تصویر ، شما یک تکسچر سیاه رنگ مستطیلی شکل را به ابعاد 4096 * 1024 مشاهده می کنید . معمولاً چنین تکسچری مرسوم نیست و حال باید دید این تکسچر از کجا آمده است؟
در واقع این محلی است برای ذخیره مکان و یا عمق پیکسل ها که مانند همان شکل depth ترسیم می شود که برای عملیات سایه پردازی PSSM بکار می رود.
PSSM , تکنیکی است که تا چهار تکسچر مختلف را از اطلاعات موقعیت پیکسل های خود دریافت کرده و بنا بر نزدیک بودن دوربین به هر یک از این پیکسل ها ، تعیین می کند که آیا سایه (shadow ) باید با کیفیت بیشتری رندر شود یا با کیفیت کمتر ؟ بحث های مفصلی است که در این قسمت نمی گنجد.

اگر گیاهی داشته باشیم که دارای تکسچر آلفا باشد ؛ در صورتی که سایه ای از موقعیت ورتکس ها به نحوی تشکیل شود که اطلاعات تکسچر خوانده نشود ؛ شما سایه را به شکل تو پر مشاهده می کنید.

اما اگر تکسچرها به نحوی محاسبه شوند که مشخص گردد کجای آلفا بوده و کجای آلفا نیست و همچنین پیکسل ها به درستی ترسیم شوند ؛ شما سایه تک تک برگ ها را مشاهده می کنید.

اگر شما به حالت Advance سوئیچ کنید ؛ می توانید تک تک مدل های بازی ، ورتکس و مدل ها و حالت های رندر شده آن را مشاهده کنید. حتی قادر هستید Vertex Shader و Pixel Shader ترسیم یک مش را نیز مشاهده کنید ؛ البته Source شیدر را در صورت وجود نشان می دهد ؛ در غیر اینصورت نتیجه کامپایل شده ای که مورد استفاده GPU است را برایتان نمایان می سازد.

برای مرور این مبحث ، تکسچرها را روی هم گذاشته ایم » تکسچر خام بدون سایه پردازی ؛ Normal ها ،depth map هر پیکسل قابل مشاهده اند که با ترکیب آنها به شکل Deferred Rendering تصویر خروجی بدست می آید.

هر کسی تکسچر شماره 3 را مشاهده کند ؛ احتمالاً به عنوان یک تکسچر خراب آن را دور می اندازد ؛ در صورتی که می توان گفت بخش عظیمی از زیبایی رندر Call Of Juares مبتنی بر این تکسچر بوده است.حالا به دقت این تکسچر را بررسی می کنیم.
تمام رنگ های قابل مشاهده مفهوم خاصی دارند ؛ رنگ آبی نمایگر Occlusion map است. اگر بتوانید اسب ها ، دم اسب ها و حلقه ای که به دور بدن آن ترسیم شده ملاحظه کنید ؛ در می یابید یک occlusion map تولید می کنند.حتی کنار تفنگ شما نیز یک occlusion تولید می شود.
رنگ زردی که مشاهده می کنید ، مکانی است که در آن سایه وجود دارد. وقتی چنان تعریف کنید که هر جایی که زرد وجود دارد به رنگ خاکستری مبدل شود ؛ گویی صحنه بدون سایه شما به صحنه سایه دار تبدیل می شود همان طور که مشاهده می کنید ؛ روی بدن اسب نیز چندین سایه وجود دارد که در تصاویر بعدی ، نتیجه آن را در می یابید.

در تکسچر 5 ، تمام جاهایی که به رنگ سفید مشخص شده اند ؛ نمایانگر مکان هایی هستند که لبه ی اشیاء جدا می شود. بدین معنا که قادریم حاشیه اشیاء را نرم تر کنیم . از طریق Normal map این حاشیه ها به دست آمده و در نهایت برای پردازش AntiAliasing روی تصویر کلی استفاده می گردد.

همانطور که ملاحظه می کنید ؛ قسمت هایی که در مورد شان صحبت شد به ویژه روی بدن اسب به صورت سایه قابل مشاهده است. در جاهای دیگر نیز اگرچه سایه ای نداریم ؛ اما می توان به وضوح Occlusion را دید.
این تصاویر ، بخش هایی از رندرینگ Call Of Juares است. در واقع تکنیک های بیشتری موجود هستند که برای آسمان ، خورشید ، آب و تکسچر جاده و همچنین فضای بارانی بکار گرفته شده اند که مجال بررسی آنها وجود ندارد.

مبحث دیگر این جلسه بررسی بازی میرمهنا است:

در قسمتی از رندرینگ این بازی ، اگر چه برگ ها سایه دارند ؛ اما با لرزش آن ها توسط باد ، هیچ حرکتی قابل مشاهده نیست . در حقیقت ، به دلیل هزینه های سخت افزاری موجود ، تکنیک مورد نیاز برای به حرکت در آوردن سایه ها حذف شده است.
اگر دیوارهای سنگی را بنگرید ؛ برجستگی های آنرا مشاهده می کنید. در حقیقت از Parallax map که به طور دستی ساخته شده است ؛ ما بعنوان Normal map استفاده کرده ایم. اما به دلیل هزینه های سخت افزاری از تکنیک Parallax map صرفنظر شده است.
حرکت پوشش گیاهی از طریق Vertex Shader مقدور شده است. همه اشیاء با استفاده از تعدادی به اصطلاح Surface map ، جزئیات (detail ) گذاری شده اند.
پارچه ای که روی درشکه اسب نمایان است ؛ علاوه بر تکسچر و Normal دارای یک detail نیز هست که شما می توانید حتی بافت ریز پارچه را بدون افت کیفیت تصویر مشاهده کنید.
اگر به دست بازیکن دقت کنید ؛ تقریباً تمام سلول های روی پوست را نیز می بینید؛ در این مورد نیز هیچ تکسچر بزرگی استفاده نشده است .
همچنین روی هر شئ که زوم کنید ؛ سایر اشیاء پیرامون به شکل محو قابل مشاهده اند.
بازی میرمهنا، بسیار تحت تأثیر بازی Call Of Juares بوده است. در واقع بامهندسی معکوسی که تحقق یافته ؛ ابتدا بازی Call Of Juares طبق شیوه ای که فرا گرفتیم بررسی شده و هسته رندر آن استخراج شده و سپس سعی کرده ایم به همان شیوه یک چرخه رندر برای این بازی بسازیم.
اگر دقت کنید اگر سر خود را بالا آورید ؛ ابرهایی که در ابتدا روشن بوده اند؛ به مرور روشنایی خود را از دست می دهند و از حالت اغراق آمیز در هاله نور خارج می شوند. این همان تکنیک HDRL است که به ویژه در Call Of Juares نمود بیشتری نسبت به میرمهنا دارد.
بعلاوه تکنیک shadow map توسط یک همکار خارجی به مدت طولانی در این پروژه انجام شده است.

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *