add block material shaders

- 'shader' property of block materials: shaders/materials/<name>.glslv, .glslf with material_vertex / material_fragment hooks and #param uniforms
- material shaders code is included into main, translucent and shadows programs through generated headers, no extra draw calls
- chunk vertex normal.w byte replaced with 'flags': bit 7 - emission flag, bits 0-6 - material shader index (vertex format size is not changed)
- doc/*/block-materials.md
This commit is contained in:
lookibed 2026-10-02 06:33:01 +03:00
parent f90750c066
commit 81489a13cf
33 changed files with 761 additions and 53 deletions

97
doc/ru/block-materials.md Normal file
View file

@ -0,0 +1,97 @@
# Материалы блоков
Материал - общий набор свойств, применяемых к группам блоков.
Определения материалов расположены в папке `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`

View file

@ -82,7 +82,7 @@
### Материал - *material*
Определяет имя материала блока в формате `пак:имя_материала`, что влияет на выбор звуков взаимодействия с блоком.
Определения материалов расположены в /block_materials.
Определения материалов расположены в /block_materials (см. [материалы блоков](block-materials.md)).
## Варианты

View file

@ -91,6 +91,7 @@ print(file.read("пак:package.json")) -- выведет содержимое p
- `textures/` - текстуры
- `shaders/` - шейдеры
- `effects/` - эффекты пост-обработки
- `materials/` - шейдеры материалов блоков
- `sounds/` - звуки и музыка
- `texts/` - файлы локализации
- GUI:

View file

@ -11,6 +11,7 @@
- [Движок генерации мира](world-generator.md)
- [Консоль](console.md)
- [Контент‐паки](content-packs.md)
- [Материалы блоков](block-materials.md)
- [Модели блоков](block-models.md)
- [Предзагрузка ассетов](assets-preload.md)
- [Рекомендации по использованию движка](engine-use-recommendations.md)