# Материалы блоков Материал - общий набор свойств, применяемых к группам блоков. Определения материалов расположены в папке `block_materials/` контент-пака. Блок ссылается на материал свойством `material` в формате `пак:имя_материала` (см. [свойства блоков](block-properties.md)). Пример (`block_materials/glass.json`): ```json { "steps-sound": "steps/glass", "place-sound": "blocks/glass_place", "break-sound": "blocks/glass_break", "sound-absorption": 0.3 } ``` ## Свойства | Имя | Тип | Описание | |------------------|--------|------------------------------------------------------------| | steps-sound | string | звук шагов | | place-sound | string | звук установки блока | | break-sound | string | звук разрушения блока | | hit-sound | string | звук удара по блоку (по умолчанию - `steps-sound`) | | sound-absorption | number | поглощение окружающих звуков, когда камера внутри блока | | shader | string | имя шейдера материала (см. ниже) | ## Шейдеры материалов Шейдер материала позволяет настроить отрисовку блоков и сущностей без замены шейдеров движка. Код шейдера материала включается в мировые шейдеры (проходы непрозрачных, полупрозрачных блоков, теней и программу сущностей), поэтому блоки с разными материалами по-прежнему отрисовываются одним вызовом на чанк. Сущность использует шейдер материала из своего свойства `material` (см. [свойства сущностей](entity-properties.md)). Материал можно переопределить в рантайме через `rig:set_material` (см. [скелет](scripting/ecs.md)). Свойство `shader` указывает имя шейдера, расположенного в папке `shaders/materials/` пака. Каждый из двух файлов опционален, но существующий файл обязан определять свою функцию: - `shaders/materials/имя.glslv` - вершинная стадия, должен определять функцию: ```glsl // position - мировая позиция вершины vec3 material_vertex(vec3 position) ``` Функция также может изменять нормаль вершины `a_realnormal` (мировые координаты), например, при смещении поверхности. - `shaders/materials/имя.glslf` - фрагментная стадия, должен определять функцию: ```glsl // color - цвет текстуры блока до применения освещения vec4 material_fragment(vec4 color) ``` Доступны все uniform-переменные мировых шейдеров (`u_timer`, `u_cameraPos`, `u_dayTime` и т.д.), атрибуты вершин (`v_position`, `v_texCoord`, `v_light`, `v_normal`) в вершинной стадии и varying-переменные (`a_texCoord`, `a_modelpos`, `a_realnormal`, `a_skyLight` и т.д.) во фрагментной. Один и тот же код материала компилируется во все программы (блоки, тени и сущности), поэтому можно использовать только общий интерфейс, объявленный в `shaders/lib/world_vertex_header.glsl`, `world_fragment_header.glsl` и `world_uniforms.glsl`. Параметры шейдера объявляются директивой `#param`, так же, как в [пост-эффектах](scripting/builtins/libgfx-posteffects.md), и управляются из скриптов библиотекой [gfx.materials](scripting/builtins/libgfx-materials.md). Пример (`shaders/materials/leaves.glslv`): ```glsl #param float p_amplitude = 0.03 #param float p_speed = 1.2 vec3 material_vertex(vec3 position) { float phase = position.x * 0.7 + position.z * 1.1 + position.y * 0.4; position.x += sin(u_timer * p_speed + phase) * p_amplitude; return position; } ``` Материалы с одинаковым `shader` используют общий код шейдера и его параметры. Имена функций-хуков и параметров автоматически делаются уникальными для каждого шейдера, поэтому разные шейдеры могут объявлять одинаковые параметры. Остальные функции и глобальные переменные всех шейдеров материалов компилируются в одну программу, поэтому их имена должны быть уникальными (используйте префикс). > [!NOTE] > Ошибки компиляции ссылаются на шейдер материала по его номеру: `3:12` означает строку 12 > шейдера номер 3. Номера печатаются в лог при загрузке контента, > `128` это сгенерированный код диспетчера, `0` шейдер движка. Ограничения: - одновременно может быть загружено до 127 шейдеров материалов - параметры-массивы не поддерживаются, имена параметров не могут начинаться с `_` - один и тот же параметр в обеих стадиях должен иметь одинаковый тип - смещение вершин должно быть непрерывным (зависеть только от позиции вершины), иначе между гранями появляются щели; оно не должно зависеть от `u_cameraPos`, так как проход теней рисуется с точки зрения источника света - у вызовов `texture()` внутри `material_fragment` не определены производные на границах материалов, используйте там `textureLod`