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
Матеріали визначають, як має виконуватися рендеринг графічного компонента (component): спрайта, карти плиток, шрифту, вузла GUI, моделі тощо.
Матеріал містить теги — інформацію, яку конвеєр рендерингу використовує для вибору об’єктів, що мають бути відрендерені. Він також містить посилання на шейдерні програми, які компілюються за допомогою доступного графічного драйвера, завантажуються в графічне обладнання та виконуються під час рендерингу компонента в кожному кадрі.
Щоб створити матеріал, клацніть правою кнопкою миші цільову папку в браузері Assets і виберіть New... ▸ Material. (Також можна вибрати в меню File ▸ New..., а потім — Material). Введіть назву нового файлу матеріалу й натисніть Ok.

Новий матеріал відкриється в редакторі Material Editor.

Файл матеріалу містить таку інформацію:
render.enable_material(). Ім’я має бути унікальним..vp), який використовується під час рендерингу з цим матеріалом. Програма вершинного шейдера виконується на GPU для кожної вершини примітивів компонента. Вона обчислює екранну позицію кожної вершини, а також може виводити змінні «varying», які інтерполюються й передаються на вхід фрагментної програми..fp), який використовується під час рендерингу з цим матеріалом. Програма виконується на GPU для кожного фрагмента (пікселя) примітива й визначає колір кожного фрагмента. Зазвичай для цього використовуються вибірки з текстур і обчислення на основі вхідних змінних (змінних varying або констант).render.predicate() використовує для збирання компонентів, що мають малюватися разом. Як це зробити, описано в документації з рендерингу. У проєкті можна використовувати щонайбільше 32 теги.Атрибути шейдера (також відомі як потоки вершин або атрибути вершин) — це механізм, за допомогою якого GPU отримує вершини з пам’яті для рендерингу геометрії. Вершинний шейдер задає набір потоків за допомогою ключового слова attribute, і в більшості випадків Defold автоматично формує та прив’язує дані на основі імен потоків. Однак іноді для досягнення певного ефекту потрібно передавати для кожної вершини додаткові дані, яких рушій не формує. Атрибут вершини можна налаштувати за допомогою таких полів:
SEMANTIC_TYPE_COLOR редактор показуватиме засіб вибору кольору, а дані й далі передаватимуться з рушія до шейдера без змін.
SEMANTIC_TYPE_NONE Типовий семантичний тип. Не впливає на атрибут, окрім передавання даних матеріалу для цього атрибута безпосередньо до буфера вершин (типове значення)SEMANTIC_TYPE_POSITION Формує дані позиції для атрибута кожної вершини. Можна використовувати разом із простором координат, щоб указати рушію, як обчислювати позиціїSEMANTIC_TYPE_TEXCOORD Формує текстурні координати для атрибута кожної вершиниSEMANTIC_TYPE_PAGE_INDEX Формує індекси сторінок для атрибута кожної вершиниSEMANTIC_TYPE_COLOR Впливає на те, як редактор інтерпретує атрибут. Якщо атрибут налаштовано із семантикою кольору, в інспекторі відображатиметься віджет вибору кольоруSEMANTIC_TYPE_NORMAL Формує дані нормалі для атрибута кожної вершиниSEMANTIC_TYPE_TANGENT Формує дані дотичної для атрибута кожної вершиниSEMANTIC_TYPE_WORLD_MATRIX Формує дані світової матриці для атрибута кожної вершиниSEMANTIC_TYPE_NORMAL_MATRIX Формує дані матриці нормалей для атрибута кожної вершиниSEMANTIC_TYPE_TEXTURE_TRANSFORM_2D Формує матрицю трансформації текстури 3x3 для атрибута кожної вершини. Для компонентів частинок рушій надає матрицю, яка перетворює координати в простір атласу для властивості зображення компонента. Для компонентів спрайтів рушій надає матрицю для кожного зображення, яке використовує компонент (за використання кількох текстур). Для компонентів моделей надається одинична матриця.TYPE_BYTE Знакові 8-бітні байтові значенняTYPE_UNSIGNED_BYTE Беззнакові 8-бітні байтові значенняTYPE_SHORT Знакові 16-бітні короткі цілі значенняTYPE_UNSIGNED_SHORT Беззнакові 16-бітні короткі цілі значенняTYPE_INT Знакові цілі значенняTYPE_UNSIGNED_INT Беззнакові цілі значенняTYPE_FLOAT Значення з рухомою крапкою (типове значення)VECTOR_TYPE_SCALAR Одне скалярне значенняVECTOR_TYPE_VEC2 2D-векторVECTOR_TYPE_VEC3 3D-векторVECTOR_TYPE_VEC4 4D-вектор (типове значення)VECTOR_TYPE_MAT2 2D-матрицяVECTOR_TYPE_MAT3 3D-матрицяVECTOR_TYPE_MAT4 4D-матрицяVertex Один раз на вершину: наприклад, атрибут позиції зазвичай передається до вершинної функції для кожної вершини сітки (типове значення)Instance Один раз на екземпляр (instance): наприклад, атрибут світової матриці зазвичай передається до вершинної функції один раз для кожного екземпляраВласні атрибути також можна використовувати для зменшення обсягу пам’яті, зайнятої на CPU та GPU, переналаштувавши потоки на використання меншого типу даних або іншої кількості елементів.
Під час виконання система матеріалів автоматично призначає типовий семантичний тип на основі імені атрибута для певного набору імен:
position — семантичний тип: SEMANTIC_TYPE_POSITIONtexcoord0 — семантичний тип: SEMANTIC_TYPE_TEXCOORDtexcoord1 — семантичний тип: SEMANTIC_TYPE_TEXCOORDpage_index — семантичний тип: SEMANTIC_TYPE_PAGE_INDEXcolor — семантичний тип: SEMANTIC_TYPE_COLORnormal — семантичний тип: SEMANTIC_TYPE_NORMALtangent — семантичний тип: SEMANTIC_TYPE_TANGENTmtx_world — семантичний тип: SEMANTIC_TYPE_WORLD_MATRIXmtx_normal — семантичний тип: SEMANTIC_TYPE_NORMAL_MATRIXmtx_texture_transform_2d — семантичний тип: SEMANTIC_TYPE_TEXTURE_TRANSFORM_2DЯкщо в матеріалі є записи для цих атрибутів, типовий семантичний тип буде перевизначено відповідно до ваших налаштувань у редакторі матеріалів.
Як і визначені користувачем константи шейдера, атрибути вершин можна оновлювати під час виконання за допомогою викликів go.get, go.set і 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)
Однак оновлення атрибутів вершин має певні особливості: чи зможе компонент використати значення, залежить від семантичного типу атрибута. Наприклад, компонент спрайта підтримує SEMANTIC_TYPE_POSITION, тому якщо ви оновите атрибут із цим семантичним типом, компонент ігноруватиме перевизначене значення, адже семантичний тип вимагає завжди формувати дані на основі позиції спрайта.
Компоненти моделей також надають доступ до власних атрибутів матеріалу через go.get(), go.set() і go.animate(). Наприклад, після визначення атрибута з іменем 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)
Наразі в моделі з кількома сітками таким способом можна звертатися лише до першої сітки. Оновлення атрибута, що задається для кожної вершини й не використовує інстансинг, також може призводити до повторного формування та завантаження даних вершин в обсязі, пропорційному розміру сітки, тому часті оновлення можуть бути витратними для великих сіток.
Якщо атрибут вершини є скаляром або вектором іншого типу, ніж Vec4, ви все одно можете задати дані за допомогою go.set:
-- The last two components in the vec4 will not be used!
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)
Те саме стосується матричних атрибутів: якщо атрибут є матрицею іншого типу, ніж Mat4, ви все одно можете задати дані за допомогою go.set.
Використання атрибута трансформації текстури для перетворення UV-координат у простір атласу:
#version 140
in vec3 position;
in vec4 texcoord0;
in mat3 texture_transform_2d;
out vec2 var_texcoord0;
void main()
{
// Extract position from the transform
vec2 atlas_pos = texture_transform_2d[2].xy;
// Extract the scale from the transform
vec2 atlas_size = vec2(
length(texture_transform_2d[0].xy),
length(texture_transform_2d[1].xy)
);
// convert to local UV (0..1)
vec2 localUV = (texcoord0 - atlas_pos) / atlas_size;
// Alternatively, if the UV coordinates already are in the 0..1 range,
// you can transform into atlas space directly by multiplying the transform:
vec2 transformedUv = texture_transform_2d * texcoord0;
// Pass the value into the fragment shader
var_texcoord0 = localUV;
// ... rest of vertex shader
}
Інстансинг (instancing) — це метод ефективного малювання багатьох копій одного об’єкта в сцені. Замість створення окремої копії об’єкта щоразу, коли він використовується, інстансинг дає графічному рушію змогу створити один об’єкт і багаторазово використовувати його. Наприклад, у грі з великим лісом замість окремої моделі для кожного дерева можна створити одну модель дерева й розмістити її сотні або тисячі разів із різними позиціями та масштабами. Тоді ліс можна відрендерити одним викликом малювання замість окремих викликів для кожного дерева.
Наразі інстансинг доступний лише для компонентів Model.
Інстансинг вмикається автоматично, коли це можливо. Defold значною мірою покладається на максимально можливе пакетування стану малювання, тому для роботи інстансингу потрібно дотриматися певних вимог:
render.enable_material)Щоб атрибут вершини повторювався для кожного екземпляра, потрібно встановити для Step function значення Instance. Для певних семантичних типів це робиться автоматично на основі імені (див. таблицю Типова семантика атрибутів вище), але це також можна налаштувати вручну в редакторі матеріалів, установивши для Step function значення Instance.
Як простий приклад, наведена нижче сцена містить чотири ігрові об’єкти (game objects), кожен із компонентом моделі:

