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

Новый материал откроется в Material Editor.

Файл материала содержит следующую информацию:
render.enable_material(). Имя должно быть уникальным..vp), используемый при рендеринге с этим материалом. Программа выполняется на GPU для каждой вершины примитива компонента. Она вычисляет положение вершины на экране и может также передавать “изменяемые” переменные, которые интерполируются и подаются на вход фрагментной программе..fp), используемый при рендеринге с этим материалом. Программа запускается на GPU для каждого фрагмента (пикселя) примитива и определяет цвет этого фрагмента. Обычно это достигается путем выборки из текстуры и вычислений на основе входящих данных (переменные или константы).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 на вершину. Для particle-компонентов движок предоставляет матрицу, которая преобразует координаты в пространство атласа для свойства image компонента. Для sprite-компонентов движок предоставляет матрицу для каждого изображения, используемого компонентом (при использовании multi-texturing). Для model-компонентов предоставляется единичная матрица.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 — вектор из 2 элементовVECTOR_TYPE_VEC3 — вектор из 3 элементовVECTOR_TYPE_VEC4 — вектор из 4 элементов (по умолчанию)VECTOR_TYPE_MAT2 — матрица 2x2VECTOR_TYPE_MAT3 — матрица 3x3VECTOR_TYPE_MAT4 — матрица 4x4Vertex — один раз на вершину (по умолчанию)Instance — один раз на экземпляр, например для мировых матрицПереопределение конфигурации атрибутов позволяет уменьшить объем данных и снизить нагрузку на память CPU и GPU.
Система материалов автоматически присваивает семантику атрибутам по их именам во время исполнения:
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_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, и если вы попытаетесь переопределить атрибут с этой семантикой, то компонент проигнорирует новое значение, поскольку семантика требует, чтобы данные всегда исходили от позиции спрайта.
Компоненты Model также предоставляют доступ к пользовательским атрибутам материала через 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:
-- Последние два компонента vec4 не будут использоваться!
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()
{
// Извлечь позицию из преобразования
vec2 atlas_pos = texture_transform_2d[2].xy;
// Извлечь масштаб из преобразования
vec2 atlas_size = vec2(
length(texture_transform_2d[0].xy),
length(texture_transform_2d[1].xy)
);
// Преобразовать в локальные UV (0..1)
vec2 localUV = (texcoord0 - atlas_pos) / atlas_size;
// Альтернативно, если UV-координаты уже находятся в диапазоне 0..1,
// можно напрямую преобразовать их в пространство атласа, умножив на матрицу:
vec2 transformedUv = texture_transform_2d * texcoord0;
// Передать значение во фрагментный шейдер
var_texcoord0 = localUV;
// ... оставшаяся часть вершинного шейдера
}
Инстансинг — это техника, используемая для эффективной отрисовки множества копий одного и того же объекта на сцене. Вместо создания отдельной копии объекта каждый раз, инстансинг позволяет движку использовать одну модель и переиспользовать её многократно. Например, в игре с большим лесом вместо того, чтобы создавать отдельную модель дерева для каждого дерева, можно создать одну модель и размещать её сотни или тысячи раз с разными позициями и масштабом. Таким образом, весь лес может быть отрисован одним вызовом отрисовки, а не отдельными вызовами для каждого дерева.
Инстансинг на данный момент доступен только для компонентов типа Model.
Инстансинг включается автоматически, если соблюдены необходимые условия. Defold активно использует пакетирование состояния отрисовки — чтобы инстансинг работал, необходимо соблюдение следующих требований:
render.enable_material()Чтобы указать, что атрибут должен повторяться на каждый экземпляр, установите для него Step function в Instance. Это делается автоматически для некоторых семантик по имени (см. таблицу Default attribute semantics), но также может быть установлено вручную в редакторе материалов, задав Step function как Instance.
Простой пример: сцена с четырьмя игровыми объектами, у каждого из которых есть компонент-модель:

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

Вершинный шейдер использует несколько атрибутов, повторяющихся на каждый экземпляр:
// Атрибуты на вершину
attribute highp vec4 position;
attribute mediump vec2 texcoord0;
attribute mediump vec3 normal;
// Атрибуты на экземпляр
attribute mediump mat4 mtx_world;
attribute mediump mat4 mtx_normal;
attribute mediump vec4 instance_color;
Обратите внимание, что mtx_world и mtx_normal по умолчанию будут использовать step function 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(), она должна использоваться в программе шейдера. Если константа определена в материале, но не используется в программе, она будет удалена из материала и станет недоступной во время выполнения.
Сэмплеры используются для отбора цветовой информации из текстуры (тайловый источник или атлас). Цветовая информация может далее быть использована для вычислений в программе шейдера.
Компоненты Sprite, Tile Map, GUI и Particle FX автоматически привязывают текстуру изображения к первому объявленному sampler2D. Компоненты Sprite также поддерживают несколько текстур: каждый сэмплер, объявленный в материале, становится именованным слотом изображения в компоненте 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 – выбирает ближайшее значение текселя в отдельной MIP-карте.FILTER_MODE_NEAREST_MIPMAP_LINEAR – выбирает ближайший тексель из двух ближайших лучших вариантов MIP-карт и затем линейно интерполирует между этими двумя значениями.FILTER_MODE_LINEAR_MIPMAP_NEAREST – линейное интерполирование в пределах отдельной MIP-карты.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, self.constants) -- <3>
tint в ярко-красныйУчтите, что элементы констант буфера ссылаются как обычная Lua таблица, но вы не можете итерироваться по буферу с помощью вызовов pairs() или ipairs().