DCSIMG
June 2010 - Posts - הבלוג של צביקה פאר

הבלוג של צביקה פאר

בבלוג זה אני אנסה לשתף את הקוראים בחקירת מגוון טכנולוגיות נפוצות פחות או יותר

June 2010 - Posts

לאן נעלם הדמו של DisplacementMapping10 ?

בגרסאות קודמות של Direct3d הופיע Demo בשם DisplacementMapping10 שבא להדגים את היכולת של Displacement Mapping בהשוואה ל לטכניקות פשוטות יותר כמו Normal mapping .

Displacment Mapping demo

התוצאה של הDemo הינה רידנור של לטאה כאשר משתמשים ב Displacement Mapping ניתן לשנות את המעטפת של הMesh (רינדור הסנפיר על הגב של הלטאה ) דבר שהינו בילתי אפשרי בטכנולוגית Normal mapping המצויה .

disp1

בהשוואה ל רינדור עם Displacment mapping

dis2

 

הבעיה עם ה Demo הזה לפי דעתי היתה איטיות גם בכרטיסים לא חזקים לכן אולי הוא ירד .

הטכניקה של Displacment mapping  (קימות כל מיני וריציות ) קיבלה boost  בDirect3d11 בשל השימוש ב Hardware tessellation stage  שמאפשר פיצול פוליגונים שהינם חלק מה mesh  לפוליגונים קטנים .

מכיוון שפעולה זו מתבצעת על ידי החומרה של כרטיסי מסך תומכי Direct3d11 יש שיפור ניכר בביצועים של אפליקציות וdemos שמשתמשים בטכנולוגיה של Displacement mapping .

Tangent space

Tangent space שלפעמים נקרא גם Texture Space  הינו מרחב בעולם התלת מימד שנוסף ל World, View ,Projection  שייעודו הינו לחסוך משאבי GPU של חישובי טרנספורמציות  של  בPixel Shader   .

כאשר מיישמים Per Pixel lighting  יש הרבה טכנולוגיות שדורשות שלכל Texel בTexture  יוצמד גם ערך של Normal  דוגמא לטכנולוגיה כזו הינה : Normal mapping.

בד"כ כלל לאובייקטים התלת מימדיים עליהם אנו צריכים לישם טכנולוגית הקשורות ל per pixel light  אנו מקבלים מהגרפיקאי שני  קבצי Resource :קובץ של Color map וקובץ של Normal map   כך שלכל Texel  ב Color Map  יש את וקטור הנורמל המשלים שלו ב Normal Map.

ערכי ה Texture מבוטאים על ידי color ערכי ה Normal  מבוטאים על ידי vector מנורמל .

אם מגדירים  את הערכים ב Normal Map  כוקטורים ב  object Space  מכיוון שכאשר מיישמים חישוב של light  ב Per pixel light  גם ה Light Direction  וגם ה Camera vector  משתתפים בחישוב היינו צריכים על כל אחד מערכי ה Normal  שדגמנו מה Normal Map  לבצע טרנספורמציה למרחב בו מוגדרים הוקטורים של ה Light  ו ה Camera  . דבר זה יגרום לעומס עבודה ב Pixel shader  .

על מנת לחסוך את הטרנספורמציה הזו מגדירים מרחב חדש בשם Tangent space 

מרחב הצירים בTangent space  מוגדר כ:

ה Vector  X  מוגדר לאורך ה U  של ה Texture  מוגדר כ Tangent

ה Vector   Y מוגדר לאורך הV של ה Texture  מוגדר Bitangent

ה Vector  Z מוגדר כנורמל של ה Surface  .  מוגדר כ Normal  

כאשר עובדים עם Tangent Space  הNormals ב Normal maps מוגדרים ב Tangent space  .

ערכי ה Normal  נדגמים מהResource view על ידי ה PixelShader בדומה לדרך שבה דוגמים Texture רגיל כאשר ערכי ה xyz  נמצאים ב ערכי הrgb

float3 n = normalize(tex2D(normalMap, IN.texCoord).rgb * 2.0f - 1.0f);

עבור כל polygon  את ה light direction  וה Camera vector  אנו צריכים להמיר ל.Tangent space  פעולה זו מתבצעת עבור כל וקטור ב Vertex Shader  וכך אנו מקבלים ב Pixel shader  את כל הוקטורים באותו מרחב (Tangent space ) דבר שחוסך לנו טרנספורמציות עבור כל texel  .

על מנת להשתמש עם Tangent space  אנו צריכים לבצע את הפעולות האילו

