ورود

View Full Version : حرفه ای: deferred shading



kochol
دوشنبه 15 آبان 1391, 11:58 صبح
سلام
دارم رو deferred shading برای انجین کار می کنم.
نورمال ها رو می خوام تو یه بافر R16G16F ذخیره کنم پس فقط می تونم دو تا کامپوننت رو ذخیره کنم خواستم ببینم که چه روشی خوبه.

الان بردارهای من تو world space هستن من هم موقع ای که نورمال رو می خوام بسازم از این بافر این کار رو می کنم.



normal.z = sqrt(1.0f - normal.x * normal.x - normal.y * normal.y);


ولی فقط این کافی نیست. چون این طوری هیچ وقت z نورمال من منفی نمی شه.

سپول
دوشنبه 15 آبان 1391, 13:14 عصر
قائدتا نباید خیلی تابلو بشه کیفیتش البته اگه در view-space کار می کنی. ولی سرعت این متد از همه بهتر هست.
اینجا رو هم می تونی ببینی. همین کار رو insomniac هم در موتورش انجام می ده.
http://www.insomniacgames.com/tech/articles/0409/files/GDC09_Lee_Prelighting.pdf

متدهای دیگه ای هم برنامه نویس یونیتی اینجا گفته که خیلی مفید هست و البته سرعت کمتری نسبت به روش معمول داره ..
من خودم از sphere-map استفاده می کنم.

http://aras-p.info/texts/CompactNormalStorage.html

kochol
دوشنبه 15 آبان 1391, 15:08 عصر
قائدتا نباید خیلی تابلو بشه کیفیتش البته اگه در view-space کار می کنی.
سلام
ممنون از جوابت مشکل من اینه که نمی دونم چه طوری نورمال ها رو به view space ببرم همون طور که گفتم نورمال هام تو world space بود.

این لینک دومی که عالی بود فکر کنم تمام روش های نگهداری نورمال رو گفته.
من هم فکر کنم sphere map از همه بهتر باشه چون هم پیاده سازیش آسونه و هم کیفیتش خیلی خوبه.
فقط چیزی که نفهمیدم اینه که با این روش هم نورمال ها باید تو view space باشن یا توی world space هم می تونه باشه.

kochol
دوشنبه 15 آبان 1391, 15:30 عصر
چیزی که معلومه اینه که تو world space جواب نمی ده

kochol
دوشنبه 15 آبان 1391, 17:04 عصر
94548مثله اینکه تو world space هم جواب می ده من یادم رفته بود که نورمال ها رو تو پیکسل شیدر نورمالایز کنم و بفرستم برای جی بافر.

نورپردازی درست شده و به نظر خیلی هم نرمتر داره نور پردازی می شه ولی بعضی جاها برفکی می شه مثل تصویر ضمیمه که اپلود کردم

این مشکل پس از تغییر کد نورمال مپ ها بوجود اومدش.

سپول
دوشنبه 15 آبان 1391, 18:32 عصر
من که هیچ وقت با world-space نرمال کار نکردم
ولی از روی ظاهر الگوریتم sphere-map انگار که درسته می تونه کار کنه توی world-space هم

من اگه جای تو بودم توی view-space هم تست می کردم چون آسونه. کافیه ماتریس view رو در نرمال های g-buffer ضرب کنی. (position هم همینطور) و کل سیستم نورپردازی رو در این space انجام بدی.

واسه این برفک ها هم نمی دونم دقیقا چیه. فقط شیدر gbuffer اون قسمت رو دوباره چک کن و مطمئن باش که gbuffer رو clear می کنی قبلش.

kochol
دوشنبه 22 آبان 1391, 20:46 عصر
سلام

من می خوام نورپردازی رو در view space انجام بدم کلا دنبال یه روشی می گردم که در هر پیکسل ضرب ماتریکس نداشته باشم.

برای این کار چه راه هایی هست برای ذخیره کردن depth؟

فکر کنم depth یه جور دیگه باید ذخیره کنم.

سپول
یک شنبه 28 آبان 1391, 12:40 عصر
با استفاده از متد ray این کار رو انجام بده.
اگه محاسباتت در world-space هست:
۱- در gbuffer به جای depth معمولی. فاصله دوربین تا پیکسل رو ذخیره کن :


float4 view_pos = mul(world_pos, view_mat);
float distance = length(view_pos);


۲- در زمان ساختن position (نورپردازی):
تو اینجا برای کشیدن از ایک fullscreen quad استفاده می کنی قاعدتا. پس اول در vertex shader از مختصات quad استفاده می کنی تا یک ray درست کنی و در pixelshader بقیه محاسبات رو ادامه می دی. منتهی مختصات quad رو باید تبدیل کنی به world (که احتمالا شروع کار در projection هست)



