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 .