Stencil buffer (трафаретный буфер) используется для контроля того, какие пиксели будут отрисованы на экране, а какие нет. Он работает совместно с глубинным буфером (depth buffer), но выполняет независимую задачу: создание масок, ограничение области рендеринга и сложные визуальные эффекты, такие как отражения, контуры и секционирование объектов.
В Three.js доступ к stencil buffer обеспечивается через объект
WebGLRenderer и параметры материала, связанные с
трафаретом.
const renderer = new THREE.WebGLRenderer({ antialias: true, stencil: true });
По умолчанию stencil buffer выключен, поэтому необходимо явно включить его при создании рендерера.
Каждое графическое примитивное в Three.js может управлять stencil buffer через свойства материала:
stencilWrite — разрешает запись в stencil buffer
(true или false).
stencilFunc — функция тестирования, определяет,
какие пиксели будут отрисованы. Основные варианты:
THREE.AlwaysStencilFunc — всегда пропускает
пиксель.THREE.NeverStencilFunc — никогда не пропускает.THREE.LessStencilFunc,
THREE.LessEqualStencilFunc,
THREE.GreaterStencilFunc и др.stencilRef — опорное значение, с которым
сравнивается содержимое stencil buffer.
stencilMask — маска для битовой операции с stencil
buffer.
stencilFail, stencilZFail,
stencilZPass — действия, выполняемые при:
stencilFail — если тест stencil не прошёл,
stencilZFail — если stencil тест прошёл, но depth
test не прошёл,
stencilZPass — если прошли и stencil, и depth тесты.
Варианты действий:
THREE.KeepStencilOp — оставить текущее значение,THREE.ZeroStencilOp — обнулить,THREE.ReplaceStencilOp — заменить на
stencilRef,THREE.IncrementStencilOp /
THREE.DecrementStencilOp.Пример настройки материала для маски:
const maskMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
stencilWrite: true,
stencilFunc: THREE.AlwaysStencilFunc,
stencilRef: 1,
stencilZPass: THREE.ReplaceStencilOp
});
Stencil buffer позволяет выделять области для последующей отрисовки объектов. Основной алгоритм:
Пример: отрисовка сферы только внутри куба-маски.
// Куб-маска
const maskGeometry = new THREE.BoxGeometry(2, 2, 2);
const mask = new THREE.Mesh(maskGeometry, maskMaterial);
scene.add(mask);
// Объект для рендеринга
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
const sphereMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
stencilWrite: true,
stencilRef: 1,
stencilFunc: THREE.EqualStencilFunc, // отрисовывать только там, где stencil равен 1
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);
В этом примере трафаретный буфер ограничивает видимость сферы только областью куба.
Stencil buffer часто используется совместно с depth buffer для создания эффектов, которые зависят от глубины объектов. Например, отражение на плоскости с маской:
Это позволяет создавать сложные эффекты отражений и просвечивания, не влияя на остальную сцену.
Three.js позволяет использовать несколько уровней масок, комбинируя
разные значения stencilRef. С помощью битовых операций
(stencilMask) можно управлять наложением масок:
stencilFunc проверяет нужные биты.THREE.AndStencilOp,
THREE.OrStencilOp, THREE.InvertStencilOp для
сложных пересечений областей.Пример:
material.stencilWrite = true;
material.stencilRef = 0b0010; // второй бит
material.stencilFunc = THREE.EqualStencilFunc;
material.stencilMask = 0b0010;
Так можно создавать эффекты многослойных масок, контуров и вырезов.
Использование stencil buffer увеличивает нагрузку на графический процессор, так как требует дополнительной памяти и операций на пиксель. Рекомендуется:
stencilZPass и
stencilFail.Stencil buffer в Three.js обеспечивает мощный инструмент для создания масок и специальных эффектов, позволяя контролировать рендеринг на пиксельном уровне, обеспечивая гибкость при построении сложных сцен.