A partir do r112, o MeshStandardMaterial padrão (neste caso especificamente como é usado ao carregar arquivos glTF, mas provavelmente também em outros cenários) está exibindo artefatos de faixas em algumas GPUs. Especificamente, vi esse problema em um Pixelbook e em todas as gerações de smartphones Pixel. O problema não ocorre nas GPUs de desktop da Nvidia que experimentei, nem em um Oculus Go ou Oculus Quest.
Também deve ser observado que observei que o novo shader do material sofreu um impacto perceptível no desempenho em relação ao r111 para meu aplicativo específico em vários dispositivos móveis, incluindo aqueles que não exibem os artefatos de renderização.
Os artefatos têm a seguinte aparência (renderizado com Three.js r112 em um Pixelbook)
A saída esperada é parecida com esta (renderizado com Three.js r111 no mesmo Pixelbook)
Link ao vivo, atualmente usando r112: https://xrdinosaurs.com
Todos os dinossauros nessa página exibem o problema, mas aqueles com grandes áreas de cores planas ou suaves (como a barriga do TRex) tendem a se destacar mais.
O material na captura de tela (colado por completo abaixo) usa a extensão glTF "KHR_materials_pbrSpecularGlossiness" e tem texturas difusas, normais e especulares / brilhantes.
{
"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
}
}
Posso confirmar o glich no meu Pixel (1). No entanto, os artefatos só parecem ocorrer quando KHR_materials_pbrSpecularGlossiness
é usado.
GLTFLoader
substitui o código do fragmento de sombreador lights_physical_fragment
pelo seguinte:@toji Você pode modificar a cópia GLTFLoader
de seu aplicativo substituindo o código acima por:
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 Mesmo que este patch não resolva o problema, devemos adicioná-lo a GLTFLoader
em qualquer caso, certo?
@ Mugen87 Sim, com certeza. Vou ver se consigo reproduzir no meu Pixel 3 também.
@toji Eu não reproduzo no meu Pixel 3 com Android 10, então pelo menos não são todos Pixels ...
Bug do driver? Não tenho certeza de qual linha está acionando isso. A presença / ausência de anti-aliasing geométrico não faria esse tipo de artefato de qualquer maneira, tenho certeza.
@toji Eu também tentei meu telefone dedicado de teste de custa cerca de US $ 30 da Target). Não entendo os artefatos de bandas, embora tenha notado que o céu está preto. Quanto ao perf: não é exatamente amanteigado, mas não é ruim. Honestamente, essa visualização 3D responde melhor do que a IU do teclado 2D neste telefone. Vai saber.
Ugh, o céu preto na verdade significa que a geração do PMREM falhou totalmente, e é devido a este bug estranho e solução alternativa que encontramos: https://github.com/GoogleWebComponents/model-viewer/pull/920. Eu pretendia colocar isso no r112, mas passou por mim. Provavelmente não relacionado ao bug do OP.
Reproduzi o erro de OP no meu OnePlus 5T no Chrome e no Firefox.
Obrigado! Aplicou o patch a GLTFLoader
e observou que o artefato de bandas foi reduzido, mas não eliminado.
Antes do patch:
Após o patch:
Basicamente, parece que consertou uma das bandas. :) (Capturas de tela tiradas em um Pixelbook, mas também observadas em um Pixel 4 XL. Não tenho outros dispositivos de teste comigo no momento.)
Fico feliz em corrigir qualquer outra mudança que você queira testar, ou você pode verificar https://github.com/toji/xr-dinosaurs se quiser testá-lo localmente. (Não requer nenhum componente de servidor.)
Quanto ao perf: não é exatamente amanteigado, mas não é ruim.
Obrigado. 😁 Tenho trabalhado muito para melhorar o desempenho. Neste caso, durante a atualização para r112, percebi a regressão de desempenho e perguntei a @mrdoob sobre isso. Ele sugeriu que pode ser o novo e mais preciso shader padrão e sugeriu trocar alguns materiais com MeshLambertMaterial
para verificar. Uma vez que o modelo de ambiente não configurou corretamente os materiais PBR de qualquer maneira, eu forcei para Lambert e o deixei lá, que recuperou quaisquer regressões de desempenho e depois algumas (uma vez que ocupa uma grande parte da janela de visualização). Deixei os dinossauros com o material padrão, uma vez que eles são o ativo "herói".
Nota secundária: Scene.environment
atualmente não funciona quando GLTFLoader
carrega malhas usando materiais especulares / brilhantes, pois o renderizador verifica MeshStandardMaterial
por exemplo
No entanto, GLTFLoader
cria um ShaderMaterial
para cada material especular / brilhante. Percebi isso hoje ao testar com o modelo T-Rex ^^. Bem, mais uma razão para finalmente concluir o # 14099.
Não consigo reproduzir os artefatos de faixas quando nenhum mapa de ambiente é usado. Tudo fica bem em um Pixel (1) com uma configuração de iluminação simples, como um ambiente e uma luz pontual.
Hum, parece haver mais problemas com materiais físicos usando um mapa de ambiente. Confira a aparência dos exemplos a seguir em um 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
Não consigo reproduzir esses artefatos no meu iMac.
Algo muito estranho está acontecendo em minha máquina, sou capaz de reproduzir esses artefatos em todos os exemplos que utilizam o novo PMREMGenerator
. Mas apenas ao executá-los localmente; ao visualizá-los online (na página threejs.org), todos parecem corretos.
Nunca experimentei esse problema e estou completamente perdido quanto ao que causa isso.
Estou executando um Windows 10 com uma GeForce GTX 750 TI, então não acho que este seja um problema específico do dispositivo.
Mas apenas ao executá-los localmente; ao visualizá-los online (na página threejs.org), todos parecem corretos.
Esteja ciente de que a versão dev
possui alterações que ainda não estão presentes em prod
. Você pode verificar o branch atual master
e, em seguida, realizar um teste local?
Você pode verificar o branch master atual e, em seguida, realizar um teste local?
A primeira coisa que tentei depois de notar esse comportamento, os mesmos resultados. Muito curioso.
Você pode testar com janelas anônimas? Às vezes, as coisas podem ser armazenadas em cache ou as extensões do navegador interferem, o que pode ser muito confuso
Tentativa de navegação anônima, mesmos resultados :(
Eu acredito que sei por que essa banda está ocorrendo agora.
Durante a geração do mip, minha versão local (incorreta) está criando uma faixa preta que não existe na versão ao vivo.
Isso também é replicado para reduzir os níveis de mip.
Isso provavelmente está acontecendo devido a alguma amostragem de coordenadas incorreta. Eu experimentei desabilitar manualmente a filtragem anisotrópica, mas o problema permanece. É difícil apontar exatamente o que está acontecendo, especialmente porque não consigo entender por que ele apresenta dois comportamentos diferentes na mesma máquina.
@elalish depois de executar alguns testes em vários exemplos, consegui localizar a causa real desses artefatos. Ao contrário do que disse no meu post anterior, a causa raiz do problema não está relacionada com a amostragem de coordenadas incorretas, mas com a maneira PMREMGenerator
está lidando com devicePixelRatio
.
Em dispositivos com ponto flutuante nominal pixelRatio
, estamos obtendo coordenadas mipmap "ruins" na textura gerada. Portanto, há pequenas lacunas e regiões sobrepostas. Eu também descobri que minha máquina tem devicePixelRatios
dependendo se estou vendo o exemplo localmente (0,899 ..) ou online (1) e é por isso que eu só estava experimentando esses artefatos localmente.
Eu configurei um teste simples desabilitando setPixelRatio
e parece resolver o problema, se esse for o caso de outros, então seria melhor refatorar a maneira PMREMGenerator
está lidando com isso.
@toji @ plut0nist se importou em verificar os exemplos a seguir nos dispositivos que apresentaram esses artefatos?
@sciecode Muito obrigado por descobrir a causa raiz! Vou ver se consigo encontrar uma solução.
@sciecode : verificado em meus dispositivos. O teste de exemplo DEV exibe uma linha preta muito óbvia no mapa de ambiente, enquanto o exemplo de TESTE não. Depuração incrível, obrigado!
Eu estava extremamente curioso para saber por que PMREMGenerator
precisava para contabilizar devicePixelRatio
em tudo, então eu fui cavar. Acontece que é porque renderer.setViewport()
fatora automaticamente o DPR em quaisquer valores que você enviar, o que parece ser claramente o comportamento errado para destinos de renderização diferentes do framebuffer padrão, que são alocados com valores de pixel exatos que não levar em conta a proporção de pixels em tudo. Eu sugeriria que o comportamento "correto" aqui é que internamente rendere.setViewport()
deve estar usando getTargetPixelRatio()
, que retorna 1
quando o alvo de renderização ativo é qualquer coisa diferente do padrão. Eu posso definitivamente ver como isso poderia introduzir problemas de compatibilidade retroativa, no entanto.
Comentários muito úteis
@elalish depois de executar alguns testes em vários exemplos, consegui localizar a causa real desses artefatos. Ao contrário do que disse no meu post anterior, a causa raiz do problema não está relacionada com a amostragem de coordenadas incorretas, mas com a maneira
PMREMGenerator
está lidando comdevicePixelRatio
.Em dispositivos com ponto flutuante nominal
pixelRatio
, estamos obtendo coordenadas mipmap "ruins" na textura gerada. Portanto, há pequenas lacunas e regiões sobrepostas. Eu também descobri que minha máquina temdevicePixelRatios
dependendo se estou vendo o exemplo localmente (0,899 ..) ou online (1) e é por isso que eu só estava experimentando esses artefatos localmente.Eu configurei um teste simples desabilitando
setPixelRatio
e parece resolver o problema, se esse for o caso de outros, então seria melhor refatorar a maneiraPMREMGenerator
está lidando com isso.@toji @ plut0nist se importou em verificar os exemplos a seguir nos dispositivos que apresentaram esses artefatos?
DEV Exemplo
Exemplo de TESTE