ShaderMaterial - Руководство по Вердж3Д - Софт Эйт Софт
Description: Узнайте как использовать ShaderMaterial в интерактивных 3Д-веб-приложениях сделанных на Вердж3Д

Material →

# ShaderMaterial

Материал, отрисованный с помощью пользовательских шейдеров. Шейдер - это небольшая программа, написанная на языке GLSL, которая выполняется на GPU. При необходимости вы можете использовать пользовательские шейдеры чтобы:

- реализовать эффект, не включенный ни в один из встроенных materials.
- объединять множество объектов в один BufferGeometry для повышения производительности.

При использовании ShaderMaterial следует помнить о следующих моментах:

- Материал `ShaderMaterial` будет правильно отображаться только с помощью WebGLRenderer, поскольку GLSL-код в свойствах vertexShader и fragmentShader свойствах должен быть скомпилирован и запущен на GPU с помощью WebGL.
- Встроенные атрибуты и юниформы передаются шейдерам вместе с вашим кодом. Если вы не хотите, чтобы WebGLProgram добавляла что-либо в ваш код шейдера, вы можете использовать RawShaderMaterial вместо этого класса.
- Вы можете использовать директиву #pragma unroll_loop для того, чтобы развернуть цикл в GLSL препроцессором шейдера. Директива должна быть размещена прямо над циклом. Форматирование цикла должно соответствовать определенному стандарту.
  - Цикл должен быть нормализован.
  - Переменная цикла должна быть валидным идентификатором.
  - Использование переменной цикла должно быть ограничено простой индексацией, например, myVariable[i] или заключено в скобки, например, int counter = (i);.
  - Условие выхода должно быть "<" или "<=".
  - Цикл должен использовать определенное форматирование символов пробела.
  - Поддерживаются встроенные циклы, каждый со своей директивой #pragma. Но GLSL-комментарии с неравными фигурными скобками внутри циклов будут нарушать разворачивание регулярного выражения. `#pragma unroll_loop for (int i = 0; i < 10; i++) { // ... }`

## Пример

`const material = new v3d.ShaderMaterial({ uniforms: { time: { value: 1.0 }, resolution: { value: new v3d.Vector2() } }, vertexShader: document.getElementById('vertexShader').textContent, fragmentShader: document.getElementById('fragmentShader').textContent });`

## Вертексные шейдеры и фрагментные шейдеры

Для каждого материала можно задать два разных типа шейдеров:

- Вертексный шейдер запускается первым; он получает атрибуты, вычисляет / манипулирует положением каждой отдельной вершины и передает дополнительные данные (изменяющиеся) фрагментному шейдеру.
- Фрагментный (или пиксельный) шейдер работает вторым; он задает цвет каждого отдельного "фрагмента" (пикселя), выводимого на экран.

В шейдерах существует три типа переменных: юниформы, атрибуты и вариации:

- Uniforms - это переменные, которые имеют одинаковое значение для всех вершин - освещение, туман, и карты теней являются примерами данных, которые могут храниться в форме. К ним может обращаться как вершинный шейдер, так и шейдер фрагмента.
- Attributes - это переменные, связанные с каждой вершиной - например, положение вершины, нормаль грани и цвет вершины - все это примеры данных, которые хранятся в атрибутах. Доступ к атрибутам возможен только в вертексном шейдере.
- Varyings - это переменные, которые передаются из вертексного шейдера во фрагментный шейдер. Для каждого фрагмента значение каждой вариации будет плавно интерполировано из значений соседних вершин.

Обратите внимание, что в пределах самого шейдера формы и атрибуты действуют как константы; вы можете изменять их значения только путем передачи различных значений в буферы из вашего кода JavaScript.

## Встроенные атрибуты и юниформы

WebGLRenderer по умолчанию предоставляет шейдерам множество атрибутов и форм; определения этих переменных добавляются в ваш код fragmentShader и vertexShader программой WebGLProgram при компиляции шейдера; вам не нужно декларировать их самостоятельно. Подробности об этих переменных см. в WebGLProgram.

