Материал, отрисованный с помощью пользовательских шейдеров. Шейдер - это небольшая программа, написанная на языке [ссылка:https://www.khronos.org/files/opengles_shading_language.pdf GLSL], которая выполняется на GPU. При необходимости вы можете использовать пользовательские шейдеры чтобы:
#pragma unroll_loop_start
for (int i = 0; i < 10; i++) {
// ...
}
#pragma unroll_loop_end
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
});
Для каждого материала можно задать два разных типа шейдеров:
В шейдерах существует три типа переменных: форма, атрибуты и вариации:
Обратите внимание, что в пределах самого шейдера формы и атрибуты действуют как константы; вы можете изменять их значения только путем передачи различных значений в буферы из вашего кода 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 type | JavaScript type | Size |
---|---|---|
float | Number | 1 |
vec2 | v3d.Vector2 | 2 |
vec3 | v3d.Vector3 | 3 |
vec3 | v3d.Color | 3 |
vec4 | v3d.Vector4 | 4 |
Обратите внимание, что буферы атрибутов не обновляются автоматически при изменении их значений. Чтобы обновить пользовательские атрибуты, установите флажок needsUpdate в true на BufferAttribute геометрии (см. подробнее BufferGeometry).
Чтобы задекларировать пользовательскую Uniform, используйте свойство 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.
parameters — (опционально) объект с одним или несколькими свойствами, определяющими внешний вид материала. Сюда можно передать любое свойство материала (включая любое свойство, унаследованное от Material).
Общие свойства см. в базовом классе Material.
Определяет, поддерживает ли этот материал клиппинг; true - позволяет рендереру передавать униформу clippingPlanes. По умолчанию false.
Пользовательские маркеры препроцессинга - объект, аналогичный свойству .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++) {
// ...
}
Если отрисованная геометрия не включает эти атрибуты, но материал включает, эти значения по умолчанию будут переданы шейдерам. Это позволяет избежать ошибок при отсутствии данных буфера.
this.defaultAttributeValues = {
'color': [1, 1, 1],
'uv': [0, 0],
'uv2': [0, 0]
};
Определяет пользовательские константы с помощью директив *#define* в коде GLSL для вертескного шейдера и фрагментного шейдера; каждая пара ключ/значение дает другую директиву:
defines: {
FOO: 15,
BAR: true
}
дает линии
#define FOO 15
#define BAR true
в коде GLSL.
Объект со следующими свойствами:
this.extensions = {
derivatives: false, // set to use derivatives
fragDepth: false, // set to use fragment depth values
drawBuffers: false, // set to use draw buffers
shaderTextureLOD: false // set to use shader texture LOD
};
Определяет, влияет ли на цвет материала глобальные настройки тумана; true, чтобы передать шейдеру форму тумана. По умолчанию - false.
Код GLSL шейдера фрагментов. Это фактический код шейдера. В приведенном примере код vertexShader и fragmentShader извлекается из DOM; его можно передать в виде строки напрямую или загрузить через AJAX.
Определяет GLSL-версию пользовательского шейдерного кода. Актуально только для WebGL 2, чтобы определить, следует ли указывать GLSL 3.0 или нет. Допустимые значения: v3d.GLSL1 или v3d.GLSL3. По умолчанию null.
Если задано, то вызывается gl.bindAttribLocation чтобы связать общий индекс вершины с переменной атрибута. По умолчанию не определено.
Определяет, использует ли этот материал освещение; true для передачи данных униформ, связанных с освещением, в этот шейдер. По умолчанию - false.
Управляет толщиной вайрфрейма. По умолчанию 1.
Из-за ограничений OpenGL Core Profile
с WebGL рендерером на большинстве платформ ширина линии всегда будет равна 1, независимо от установленного значения.
Если установлено значение true, атрибуты morph target доступны в вертексном шейдере. По умолчанию false.
Если установлено значение true, атрибуты morph normal доступны в вертексном шейдере. По умолчанию false.
Определяет, будет ли материал отображаться с плоским затенением. По умолчанию false.
Определяет, использует ли материал скиннинг; true для передачи атрибутов скиннинга в шейдер. По умолчанию false.
Объект формы:
{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }
определяет униформы, которые будут переданы в код шейдера; ключи - имена униформ, значения - определения формы.
{ value: 1.0 }
где value - значение униформы. Имена должны совпадать с именем формы,
как определено в коде GLSL. Обратите внимание, что униформы обновляются на каждом кадре,
поэтому обновление значения униформы немедленно обновит значение, доступное коду GLSL.
Может использоваться для принудительного изменения униформы при смене униформы в Object3D.onBeforeRender(). По умолчанию false.
Определяет, будет ли использоваться раскраска вертексов. По умолчанию false.
Код вертексного шейдера GLSL. Это фактический код шейдера. В приведенном выше примере, код vertexShader и fragmentShader извлекается из DOM; он может быть передан в виде строки напрямую или загружаться через AJAX.
Рендер геометрии виде сетки (используя GL_LINES вместо GL_TRIANGLES). По умолчанию false (т.е. рендеринг в виде плоских полигонов)..
Управляет толщиной вайрфрейма. По умолчанию 1.
Из-за ограничений OpenGL Core Profile
с WebGL рендерером на большинстве платформ ширина линии всегда будет равна 1, независимо от установленного значения.
Общие методы см. в базовом классе Material.
Генерирует мелкую копию этого материала. Обратите внимание, что вертексный и фрагментный шейдеры копируются референсом, как и описания атрибутов; это означает, что клоны материала будут иметь одинаковые скомпилированные WebGLProgram. Однако униформы копируются по значению, что позволяет иметь разные наборы униформ для разных копий материала.
О том как получить исходный код этого модуля читайте тут.