Матеріал налаштовано так, що він містить один власний атрибут вершини, який повторюється для кожного екземпляра:

У вершинному шейдері задано кілька атрибутів для кожного екземпляра:
// Per vertex attributes
attribute highp vec4 position;
attribute mediump vec2 texcoord0;
attribute mediump vec3 normal;
// Per instance attributes
attribute mediump mat4 mtx_world;
attribute mediump mat4 mtx_normal;
attribute mediump vec4 instance_color;
Зауважте, що для mtx_world і mtx_normal типово налаштовано функцію кроку Instance. Це можна змінити в редакторі матеріалів: додайте для них записи та встановіть для Step function значення Vertex. Тоді атрибут повторюватиметься для кожної вершини, а не для кожного екземпляра.
Щоб перевірити, чи працює інстансинг у цьому випадку, скористайтеся вебпрофайлером. Оскільки між екземплярами коробки змінюються лише атрибути, задані для кожного екземпляра, їх можна відрендерити одним викликом малювання:

OpenGL 3.1 на настільних платформах і OpenGL ES 3.0 на мобільних надають інстансинг як базову можливість. Старіші контексти OpenGL ES і WebGL можуть підтримувати його через розширення, наприклад ANGLE_instanced_arrays; інші старіші адаптери його не підтримують. Коли інстансинг недоступний, рендеринг типово продовжує працювати, але може бути менш продуктивним.
Використовуйте graphics.get_adapter_info(), щоб виявити підтримку й за потреби вибрати менш витратний матеріал або пропустити вміст із великою кількістю екземплярів. Поле features — це масив констант підтримуваних можливостей, а не таблиця, ключами якої є ці константи:
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
)
Константи шейдера, або uniform-змінні, — це значення, які передаються з рушія до програм вершинного й фрагментного шейдерів. Щоб використовувати константу, визначте її у файлі матеріалу як властивість Vertex Constant або Fragment Constant. У шейдерній програмі потрібно визначити відповідні змінні uniform. У матеріалі можна задати такі константи:
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, у якому .x — час, що минув від запуску рушія, .y — час від попереднього кадру, а .z і .w наразі дорівнюють нулю. Рушій оновлює це значення автоматично; його не потрібно оновлювати за допомогою go.set(). Приклад див. в уроці з Shadertoy.
Оголосіть константу Time з іменем time у сучасному блоці uniform GLSL:
uniform fragment_inputs
{
vec4 time;
};
CONSTANT_TYPE_USERПриклад:
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_MATRIX4Приклад:
go.set("#sprite", "m", vmath.matrix4())
У скрипті GUI читайте та записуйте константи матеріалу вузла за допомогою gui.get() і gui.set() замість функцій go. Підтримуються компоненти векторів, матричні константи та масиви констант. Індекси масиву в таблиці параметрів починаються з 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 })
Щоб константа матеріалу типу CONSTANT_TYPE_USER або CONSTANT_TYPE_USER_MATRIX4 була доступна через go.get() і go.set() або gui.get() і gui.set(), вона має використовуватися в шейдерній програмі. Якщо константу визначено в матеріалі, але не використано в програмі, її буде видалено з матеріалу й вона буде недоступна під час виконання.
Семплери використовуються для вибірки інформації про колір із текстури (джерела плиток або атласу). Цю інформацію потім можна використовувати для обчислень у шейдерній програмі.
Компоненти спрайтів, карт плиток, GUI та ефектів частинок автоматично прив’язують текстуру свого зображення до першого оголошеного sampler2D. Компоненти спрайтів також підтримують кілька текстур: кожен семплер, оголошений у матеріалі, стає іменованим слотом зображення в компоненті Sprite. Перша текстура надає дані анімації спрайта й визначає послідовність кадрів. Для кожного кадру ідентифікатор його зображення використовується для пошуку відповідного зображення в кожній додатковій текстурі, яка надає власні UV-координати. Тому призначені атласи або джерела плиток мають містити відповідні ідентифікатори кадрів і зображення подібної форми; відмінності у формах зображень, упакованих за полігонами, можуть спричинити просочування сусідніх текстур. Докладніше див. у розділі Спрайти з кількома текстурами.
Для компонента або процесу рендерингу, що не надає додаткового слота текстури, використовуйте render.enable_texture(), щоб прив’язати додаткові семплери текстур зі скрипту рендерингу.
![]()
-- mysprite.fp
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D MY_SAMPLER;
void main()
{
gl_FragColor = texture2D(MY_SAMPLER, var_texcoord0.xy);
}
Щоб задати налаштування семплера компонента, додайте семплер за іменем у файл матеріалу. Якщо не налаштувати семплер у файлі матеріалу, використовуватимуться глобальні налаштування проєкту graphics.