// in vertex shader faghat baraye 4 vertex ejra mishavad
float4 pos_world = mul(input.pos, inv_viewproj);
output.view_ray = pos_world.xyz - camera_pos.xyz;


حالا در pixel shader. چون فاصله تا دوربین رو در gbuffer نگه داشتی. می تونی به سرعت بازسازی کنی position :


float3 ray = normalize(input.view_ray);
float distance = tex2D(depth_sampler, input.coord);
float3 pos_world = camera_pos + ray*distance;


این چیزی هم که گفتم در world-space جواب می ده. اگه مشکلی توی فهمیدن این متد داری بپرس

kochol
یک شنبه 28 آبان 1391, 22:37 عصر
سلام
واقعا ممنون از جوابت خیلی مفید بود.

خواستم ببینم این screen quad من باید چه شکلی باشه؟

سپول
دوشنبه 29 آبان 1391, 00:08 صبح
خواهش..

screen quad برای من در مختصات projection هست. ۴ نقطه که گوشه هاش میشه اینا .. یادم نیست که مختصات projection از -1 تا 1 بود یا نه ... خلاصه این رو امتحان اگه نشد به جای 1.0 عدد 0.5 رو بگذار


// top-left corner
(-1.0, 1.0, 1.0)

// bottom right corner
(1.0, -1.0, 1.0)


z هم که ۱ بگذار (ولی ztest رو غیر فعال کن) چون می خوای بیشترین z رو در vertex-shader داشته باشی. برای حساب کردن view_ray لازم هست.

kochol
دوشنبه 29 آبان 1391, 06:04 صبح
سلام
ممنون از کمکت

الان همه چی درست شده و خروجی deferred renderer من با Forwrad renderer ام یکی شده که خودش نشون می محاسبات نورپردازیم درست شده.

فقط من تو اینجا که داریم view ray درست می کنیم world pos رو تقسیم بر w کردم تا درست شد.

// in vertex shader faghat baraye 4 vertex ejra mishavad
float4 pos_world = mul(input.pos, inv_viewproj);
pos_world /= posworld.w;
output.view_ray = pos_world.xyz - camera_pos.xyz;

الان هم می خوام نورهای نقطه ای رو توسط یک کره بکشم با همون کره می شه این view ray رو ساخت یا اینکه اول با stencil ماسک کنم بعد با همون full screen quad نور های نقطه ایمو رسم کنم.

سپول
سه شنبه 30 آبان 1391, 13:40 عصر
سلام
ممنون از کمکت

الان همه چی درست شده و خروجی deferred renderer من با Forwrad renderer ام یکی شده که خودش نشون می محاسبات نورپردازیم درست شده.

فقط من تو اینجا که داریم view ray درست می کنیم world pos رو تقسیم بر w کردم تا درست شد.

// in vertex shader faghat baraye 4 vertex ejra mishavad
float4 pos_world = mul(input.pos, inv_viewproj);
pos_world /= posworld.w;
output.view_ray = pos_world.xyz - camera_pos.xyz;

الان هم می خوام نورهای نقطه ای رو توسط یک کره بکشم با همون کره می شه این view ray رو ساخت یا اینکه اول با stencil ماسک کنم بعد با همون full screen quad نور های نقطه ایمو رسم کنم.

اون تقسیم بر w هم درسته فکر کنم. من یادم رفته بود

جمله آخر هم نفهمیدم سوالی بود یا معمولی ...

kochol
سه شنبه 30 آبان 1391, 13:58 عصر
جمله آخر هم نفهمیدم سوالی بود یا معمولی ...
سوال بود D:

تست که زدم سرعت رندر خیلی بالا بود و من خیلی حال کردم دستت درد نکنه بابت تمام کمک هات

با 1000 تا نور 32 fps می داد
با 400 تا نور 90 fps می داد من که خیلی راضی هستم از سرعت رندر.

jack
سه شنبه 30 آبان 1391, 15:55 عصر
سلام
ایا تلاشی برای استفاده از prepass renderer که آقای ولف انگل ابداع کرده کردید ؟ و یک سوال دیگه که خود اقای انگل در سایت gamedev گفته می شه light indexed deferred lighting رو در prepass renderer پیاده سازی کرد اگر بشه همچین کاری کرد به راحتی می شه fps خیلی بالایی گرفت و بشه رو خیلی از device ها این تکنیک رو پیاده سازی کرد. که بتوانیم مینیمم کارت گرافیک رو 128 مگ در نظر بگیریم.

