Atualizando de 107 para 108, notei que partes do meu modelo agora parecem ter os normais invertidos. Isso ocorre apenas com materiais de dupla face.
Veja aqui: https://vaulted-jonquil.glitch.me/
É assim que deve ser, com o padrão sendo recortado em ambas as rodas. Era assim em 107
No 108, embora uma das rodas tenha o padrão parecendo que está saindo:
@pushmatrix Você pode confirmar se este modelo fornece ou não suas próprias tangentes? Estou curioso para saber se isso pode estar relacionado a # 11438.
Eu não acredito que especifique suas próprias tangentes
Usando um caso de teste diferente, git bissect aponta para # 17586 como o PR que iniciou o problema se a malha for dupla-face e tiver escala X negativa. Isso estava em r.109, não em r.108, no entanto.
Isso não foi testado no modelo deste PR porque esse modelo não está disponível.
Aqui está o glb de teste
wheel.glb.zip
De 3 anos atrás: https://github.com/mrdoob/three.js/issues/10331#issue -194807426
Basicamente, parece que ... gl_FrontFace não está funcionando corretamente com materiais de dupla face nas GPUs Adreno.
Este _ainda_ é um problema que precisamos resolver?
//
Este modelo parece ser renderizado corretamente em minha máquina se removermos a solução alternativa Adreno em normalmap_pars_fragment
:
#ifdef DOUBLE_SIDED
// Workaround for Adreno GPUs gl_FrontFacing bug. See #15850 and #10331
bool frontFacing = dot( cross( S, T ), N ) > 0.0;
mapN.xy *= ( float( frontFacing ) * 2.0 - 1.0 );
#else
mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
#endif
Hmm, também me lembro de ter lido esse comentário; Acho que me deparei com isso enquanto olhava para esse bug, que aparentemente foi corrigido no r108 (pelo menos a atualização corrigiu para nós): https://github.com/GoogleWebComponents/model-viewer/issues/740
Talvez esteja relacionado? FWIW, recebi alguns comentários sobre GPUs Adreno antigas, então, aparentemente, eles ainda são bastante comuns.
Só para confirmar, isso ainda acontece em dev
:
Só para confirmar, isso ainda acontece no dev:
Direito. Mas não se você remover a solução alternativa para o bug Adreno.
Mas não se você remover a solução alternativa para o bug Adreno.
Que tal remover a solução alternativa de vez em quando procurar uma solução diferente? A implementação atual leva a imagens erradas, independentemente da plataforma que você está usando.
@ Mugen87 Neste caso particular, acredito que as geometrias são espelhos uma da outra, mas compartilham o mesmo mapa normal.
Eu concordo com você. Eu investi muitas horas tentando encontrar uma solução alternativa compatível com Adreno que seja correta em todos os casos de uso.
Inspecionando o modelo do modelo da roda, cada roda tem seu próprio escudo UV. Ele não compartilha um.
E a ordem do vértice é oposta.
Porém a orientação da face é a mesma, pelo menos no Blender.
Portanto, não tenho certeza se é um bug no r108 ou se o r108 agora está fazendo as coisas corretamente. ¯_ (ツ) _ / ¯
@pushmatrix você pode comparar com Unity ou Blender?
@mrdoob
@pushmatrix
O Unity é difícil de ver porque a luz está na mesma direção da câmera, mas parece que o Unity também está errado? 🤔
@mrdoob
Sim, depende um pouco da iluminação, acaba sendo uma ilusão e parece que apareceu em alguns lugares. Mas quando você gira, ele desaparece.
Aqui está em outra luz, onde parece correto
@mrdoob As faces frontais têm ordem de enrolamento no sentido anti-horário em three.js. Normalmente, os UVs dos 3 vértices de cada face também têm ordem de enrolamento no sentido anti-horário no mapa de UV.
Neste exemplo, minha _conjectura_ é o modelo à esquerda tem UVs anti-horário e o modelo à direita tem UVs _clockwise_. O modelo à direita está renderizando incorretamente em three.js quando doubleSide
é true
.
AFAIK, a remoção da solução alternativa Adreno corrige o problema para GPUs não Adreno.
@pushmatrix Seu exemplo do Unity parece ter luzes direcionais de duas direções. Isso torna difícil discernir o que está acontecendo. Uma única luz pode ser preferível.
@WestLangley Estou usando o mesmo mapa de ambiente que o visualizador de modelo está usando, mas provavelmente não tem a mesma rotação. Vou tentar com uma única luz.
@WestLangley Luz direcional única girando. Eu sinto que estou olhando para uma ilusão de ótica
Parece que o Unity faz os sulcos aparecerem e desaparecerem dependendo de como a luz o atinge, mas pelo menos é consistente para ambos.
Threejs também é consistente, mas um definitivamente parece sempre estourado:
Eu sinto que há algo errado com o Unity ...
Como se precisasse de algo parecido. material.normalMapScale.x = -1
.
@WestLangley
@mrdoob As faces frontais têm ordem de enrolamento no sentido anti-horário em three.js. Normalmente, os UVs dos 3 vértices de cada face também têm ordem de enrolamento no sentido anti-horário no mapa de UV.
Neste exemplo, minha _conjectura_ é o modelo à esquerda tem UVs anti-horário e o modelo à direita tem UVs _clockwise_. O modelo à direita está renderizando incorretamente em three.js quando
doubleSide
étrue
.AFAIK, a remoção da solução alternativa Adreno corrige o problema para GPUs não Adreno.
Obrigado, isso faz sentido. Eu acho que ainda merece mais investigação. Se Sketchfab parece correto em todos os dispositivos, podemos ter que olhar seus shaders.
Eu dei uma olhada no respectivo código de sombreador hoje e parece que eles não estão usando o "Mapeamento normal do espaço tangente por pixel".
De acordo com esta postagem , Sketchfab espera definições tangentes em ativos ou esses dados são
gerar com base em coordenadas uv. Isso corresponde ao que vi no código GLSL.
Se eu adicionar tangentes ao modelo via BufferGeometryUtils.computeTangents()
e definir Material.vertexTangents
como true
, o resultado parece bom:
BTW: Há algum problema em compartilhar trechos de código do Sketchfab neste post ^^? Afinal, não é um código aberto.
Para consistência, aqui está o Sketchfab com 1 luz direcional se movendo para frente e para trás:
Sim, uma coisa a ter em mente é que o Sketchfab faz o processamento no final deles quando você carrega um modelo, então muito provavelmente eles podem estar gerando / alterando coisas. O que você está vendo não é um glTF, mas um arquivo glTF convertido em seu próprio formato.
@pushmatrix Você pode _por favor_ demonstrar que # 17958 funciona para o seu modelo?
three.js calcula tangentes no sombreador de fragmento. Acredito que funcione corretamente se um hack para acomodar certas GPUs Adreno com erros for removido. Veja # 17958.
//
Sketchfab calcula tangentes na CPU quando tangentes são necessárias e não são fornecidas pelo modelo. ( @donmccurdy Isso é o que a especificação glTF requer.)
three.js pode fazer isso também, mas significará adicionar tangentes corretas a todas as geometrias integradas. three.js também terá que implementar o algoritmo MIKKTSpace para substituir ComputeTangents()
. Como three.js oferece suporte a geometrias indexadas e não indexadas, espero que isso exija um esforço considerável.
Corrige isso!
Ok, então parece que a solução aqui é reverter a solução alternativa do Adreno (# 17958) e recomendar às pessoas que usem BufferGeometryUtils.computeTangents()
quando o modelo não tiver tangentes e o objetivo for dar suporte às GPUs Adreno (# 15850) .
Parece bom?
Outra solução é chamar BufferGeometryUtils.computeTangents()
no motor automaticamente quando não for fornecido e remover todo o código que calcula tangentes no sombreador de fragmento ... 🤔
BufferGeometryUtils.computeTangents()
atualmente requer um índice, portanto não pode ser usado no núcleo. No entanto, acho que seria preferível se three.js
pudesse gerar tangentes de acordo com o MIKKTSpace em algum ponto e depois remover perturbNormal2Arb()
.
@WestLangley escreveu:
significará adicionar tangentes corretas a todas as geometrias integradas.
Mudando de ideia ... Tangentes não são necessariamente necessárias. Em vez disso, eu restauraria o método BufferGeometry.computeTangents()
e "substituiria" esse método para todas as geometrias integradas para as quais podemos definir tangentes exatas analiticamente.
//
Outra solução é chamar BufferGeometryUtils.computeTangents () no mecanismo automaticamente quando não for fornecido e remover todo o código que calcula tangentes no sombreador de fragmento ...
Isso parece certo para mim.
BufferGeometryUtils.computeTangents () atualmente requer um índice, portanto, não pode ser usado no núcleo.
Eu acho que isso é facilmente corrigido. E terá que ser consertado para oferecer suporte a https://github.com/mrdoob/three.js/issues/17804#issuecomment -557135610.
seria preferível se three.js pudesse gerar tangentes de acordo com MIKKTSpace em algum ponto e, em seguida, remover perturbNormal2Arb () ...
Não sei se o MikkTSpace deve necessariamente substituir o cálculo do sombreador de fragmento. O shader quase não tem custo de desempenho e funciona bem para a maioria dos modelos. A pré-computação de tangentes sempre tem um custo inicial por vértice e nenhum benefício, exceto nesses casos específicos. 😕 Apesar do que a especificação glTF diz, estou tendo dificuldade em justificar fazer isso por padrão.
Seria bom se BufferGeometryUtils.computeTangents
pudesse implementar a abordagem MikkTSpace - esse é o melhor algoritmo, se você deve pré-calculá-los. Mas provavelmente seria mais fácil colocar o MikkTSpace em ferramentas como glTF-Pipeline ou gltfpack, que podem usar a implementação nativa existente e fazer o cálculo com antecedência, offline.
@donmccurdy
Mas, digamos ... no caso de uso <model-viewer>
, não acho que haja uma maneira confiável de saber se o usuário tem uma GPU Adreno, mas gostaríamos de olhar certo (https: // github. com / GoogleWebComponents / model-viewer / issues / 740).
<model-viewer>
(e outros projetos que desejam suporte x-gpu) devem chamar BufferGeometryUtils.computeTangents
quando as tangentes não são fornecidas, ou três?
@pushmatrix
Haha, acabei de perceber de onde vêm essas rodas 😁
@mrdoob 🕵
Ok, então, vamos reverter a solução alternativa por enquanto.
Comentários muito úteis
Corrige isso!