Начиная с версии r112, MeshStandardMaterial по умолчанию (в данном случае, в частности, поскольку он используется при загрузке файлов glTF, но, вероятно, и в других сценариях) демонстрирует артефакты полос на некоторых графических процессорах. В частности, я видел эту проблему в Pixelbook и в каждом поколении телефонов Pixel. Проблема не возникает на графических процессорах Nvidia для настольных ПК, которые я пробовал, а также на Oculus Go или Oculus Quest.
Также следует отметить, что я заметил, что новый шейдер материала значительно снизил производительность по сравнению с r111 для моего конкретного приложения на различных мобильных устройствах, включая те, которые не демонстрируют артефакты рендеринга.
Артефакты выглядят так (отрисованы с помощью Three.js r112 в Pixelbook)
Ожидаемый результат выглядит следующим образом (визуализировано с помощью Three.js r111 в том же Pixelbook)
Живая ссылка, в настоящее время используется r112: https://xrdinosaurs.com
Все динозавры на этой странице демонстрируют проблему, но динозавры с большими участками плоского или гладкого цвета (например, живот TRex), как правило, выделяются больше.
Материал на снимке экрана (полностью вставлен ниже) использует расширение glTF «KHR_materials_pbrSpecularGlossiness» и имеет текстуры диффузного, нормального и зеркального / глянцевого.
{
"doubleSided": true,
"emissiveFactor": [
0,
0,
0
],
"extensions": {
"KHR_materials_pbrSpecularGlossiness": {
"diffuseFactor": [
0.46512957319999998,
0.46512957319999998,
0.46512957319999998,
1
],
"diffuseTexture": {
"index": 4,
"texCoord": 0
},
"glossinessFactor": 0.27610518290000002,
"specularFactor": [
0.92244664629999995,
0.92244664629999995,
0.92244664629999995
],
"specularGlossinessTexture": {
"index": 6,
"texCoord": 0
}
}
},
"name": "TRex",
"normalTexture": {
"index": 5,
"scale": 1,
"texCoord": 0
}
}
Я могу подтвердить сбой на моем Pixel (1). Однако артефакты, кажется, возникают только при использовании KHR_materials_pbrSpecularGlossiness
.
GLTFLoader
заменяет код блока шейдера lights_physical_fragment
следующим:@toji Не могли бы вы изменить копию своего приложения GLTFLoader
, заменив приведенный выше код на:
var lightPhysicalFragmentChunk = [
'PhysicalMaterial material;',
'material.diffuseColor = diffuseColor.rgb;',
'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );',
'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );',
'material.specularRoughness = max( 1.0 - glossinessFactor, 0.0525 );// 0.0525 corresponds to the base mip of a 256 cubemap.',
'material.specularRoughness += geometryRoughness;',
'material.specularRoughness = min( material.specularRoughness, 1.0 );',
'material.specularColor = specularFactor.rgb;',
].join( '\n' );
@elalish Даже если этот патч не решает проблему, мы должны в любом случае добавить его в GLTFLoader
, верно?
@ Mugen87 Да, конечно. Я посмотрю, смогу ли я воспроизвести свой Pixel 3.
@toji Я не воспроизводю свой Pixel 3 с Android 10, так что, по крайней мере, это не все пиксели ...
Ошибка драйвера? Я не уверен, какая линия его вызывает. Я почти уверен, что присутствие / отсутствие геометрического сглаживания в любом случае не приведет к появлению такого артефакта.
@toji Я также только что попробовал свой специальный дерьмовый телефон-тестер (Alcatel, который стоит около 30 долларов от Target). Я не вижу артефактов полос, хотя заметил, что небо черное. Насчет перфоманса: не совсем маслянистый, но и неплохой. Честно говоря, этот 3D-вид реагирует лучше, чем 2D-интерфейс клавиатуры на этом телефоне. Иди разбери.
Ух, черное небо на самом деле означает, что генерация PMREM полностью завершилась неудачей, и это из-за этой странной ошибки и обходного пути, которые мы нашли: https://github.com/GoogleWebComponents/model-viewer/pull/920. Я хотел вставить это в r112, но это ускользнуло от меня. Скорее всего, это не связано с ошибкой OP.
Я воспроизвел ошибку OP на своем OnePlus 5T как в Chrome, так и в Firefox.
Благодаря! Применил патч к GLTFLoader
и заметил, что артефакт полосатости уменьшился, но не исчез.
Перед патчем:
После патча:
По сути, похоже, что закрепили одну из полос. :) (Скриншоты сделаны на Pixelbook, но также наблюдались на Pixel 4 XL. На данный момент у меня нет других тестовых устройств.)
С радостью внесем исправления в любые другие изменения, которые вы хотите протестировать, или вы можете проверить https://github.com/toji/xr-dinosaurs, если хотите протестировать его локально. (Не требует никаких серверных компонентов.)
Насчет перфоманса: не совсем маслянистый, но и неплохой.
Спасибо. 😁 Усердно работал над исполнением. В этом случае во время обновления до r112 я заметил регресс производительности и спросил об этом @mrdoob . Он предположил, что это может быть новый, более точный стандартный шейдер, и предложил заменить некоторые материалы на MeshLambertMaterial
для проверки. Поскольку в модели среды все равно не были должным образом настроены материалы PBR, я принудительно передал ее Ламберту и оставил там, что позволило восстановить все регрессии производительности, а затем и некоторые (так как они занимают большую часть окна просмотра). Оставил динозавров с стандартный материал, так как они являются активом «героя».
Замечание: Scene.environment
настоящее время не работает, когда GLTFLoader
загружает сетки с использованием материалов specular / glossiness, поскольку средство визуализации проверяет MeshStandardMaterial
например.
Однако GLTFLoader
создает ShaderMaterial
для каждого материала specular / glossiness. Осознал это сегодня при тестировании с моделью T-Rex ^^. Что ж, еще одна причина наконец-то доделать # 14099.
Я не могу воспроизвести артефакты полос, если не используется карта среды. На Pixel (1) все выглядит хорошо с простой настройкой освещения, такой как окружающий и точечный свет.
Гм, похоже, есть больше проблем с физическими материалами, использующими карту окружающей среды. Посмотрите, как следующие примеры выглядят на Pixel 1, Android 10.
https://threejs.org/examples/webgl_materials_envmaps_exr
https://threejs.org/examples/webgl_materials_physical_clearcoat
https://threejs.org/examples/webgl_materials_envmaps_hdr
Я не могу воспроизвести эти артефакты на моем iMac.
Что-то довольно странное происходит на моей машине, я могу воспроизвести эти артефакты во всех примерах, использующих новый PMREMGenerator
. Но только при локальном запуске; при просмотре их в Интернете (со страницы threejs.org) все они кажутся правильными.
Я никогда не сталкивался с такой проблемой, и я совершенно не понимаю, что ее вызывает.
Я использую Windows 10 с GeForce GTX 750 TI, поэтому не думаю, что это проблема конкретного устройства.
Но только при локальном запуске; при просмотре их в Интернете (со страницы threejs.org) все они кажутся правильными.
Имейте в виду, что в версии dev
есть изменения, которых пока нет в prod
. Не могли бы вы проверить текущую ветку master
а затем выполнить локальный тест?
Не могли бы вы проверить текущую главную ветку, а затем выполнить локальный тест?
Первое, что я попробовал, заметив такое поведение, - те же результаты. Действительно любопытно.
Не могли бы вы протестировать с окнами в режиме инкогнито? Иногда что-то может быть кешировано, или расширения браузера мешают, что может сбивать с толку.
Пробовал с инкогнито, те же результаты :(
Думаю, я знаю, почему возникает эта полосатость.
Во время генерации mip моя локальная (неправильная) версия создает черную полосу, которой нет в живой версии.
Это также распространяется на более низкие уровни MIP.
Вероятно, это происходит из-за некорректной выборки координат. Я экспериментировал с отключением анизотропной фильтрации вручную, но проблема осталась. Трудно точно определить, что происходит, особенно потому, что я не могу понять, почему это проявляет два разных поведения на одной и той же машине.
@elalish, выполнив несколько тестов на нескольких примерах, я смог точно определить PMREMGenerator
обрабатывает devicePixelRatio
.
На устройствах с номинальной плавающей запятой pixelRatio
мы получаем "плохие" координаты mipmap на сгенерированной текстуре. Так что есть небольшие пробелы и пересекающиеся области. Я также обнаружил, что моя машина имеет разные devicePixelRatios
зависимости от того, просматриваю ли я пример локально (0.899 ..) или онлайн (1), и поэтому я обнаружил эти артефакты только локально.
Я установил простой тест, отключив setPixelRatio
и, похоже, он решил проблему, если это так для других, тогда было бы лучше провести рефакторинг так, как PMREMGenerator
обрабатывает его.
@toji @ plut0nist Не могли бы вы проверить следующие примеры на устройствах, на которых представлены эти артефакты?
@sciecode Большое спасибо за выяснение первопричины! Я посмотрю, смогу ли я найти решение.
@sciecode : Проверено на моих устройствах. Тест DEV Example показывает очень очевидную черную линию на карте среды, а тест TEST - нет. Отличная отладка, спасибо!
Мне было очень любопытно, почему PMREMGenerator
вообще нужно учитывать для devicePixelRatio
, поэтому я пошел копать. Оказывается, это потому, что renderer.setViewport()
автоматически преобразовывает DPR в любые значения, которые вы ему отправляете, что кажется явно неправильным поведением для целей рендеринга, кроме стандартного фреймбуфера, которые выделяются с точными значениями пикселей, которые не учитывать соотношение пикселей вообще. Я бы посоветовал «правильное» поведение здесь: внутренне rendere.setViewport()
должен использовать getTargetPixelRatio()
, который возвращает 1
когда активная цель рендеринга отличается от значения по умолчанию. Однако я определенно вижу, как это может вызвать проблемы с обратной совместимостью.
Самый полезный комментарий
@elalish, выполнив несколько тестов на нескольких примерах, я смог точно определить
PMREMGenerator
обрабатываетdevicePixelRatio
.На устройствах с номинальной плавающей запятой
pixelRatio
мы получаем "плохие" координаты mipmap на сгенерированной текстуре. Так что есть небольшие пробелы и пересекающиеся области. Я также обнаружил, что моя машина имеет разныеdevicePixelRatios
зависимости от того, просматриваю ли я пример локально (0.899 ..) или онлайн (1), и поэтому я обнаружил эти артефакты только локально.Я установил простой тест, отключив
setPixelRatio
и, похоже, он решил проблему, если это так для других, тогда было бы лучше провести рефакторинг так, какPMREMGenerator
обрабатывает его.@toji @ plut0nist Не могли бы вы проверить следующие примеры на устройствах, на которых представлены эти артефакты?
Пример DEV
ТЕСТ Пример