Некоторые из этих форм или атрибутов (например, относящиеся к освещению, туману и т.д.) требуют установки свойств на материале, чтобы WebGLRenderer скопировал соответствующие значения на GPU - обязательно установите эти флажки, если вы хотите использовать эти возможности в собственном шейдере.

Если вы не хотите, чтобы WebGLProgram добавлял что-либо в ваш код шейдера, вы можете использовать RawShaderMaterial вместо этого класса.

## Пользовательские атрибуты и юниформы

Как пользовательские атрибуты, так и юниформы должны быть задекларированы в коде шейдера GLSL (в vertexShader и/или fragmentShader). Пользовательские юниформы должны быть определены в свойстве uniforms вашего ShaderMaterial, тогда как любые пользовательские атрибуты должны быть определены через экземпляры BufferAttribute. Обратите внимание, что varying нужно объявлять только в коде шейдера (не в материале).

Чтобы задекларировать пользовательский атрибут, обратитесь к странице BufferGeometry для ознакомления, и странице BufferAttribute для детального рассмотрения API BufferAttribute.

При создании атрибутов каждый массив, который вы создаете для хранения данных атрибута, должен быть кратен размеру вашего типа данных. Например, если ваш атрибут имеет тип v3d.Vector3, и у вас 3000 вершин в массиве BufferGeometry, значение вашего типизированного массива должно быть создано с длиной 3000 * 3, или 9000 (по одному значению на компонент). Таблица размеров каждого типа данных приведена ниже (для справки):

Размеры атрибутов
Тип GLSL | Тип «Ява Скрипта» | Размер
--- | --- | ---
float | Float | 1
vec2 | v3d.Vector2 | 2
vec3 | v3d.Vector3 | 3
vec3 | v3d.Color | 3
vec4 | v3d.Vector4 | 4

Обратите внимание, что буферы атрибутов не обновляются автоматически при изменении их значений. Чтобы обновить пользовательские атрибуты, установите флажок needsUpdate в true на BufferAttribute геометрии (см. подробнее BufferGeometry).

Чтобы объявить пользовательский юниформ, используйте свойство `uniforms`:

`uniforms: { time: { value: 1.0 }, resolution: { value: new v3d.Vector2() } }`

Рекомендуется обновлять пользовательские значения Uniform в зависимости от object и camera в Object3D.onBeforeRender, поскольку Material может быть общим для meshes, matrixWorld из Scene и Camera обновляются в WebGLRenderer.render, а некоторые эффекты рендерят scene со своими частными cameras.

## Конструктор

### ShaderMaterial(parameters : Object)

parameters — (необ.) объект с одним или несколькими свойствами, определяющими внешний вид материала. Сюда можно передать любое свойство материала (включая любое свойство, унаследованное от Material).

## Свойства

Общие свойства см. в базовом классе Material.

### # .clipping : Boolean

Определяет, поддерживает ли этот материал клиппинг; true - позволяет рендереру передавать униформу clippingPlanes. По умолчанию false.

### # .customPrepTokens : Object

Пользовательские маркеры препроцессинга - объект, аналогичный свойству .defines, но вместо добавления директивы #define для каждой пары ключ/значение они вручную заменяются в коде GLSL перед компиляцией шейдера. Используется в директиве #pragma unroll_loop для определения инициализатора цикла и значений условия так же, как и в директиве #define, но поскольку разворачивание выполняется до компиляции, эти значения также должны быть известны заранее, поэтому это свойство является отдельным контейнером для таких значений:

`customPrepTokens: { MAX_SIZE: 10 }`

делает следующий код:

`for (int i = 1; i <= MAX_SIZE; i++) { // ... }`

перед компиляцией:

`for (int i = 1; i <= 10; i++) { // ... }`

### # .defaultAttributeValues : Object

Если отрисованная геометрия не включает эти атрибуты, но материал включает, эти значения по умолчанию будут переданы шейдерам. Это позволяет избежать ошибок при отсутствии данных буфера.

