یک مزیت عمده این رویکرد این است که هر قطعه ای که در G-buff قرار دارد، اطلاعات واقعی فرگمنت است که به عنوان یک پیکسل صفحه نمایش به پایان می رسد، depth test ، این اطلاعات قطعه را به عنوان بیشترین فرگمنت نتیجه می دهد .
همچنین آن با چند معایب همراه است G-buffer نیاز دارد که ما مقدار نسبتا زیاد اطلاعات صحنه را در بافرهای رنگ تکسچر ذخیره کنیم که تمام حافظه را می خورد، به ویژه زمانی که اطلاعات صحنه مثل موقعیت بردار ها به دقت بالایی نیاز دارد.عیب دیگر آن این است که blending را پشتیبانی نمی کند(چون ما فقط اطلاعات بیشترین فرگمنت را داریم) و MSAA دیگر کار نمی کند.چندین راه حل برای این عیب ها وجود دارد که ما در آخر آموزش آن را بررسی می کنیم.
پر کردن G-buffer در پاس geometry بسیار کارآمد است زیرا ما مستقیما اطلاعات شیء مانند موقعیت، رنگ یا عادی را به یک فریم بافر با یک مقدار کوچک یا صفر پردازش اطلاعات ذخیره می کنیم. با استفاده از چندین اهداف رندر (MRT) ما حتی می توانیم همه اینها را در یک پاسورد رندر انجام دهیم.
جی بافر مجموعه ای از تمام بافت هایی است که برای ذخیره اطلاعات مربوط به نورپردازی مورد استفاده قرار می گیرد. بگذارید در این لحظه به طور خلاصه تمام اطلاعاتی که نیاز داریم تا در یک فرگمنت با رندر پیش فرض به نمایش بگذاریم مرور کنیم:
یک مختصات سه بعدی برای محاسبه ی مقدار موقعیت فرگمنت درون یابی شده (interpolated fragment) که برای lightDir و viewDir استفاده می شود.
یک بردار رنگ RGB diffuse همچنین عنوان albedo شناخته شده است.
یک بردار نرمال سه بعدی برای تعیین شیب سطح.
یک float برای شدت اسپکولار
تمام موقعیت های منبع نور و بردارهای رنگ.
بازیکن یا بردار موقعیت دید(viewer's position)
یک بردار رنگ RGB diffuse همچنین عنوان albedo شناخته شده است.
یک بردار نرمال سه بعدی برای تعیین شیب سطح.
یک float برای شدت اسپکولار
تمام موقعیت های منبع نور و بردارهای رنگ.
بازیکن یا بردار موقعیت دید(viewer's position)
با استفاده از این متغیرها (در هر فرگمنت) که در اختیار داریم می توانیم نور پردازی (Blinn-) Phong را محاسبه کنیم. موقعیت و رنگ های منبع نور و موقعیت دید بازیکن را می توان با استفاده از متغیرهای یکپارچه(uniform ) پیکربندی کرد، اما متغیرهای دیگر هر کدام از اجزای یک شیء خاص هستند. اگر ما به نحوی بتوانیم داده های دقیق مشابه را به تصویب نور پایانی منتقل کنیم، ما می توانیم همان نورپردازی را محاسبه کنیم، حتی اگر بخش هایی از یک quad دوبعدی را رندر کنیم.
در OpenGL هیچ محدودیتی برای چیزی که ما می توانیم در یک تکسچر ذخیره کنیم وجود ندارد، به طوری که منطقی است که تمام داده های هر فرگمنت را در یک یا چند تکسچر هایی که روی صفحه پر شده با نام G-buffer ذخیره کرده و بعدا در پاس نور پردازی استفاده شود. چون تکسچر های G-buffer اندازه ی یکسانی با quad دوبعدی در پاس نور پردازی خواهد داشت،ما دقیقاً همان اطلاعات قطعه ای که در تنظیمات forward rendering 0داشته ایم، دریافت می کنیم، اما این بار در پاس نور پردازی ؛ یک نقشه بر روی یک نقشه وجود دارد.
اطلاعاتی که ما برای ذخیره هر فرگمنت نیاز داریم یک بردار موقعیت ، یک بردار طبیعی، یک بردار رنگ و یک مقدار شدت اسپکولار است. بنابراین در پاس geometry ، ما باید تمام اشیاء صحنه را رندر کنیم و این اجزاء داده را در G-buffer ذخیره کنیم.
برای پاس geometry ، باید یک شیء فریم بافر را مقدار دهی اولیه کنیم ، تا به طور مستقیم gBuffer را فراخوانی کند. gBuffer متشکل از چندین buffer متصل و یک شیء رندر بافرعمق (single depth render buffer object) است. برای موقعیت و تکسچر نرمال، ترجیحا از یک تکسچر با دقت بالا (16 یا 32 بیتی float در هر جزء) و مقادیر albedo و مقادیر specular با یک تکسچرپیش فرض (دقت 8 بیتی در هر جزء) استفاده کنیم.
برای پاس geometry ، باید یک شیء فریم بافر را مقدار دهی اولیه کنیم ، تا به طور مستقیم gBuffer را فراخوانی کند. gBuffer متشکل از چندین buffer متصل و یک شیء رندر بافرعمق (single depth render buffer object) است. برای موقعیت و تکسچر نرمال، ترجیحا از یک تکسچر با دقت بالا (16 یا 32 بیتی float در هر جزء) و مقادیر albedo و مقادیر specular با یک تکسچرپیش فرض (دقت 8 بیتی در هر جزء) استفاده کنیم.
از آنجا که ما از رندر چند هدفه (multiple render targets) استفاده می کنیم، باید به صراحت به OpenGL بگوئیم که کدام buffer های رنگ GBuffer مرتبط است ما می خواهیم با glDrawBuffers رندر کنیم.
همچنین جالب توجه است که در اینجا این است که ما اطلاعات موقعیت و اطلاعات نرمال را در بافت RGB ذخیره می کنیم،همانطور که ما هر 3 مولفه را در اختیار داریم، اما اطلاعات رنگ و اطلاعات اسپکولار را در یک بافت RGBA ترکیب می کنیم؛
این ما را از مجبور بودن برای تعریف یک تکسچر بافر رنگ اضافی بی نیاز می کند و باعث صرفه جویی می شود.چون پایپ لاین deferred shading تان پیچیده تر شده و اطلاعات بیشتری نیاز دارد، شما به سرعت دنبال راه های جدیدی برای ترکیب اطلاعات در تکسچر ها به طور تکی می گردید.
بعد ما باید به G-buffer رندر کنیم. با فرض اینکه هر جسم دارای یک Diffuse ، یک تکسچر نرمال و تکسچر شدت اسپکولار است، می خواهیم چیزی شبیه به شیدر فرگمنت زیر را در G-buffer رندر کنیم:
همچنین جالب توجه است که در اینجا این است که ما اطلاعات موقعیت و اطلاعات نرمال را در بافت RGB ذخیره می کنیم،همانطور که ما هر 3 مولفه را در اختیار داریم، اما اطلاعات رنگ و اطلاعات اسپکولار را در یک بافت RGBA ترکیب می کنیم؛
این ما را از مجبور بودن برای تعریف یک تکسچر بافر رنگ اضافی بی نیاز می کند و باعث صرفه جویی می شود.چون پایپ لاین deferred shading تان پیچیده تر شده و اطلاعات بیشتری نیاز دارد، شما به سرعت دنبال راه های جدیدی برای ترکیب اطلاعات در تکسچر ها به طور تکی می گردید.
بعد ما باید به G-buffer رندر کنیم. با فرض اینکه هر جسم دارای یک Diffuse ، یک تکسچر نرمال و تکسچر شدت اسپکولار است، می خواهیم چیزی شبیه به شیدر فرگمنت زیر را در G-buffer رندر کنیم:
چون ما از رندر چند هدفه(multiple render targets) استفاده می کنیم، layout specifier به OpenGL می گوید که کدام بافر رنگ فریم بافر فعالی است که در حال حاضر برای رندر استفاده می کنیم.
در نظر داشته باشید که با محاسبات نور پردازی بسیار مهم است که تمام متغیرها را در یک فضای مختصات نگه دارید؛ در این مورد ما همه متغیرها را در فضای جهان(world-space) ذخیره و محاسبه می کنیم.
اگر ما اکنون مجبور بودیم یک مجموعه بزرگ از اشیاء را در فریم بافرgBuffer رندر کنیم و محتویات آن را نمایش دهیم بوسیله پراجکت کردن بافر های رنگ آن بر روی چهار نقطه صفحه پر شده، چیزی شبیه به این را می بینیم:
در نظر داشته باشید که با محاسبات نور پردازی بسیار مهم است که تمام متغیرها را در یک فضای مختصات نگه دارید؛ در این مورد ما همه متغیرها را در فضای جهان(world-space) ذخیره و محاسبه می کنیم.
اگر ما اکنون مجبور بودیم یک مجموعه بزرگ از اشیاء را در فریم بافرgBuffer رندر کنیم و محتویات آن را نمایش دهیم بوسیله پراجکت کردن بافر های رنگ آن بر روی چهار نقطه صفحه پر شده، چیزی شبیه به این را می بینیم:
سعی کنید تجسم کنید که موقعیت فضای جهان و بردارهای نرمال واقعاً درست است. به عنوان مثال، بردارهای نرمال که به سمت راست می آیند، بیشتر به یک رنگ قرمز تراز می شوند، بردارهای موقعیت هم مشابه آن ازorigin صحنه به سمت راست است. به زودی از محتوای G-buffer راضی می شوید، وقت آن است که به مرحله بعدی بروید: پاس lighting.
با یک مجموعه بزرگ از داده های فرگمنتی در G-Buffer که در اختیار ما قرار دارد، می توانیم به طور کامل رنگ های نور نهایی صحنه را با تکرار بر هر یک از پیکسل بافت های G-Buffer با استفاده از پیکسل و استفاده از محتوای آنها به عنوان ورودی به الگوریتم های نور محاسبه کنیم. از آنجا که مقادیر بافت G-buffer مقادیر تبدیل شده فرگمنت نهایی را نشان می دهد، ما فقط باید عملیات گران قیمت نورپردازی را یک بار در هر پیکسل یکبار انجام دهیم.
این باعث می شود که deferred shading بسیار کارآمد باشد، به ویژه در صحنه های پیچیده که در آن ما می توانیم به راحتی فرگمنت شیدر های گران قیمت را در هر پیکسل در تنظیمات forward rendering فراخوانی کنیم.
برای پاس نور ما قصد داریم یک چهارگوش(quad) دوبعدی را در صفحه رندر کنیم(کمی شبیه به post-processing effect) و یک نور پردازی گران قیمت فرگمنت شیدری را روی هر پیکسل اجرا کنیم.