אני אשתדל לדבר כמה שיותר על אפקטים שונים אך זה יהיה המימוש יהיה בסוף מאוד פשוט כדי שיהיה קל להבין את זה גם אם לא תכנתתם גראפיקה בעברכם!
מחשב הוא מערכת המורכבת מרכיבים חומרתיים המסוגלים לבצע חישובים.
במחשב יש כמה רכיבים עיקריים אך שני הרכיבים החישוביים החשובים הם - CPU
ו-ALU
.
ה-CPU
הוא השבב הראשי שמקבל פקודות ויודע להמיר אותם לאותות חשמליים המבצעים פעולות.
איזה סוג של פעולות?
RAM
. ה-ALU
הוא תת מערכת בתוך ה-CPU
אשר מבצע את החישובים והבדיקות הלוגיות.
ה-ALU
בד”כ מבצע פעולות על מספרים שלמים,
ולעיתים קיים גם רכיב מיוחד בשם FLU - Floating Logic Unit
שמבצע פעולות על מספרים עשרוניים.
למרות שכיום ה-CPU
הוא רכיב מרכזי במערכת המסוגל לחשב ולבצע פעולות לוגיות הוא אינו מסוגל לחשב מספיק מהר ערכים גראפיים כדי לרנדר/לצייר תמונות.
המונח העיקרי הוא Software Renderer
- ז”א ציור בעזרת ה-CPU
.
החסרונות של רנדור בעזרת ה-CPU
:
והנקודה האחרונה היא החשובה - הCPU
אינו בנוי לרנדר תמונות ואינו מספיק מותאם לפעולות האלו.
ולכן נברא בשנות ה-90 ה-GPU
.
ה-GPU
היא מערכת נוספת חישובית אשר נבנתה כדי לרנדר תמונות.
מה כרוך ברנדור תמונה דו מימדית או תלת מימדית?
הסיבה העיקרית לבניית המעבדים הגראפיים היא יצירת כרטיס מותאם למקביליות מאוד גבוה.
בגלל שהקוד מבצע את אותו הקוד עבור כל פיקסל במסך ניתן למקבל אותו הרבה יותר בקלות.
בעזרת ה-CPU
היינו יכולים למקבל בעזרת תהליכונים:
אך הבעיה העיקרית בה שזה מוגבל לכמות ה-Coreים שיש.
ב-GPU
יש הרבה יותר Coreים.
לא 4, לא 8 ולא 16 - מאות ואלפים!
ל-GTX 1080 יש 2560 Cores!
כל Core יוכל לחשב כל פיקסל ואם אלו חישובים מאוד פשוטים אפילו לא ייקח לו הרבה זמן.
תמונות ירונדרו בצורה מאוד מהירה!
מה שקורה בכרטיס מסך מתחלק לשלבים, הבנת ההתנהגות תעזור לנו להבין כיצד לכתוב קוד למעבד הגראפי.
מה שמסומן בירוק ניתן לתכנת אותו!
השלב שבו המעבד הגראפי טוען את כל המידע שהוא צריך מהמעבד למעבד הגראפי.
בתהליך הזה עובר המידע דרך צינורות הנקראים Bus
ואלו מסוגלים להעביר מידע בצורה מהירה.
לכרטיס הגראפי יש זיכרון משל עצמו ולכן כאשר זיכרון נטען לא צריך להעביר אותו פעמיים.
איזה מידע נטען?
זהו שלב שניתן לתכנת אותו!
Vertex הוא נקודה או ווקטור.
שלב הוורטקסים הוא בעצם תוכנה אשר מחשבת את מיקום הנקודות מחדש.
אילו חשובים נכנסים לכאן?
שלב החלוקה מחלק את הצורות הגדולות לצורות קטנות יותר.
למשל מלבנים למשולשים!
תזכרו את זה כי ברנדור גראפי תלת מימדי עובדים הרבה עם משולשים ולא ריבועים.
גם אם קיימים ריבועים שלב החלוקה מחלק אותם למשולשים!
לכן הכי נוח לעבוד עם משולשים מלכתחילה.
זהו שלב שניתן לתכנת אותו!
בגרסאות הראשונות - כשאני למדתי תכנות גראפי - לא היה את השלב הזה כשלב שניתן לתכנת אותו.
מה שהוא עושה זה בעצם נותן אופציה לערוך צורה שלמה ולא את כל הנקודה.
מה ניתן לעשות עם זה?
חלק מהתהליך צריך להמיר תמונות תלת מימדיות לדו מימדיות כי המסך שלנו לא תומך בתלת מימד (עדיין).
השלב הזה לוקח את הנקודות ומחשב את המיקום שלהם בדו מימד.
פרגמנט הוא בעצם פיקסל - מכיל צבע
בשלב הזה אנחנו יכולים לשלב אפקטים שונים או למסך את הצבע כרצוננו - להפוך לשחור לבן, להכהות, לחדד וכדו’…
למשל להפוך תמונה לשחור לבן:
הצבעים מתערבבים כי כתוצאה מהחישוב יכול להיות לנו כמה צבעים עבור פיקסל אחד!
שילוב הצבעים תלוי בפונקציות הנבחרות.
OpenGL
זהו API עבור רנדור דו מימדי ותלת מימדי.
לעיתים גם נקרא כ-“האסמבלי של כרטיסי המסך”.
ניתן להפיק בעזרתו גראפיקה עבור אפליקציות שונות - וידאו, בניית סצנות, אפליקציות רגילות, משחקים וכדו’…
בעצם כל דבר שצריך רנדור מהיר של תמונות.
בפוסט הזה אני לא אדבר על ה-API של OpenGL
מכיוון שנכתבו ספרים רבים עליו והוא מאוד מורכב.
זוהי השפה הנותנת לנו אפשרות לתכנת את החלקים שניתן לתכנת אותם בכרטיס המסך, שהם -
תחביר השפה דומה מאוד לשפת C.
בעל כמה פיצ’רים מיוחדים לתכנות כרטיסי מסך.
בשפה יש מבנים שימושיים כגון vec2
,vec3
,mat3
, וכדו’…
שיידרים אלו תוכנות קטנות שמקבלות נתונים ומוציאות נתונים.
עבור כל כל נקודה או צבע רץ אותו שיידר - ולכן המקביליות של כרטיסי המסך כל כך אפקטיבית.
נכיר את הפיצ’רים הבסיסיים בשפה ע”י היכרות ראשונית עם שיידרים:
איך נראה Vertex Shader
בסיסי?
1 |
|
קודם כל צריך לבצע הפנייה באיזה גרסא אנחנו משתמשים - #version 330 core
.
גרסא - 3.3
.
כל משתנה שמתחיל ב-gl_
הוא משתנה של OpenGL פנימי.
ז”א שיש משתנים שיכולים להיות מאותחלים ולקבל ערך בשיידר ויש כאלו משתנים שכבר אותחלו לפני זה ואפשר להשתמש בהם.
למשל gl_vertex
הוא משתנה שאותחל לפני.
משתנה gl_Position
זה משתנה שהקוד של השיידר שלנו צריך לאתחל.
המשתנה מייצג את המיקום הסופי של הורטקס בתלת מימד.
הוא הורטקס הנוכחי שהשיידר עובד עליו.
זהו בעצם עצם מסוג vec3
.
בתכנות תלת מימדי משתמשים במטריצות.
מטריצה זה מערך דו מימדי של ערכים.
ה-ModelViewProjection Matrix
משלב 3 מטריצות לאחד כדי לבצע חישובים קלים על הוורטקסים שלנו.
מהו הוא מחזיק?
מחזיק את הערכים לאובייקט שלנו שבצעים המרה מקורדינטות לוקאליות לקורדינטות של העולם שלנו.
למשל אם הדמות שלנו זזה קדימה זה ייצוג פה.
אחרי שהזזנו את כל העולם שלנו ואת הדמות המטריצה הזו מזיזה הכל עבור המצלמה שלנו.
אם למשל סיבבנו את המצלמה אחורה אז אנחנו צריכים לסובב גם את העולם שלנו לפי התזוזה הזו.
זוהי מטריצה די מסובכת להבנה בהתחלה אבל העיקר להבין שמה שזה מייצג זה המרה בין המצלמה שלנו למסך!
בסופו של דבר עלינו להתאים את הקאורדינטות התלת מימדיות למסך דו מימדי.
שימו לב לטרפז הסגול, הטרפז הזה הוא שימוש קלאסי במצלמה שנקראת - Perspective View.
השיידר הבסיסי צריך לאתחל את המשתנה gl_FragColor
.
1 |
|
המשתנה הזה אומר באיזה צבע לצבוע את הפיקסל.vec4
מכיל את המידע rgba של הפיקסל.
למשל הצבא הזה יהיה - ירוק כי רכיב ה-Green שלו הוא 1.0.
הערכים יכולים לנוע בין 0.0 ל1.0.
מטרת השיידר הזה הוא לייצר גאומטריה חדשה - למשל קווים, ריבועים, משולשים וכדו’…
1 |
|
זהו שיידר קצת מורכב אז לא אסביר על הכל בו, שימו לב לכמה דברים.
gl_Position
הוא המיקום הנוכחי של הורטקס. EmitVertex
היא קריאה לפונקציה ליצירה של ורטקס ע”פ הערכים הקיימים. EndPrimitive
- גאומטריה פשוטה כמו קווים ומשולשים נקראים צורות פרימיטיביים.אנחנו נעבור על layout
בחלקים הבאים כשאסביר יותר על כתיבת שיידרים.
לכתוב תכנית שטוענת שיידרים ועושה בהם שימוש זה עניין מורכב - ולכן יש באינטרנט אתרים שנותנים לכתוב שיידרים ולנסות אותם.
ניתן להחליף בין Vertex ל-Fragment.
יש בקוד הבסיסי פיצ’רים שעוד לא דיברתי עליהם, העקרון החשוב הוא.
ב-Vertex Shader הם עורכים את gl_Position
:
1 | vec4 pos = modelViewMatrix * vec4(position, 1.0); |
וב-Fragment Shader הם עורכים את gl_FragColor
:
1 | gl_FragColor = vec4(fNormal, 1.0); |
1 | precision highp float; |
אם נוריד ערכים מהצבעים בעזרת החסרת vec4
נקבל תוצאה שונה:vec4
לצבע עובד בקומפוננטות rgba
.
זאת אומרת:
1 | red - 0.2 |
1 | precision highp float; |
תכנות גראפי הוא אחד התחומים הכיפיים והמעניינים בעולם התוכנה,
התוצאות של כתיבת הקוד הן מול העיניים.
בפרקים הבאים נעסוק יותר בשפת Glsl
, בפיצ’רים שלה ונסביר יותר גם על OpenGl
.
תודה על הקריאה!