به طور معمول هنگامی که ما یک فرگمنت را در یک صحنه بزرگ به تصویر می کشیم، سهم هر منبع نور در یک صحنه صرف نظر از فاصله آنها تا فرگمنت محاسبه می کنیم. بخش بزرگی از این منابع نور هرگز به فرگمنت نمی رسد، پس چرا تمام محاسبات نور از بین نمی رود؟
ایده در حجم نور، محاسبه شعاع یا حجم یک منبع نور است یعنی منطقه که نور آن قادر به فرگمنت ها برسد. همانطور که اکثر منابع نور از برخی از فرم های attenuation استفاده می کنند، می توانیم از آن برای محاسبه حداکثر فاصله یا شعاع نور آنها استفاده کنیم. سپس ما فقط محاسبات نورپردازی گران را انجام می دهیم اگر یک فرگمنت در داخل یک یا چند تای این حجم نور وجود داشته باشد. این می تواند مقدار قابل توجهی از محاسبات ما را ذخیره کند، زیرا اکنون فقط نور را محاسبه می کنیم که در آن ضروری است.
حلیه ی این عملکرد بیشتر بدان معنی است که اندازه یا شعاع حجم نور یک منبع نور است.
برای به دست آوردن شعاع حجم نور، اساسا ما باید معادله attenuation را برای روشنایی که به نظر می رسد تیره باشد حل کنیم. ما فرض می کنیم که تاریک است ، این می تواند 0.0 یا چیزی کمی روشن تر باشد اما همچنان تاریک مانند 0.03 است. برای نشان دادن اینکه چگونه می توانیم شعاع حجم نور را محاسبه کنیم، می توانیم از یکی از توابع سخت افزاری تضعیف شده ای که ما در آموزش light casters معرفی کردیم استفاده کنیم:
آنچه که ما می خواهیم انجام دهیم، این است که معادله را برای زمانی که Flight 0.0 است، حل کنیم، هنگامی که نور در آن فاصله کاملا تاریک است. با این حال، این معادله دقیقا به مقدار 0.0 نمی رسد، بنابراین راه حل نخواهد بود. اما آنچه ما می توانیم انجام دهیم هرچند معادله 0.0 را حل نمی کند، اما آن را برای یک مقدار روشنایی که نزدیک به 0.0 است، اما هنوز آن را تیره می بینیم. مقدار روشنایی که ما برای این صحنه Demo آموزشی قابل قبول انتخاب می کنیم، 5/256 است؛ به طور پیشفرض فریم بافر 8 بیتی به 256 تقسیم می شود که می تواند بسیاری از شدت ها را بر هر جزء نشان دهد.
تابع تضعیف(attenuation ) عمدتا تاریک استفاده شده در محدوده قابل مشاهده است، بنابراین اگر ما آن را محدود به روشنایی حتی تاریک تر از 25/ 55، بکنیم حجم نور بیش از حد بزرگ می شود و در نتیجه کمتر موثر است. تا زمانی که یک کاربر نمی تواند یک قطع نور ناگهانی از منبع نور را در مرزهای حجم آن ببیند، خوب خواهد بود. البته این همیشه به نوع صحنه بستگی دارد؛ یک آستانه بالاتر روشنایی موجب کاهش حجم نور و در نتیجه کارایی بهتر می شود، اما می تواند مصنوعات قابل توجهی را تولید کند که در آن نور به نظر می رسد در یک مرز حجمی شکسته شود.
اینجا I max
عنصر رنگی ترین منبع نور است. ما از درخشان ترین مولفه نور منبع نور استفاده می کنیم، زیرا حل معادله برای شدت روشنایی نور، بهترین مقدار شعاع حجم نور را نشان می دهد.
از اینجا به بعد ما حل معادله را ادامه می دهیم:
عنصر رنگی ترین منبع نور است. ما از درخشان ترین مولفه نور منبع نور استفاده می کنیم، زیرا حل معادله برای شدت روشنایی نور، بهترین مقدار شعاع حجم نور را نشان می دهد.
از اینجا به بعد ما حل معادله را ادامه می دهیم:
آخرین معادله، یک معادله به فرم ax2 + bx + c = 0 است که ما می توانیم با استفاده از معادله درجه دوم حل کنیم:
این به ما یک معادله عمومی می دهد که به عنوان مثال به ما اجازه می دهد x را محاسبه کنیم. شعاع حجم نور برای منبع نور با توجه به پارامتر گرفته شده ثابت، خطی و درجه دوم:
این معادله تقریباً شعاع بین 1.0 و 5.0 را بر اساس بیشینه ی شدت نور بر می گرداند.
ما این شعاع را برای هر منبع نور صحنه محاسبه می کنیم و اگر یک فرگمنت در داخل منبع نور باشد فقط از آن برای محاسبه نور این منبع نور استفاده می کنیم. در زیر روشنایی به روز شده پاس نور در فرگمنت شیدراست که به حساب حجم نور محاسبه شده است. توجه داشته باشید که این رویکرد صرفا برای اهداف آموزشی انجام می شود و در یک محیط عملی قابل اجرا نیست، زیرا ما به زودی بحث خواهیم کرد:
نتایج دقیقا همانند قبل است، اما در این زمان هر نور فقط روشنایی برای منابع نور را محاسبه می کند که در آن حجم آن قرار دارد.
شما می توانید کد اصلی نسخه ی نمایشی را در اینجا پیدا کنید.
https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/8.2.deferred_shading_volumes/deferred_shading_volumes.cpp
شما می توانید کد اصلی نسخه ی نمایشی را در اینجا پیدا کنید.
https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/8.2.deferred_shading_volumes/deferred_shading_volumes.cpp
فرگمنت شیدر در بالا نشان داده شده در واقع واقعا کار نمی کند و فقط نشان می دهد که چگونه می توانیم از حجم نور برای کاهش محاسبات نور استفاده کنیم. واقعیت این است که GPU ها و GLSL شما در حلقه ها و شاخه های بهینه سازی بدی هستند. دلیل این امر این است که اجرای شیدر در GPU بسیار موازی است و اکثر معماریها نیاز دارند مجموعه ای بزرگ از thread ها کد شیدر یکسانی برای اجرا داشته باشند تا کارآمد باشند. این اغلب به این معنی است که یک شیدر همیشه تمام شاخه های یک دستور را اجرا می کند تا اطمینان حاصل شود که اجرای شیدر یکسان است، و بهینه سازی چک شعاع قبلی کاملا بی فایده است؛ ما هنوز روشنایی را برای همه منابع نور محاسبه میکنیم!