سپول
چهارشنبه 01 آذر 1391, 17:50 عصر
@kochol: خیلی خوبه. روی چه سخت افزاری تست کردی ؟
بدون روش های optimization باز هم بعیده برای هر سخت افزاری سرعت خوبی بگیری . در ضمن باز هم fps با نوع پوششی که نور ها روی صفحه مانیتور می دهند کلی فرق می کنه. یعنی اگه نورت مساحت زیادی از صفحه رو پوشش بده سرعت تصاعدی پایین میاد (که در زاویه دید و بازی شما فکر نکنم همچین چیزی بشه)
در هر صورت بیشتر تست کن اگه دیدی مشکل سرعت داری باز هم روش هایی برای optimize کردن deferred rendering هست.

@jack: اتفاقا این پیشنهاد رو من هم به کوچول دادم ولی گویا با پیاده سازی deferred rendering راحتتر بود.
ولی اون چیزی که مسلم هست اینه deferred lighting (light prepass) برای سخت افزار قدیمیتر بهتر جواب می ده. این روش رو جتی در hmrengine هم پیاده سازی کردم و خوب جواب می داد. تنها مشکلش اینه که صحنه رو دو بار باید draw کنی و این مورد با نیاز موتورهای نسل بعدی جور در نمیاد. ولی از اونجا که کوچول با directx9 در حال نوشتن رندرر هست بهترین گزینه بود.

یه نگاهی به انجین ها و بازی هایی که با این متد ساخته شدن می تونین بندازین :
http://en.wikipedia.org/wiki/Deferred_shading#Deferred_lighting_in_commercial_g ames

این هم پست من در مورد پیاده سازی این روش :
http://www.hmrengine.com/blog/?p=250

jack
چهارشنبه 08 آذر 1391, 17:11 عصر
http://en.wikipedia.org/wiki/Deferred_shading#Deferred_lighting_in_commercial_g ames[/url]

این هم پست من در مورد پیاده سازی این روش :
http://www.hmrengine.com/blog/?p=250

یک سری از بازی هایی که توی لینک بالا اشاره شده خیلی جدیدن صد در صد با dx10 به بالا ساخته شدن من فکر می کنم میشه توی prepass-render یک جورایی کل صحنه رو رندر نکنیم مثلا با depth test اشیای دور رو در (هر دو بار رندر ) حذف کنیم یا روشهای دیگه مثلا اشیایی که دارای نور کامل هستند از prepass-render حذف بشن برن توی forward-render

این هم تاریخ انتشار چند تا از اون بازی ها
BioShock Infinite 2013
Brink 2011
Crysis 2 2011
Dead Space 2 2011
Deus Ex: Human Revolution 2011

در ضمن سایتت رو هم دیدم خیلی خوب توضیح داده بودی
عالی

سپول
پنج شنبه 09 آذر 1391, 14:04 عصر
درسته جدید هستند ولی باز هم فکر می کنم که tech اشون برای سخت افزار dx9 باشه. از اونجا که این بازی ها در اصل برای کنسول ها ساخته می شوند و بعدش برای pc پورتشون می کنند. قاعدتا تکنولوژی ایشون هم بر همون اساس هست. حتی اگه به فرض روی pc از api directx10 به بالا استفاده کنند.

یک بازی که یادم بود که موتورش رو بر اساس سخت افزارهای نسل بعدی و pc ساختند بعد روی کنسول ها پورت کردند، موتور frostbite2 بود که برای بازی battlefield3 ساختند. که همه منتقد ها هم می گفتند کلا روی pc روانتر و بهتره. اون هم روی pc از deferred rendering منتها با استفاده از compute shader استفاده کرده بود.

در مورد optimize کردنش هم منظورت رو درست نفمیدم. ولی کلا مشکل light prepass اینه که باید دو بار کل صحنه رو کشید. ولی در deferred معمولی این کار یک بار انجام می شه. تنها نقطه ضعفش نسبت به deferred همینه. من راه های خاصی جز کاری که در stalker جدید کرده بودنند ندیدم برای این مورد.
توی موتور stalker جدید، یک روش ترکیبی اجرا می کنه که میاد به جای اینکه فقط نرمال ها رو نگه داره ... رنگ و اطلاعات دیگه material هارو توی gbuffer (شبیه همون روش deferred) می ریزه.. ولی نور پردازی رو با روش light prepass انجام می ده. من این رو تست نکردم ولی انگار fill-rate کارت گرافیک رو پایین آورده و در ضمن صحنه هم یک بار می کشه. که البته این روش مزیت داشتن MSAA روی سخت افزار dx9 (مانند کنسول ها) رو از بین می بره.