This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Materiały służą do określania, jak powinien być renderowany komponent graficzny (sprite, mapa kafelków, font, węzeł GUI, model itd.).
Materiał przechowuje tagi, czyli informacje używane w potoku renderowania do wyboru obiektów, które mają zostać wyrenderowane. Zawiera też odwołania do programów shaderów, które są kompilowane przez dostępny sterownik graficzny, wgrywane do sprzętu graficznego i wykonywane za każdym razem, gdy komponent jest renderowany w danej klatce.
Aby utworzyć materiał, right click docelowy folder w przeglądarce Assets i wybierz New... ▸ Material. (Możesz też wybrać File ▸ New... z menu, a następnie Material). Nadaj nowemu plikowi materiału nazwę i naciśnij Ok.

Nowy materiał otworzy się w Material Editor.

Plik materiału zawiera następujące informacje:
render.enable_material(). Nazwa powinna być unikalna..vp) używany podczas renderowania z tym materiałem. Program shadera wierzchołków działa na GPU dla każdego wierzchołka prymitywu komponentu. Oblicza pozycję każdego wierzchołka na ekranie i opcjonalnie generuje też zmienne „varying”, które są interpolowane i przekazywane do programu fragmentów..fp) używany podczas renderowania z tym materiałem. Program działa na GPU dla każdego fragmentu (piksela) prymitywu i służy do określenia koloru każdego fragmentu. Zwykle robi się to przez odczyty tekstur i obliczenia oparte na zmiennych wejściowych (zmiennych varying albo stałych).render.predicate() korzysta do zbierania komponentów, które powinny zostać narysowane razem. Więcej informacji o tym, jak to zrobić, znajdziesz w dokumentacji renderowania. Maksymalna liczba tagów, których możesz użyć w projekcie, to 32.Atrybuty shadera (nazywane też strumieniami wierzchołków albo atrybutami wierzchołków) to mechanizm, dzięki któremu GPU pobiera wierzchołki z pamięci, aby renderować geometrię. Program shadera wierzchołków określa zestaw strumieni za pomocą słowa kluczowego attribute i w większości przypadków Defold tworzy oraz wiąże dane automatycznie w tle na podstawie nazw strumieni. Zdarza się jednak, że chcesz przekazać więcej danych na wierzchołek, aby uzyskać konkretny efekt, którego silnik sam nie produkuje. Atrybut wierzchołka można skonfigurować za pomocą następujących pól:
SEMANTIC_TYPE_COLOR spowoduje, że w edytorze pojawi się wybierak koloru, a dane nadal będą przekazywane bez zmian z silnika do shadera.
SEMANTIC_TYPE_NONE Domyślny typ semantyczny. Nie ma żadnego innego wpływu na atrybut poza bezpośrednim przekazaniem danych materiału dla tego atrybutu do bufora wierzchołków (domyślnie)SEMANTIC_TYPE_POSITION Generuje dane pozycji dla atrybutu na poziomie wierzchołka. Można go łączyć z przestrzenią współrzędnych, aby określić silnikowi sposób obliczania pozycjiSEMANTIC_TYPE_TEXCOORD Generuje współrzędne tekstury dla atrybutu na poziomie wierzchołkaSEMANTIC_TYPE_PAGE_INDEX Generuje indeksy stron dla atrybutu na poziomie wierzchołkaSEMANTIC_TYPE_COLOR Wpływa na sposób interpretacji atrybutu przez edytor. Jeśli atrybut ma semantykę koloru, w inspektorze pojawi się widżet wyboru koloruSEMANTIC_TYPE_NORMAL Generuje dane normalnej dla atrybutu na poziomie wierzchołkaSEMANTIC_TYPE_TANGENT Generuje dane stycznej dla atrybutu na poziomie wierzchołkaSEMANTIC_TYPE_WORLD_MATRIX Generuje dane macierzy świata dla atrybutu na poziomie wierzchołkaSEMANTIC_TYPE_NORMAL_MATRIX Generuje dane macierzy normalnych dla atrybutu na poziomie wierzchołkaSEMANTIC_TYPE_TEXTURE_TRANSFORM_2D Generuje dla atrybutu macierz transformacji tekstury 3x3 na wierzchołek. Dla komponentów particle engine udostępnia macierz, która transformuje współrzędne do przestrzeni atlasu dla właściwości obrazu komponentu. Dla komponentów sprite engine udostępnia macierz dla każdego obrazu używanego przez komponent (przy użyciu wielu tekstur). Dla komponentów modelu udostępniana jest macierz jednostkowa.TYPE_BYTE Wartości 8-bitowe ze znakiemTYPE_UNSIGNED_BYTE Wartości 8-bitowe bez znakuTYPE_SHORT Wartości 16-bitowe ze znakiemTYPE_UNSIGNED_SHORT Wartości 16-bitowe bez znakuTYPE_INT Wartości całkowite ze znakiemTYPE_UNSIGNED_INT Wartości całkowite bez znakuTYPE_FLOAT Wartości zmiennoprzecinkowe (domyślnie)VECTOR_TYPE_SCALAR Pojedyncza wartość skalarnaVECTOR_TYPE_VEC2 Wektor 2DVECTOR_TYPE_VEC3 Wektor 3DVECTOR_TYPE_VEC4 Wektor 4D (domyślnie)VECTOR_TYPE_MAT2 Macierz 2DVECTOR_TYPE_MAT3 Macierz 3DVECTOR_TYPE_MAT4 Macierz 4DVertex Raz na wierzchołek, np. atrybut pozycji zwykle jest przekazywany do funkcji wierzchołków dla każdego wierzchołka w siatce (domyślnie)Instance Raz na instancję, np. atrybut macierzy świata zwykle jest przekazywany do funkcji wierzchołków raz na instancjęWłasne atrybuty można też wykorzystać do zmniejszenia zużycia pamięci po stronie CPU i GPU, przestawiając strumienie na mniejszy typ danych albo inną liczbę elementów.
System materiałów automatycznie przypisze domyślny typ semantyczny na podstawie nazwy atrybutu w czasie działania dla następującego zestawu nazw:
position - semantic type: SEMANTIC_TYPE_POSITIONtexcoord0 - semantic type: SEMANTIC_TYPE_TEXCOORDtexcoord1 - semantic type: SEMANTIC_TYPE_TEXCOORDpage_index - semantic type: SEMANTIC_TYPE_PAGE_INDEXcolor - semantic type: SEMANTIC_TYPE_COLORnormal - semantic type: SEMANTIC_TYPE_NORMALtangent - semantic type: SEMANTIC_TYPE_TANGENTmtx_world - semantic type: SEMANTIC_TYPE_WORLD_MATRIXmtx_normal - semantic type: SEMANTIC_TYPE_NORMAL_MATRIXmtx_texture_transform_2d - semantic type: SEMANTIC_TYPE_TEXTURE_TRANSFORM_2DJeśli w materiale masz wpisy dla tych atrybutów, domyślny typ semantyczny zostanie zastąpiony tym, który skonfigurowałeś w Material Editor.
Podobnie jak w przypadku stałych shaderów zdefiniowanych przez użytkownika, możesz też aktualizować atrybuty wierzchołków w czasie działania, wywołując go.get(), go.set() i go.animate():