Для компонентів моделей потрібно задати семплери з потрібними налаштуваннями у файлі матеріалу. Після цього редактор дасть змогу задати текстури для будь-якого компонента моделі, що використовує цей матеріал:

-- 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, оголошеним у фрагментному шейдері.WRAP_MODE_REPEAT повторює дані текстури поза діапазоном [0,1].WRAP_MODE_MIRRORED_REPEAT повторює дані текстури поза діапазоном [0,1], але кожне друге повторення є дзеркальним.WRAP_MODE_CLAMP_TO_EDGE встановлює для даних текстури зі значеннями понад 1.0 значення 1.0, а для значень менше 0.0 — значення 0.0, тобто крайні пікселі повторюватимуться до межі.Default використовує типовий варіант фільтрації, заданий у файлі game.project у розділі Graphics параметрами Default Texture Min Filter і Default Texture Mag Filter.FILTER_MODE_NEAREST використовує тексель із координатами, найближчими до центра пікселя.FILTER_MODE_LINEAR обчислює зважене лінійне середнє для масиву 2x2 текселів, найближчих до центра пікселя.FILTER_MODE_NEAREST_MIPMAP_NEAREST вибирає значення найближчого текселя в межах окремого mipmap-рівня.FILTER_MODE_NEAREST_MIPMAP_LINEAR вибирає найближчий тексель у двох найближчих відповідних mipmap-рівнях, а потім виконує лінійну інтерполяцію між цими двома значеннями.FILTER_MODE_LINEAR_MIPMAP_NEAREST виконує лінійну інтерполяцію в межах окремого mipmap-рівня.FILTER_MODE_LINEAR_MIPMAP_LINEAR використовує лінійну інтерполяцію для обчислення значення в кожному з двох рівнів, а потім виконує лінійну інтерполяцію між цими двома значеннями.Під час малювання конвеєр рендерингу отримує значення констант із типового системного буфера констант. Ви можете створити власний буфер констант, щоб перевизначити типові константи й задавати uniform-змінні шейдерної програми програмно в скрипті рендерингу:
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 яскраво-червоний колірЗауважте, що до елементів-констант буфера можна звертатися як до звичайної таблиці Lua, але перебирати буфер за допомогою pairs() або ipairs() не можна.