נצרף אלמנט של Tangent  ל

D3D10_INPUT_ELEMENT_DESC

   { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0 },

אשר יוכנס לפקודת  CreateInputLayout

מכיוון שיש לנו גם את הערך של ה Tangent  וגם את הערך של הNormal  אנו חוסכים את המרכיב של ה Bitangent  בכל Vertex אותו נחשב בVertex Shader  באמצעות Cross product .

במקרה והobject  שאנו הולכם לרנדר לא מכיל ערכי Tangent  מחושבים עבור כל ווקטור  אנו צריכים לחשב את הערכים האילו לפני ששולחים את הVertexים לInput-Assembler Stage .

יש הרבה דוגמאות קוד ברשת לקוד שעובר על כל הפוליגונים של ישות ומחולל ומחולל לכל Vertex את ערכי ה Tangent שלו .

ב Vertex Shader  אנו כאמור צריכים להמיר את המרחב של ה Viewer vector  והlight direction  ל Tangent space 

השלבים ביצירת מטריצת ההמרה לTangent space הינם :

אנו כופלים את הערכים של ה Vertex  במטריצה ההופכית המשוחלפת של ה World transformation

  float3 n = mul(IN.normal, (float3x3)worldInverseTransposeMatrix);

      float3 t = mul(IN.tangent.xyz, (float3x3)worldInverseTransposeMatrix);

אנו מחשבים את רכיב ה Bitangent  על ידי Corss product  כאשר ה ערך של IN.tangent.w מכי לערכים או של 1- או 1 שמצבעים על הקוטביות של ה Tangenet space coordinates

      float3 b = cross(n, t) * IN.tangent.w;

מרכיבים את מטריצת ההמרה למרחב ה Tangent sapce

      float3x3 tbnMatrix = float3x3(t.x, b.x, n.x,

                                    t.y, b.y, n.y,

                                    t.z, b.z, n.z);

המטריצה קודם מחזירה את הvetcor ל מרחב העצם ממרחב העולם ואח"כ מעבירה את העצם למרחב ה Tangent

כעת שיש לנו את מטריצת ההמרה אנו מכפילים את ערכי ה Light direction  וה camera vector  ב מטריצת ההמרה .

את הערכים המומרים שקיבלו אנו מציבים בstruct  התוצאה של ה Vertex shader  והם ישמשו ב חישוב ה light  ב pixel shader .

כאשר בשלב של ה Pixel shader כל הוקטורים או הערכים שמשמשים לחישובי אור וכד נמצאים במרחב ה Texture דבר שחוסך לנו המרות של וקטורים ב pixel shader .

שילוב בין Directshow ל Direct3d

איזה דוד שאל שאלה בפורום תמיכה של Codeproject .

יש לו אפליקציה שמרנדרת Scene  של Direcrt3D והוא מעוניין לשלב את התוצאה שלה עם streaming של וידיאו באמצעות DirectShow filter .

הוא שואל איך עושים את זה ?

ובכן לפי דעתי הכיוון הוא לא נכון .שילוב נכון של directshow video  ו Direct3d עדיף שיתבצע באמצעות התשתית של Direct3d ולא של Directshow  .

לכך יש מספר סיבות .

1.התשתית של Direct3D מתעדכנת טכנולוגית ומקבלת תשומת לב ממיקרוסופט בניגוד ל Directshow שתקוע כבר למעלה מ10 שנים באותו מקום .

2.על מנת לעבוד את התוצאה של הdx pipeline בתוך directshow filter  צריכים גישה של הcpu לתוצר של הoutput merger stage.

אומנם הרינדור של Direct3d יכול להתבצע על Resource מסוג Texture אבל הResource חייב להיות מוגדר עםdefault usage שהכוונה שרק ל GPU יש הרשאת כתיבה וקריאה מה Resource הCPU  לא יכול לגשת לTexture שהוגדר כ ID3D10RenderTargetView .

3.גם אם היינו משיגים את התוצאה של הdx pipeline המיזוג שלה עם הsurface של הdirectshow הינה פעולה יקרת משאבים מבחינת CPU סביר להניח שהפורמטים שונים ויש מצב שעל כל byte נצטרך לבצע פקודת if בCPU + הצבות וחישובים ,וכל frame מורכב מ 640 * 480 קריאות כאילו .

מניסיון מחשב חזק יכול לתמוך בפעולה כזו אבל חלק ניכר מהמשאבים כל הזמן ילך על הפעולה הזו .