go.set("#sprite", "tint", vmath.vector4(1,0,0,1))
go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2)
Aktualizowanie atrybutów wierzchołków ma jednak pewne ograniczenia. To, czy komponent może użyć danej wartości, zależy od typu semantycznego atrybutu. Na przykład komponent sprite obsługuje SEMANTIC_TYPE_POSITION, więc jeśli zaktualizujesz atrybut mający ten typ semantyczny, komponent zignoruje nadpisaną wartość, ponieważ typ semantyczny określa, że dane powinny być zawsze generowane przez pozycję sprite’a.
Komponenty Model również udostępniają niestandardowe atrybuty materiału przez go.get(), go.set() i go.animate(). Na przykład po zdefiniowaniu w materiale modelu atrybutu o nazwie my_attribute:
go.set("#model", "my_attribute", vmath.vector4(1, 0, 0, 1))
go.animate("#model", "my_attribute", go.PLAYBACK_LOOP_PINGPONG,
vmath.vector4(0, 1, 0, 1), go.EASING_LINEAR, 2)
W ten sposób można obecnie adresować tylko pierwszą siatkę modelu zawierającego wiele siatek. Aktualizacja nieinstancjonowanego atrybutu przypisanego do wierzchołków może również przebudować i przesłać dane wierzchołków proporcjonalne do rozmiaru siatki, dlatego częste aktualizacje mogą być kosztowne dla dużych siatek.
W przypadkach, gdy atrybut wierzchołka jest skalarem albo wektorem innym niż Vec4, nadal możesz ustawić dane za pomocą go.set:
-- Ostatnie dwa komponenty wektora vec4 nie będą używane!
go.set("#sprite", "sprite_position_2d", vmath.vector4(my_x,my_y,0,0))
go.animate("#sprite", "sprite_position_2d", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,2,0,0), go.EASING_LINEAR, 2)
To samo dotyczy atrybutów macierzowych. Jeśli atrybut jest macierzą inną niż Mat4, nadal możesz ustawić dane za pomocą go.set.
Użycie atrybutu transformacji tekstury do konwersji współrzędnych UV do przestrzeni atlasu:
#version 140
in vec3 position;
in vec4 texcoord0;
in mat3 texture_transform_2d;
out vec2 var_texcoord0;
void main()
{
// Wyodrębnij pozycję z transformacji
vec2 atlas_pos = texture_transform_2d[2].xy;
// Wyodrębnij skalę z transformacji
vec2 atlas_size = vec2(
length(texture_transform_2d[0].xy),
length(texture_transform_2d[1].xy)
);
// konwersja do lokalnych UV (0..1)
vec2 localUV = (texcoord0.xy - atlas_pos) / atlas_size;
// Alternatywnie, jeśli współrzędne UV są już w zakresie 0..1,
// możesz przekształcić je bezpośrednio do przestrzeni atlasu,
// mnożąc przez transformację:
vec2 transformedUv = (texture_transform_2d * vec3(texcoord0.xy, 1.0)).xy;
// Przekaż wartość do shadera fragmentów
var_texcoord0 = localUV;
// ... reszta shadera wierzchołków
}
Instancjonowanie (instancing) to technika używana do wydajnego rysowania wielu kopii tego samego obiektu w scenie. Zamiast tworzyć osobną kopię obiektu za każdym razem, gdy jest używany, instancjonowanie pozwala silnikowi graficznemu utworzyć jeden obiekt, a następnie wielokrotnie go wykorzystywać. Na przykład w grze z dużym lasem, zamiast tworzyć osobny model drzewa dla każdego drzewa, instancjonowanie pozwala utworzyć jeden model drzewa i umieścić go setki lub tysiące razy w różnych pozycjach i skalach. Las można wtedy wyrenderować jednym wywołaniem rysowania zamiast osobnymi wywołaniami dla każdego drzewa.
Instancing jest obecnie dostępny tylko dla komponentów Model.
Instancing jest włączane automatycznie, gdy to możliwe. Defold mocno opiera się na batchowaniu stanu rysowania tak bardzo, jak to możliwe - aby instancing działał, muszą być spełnione pewne wymagania:
render.enable_material()Aby skonfigurować atrybut wierzchołka tak, żeby był powtarzany dla każdej instancji, trzeba ustawić Step function na Instance. Dla niektórych typów semantycznych dzieje się to automatycznie na podstawie nazwy (zobacz tabelę Default attribute semantics powyżej), ale można też ustawić to ręcznie w edytorze materiałów, ustawiając Step function na Instance.
W prostym przykładzie poniższa scena ma cztery obiekty gry, każdy z komponentem modelu:

