Unity איך ליצור Shader
Shader הוא סקריפט קטן המכיל חישובים מתמטיים ואלגוריתמים לחישוב הצבע של כל פיקסל שעובד, בהתבסס על קלט התאורה ותצורת החומר.
Unity משתמש ב-Shaders הכתובים בשפות הבאות:
- שפת תכנות בשם HLSL משמשת לכתיבת תוכניות ההצללה עצמן.
- שפה ספציפית ל-Unity הנקראת ShaderLab משמשת להגדרת אובייקט Shader, שפועל כמיכל לתוכניות הצללה.
כדי ליצור הצללה ב-Unity, בצע את השלבים הבאים:
צור Shader
- לחץ לחיצה ימנית על תצוגת הפרויקט -> 'Create' -> 'Shader'
בהתאם לגרסת Unity שבה אתה משתמש, אפשרויות ה-Shader עשויות להיות שונות, אבל הנה המשמעות של כל אחת מהאפשרויות:
- 'Standard Surface Shader': הצללה זו תוכננה לעבוד עם מערכת העיבוד הפיזי (PBR) של Unity. זה מאפשר למפתחים ליצור חומרים המגיבים לתנאי תאורה בצורה מציאותית. הוא תומך בתכונות רינדור שונות כמו מיפוי רגיל, הדגשות מרהיבות והשתקפויות. זהו מכשיר הצללה רב-תכליתי המספק איזון טוב בין ריאליזם לביצועים.
- 'Unlit Shader': כפי שהשם מרמז, הצללה לא מוארת אינה מתחשבת בתנאי תאורה. הוא משמש לעתים קרובות לעיבוד אפקטים שאינם זקוקים לתאורה מציאותית, כגון רכיבי ממשק משתמש, מערכות חלקיקים או אפקטים מיוחדים. הצללים לא מוארים הם בדרך כלל יעילים יותר ויכולים להיות שימושיים במצבים שבהם זה דורש שליטה מלאה על המראה של אובייקט ללא כל חישובי תאורה.
- 'Image Effect Shader': הצללות אפקט תמונה משמשות להחלת אפקטים של פוסט-עיבוד על כל המסך או על יעדי רינדור ספציפיים. הם מאפשרים למפתחים לשנות את התמונה המעובדת הסופית לאחר השלמת העיבוד הראשי. דוגמאות לאפקטים של תמונה כוללות טשטוש, דירוג צבע, עיוות או פילטרים מסוגננים. ניתן להשתמש בהם כדי לשפר את האיכות החזותית או ליצור אפקטים אמנותיים ספציפיים.
- 'Compute Shader': הצללה ממוחשבת היא סוג של הצללה שפועלת על ה-GPU אך אינה פועלת על פיקסלים ישירות. הוא משמש לחישובים למטרות כלליות על נתונים מקבילים, ומאפשר למפתחים לבצע חישובים מורכבים או סימולציות ביעילות. הצללות מחשוב משמשות בדרך כלל למשימות כמו הדמיות פיזיקה, יצירת פרוצדורות או עיבוד נתונים.
- 'Ray Tracing Shader': הצללים למעקב אחר קרניים משתמשים בטכנולוגיית מעקב אחר קרניים, המדמה את התנהגות האור בצורה מדויקת יותר בהשוואה לטכניקות רסטר מסורתיות. הצללים למעקב אחר קרני משמשים בדרך כלל להשגת תאורה, השתקפויות וצללים מציאותיים ביותר ביישומים בזמן אמת. הם דורשים חומרה רבת עוצמה ומשמשים לעתים קרובות בתחומים עתירי גרפיקה כמו משחקים או הדמיה ארכיטקטונית.
- לאחר בחירת הצללה, הקלד כל שם והקש Enter
ה-Shader החדש נוצר וניתן לפתוח אותו בכל עורך סקריפט ולשנות אותו כך שיתאים לצרכים שלך.
ברירת מחדל 'Standard Surface Shader':
Shader "Custom/NewSurfaceShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
ברירת מחדל 'Unlit Shader':
Shader "Unlit/NewUnlitShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
ברירת מחדל 'Image Effect Shader':
Shader "Hidden/NewImageEffectShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
// just invert the colors
col.rgb = 1 - col.rgb;
return col;
}
ENDCG
}
}
}
ברירת מחדל 'Compute Shader':
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain
// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D<float4> Result;
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
// TODO: insert actual code here!
Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
}
ברירת מחדל 'Ray Tracing Shader':
RWTexture2D<float4> RenderTarget;
#pragma max_recursion_depth 1
[shader("raygeneration")]
void MyRaygenShader()
{
uint2 dispatchIdx = DispatchRaysIndex().xy;
RenderTarget[dispatchIdx] = float4(dispatchIdx.x & dispatchIdx.y, (dispatchIdx.x & 15)/15.0, (dispatchIdx.y & 15)/15.0, 0.0);
}
סיכום
לכל סוג הצללה יש חוזקות ושימושים משלו. חשוב לבחור את ההצללה המתאים על סמך הדרישות הספציפיות שלך והאפקטים החזותיים שאתה שואף להשיג בפרויקט שלך.