ورود

View Full Version : سوال: نور جهت دار و shadow map



kochol
شنبه 03 بهمن 1388, 17:26 عصر
سلام

من می خوام یه shadow map برای نور جهت دار بسازم ولی نمی دونم چه طوری باید بر اساس موقعیت دوربین ماتریس سایه رو ساخت.

mohamnag
یک شنبه 04 بهمن 1388, 00:40 صبح
سایه شما به موقعیت دوربین وابسته نیست که، به منبع نور وابسته است و سطحی که می خواد روش بیوفته و شی سازنده سایه. بعد از اینکه تکسچر یا مش حاصله رو بدست آوردید برای ترسیمش به دوربین و موقعیتش احتیاج دارید.

kochol
یک شنبه 04 بهمن 1388, 11:25 صبح
shadow map توسط Render To Texture کار می کنه و باید یه دوربین بزاری که بتونی صحنه رو از دید نور ببینی و چون نور جهت دار مکان نداره و فقط جهت داره پیدا کردن مکانی مناسب برای این نور کاری سخت است و از اونجایی که می خوای کیفیت نهایی هم خوب باشه باید یه مکان مناسب براش پیدا کنی.

برای اطلاعات بیشتر هم سری به این لینک ها بزن.

*
http://www.gamerendering.com/category/shadows/shadow-mapping/
*
http://http.developer.nvidia.com/GPUGems/gpugems_ch14.html
*
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter17.html
*
http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html
*
http://hax.fi/asko/PSSM.html
*
http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_vrcia/

من آدمی نیستم که حتی زحمت سرچ تو گوگل رو هم بخوام بندازم گردن دیگران دو روز رو این موضوع کار کردم و بعد که به نتیجه ای نرسیدم این پست رو دادم.

Nima_NF
یک شنبه 04 بهمن 1388, 17:51 عصر
نور جهت دار، یعنی نوری در بی نهایت (مانند خورشید). نوری که در بینهایت هست چون فاصله اش خیلی دور هست، پرتو های نوری آن همگی موازی هم هستند.

کلا دو نوع نور جهت دارد داریم، یکی اینکه خورشید، ماه و ... هستند که فوق العاده دور هستند و مکان آن ها نیز نهایت بازه عدد شما هست (مثلا نهایت بازه double/float)
نوع دیگر، نور جهت داری هست که فاصله اس دور هست و حتما باید برای آنتهای آن علاوه بر جهت، یک مکان انتهای در نظر بگیرید. حتی اگر قرار هست در موتور شما ساخته شود اگر آفتاب نیست، باید مکان انتهای برایش در نظر بگیرید. (تذکر: با این حال، این نقطه انتهایی، فقط برای محاسبه شدت سایه که بر اساس depth که بین 0 و 1 هست استفاده می شود نه خود نور، خود نور و سایه همواره موازی هستند.)

بنابراین میزان depth در حالت خورشید (بدون مکان انتهایی) تاثر گذار نیست و همه سایه ها معمولا بدون در نظر گرفتن depth یکدست هستند، مگر اینکه فاصله آنقدر بین اشیا زیاد باشید که در مقایسه با بازه double/float به چشم بیایید.

در این حالت، دو راه می توانید استفاده کنید:
- یکی اینکه اگر واقعا هدف دور بودن هست، برای تمامی سایه ها اصلا از نقطه ای استفاده نکنید و فقط از همان بردار استفاده کنید، یعنی هر vertex با یک بردارثابت محاسبه شود.
(تذکر مهم: فرض بر این هست که شما از دریچه دید یک دوربین نگاه نمی کنید، فقط محاسبات را انجام می دهید و نقاط سیاه و سفید را در عکس سایه تشکیل می دهید. چون perspective در کار نیست و همه چیز عمود هست، چرا ؟ چون فاصله و منبع نور بسیار بزرگ هست)

-راه دیگر، واقعا دوربین را در بی نهایت فرض کنید (نهایت بازه عددی)، مطمئنا کیفیت خوبی نخواهید داشت.