Materiał jest skonfigurowany w ten sposób, z jednym własnym atrybutem wierzchołka, który jest powtarzany dla każdej instancji:

Program shadera wierzchołków ma zdefiniowanych kilka atrybutów per instancję:
// Atrybuty per wierzchołek
attribute highp vec4 position;
attribute mediump vec2 texcoord0;
attribute mediump vec3 normal;
// Atrybuty per instancja
attribute mediump mat4 mtx_world;
attribute mediump mat4 mtx_normal;
attribute mediump vec4 instance_color;
Zwróć uwagę, że mtx_world i mtx_normal będą domyślnie skonfigurowane do używania funkcji kroku Instance. Można to zmienić w edytorze materiałów, dodając dla nich wpis i ustawiając Step function na Vertex, co sprawi, że atrybut będzie powtarzany dla każdego wierzchołka zamiast dla każdej instancji.
Aby sprawdzić, czy instancing działa w tym przypadku, możesz zajrzeć do web profiler. Ponieważ jedyną rzeczą, która różni się między instancjami pudełka, są atrybuty per instancję, całość można wyrenderować jednym wywołaniem rysowania:

OpenGL 3.1 na komputerach i OpenGL ES 3.0 na urządzeniach mobilnych udostępniają instancing jako funkcję podstawową. Starsze konteksty OpenGL ES i WebGL mogą nadal obsługiwać go przez rozszerzenie, takie jak ANGLE_instanced_arrays; inne starsze adaptery go nie obsługują. Gdy instancing jest niedostępny, renderowanie domyślnie nadal działa, ale może być mniej wydajne.
Użyj graphics.get_adapter_info(), aby wykryć obsługę i w razie potrzeby wybrać tańszy materiał albo pominąć zawartość intensywnie korzystającą z instancji. Pole features jest tablicą obsługiwanych stałych funkcji, a nie tabelą indeksowaną tymi stałymi:
local function has_context_feature(feature)
local adapter_info = graphics.get_adapter_info()
for _, supported_feature in ipairs(adapter_info.features) do
if supported_feature == feature then
return true
end
end
return false
end
local instancing_supported = has_context_feature(
graphics.CONTEXT_FEATURE_INSTANCING
)
Stałe shaderów, czyli “uniformy”, to wartości przekazywane z silnika do programów shaderów wierzchołków i fragmentów. Aby użyć stałej, definiujesz ją w pliku materiału jako właściwość Vertex Constant albo Fragment Constant. Odpowiadające im zmienne uniform muszą zostać zdefiniowane w programie shadera. W materiale można ustawić następujące stałe:
CONSTANT_TYPE_WORLDCONSTANT_TYPE_VIEWCONSTANT_TYPE_PROJECTIONCONSTANT_TYPE_VIEWPROJCONSTANT_TYPE_WORLDVIEWCONSTANT_TYPE_WORLDVIEWPROJCONSTANT_TYPE_WORLD_INVERSECONSTANT_TYPE_VIEW_INVERSECONSTANT_TYPE_PROJECTION_INVERSECONSTANT_TYPE_VIEWPROJ_INVERSECONSTANT_TYPE_WORLDVIEW_INVERSECONSTANT_TYPE_WORLDVIEWPROJ_INVERSECONSTANT_TYPE_NORMALCONSTANT_TYPE_TIMEvector4 dostarczany przez silnik, w którym .x jest czasem od uruchomienia silnika, .y czasem delta od poprzedniej klatki, a .z i .w mają obecnie wartość zero. Silnik aktualizuje tę wartość automatycznie; nie trzeba jej aktualizować za pomocą go.set(). Przykład znajdziesz w tutorialu Shadertoy.
Zadeklaruj stałą Time o nazwie time w nowoczesnym bloku uniformów GLSL:
uniform fragment_inputs
{
vec4 time;
};
CONSTANT_TYPE_USERPrzykład:
go.set("#sprite", "tint", vmath.vector4(1,0,0,1))
go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2)
CONSTANT_TYPE_USER_MATRIX4Przykład:
go.set("#sprite", "m", vmath.matrix4())
W skrypcie GUI odczytuj i zapisuj stałe materiału węzła za pomocą gui.get() i gui.set(), a nie funkcji go. Obsługiwane są składowe wektorów, stałe macierzowe i tablice stałych. Indeksy tablic w tabeli opcji zaczynają się od 1:
local node = gui.get_node("button")
local tint = gui.get(node, "tint")
gui.set(node, "tint.x", 0.5)
gui.set(node, "light_matrix", vmath.matrix4())
gui.set(node, "tint_array", vmath.vector4(1, 0, 0, 1), { index = 1 })
Aby stała materiału typu CONSTANT_TYPE_USER albo CONSTANT_TYPE_USER_MATRIX4 była dostępna przez go.get() i go.set() lub gui.get() i gui.set(), musi być używana w programie shadera. Jeśli stała jest zdefiniowana w materiale, ale nie jest używana w programie, zostanie usunięta z materiału i nie będzie dostępna w czasie działania.
Samplery służą do pobierania informacji o kolorze z tekstury (źródła kafelków lub atlasu). Informacje o kolorze można następnie wykorzystać do obliczeń w programie shadera.
Komponenty sprite, tilemap, GUI i efektów cząsteczkowych automatycznie wiążą swoją teksturę obrazu z pierwszym zadeklarowanym sampler2D. Komponenty sprite obsługują również wiele tekstur: każdy sampler zadeklarowany w materiale staje się nazwanym slotem obrazu w komponencie Sprite. Pierwsza tekstura dostarcza danych animacji sprite’a i steruje kolejnością klatek. W każdej klatce jej identyfikator obrazu służy do znalezienia odpowiadającego obrazu w każdej dodatkowej teksturze, która dostarcza własne współrzędne UV. Przypisane atlasy lub źródła kafelków powinny więc zawierać zgodne identyfikatory klatek i obrazy o podobnym kształcie; różniące się kształty spakowanych wielokątów mogą powodować przenikanie tekstur. Szczegóły opisano w sekcji Sprite’y z wieloma teksturami.
W przypadku komponentu lub przepływu renderowania, który nie udostępnia dodatkowego slotu tekstury, użyj render.enable_texture(), aby powiązać dodatkowe samplery tekstur ze skryptu renderowania.
![]()
-- mysprite.fp
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D MY_SAMPLER;
void main()
{
gl_FragColor = texture2D(MY_SAMPLER, var_texcoord0.xy);
}
Ustawienia samplera komponentu możesz określić, dodając sampler po nazwie w pliku materiału. Jeśli nie skonfigurujesz samplera w pliku materiału, zostaną użyte globalne ustawienia projektu Graphics.

