Черный фон для three.js спрайты с глубочайшей истинностью

#three.js #transparency

#three.js #прозрачность

Вопрос:

введите описание изображения здесь

Я экспериментировал с преобразованием пользовательского атрибута BufferGeometry пример (https://threejs.org/examples/webgl_buffergeometry_custom_attributes_particles.html ) в сквозную анимацию, и я обнаруживаю, что спрайты имеют темный фон (и те, которые я создаю сам), если для depthTest установлено значение true. Смотрите изображение.

Спрайт в примере пользовательского атрибута имеет прозрачный фон, но это, по-видимому, игнорируется при его визуализации, если для depthTest установлено значение true.

Я перепробовал множество пользовательских правил наложения, но не могу найти способ удалить фон, только немного уменьшить эффект. Фон исчезает, если для параметра depthTest установлено значение false.

Является ли это известным ограничением? Есть ли какой-то обходной путь?

Я изменяю этот вопрос, чтобы добавить более четкие изображения с другим шаровым спрайтом (также с прозрачным фоном). Это изображение имеет значение depthTest равное true для пользовательского шейдерматериала, используемого в https://threejs.org/examples/webgl_buffergeometry_custom_attributes_particles.html three.js пример.

введите описание изображения здесь

Для сравнения, при этом используется несколько точечных материалов из разных three.js пример (https://threejs.org/examples/webgl_points_sprites.html ), также с depthTest, установленным в true, и с использованием параметра PointsMaterial map для спрайта.

введите описание изображения здесь

Как вы можете видеть, второй пример PointsMaterial работает так, как ожидалось. Поскольку PointsMaterial принимает только один фиксированный размер и цвет, мне нужно создать 36 различных геометрий точек для рендеринга этого изображения.

Я бы предпочел использовать пользовательский шейдер в первом примере (который имеет пользовательские атрибуты размера и цвета и требует только одной геометрии). Есть ли способ определить пользовательский шейдер для поддержки depthTest, как это делает PointsMaterial?

Ответ №1:

WebGL имеет буфер глубины, который используется для определения, какие пиксели скрываются за другими пикселями. Если один пиксель скрывается за другим, он не отображается. Обычно это то, что вы хотели бы, зачем вам тратить время GPU на рендеринг пикселей, которые вы никогда не увидите? Рассмотрим пример depthbuffer ниже, белые квадраты ближе к камере, а более темные — дальше:

введите описание изображения здесь

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

введите описание изображения здесь

Квадраты, которые находятся ближе, блокируют часть квадратов, которые находятся дальше в буфере глубины, поэтому закрытые пиксели не отображаются. Вот почему полезно установить для depthTest значение false. По сути, вы говорите программе визуализации прекратить тестирование того, какие пиксели находятся позади других, и просто визуализировать их все. Вот он снова с depthTest = false :

введите описание изображения здесь

Если вы должны установить значение depthTest (например, если вы хотите, чтобы спрайты скрывались за сплошной стеной), вы можете установить depthWrite значение false для материала спрайта. Он все равно будет проверять, какие пиксели находятся позади других, но пиксели из спрайтов не будут записаны в DepthBuffer, поэтому ни один спрайт не сможет заблокировать другой спрайт.

 depthTest: true;   // Tests pixel depth
depthTest: false;  // Does not test pixel depth
depthWrite: true;  // Writes pixel depth to depthBuffer
depthWrite: false; // Does not write pixel depth to depthBuffer
  

Что касается режима наложения, я предпочитаю THREE.AdditiveBlending , потому что он дает частицам приятный эффект свечения, когда они накапливаются одна поверх другой. Но это зависит от вас.

Комментарии:

1. Спасибо за этот ответ. Я думаю, что мой первоначальный вопрос был недостаточно ясен. Я добавил больше примеров. В-третьих, js, похоже, поддерживает depthTest в примере PointsMaterial, но не в примере пользовательского шейдера. Я пытаюсь понять, есть ли способ настроить пользовательский шейдер так, чтобы он работал так, как это делает PointsMaterial.

2. Кроме того, отключение depthWrite в моем случае не работает. Важно, чтобы шары отображались в правильном порядке. Когда я отключаю depthWrite, отображение отображается некорректно.

3. Я думал, вы готовы попробовать другие правила наложения. Вот почему я рекомендовал THREE.AdditiveBlending , поскольку у аддитивных цветов нет проблем с упорядочением, когда они перекрываются.

4. Аддитивное смешивание не позволяет создавать непрозрачные шары, которых я хочу достичь, но я уверен, что это было бы полезно для других случаев использования, где требуются полупрозрачные объекты.