- اما راه دیگر استفاده از همان نقطه انتهایی هست که در موتور در بازی باید توسط طراح مشخص شود. مثلا به اندازه مکانی که sphere که با texture آسمان هست.
البته از این میزان فقط برای محاسبه میزان depth برای shadow استفاده کنید و خود نور یا خود سایه را همگی موازی رسمی کنید (چون هدف فاصله دور بودن هست)

seyedof
دوشنبه 05 بهمن 1388, 09:15 صبح
سلام

برای اینجور نورها باید از تصویرگری Ortho استفاده بشه. توی ساخت ماتریس دوربین Ortho باید بتونید یک جوری بسازیدش که کل محیط شما داخل Frustum قرار بگیره. یا حداقل اوون قسمتی که میخواهید روش Shadow Map اعمال بشه داخل این Frustum قرار بگیره.

ممنون علی

kochol
سه شنبه 06 بهمن 1388, 20:11 عصر
سلام

ممنون از توضیحاتتون ولی من در حقیقت روش محاسبه ماتریس VIEW نور می خوام و می خوام طوری تنظیمش کنم که هر جایی رو که دوربین می بینه نور هم ببینه و نه اینکه نقاط بیشتری رو ببینه.

سپول
شنبه 10 بهمن 1388, 12:13 عصر
View Frustum رو که درست می کنی مختصاتش در world هست، از اون یک box درست کن .
Light هم یکجور ماتریس view از خودش (مانند دوربین) از خودش باید درست کنه ، اون ماتریس هم درست کن و اون box رو در ViewLightMatrix ضرب کن. اینجوری در واقع محدوده ViewFrustum ات در فضای دید نور در میاد.
پارامتر های اون box آخری که بوجود میاد رو می تونی به یک تابعی مانند D3XMatrixOrthoOffCenterLH (تا تابعی که خودت می نویسی) بدی.
ِ

ِD3DXMatrixOrthoOffCenterLH( &mat, box.min.x, box.max.x, box.min.y, box.max.y, zLightNear, zLightFar)


این می شه ماتریس projection ای که باید صحنه رو باهاش بکشی (برای ShadowMap) ماتریس View نور هم که داری و تمام.

kochol
یک شنبه 11 بهمن 1388, 13:49 عصر
آقا ممنون

ولی این جواب شما جواب سوال بعدی من بود D:

چون نور من جهت دار هستش من مکان خاصی برای نورم ندارم و کاری که الان می کنم اینه که از مکان دوربین انقدر در جهت دید دوربین می رم جلو تا به نقطه ای با y=0 برسم بعد از اون نقطه به اندازه دو برابر فاصله دوربین تا اونجا در جهت نور بر می گردم.

نتیجه ای که می ده بدک نیست ولی می خواستم کار اصولی این را هم بدونم.

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


kge::math::Vector v = pCam->GetTarget() - pCam->GetPosition();
float l = v.GetLength();
v.Normalize();
float f = pCam->GetPosition().y / v.y;
v = v * f;
v = pCam->GetPosition() - v;
kge::math::Vector d(-0.00078, 0.46189, 0.51568);
d.Normalize();

d = d * (f * -2.0f);
d = d + v;



d = مکان دوربین نور
v = نقطه ای که دوربین نور به اونجا نگاه می کنه.

kochol
چهارشنبه 14 بهمن 1388, 12:07 عصر
سلام

از اونجایی که من دارم یه بازی استراتژیک می سازم و در این بازی دوربین دور است پس به نظرم self shadowing لازم نیست و فقط سایه ها روی terrain بیافتند کافیه پس اول از همه به جای تکستچر float از یه تکستچر معمولی استفاده کردم و فیلتر Anisotropic رو هم فعال کردم و نتیجه خیلی خوب بود و همین طور هم سایه لبه های نرمی پیدا کرد.

kochol
چهارشنبه 21 بهمن 1388, 16:05 عصر
سلام

البته این کار اشکالاتی هم داره.

