Shadery w Unity
Transcript of Shadery w Unity
Shadery w Unity
Wstęp
Potok renderowania w Unity korzysta z
trzech podstawowych elementów:
Trójwymiarowe modele – Unity korzysta z
modeli w formacie *.fbx (wspierane są też
inne formaty ale są one konwertowane w tle
do *.fbx)
Materiały – jest to interfejs pozwalający
inicjalizować programy cieniowania
odpowiednimi danymi (teksturami i
właściwościami)
Programy cieniujące – skrypty przetwarzające
wierzchołki i fragmenty w celu określenia
koloru odpowiednich pikseli na ekranie
Dostępne jednostki cieniowania
Surface Shader
Wysokopoziomowy program cieniowania
zalecany przy efektach korzystających ze
świateł. Rozbijany jest później na serię
jednostek cieniujących wierzchołki oraz
fragmenty
Vertex&Fragment Shaders
Zgodnie z nazwą jednostki cieniowania
odpowiedzialne za przetwarzanie
wierzchołków i fragmentów
Dostępne są również nowsze jednostki
(geometry, hull i domain shader’y) ale ich nie
będziemy poruszać
Dostępne jednostki cieniowania cd.
Fixed Function Shaders
Przestarzałe rozwiązanie bazujące
na stałym potoku renderowania
Zbiór funkcji wykonujących
podstawowe operacje (np.
mieszanie kolorów, tekstur,
wykorzystanie podstawowych
modeli oświetlenia itp.)
ShaderLab – wstęp
Shader "MyShader"
{
Properties
{
//
}
SubShader
{
CGPROGRAM
//
ENDCG
}
SubShader
{
}
Fallback "Diffuse"
}
Językiem wykorzystywanym w Unity do tworzenia programów cieniowania jest
ShaderLab
Na początku pliku zdefiniowana jest
nazwa programu -> Shader „MyShader”
Ciało programu zawiera:
Sekcję z własnościami programu
cieniowania -> Properties
własności te można ustawiać z poziomu
edytora Unity
ShaderLab – wstęp cd.
Zbiór sekcji z różnymi wersjami programu
-> SubShader
sprawdzając od góry uruchamiana jest
pierwsza napotkana wersja, która może
zostać wykonana na dostępnej karcie
graficznej
jeżeli żadna wersja nie może zostać
wykonana, korzystając ze słowa
kluczowego Fallback możemy
wyznaczyć, inny (zastępczy) program
cieniowania
Kod programu (język GLSL/CG) znajduje
się pomiędzy dyrektywami CGPROGRAM
… ENDCG
Shader "MyShader"
{
Properties
{
//
}
SubShader
{
CGPROGRAM
//
ENDCG
}
SubShader
{
}
Fallback "Diffuse"
}
ShaderLab – sekcja Properties
Shader "MyShader"
{
Properties
{
_MyTexture ("My texture", 2D) = "white" {}
_MyNormalMap ("My normal map", 2D) = "bump” {}
// Grey
_MyInt ("My integer", Int) = 2
_MyFloat ("My float", Float) = 1.5
_MyRange ("My range", Range(0.0, 1.0)) = 0.5
_MyColor ("My colour", Color) = (1, 0, 0, 1)
// (R, G, B, A)
_MyVector ("My Vector4", Vector) = (0, 0, 0, 0)
// (x, y, z, w)
}
}
Właściwości definiujemy w formacie:
nazwa (etykieta, typ) = wartość_domyślna
Podstawowe typy danych:
2D – sampler2D (tekstura), domyślną
wartością może być np. „white”, „black”,
„gray”, „bump” (normal mapa)
Cube – samplerCube (6 tekstur tworzących
kostkę),
Int, Float (Range)
Color
Vector (zawsze czterowymiarowy)
…
ShaderLab – sekcja SubShader
SubShader
{
Tags { "RenderType"="Opaque” "Queue"="Geometry+1"
"ForceNoShadowCasting"="True" }
LOD 200
Offset -1, -1
CGPROGRAM
#pragma surface surf Lambert decal:blend
sampler2D _MainTex;
struct Input { float2 uv_MainTex; };
void surf (Input IN, inout SurfaceOutput o)
{
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Sekcja SubShader ma zazwyczaj następującą strukturę:
Tagi i ustawienia programu cieniowania
Kod programu w języku GLSL/CG
(pomiędzy dyrektywami CGPROGRAM
… ENDCG)
Dyrektywy kompilacji
Deklaracje zmiennych globalnych
Deklaracje struktur danych wejściowych
i/lub wyjściowych
Kod jednostek cieniowania
ShaderLab – sekcja SubShaderTagi i ustawienia programu cieniowania
Dokumentacja opisuje 7 podstawowych tagów:
Dwa najważniejsze: Queue, RenderType
Queue - określa kolejność wyświetlania na ekranie.
Parametrem jest liczba. Istnieje kilka stałych takich
jak: Background, Geometry, AlphaTest, Transparent,
Overlay
RenderType – określa sposób wyświetlania wyniku. Z
najważniejszych typów wyróżnić można: Opaque –
nieprzezroczysty, Transparent – (pół)przezroczysty,
TransparentCutout – (pół)przezroczyste fragmenty są
obcinane
https://docs.unity3d.com/Manual/SL-SubShaderTags.html
ShaderLab – sekcja SubShaderTagi i ustawienia programu cieniowania cd.
Pozostałe: DisableBatching,
ForceNoShadowCasting, IngoreProjector,
CanUseSpriteAtlas, PreviewType
Ustawienia mogą dotyczyć między innymi:
Bufora głębi: Cull [Back|Front|Off], ZWrite
[On|Off], ZTest [Less|Greater|Equal|…], Offset
[Factor|Units],
Świateł: Lighting [On|Off]
Level of Details: LOD [liczba]
ShaderLab – sekcja SubShaderKod programu w języku GLSL/CG - Dyrektywy kompilacji
#include "UnityCG.cginc"
#pragma surface surfaceFunction lightModel
[optionalparams]
#pragma vertex name
#pragma fragment name
#pragma geometry name
#pragma hull name
#pragma domain name
#pragma target name
#pragma only_renderers space_separated_names
#pragma exclude_renderers space_separated_names
#pragma multi_compile …
#pragma enable_d3d11_debug_symbols
#pragma hardware_tier_variants renderer_name
Na podstawie tych dyrektyw karta graficzna
określa, która sekcja SubShader powinna
zostać wybrana
Pozwalają określić wymaganą wersję
OpenGL/DirectX
Umożliwiają ograniczenie użyteczności
materiału do określonych komponentów Unity
(Renderer’ów)
Dyrektywy pozwalają wczytywać pliki
biblioteczne
Za pomocą dyrektyw deklaruje się jednostki
cieniowania
ShaderLab – sekcja SubShaderKod programu w języku GLSL/CG - Deklaracje zmiennych globalnych
Properties
{
_MyTexture ("My texture", 2D) = "white" {}
_MyNormalMap ("My normal map", 2D) = "bump" {}
_MyInt ("My integer", Int) = 2
_MyFloat ("My float", Float) = 1.5
_MyRange ("My range", Range(0.0, 1.0)) = 0.5
_MyColor ("My colour", Color) = (1, 0, 0, 1)
_MyVector ("My Vector4", Vector) = (0, 0, 0, 0)
}
SubShader
{
CGPROGRAM
sampler2D _MyTexture, _MyNormalMap;
int _MyInt;
float _MyFloat, _MyRange;
half4 _MyColor;
float4 _MyVector;
ENDCG
}
Aby używać właściwości nie wystarczy zadeklarowanie ich w
sekcji Properties
Wymagana jest deklaracja
zmiennych globalnych do których
zostaną przypisane wartości
nazwy muszą się zgadzać z
nazwami w sekcji Properties
Typy mogą być bardziej
restrykcyjne np. ograniczenie
wektorów do dwóch lub trzech
wymiarów, zmniejszenie
dokładności float’a do half itp.
ShaderLab – sekcja SubShaderKod programu w języku GLSL/CG - Deklaracje struktur danych
#pragma surface surf Lambert
struct Input
{
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = 1; // 1 = (1,1,1,1) = white
}
Istnieje możliwość zdefiniowania struktur danych wejściowych i wyjściowych z
poszczególnych jednostek cieniujących
Surface Shader’y
(https://docs.unity3d.com/Manual/SL-SurfaceShaders.html)
Istnieją trzy struktury danych
wyjściowych:
SurfaceOutput (standard z Unity 4 -
materiały Diffuse lub Specular)
SurfaceOutputStandard i
SurfaceOutputStandard Specular
(standard z Unity 5 – materiały Standard)
ShaderLab – sekcja SubShaderKod programu w języku GLSL/CG - Deklaracje struktur danych cd.
#pragma surface surf Lambert
struct Input
{
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = 1; // 1 = (1,1,1,1) = white
}
Dane wejściowe dla Surface Shader’ów
należy zdefiniować. Mogą zawierać:
Koordynaty tekstury (zmienne
zaczynające się na uv_ lub uv2_)
Interpolowany kolor piksela (zmienna z
wiązaniem : COLOR)
pozycję na ekranie i w świecie
Wektory odbicia i normalne
ShaderLab – sekcja SubShaderKod programu w języku GLSL/CG - Deklaracje struktur danych cd.
#pragma vertex vert
#pragma fragment frag
struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert (float4 vertex : POSITION, float2 uv : TEXCOORD0)
{
v2f o;
o.pos = UnityObjectToClipPos(vertex);
o.uv = uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.uv, 0, 0);
}
Vertex & Fragment Shader’y
Dla tych jednostek cieniujących trzeba
zdefiniować strukturę wejściową i wyjściową
(dla Vertex Shader’a mogą to być parametry
wywołania)
Przypisywanie wartości opiera się na
wiązaniach jak TEXCOORD0, SV_POSITION itp.
(listę dostępnych wiązań można znaleźć w
dokumentacji)
Vertex Shader zwraca strukturę, która jest
wejściem do Fragment Shader’a
Fragment Shader zwraca obliczony kolor
fragmentu (typ fixed4 powiązany z SV_Target)
ShaderLab – sekcja SubShader
Przykłady (Surface Shader)
Simple Diffuse – tylko światło rozposzone
Textured – model z teksturą
Bumped – dodana normal mapa
Rim – poświata dookoła obiektu
Sliced – wycięta część fragmentów
Cubemap – dodane odbicie (z cubemap’y)
Details – dodana druga tekstura z detalami
VertexData – wyświetlenie normalnych
Normals Extrusion – wyciągnięcie modelu wzdłuż normalnych
Snow – efekt pokrywy śnieżnej
Kod programu w języku GLSL/CG - Kod jednostek cieniowania
ShaderLab – sekcja SubShader
Przykłady (Fragment Shader)
VertexLit – tylko tekstura, bez świateł
SolidColor – jednolity kolor
UV – kolory koordynatów tekstury
Vpos – wycięcie szachownicy w modelu
Vface – pokolorowanie front i back face’ów
Vertex1d – przekształcenie współrzędnej w losowe kolory
WrlSpN – wyświetlenie normalnych (globalnych)
Triplanar – tekstura naniesiona z trzech kątów
Kod programu w języku GLSL/CG - Kod jednostek cieniowania cd.
ShaderLab – sekcja SubShader
Przykłady (Fragment Shader)
SkyRefl – odbicie nieba na powierzchni obiektu
ManyTex – wiele tekstur naniesionych na obiekt
ChBoard – wzór szachownicy wygenerowany na obiekcie
Diffuse – światło rozproszone
Ambient – światło otoczenia
ShadCast – rzucanie cienia
ShadRecv – wyświetlenie cieni innych obiektów
Kod programu w języku GLSL/CG - Kod jednostek cieniowania cd.
ShaderLab – sekcja SubShader
Przykłady
Falująca podłoga
Wyciąganie wierzchołków wzdłuż
normalnych zależnie od czasu
Dostępne zmienne:
_Time[4] = {t/20, t, t*2, t*3}
_SinTime[4] = {sin(t/8), sin(t/4), sin(t/2),
sin(t)}
gdzie t to aktualny czas
Zaawansowane – czas w jednostkach cieniujących
ShaderLab – sekcja SubShader
Niektórych efektów nie da się uzyskać za pomocą pojedynczej sekwencji jednostek cieniowania
Z tego powodu wprowadzony został mechanizm przejść (ang. Pass)
Każde kolejne przejście może korzystać z danych wyjściowych poprzedniego przejścia zapisanych w odpowiednich buforach
Przykładem wykorzystania jest użycie predefiniowanego przejścia GrabPass, które zwraca fragment obrazu zasłanianego przez nasz obiekt
Pozwala stworzyć takie materiały jak szkło czy woda
Zaawansowane – programy cieniujące wykorzystujące wiele przejść
Physically based rendering
Model oświetlenia oparty na
właściwościach fizycznych
materiałów
Kosztowniejszy od wcześniejszych
podejść opartych o światło
rozproszone (Diffuse) i odbicia
lustrzane (Specular)
Dający bardziej realistyczne efekty i
więcej możliwości
Unity dostarcza dwie wersje
materiałów: lustrzaną i metaliczną
Physically based rendering
Wersja metaliczna zawiera trzy parametry:
Kolor bazowy materiału
Poziom gładkości
Poziom metaliczności
Wersja metaliczna (metallic)
Physically based rendering
Wersja lustrzana zawiera trzy parametry:
Kolor bazowy materiału
Poziom gładkości
Kolor odbicia lustrzanego
Wersja lustrzana (specular)
Substance (by Allegorithmic)
Alternatywa do pisania
zaawansowanych programów
cieniujących ręcznie – Substance
Designer
Produkt firmy Allegorithmic
pozwalający na tworzenie
materiałów za pomocą łączenia
bloczków
Możliwość eksportu materiału do
silników gier takich jak Unity czy
Unreal Engine 4
Substance (by Allegorithmic)
Na podstawie parametrów
generowane są tekstury oraz
prostszy materiał, który z nich
korzysta
Parametry można modyfikować
w czasie działania aplikacji
(generacja nowej tekstury – może
być kosztowne)
Parametry definiuje się tworząc
„substancję” w Substance
Designer’ze
Przykład materiałów generowanych dynamicznie
Materiały
http://www.alanzucconi.com/2015/06/10/a-gentle-introduction-to-shaders-in-unity3d/
https://docs.unity3d.com/Manual/SL-Reference.html
https://docs.unity3d.com/Manual/GraphicsTutorials.html
http://http.developer.nvidia.com/Cg/
https://blogs.unity3d.com/2015/02/18/working-with-physically-based-shading-a-practical-approach/
https://unity3d.com/learn/tutorials/topics/graphics
https://www.allegorithmic.com/
https://github.com/Podmuch/ShadersOverview.git