Unity Cum se creează un Shader
Shader este un mic script care conține calcule matematice și algoritmi pentru calcularea culorii fiecărui pixel redat, pe baza intrării de iluminare și a configurației Materialului.
Unity folosește Shaders care sunt scrise în următoarele limbi:
- Un limbaj de programare numit HLSL este folosit pentru a scrie programele shader în sine.
- Un limbaj specific Unity numit ShaderLab este folosit pentru a defini un obiect Shader, care acționează ca un container pentru programele shader.
Pentru a crea un shader în Unity, urmați pașii de mai jos:
Creați un Shader
- Faceți clic dreapta pe vizualizarea Proiect -> 'Create' -> 'Shader'
În funcție de versiunea Unity pe care o utilizați, opțiunile Shader pot diferi, dar iată ce înseamnă fiecare dintre opțiuni:
- 'Standard Surface Shader': Acest shader este proiectat să funcționeze cu sistemul Unity's Physically Based Rendering (PBR). Permite dezvoltatorilor să creeze materiale care răspund la condițiile de iluminare în mod realist. Acceptă diverse caracteristici de randare, cum ar fi maparea normală, evidențierea speculară și reflexiile. Este un shader versatil care oferă un echilibru bun între realism și performanță.
- 'Unlit Shader': După cum sugerează și numele, un shader neluminat nu ia în considerare condițiile de iluminare. Este adesea folosit pentru redarea efectelor care nu au nevoie de iluminare realistă, cum ar fi elementele UI, sistemele de particule sau efectele speciale. Umbritoarele neluminate sunt de obicei mai eficiente și pot fi utile în situațiile în care necesită control deplin asupra aspectului unui obiect fără calcule de iluminare.
- 'Image Effect Shader': Umbriatoarele efect de imagine sunt folosite pentru a aplica efecte post-procesare pe întregul ecran sau pe anumite ținte de randare. Acestea permit dezvoltatorilor să modifice imaginea redată finală după ce randarea principală este finalizată. Exemple de efecte de imagine includ estomparea, gradarea culorilor, distorsiunea sau filtrele stilizate. Ele pot fi folosite pentru a îmbunătăți calitatea vizuală sau pentru a crea efecte artistice specifice.
- 'Compute Shader': Un compute shader este un tip de shader care rulează pe GPU, dar nu funcționează direct pe pixeli. Este folosit pentru calcule de uz general pe date paralele, permițând dezvoltatorilor să efectueze calcule sau simulări complexe în mod eficient. Umbritoarele de calcul sunt utilizate în mod obișnuit pentru sarcini precum simulări de fizică, generare procedurală sau procesarea datelor.
- 'Ray Tracing Shader': Umbritoarele de urmărire a razelor utilizează tehnologia de urmărire a razelor, care simulează comportamentul luminii mai precis în comparație cu tehnicile tradiționale de rasterizare. Umbritoarele de urmărire a razelor sunt utilizate în mod obișnuit pentru a obține lumini, reflexii și umbre extrem de realiste în aplicații în timp real. Acestea necesită hardware puternic și sunt adesea utilizate în domenii intensive în grafică, cum ar fi jocurile sau vizualizarea arhitecturală.
- După selectarea shader-ului, tastați orice nume și apăsați Enter
Noul Shader este creat și poate fi deschis în orice editor de script și modificat pentru a se potrivi nevoilor dumneavoastră.
Implicit '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"
}
Implicit '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
}
}
}
Implicit '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
}
}
}
Implicit '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);
}
Implicit '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);
}
Concluzie
Fiecare tip de shader are propriile sale puncte forte și utilizări. Este important să alegeți shaderul potrivit în funcție de cerințele dvs. specifice și de efectele vizuale pe care doriți să le obțineți în proiectul dvs.