Dla komponentów modelu musisz określić samplery w pliku materiału z ustawieniami, jakie chcesz. Edytor pozwoli wtedy ustawić tekstury dla dowolnego komponentu modelu, który używa tego materiału:

-- mymodel.fp
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D TEXTURE_1;
uniform lowp sampler2D TEXTURE_2;
void main()
{
lowp vec4 color1 = texture2D(TEXTURE_1, var_texcoord0.xy);
lowp vec4 color2 = texture2D(TEXTURE_2, var_texcoord0.xy);
gl_FragColor = color1 * color2;
}

sampler2D zadeklarowanego w shaderze fragmentów.WRAP_MODE_REPEAT powtórzy dane tekstury poza zakresem [0,1].WRAP_MODE_MIRRORED_REPEAT powtórzy dane tekstury poza zakresem [0,1], ale co drugie powtórzenie będzie odbite lustrzanie.WRAP_MODE_CLAMP_TO_EDGE ustawi dane tekstury dla wartości większych niż 1.0 na 1.0, a wszystkie wartości mniejsze niż 0.0 na 0.0, czyli piksele krawędzi zostaną powtórzone do brzegu.Default używa domyślnej opcji filtra określonej w pliku game.project w sekcji Graphics jako Default Texture Min Filter i Default Texture Mag Filter.FILTER_MODE_NEAREST używa texela o współrzędnych najbliższych środkowi piksela.FILTER_MODE_LINEAR ustawia ważoną średnią liniową z układu 2x2 texeli położonych najbliżej środka piksela.FILTER_MODE_NEAREST_MIPMAP_NEAREST wybiera wartość najbliższego texela w pojedynczym mipmapie.FILTER_MODE_NEAREST_MIPMAP_LINEAR wybiera najbliższy texel z dwóch najlepszych najbliższych mipmap, a następnie interpoluje liniowo między tymi dwoma wartościami.FILTER_MODE_LINEAR_MIPMAP_NEAREST interpoluje liniowo wewnątrz pojedynczego mipmapa.FILTER_MODE_LINEAR_MIPMAP_LINEAR używa interpolacji liniowej do obliczenia wartości w każdej z dwóch map, a następnie interpoluje liniowo między tymi dwiema wartościami.Gdy potok renderowania rysuje, pobiera wartości stałych z domyślnego systemowego bufora stałych. Możesz utworzyć własny bufor stałych, aby nadpisać wartości domyślne i zamiast tego ustawiać uniformy programów shaderów programowo w skrypcie do renderowania:
self.constants = render.constant_buffer() -- <1>
self.constants.tint = vmath.vector4(1, 0, 0, 1) -- <2>
...
render.draw(self.my_pred, {constants = self.constants}) -- <3>
tint na jaskrawą czerwieńZwróć uwagę, że elementy stałych w buforze są odwoływane jak zwykła tabela Lua, ale nie można iterować po buforze za pomocą pairs() ani ipairs().