4.בdirectshow filter  אין גישה לכל נתוני התוצר של הoutput merger stage הכוונה לZ- Buffer ו stencil Buffer דבר שלא יאפשר לבצע חישובי הסתרות וכד כלומר הוידיאו לא חלק מהעולם של ה3D.

5.הוידיאו לא יהיה חלק אינטגרלי מהעולם כלומר כל חישובי ההצללה והתאורה לא יכללו בvideo מכיוון שהם נעשים בPixel shader .

בפוסט הבא אני אשתדל לכתוב איך לפתור את הבעיה באמצעות הפיכת ה Video Surface לDirect3D texture resource ושילובה בrendering של ה Sence .

שילוב בין שתי אפליקציות המרנדרות dx sences

לפעמים יש צורך לשלב בין שני scene ים ששתי אפליקציות Direct3D שונות יוצרות לתוך Scene   אחד .

לדוגמא: אני רוצה להשתמש באפליקציה שלי בBing maps  לצורך יצירת ועדכון הterrain ומעל הTerrain  אני צריך לרנדר  את האובייקטים שלי .

בניגוד למקרה עם אפליקציות 2D שאולי אפשר לשלב תמונות על ידי משחק עם ערכי alpha המצב בעולם של התלת מימד מורכב בהרבה .

הטכנולוגיות יכולות להיות מדור שונהBing  עובד מול Direct3d9  ואני עובד עם Direct3d11  .כל ה api והאובייקטים שונים מאוד .

פעולת הrender חייבת להיות משותפת על מנת שהZ-buffer filter  יפעל גם על האובייקטים שלי וגם על האובייקטים של Bing .כלומר אם מכונית שאני מרנדר נמצאת מאחורי הר שbing  מרדנר ההר צריך להסתיר את המכונית שאני מרנדר .

פעולות בshaders  של הצללה ואור צריכות להיות משותפות .(הקונספט של שמש בגבעון דום וירח בעמק איילון לא תופס כאן ) אותו מקור תאורה משפיע הן על האובייקטים שלי והן על האובייקטים המיובאים .

כמו כן יש אוביקטים בscene  של Bing  שאני לא רוצה שירונדרו אצלי באפליקציה אני רוצה רק את הTerrain  נטו מבלי כפתורים שBing מרנדרת על הscene  שלה .

מכיוון שאי אפשר לשתף את הsurface ים בין האפליקציות וbing לא פותח לנו api  של קבלת הResource ים מbing  Vertexים והTexture ים ) אנו צריכים להוציא את הResources מBing לא בדרך המלך.

הפתרון שמימשנו

הפתרון מתבסס על יירוט של הקריאות ל dx api  על ידי Bing .

יצרנו אפליקצית .net win form שמריצה WebBrowser Control ולתוך ה WebBrowser control  אנו טוענים עמוד html  מקומי שמציג את Bing  אפשר לשלוט על Bing  באמצעות פקודות של automation  פשוטת של בחירת המיקום בעולם שהמפה מציגה וכד .

אנו יוצרים  proxy dll   שתפקידו ליירט קריאות מBing  ל d3d9.dll ישנם מספר דוגמאות לשלד של dll  כזה במרחבי ה Web  . הDLL בשם  d3d9.dll  ממוקם בספריה שמריצה את האפליקציה עם Bing ולכן Bing טוען את הProxy dll שלנו כאשר הוא קורא לCreateDevice

אנו כתבנו proxy ל interface ים החשובים של Dx9 אשר הם נקראים במקום האורגינלים .

ברגע שאנו מיירטים פקודה שBing פקד וזו פקודה שמעדכנת Resource  אנו מעתיקם את המידע שלה ל shared memory  שמשותף ל dll  המירט ו האפליקציה שלנו וכך יש לנו ביד את הpre resource  ואנו מכניסים אותו ל pipline  שלנו בתהליך הRender  שלנו .

אנו צריכים לקלף או להתאים את הResource לDX11  יש שוני מהותי בין העבודה עם Resources  בDX9 שהשתנה עם המעבר ל DX10 יש שונה בהדרת הSurfaceים וכד

אין צורך שתהליך הירוט יעביר את קריאות הRender  ל d3d9.dll האורגינל חבל על תעבורה על הBus המיותרת ועבודת הכרטיס מסך.יש פקודות בעיקר אתחול שכן צריכות לקרא ל d3d9.dll המקורי על מנת ש bing  יוכל לאתחל את העבודה שלו. הכל בתלות במשחק של trial and error .