Какой самый простой способ визуализации перекрывающихся прозрачных сеток в файле THREE.js? - PullRequest
0 голосов
/ 28 февраля 2019

Я хотел бы визуализировать прозрачные поверхности, которые частично перекрываются в файле THREE.js.Я не ищу идеальный рендеринг нескольких перекрывающихся поверхностей, но просто хотел бы что-то, что выглядит немного лучше, чем текущий результат - где, например, если у меня есть два эллипсоида, тот, чей центр находится сзади, рендерится все со ссылкой на эту глубину, даже если части его поверхности эффективно находятся перед другой.Я должен также упомянуть, что я использую OrbitControls, поэтому я не могу просто один раз упорядочить их статически и забыть о них.

Я видел, что Глубокий пилинг обычно является техникой для этого, и даже нашел кого-то, ктонаписал пример, делающий это в THREE.js.К сожалению, он также выглядит довольно сложным и, возможно, тяжелым по производительностиМне было интересно, если бы были более простые альтернативы.Что-то, что я рассмотрел, - это просто разбить каждую сетку на ее основные треугольники и выдвинуть каждую в отдельную геометрию, но я не знаю, сколько из этого может привести к снижению производительности, и это сделает все дальнейшие операции масштабирования / вращения более сложными.Я видел, что класс THREE BufferGeometry имеет опцию для «групп», которые будут отображаться в отдельных вызовах, но это само по себе не может исправить это.Есть ли что-нибудь еще, что вы думаете, я мог бы сделать?Может быть, использовать пользовательский шейдер?Или мне действительно стоит пойти с глубинным пилингом?

1 Ответ

0 голосов
/ 01 марта 2019

enter image description here

Прозрачность Screendoor может использоваться для создания стабильного перекрытия прозрачности между кадрами, но имеет несколько артефактов, которые могут быть нежелательны.Суть этой техники заключается в отбрасывании пикселей в шаблоне пространства экрана в зависимости от того, насколько непрозрачным должен быть объект.Шаблон может быть получен из текстуры или сгенерирован в шейдере.Фрагменты, которые не отброшены, все еще записывают в глубину, и альфа-смешение не используется.

Вот небольшой код для начала работы.

Создание DataTexture с помощьюшаблон дизеринга:

const data = new Float32Array(16);
data[0] = 1.0 / 17.0;
data[1] = 9.0 / 17.0;
data[2] = 3.0 / 17.0;
data[3] = 11.0 / 17.0;

data[4] = 13.0 / 17.0;
data[5] = 5.0 / 17.0;
data[6] = 15.0 / 17.0;
data[7] = 7.0 / 17.0;

data[8] = 4.0 / 17.0;
data[9] = 12.0 / 17.0;
data[10] = 2.0 / 17.0;
data[11] = 10.0 / 17.0;

data[12] = 16.0 / 17.0;
data[13] = 8.0 / 17.0;
data[14] = 14.0 / 17.0;
data[15] = 6.0 / 17.0;

ditherTex = new THREE.DataTexture(data, 4, 4, THREE.LuminanceFormat, THREE.FloatType);
ditherTex.minFilter = THREE.NearestFilter;
ditherTex.magFilter = THREE.NearestFilter;
ditherTex.anisotropy = 1;
ditherTex.wrapS = THREE.RepeatWrapping;
ditherTex.wrapT = THREE.RepeatWrapping;

И некоторый код шейдера для отбрасывания фрагментов по:

// ...
uniform sampler2D ditherTex;    
void main() {

    // ...

    // get the color of the surface and discard pixels based on the dither pattern       
    vec4 texColor = texture2D(diffuseTex, vUv);
    vec4 color = texColor * vec4(color.rgb, opacity);

    if(texture2D(ditherTex, gl_FragCoord.xy / 4.0).r > color.a) discard;

    // ...

}

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

И, наконец, некоторые вещи, которые следует иметь в виду:

  • Непрозрачность текстуры должнаиспользовать при сравнении с текстурой дизеринга.

  • Артефакты дверцы экрана могут быть смягчены с помощью некоторых методов сглаживания для смешивания окружающих пикселей.

  • Material.transparent должно быть false.

  • Поскольку фрагменты не являются смешанными объектами с одинаковой непрозрачностью, они не будут иметь видимого перекрытия.

Надеемся, чтопомогает!Дайте мне знать, если у вас есть другие вопросы.

...