`this.defaultAttributeValues = { 'color': [1, 1, 1], 'uv': [0, 0], 'uv2': [0, 0] };`

### # .defines : Object

Определяет пользовательские константы с помощью директив *#define* в коде GLSL для вертескного шейдера и фрагментного шейдера; каждая пара ключ/значение дает другую директиву:

`defines: { FOO: 15, BAR: true }`

дает линии

`#define FOO 15 #define BAR true`

в коде GLSL.

### # .fog : Boolean

Определяет, влияет ли на цвет материала глобальные настройки тумана; true, чтобы передать шейдеру форму тумана. По умолчанию - false.

### # .fragmentShader : String

Код GLSL шейдера фрагментов. Это фактический код шейдера. В приведенном примере код vertexShader и fragmentShader извлекается из DOM; его можно передать в виде строки напрямую или загрузить через AJAX.

### # .glslVersion : String

Определяет GLSL-версию пользовательского шейдерного кода. Актуально только для WebGL 2, чтобы определить, следует ли указывать GLSL 3.0 или нет. Допустимые значения: `v3d.GLSL1` или `v3d.GLSL3`. По умолчанию `null`.

### # .index0AttributeName : String

Если задано, то вызывается gl.bindAttribLocation чтобы связать общий индекс вершины с переменной атрибута. По умолчанию `undefined`.

### # .isShaderMaterial : Boolean

Флаг, указывающий что данный объект является экземпляром ShaderMaterial. Только для чтения.

### # .lights : Boolean

Определяет, использует ли этот материал освещение; true для передачи данных униформ, связанных с освещением, в этот шейдер. По умолчанию - false.

### # .linewidth : Float

Управляет толщиной вайрфрейма. По умолчанию 1.

Из-за ограничений WebGL на большинстве платформ ширина линии всегда будет равна `1`, независимо от установленного значения.

### # .flatShading : Boolean

Определяет, будет ли материал отображаться с плоским затенением. По умолчанию `false`.

### # .uniforms : Object

Объект вида:

`{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }`

определяет юниформы, которые будут переданы в код шейдера; ключи - имена униформ, значения - определения.

`{ value: 1.0 }`

где value - значение юниформы. Имена должны совпадать с именем формы, как определено в коде GLSL. Обратите внимание, что юниформы обновляются на каждом кадре, поэтому обновление значения юниформы немедленно обновит значение, доступное коду GLSL.

### # .uniformsNeedUpdate : Boolean

Может использоваться для принудительного изменения юниформы при смене юниформы в Object3D.onBeforeRender(). По умолчанию `false`.

### # .vertexColors : Boolean

Определяет, будет ли использоваться раскраска вертексов. По умолчанию `false`.

### # .vertexShader : String

Код вертексного шейдера GLSL. Это фактический код шейдера. В приведенном выше примере, код `vertexShader` и `fragmentShader` извлекается из DOM; он может быть передан в виде строки напрямую или загружаться через AJAX.

### # .wireframe : Boolean

Рендер геометрии виде сетки (используя GL_LINES вместо GL_TRIANGLES). По умолчанию false (т.е. рендеринг в виде плоских полигонов)..

### # .wireframeLinewidth : Float

Управляет толщиной вайрфрейма. По умолчанию 1.

Из-за ограничений WebGL на большинстве платформ ширина линии всегда будет равна `1`, независимо от установленного значения.

## Методы

Общие методы см. в базовом классе Material.

### # .clone() → ShaderMaterial this : ShaderMaterial

Создаёт неглубокую копию этого материала. Обратите внимание, что вертексный и фрагментный шейдеры копируются по ссылке, как и описания атрибутов; это означает, что клоны материала будут иметь одинаковые скомпилированные WebGLProgram. Однако юниформы копируются по значению, что позволяет иметь разные наборы униформов для разных копий материала.

## Исходный файл

О том как получить исходный код этого модуля читайте тут.