1- اگر یک برامدگی در زمین باشد سایه هر دو طرف اون بر آمدگی می افتد و همین طور هم روی زمین یعنی یه جسم 3 تا سایه می ندازه.

سپهر تمام کار هایی رو که گفتی انجام دادم ولی چند تا مشکل دارم.

1- وقتی که min و max باکس رو برای ماتریس پروجکشن می فرستم اگه x, y رو بدم که اصلا درست در نمی یاد و فقط وسط صحنه سایه داره ولی اگه x,z رو بدم تقریبا درست در می یاد.

2- مشکل من با کد شیدر است وقتی ماتریس پرسپکتیو دارم درسته ولی وقتی اورتوگونال می شه دیگه کار نمی کنه.

من بعد از ضرب در ماتریس لایت مقدار z رو ست می کنم تو shadow map و بعد هم که این مقدار رو موقع سایه گزاری چک می کنم.



// shadow
Input.ProjTex.xy /= Input.ProjTex.w;
Input.ProjTex.x = 0.5f * Input.ProjTex.x + 0.5f;
Input.ProjTex.y = -0.5f * Input.ProjTex.y + 0.5f;

float depth = Input.ProjTex.z;// / Input.ProjTex.w;

float s0 = (tex2D(ShadowMapS, Input.ProjTex.xy).r
+ SHADOW_EPSILON >depth) ? 0.0f : 1.0f;

kochol
پنج شنبه 22 بهمن 1388, 03:52 صبح
سلام

اول از همه از دوست خوبم سپول به خاطر راهنمایی هایی که کرد تشکر می کنم ولی همه فوت کار رو نگفت.

حالا من روش کامل و صحیح تر این کار رو می گم.

1- باید حداقل مقدار برای صفحه دور دوربین رو پیدا کنید تا frustum دوربین کوچک شود.
2- 8 نقطه ای رو که این frustum رو می سازه پیدا کنید.
3- ماتریس view برای لایت بسیار مهم است که دقیق حساب بشه چون بعدا باید این 8 تا نقطه رو در این ماتریس ضرب کنیم.
4- برای بدست اوردن مکان نور ابتدا مرکز frustum رو بدست می یاریم با میانگین گرقتن اون 8 تا نقطه
5- به اندازه far value از اون نقطه در جهت عکس جهت نور حرکت می کنیم اگه یه offset هم بدیم بد نیست برای محکم کاری.
6- حالا اون ماتریس view رو با داشتن مکان دوربین نور بدست امده و وسط frustum به عنوان نقطه ای که دوربین نور به انجا نگاه می کند می سازیم.
7- اون 8 نقطه frustum رو در ماتریس view ضرب می کنیم.
8- حالا از روی این 8 تا نقطه جدید یه AABB می سازیم یعنی مقادیر min و max هر مولفه رو حساب می کنیم.
9- حالا نوبت به ست کردن ماتریس projection می رسه.


matOrtho.SetOrthoOffscreenLH(aabb.m_vMin.x , aabb.m_vMax.x , aabb.m_vMin.y , aabb.m_vMax.y , aabb.m_vMin.z , aabb.m_vMax.z + nearClipOffset);


با استفاده از این کد اون 2 تا مشکلی رو که در پست قبلی مطرح کردم برطرف شدند و همه چیز کار می کنه.

این سایه خیلی وقت من رو گرفت و باید برم رو یه قسمت دیگه ای کار کنم ولی خیلی دوست داشتم رو LispSM ها هم کار کونم اخه ازشون خوشم اومده اگه یه وقت آزاد پیدا کردم این کار رو می کنم.

kochol
سه شنبه 07 اردیبهشت 1389, 16:13 عصر
سایه رو به موتور اضافه کردم ولی یه مشکلی داره مثلا اگر یه جسمی از دید دوربین خارج بشه سایش هم محو می شه ولی در کل خیلی خوب در اومد مخصوصا وقتی که دوربین رو می یاری روی یه سایه و با cull شدن دیگر ابجکت ها کل اون شکل در shadow map رندر می شه و کیفیت میره بالا