Al actualizar de 107 a 108, he notado que algunas partes de mi modelo ahora parecen tener valores normales invertidos. Esto solo ocurre con materiales de doble cara.
Ver aquí: https://vaulted-jonquil.glitch.me/
Así es como debería verse, con el patrón con sangría en ambas ruedas. Así fue en 107
En 108, aunque una de las ruedas tiene el patrón que parece estar saliendo:
@pushmatrix ¿Puede confirmar si este modelo proporciona o no sus propias tangentes? Tengo curiosidad por saber si esto puede estar relacionado con el # 11438.
No creo que especifique sus propias tangentes
Usando un caso de prueba diferente, git bisect apunta a # 17586 como el PR que inició el problema si la malla es de doble cara y tiene una escala negativa X. Sin embargo, eso estaba en r.109, no en r.108.
Esto no se probó en el modelo de este PR porque ese modelo no está disponible.
Aquí está la prueba glb
wheels.glb.zip
Desde hace 3 años: https://github.com/mrdoob/three.js/issues/10331#issue -194807426
Básicamente, parece que ... gl_FrontFace no funciona correctamente con materiales de doble cara en las GPU Adreno.
¿Es este _todavía_ un problema que debemos resolver?
//
Este modelo parece renderizarse correctamente en mi máquina si eliminamos la solución alternativa de Adreno en 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, recuerdo haber leído ese comentario también; Creo que lo encontré mientras miraba este error, que aparentemente se solucionó en r108 (al menos la actualización lo solucionó para nosotros): https://github.com/GoogleWebComponents/model-viewer/issues/740
¿Quizás esté relacionado? FWIW, he recibido algunos comentarios sobre las antiguas GPU Adreno, por lo que aparentemente todavía son bastante comunes.
Solo para confirmar, esto todavía sucede en dev
:
Solo para confirmar, esto todavía sucede en dev:
Correcto. Pero no si elimina la solución alternativa del error Adreno.
Pero no si elimina la solución alternativa del error Adreno.
¿Qué tal eliminar la solución temporal por ahora y luego buscar una solución diferente? La implementación actual conduce a imágenes incorrectas sin importar qué plataforma esté utilizando.
@ Mugen87 En este caso particular, creo que las geometrías son espejos entre sí, pero comparten el mismo mapa normal.
Estoy de acuerdo contigo. He invertido muchas horas tratando de encontrar una solución alternativa compatible con Adreno que sea correcta en cada caso de uso.
Al inspeccionar el modelo de modelo de rueda, cada rueda tiene su propia carcasa UV. No comparte uno.
Y el orden de los vértices es opuesto.
Sin embargo, la orientación de la cara es la misma, al menos en Blender.
Así que no estoy seguro de si es un error en r108, o si r108 ahora está haciendo las cosas correctamente. ¯_ (ツ) _ / ¯
@pushmatrix se puede comparar con Unity o Blender?
@mrdoob
@pushmatrix
Unity es difícil de ver porque la luz está en la misma dirección que la cámara, pero ¿parece que Unity también está mal? 🤔
@mrdoob
Sí, depende un poco de la iluminación, termina siendo una ilusión y parece que apareció en algunos lugares. Pero cuando giras, desaparece.
Aquí está bajo otra luz, donde parece correcto
@mrdoob Las caras frontales tienen un orden de enrollamiento en sentido antihorario en three.js. Normalmente, los rayos ultravioleta de los 3 vértices de cada cara también tienen un orden de enrollamiento en sentido antihorario en el mapa de rayos ultravioleta.
En este ejemplo, mi _conjetura_ es que el modelo de la izquierda tiene UV en sentido antihorario y el modelo de la derecha tiene UV _ en sentido horario_. El modelo de la derecha se muestra incorrectamente en three.js cuando doubleSide
es true
.
AFAIK, la eliminación de la solución alternativa de Adreno soluciona el problema de las GPU que no son de Adreno.
@pushmatrix Su ejemplo de Unity parece tener luces direccionales desde dos direcciones. Eso hace que sea difícil discernir lo que está sucediendo. Puede ser preferible una sola luz.
@WestLangley Estoy usando el mismo mapa de entorno que usa el visor de modelos , pero es probable que no tenga la misma rotación. Lo intentaré con una sola luz.
@WestLangley Luz direccional única que gira alrededor. Siento que estoy mirando una ilusión óptica
Parece que Unity hace que los surcos entren y salgan dependiendo de cómo la luz lo golpee, pero al menos es consistente para ambos.
Threejs también es consistente, pero uno definitivamente parece siempre salido:
Siento que hay algo mal en el de Unity ...
Como si necesitara algo como. material.normalMapScale.x = -1
.
@WestLangley
@mrdoob Las caras frontales tienen un orden de enrollamiento en sentido antihorario en three.js. Normalmente, los rayos ultravioleta de los 3 vértices de cada cara también tienen un orden de enrollamiento en sentido antihorario en el mapa de rayos ultravioleta.
En este ejemplo, mi _conjetura_ es que el modelo de la izquierda tiene UV en sentido antihorario y el modelo de la derecha tiene UV _ en sentido horario_. El modelo de la derecha se muestra incorrectamente en three.js cuando
doubleSide
estrue
.AFAIK, la eliminación de la solución alternativa de Adreno soluciona el problema de las GPU que no son de Adreno.
Gracias, eso tiene sentido. Sin embargo, creo que aún merece más investigación. Si Sketchfab se ve correcto en todos los dispositivos, es posible que tengamos que mirar sus sombreadores.
Hoy eché un vistazo al código de sombreado respectivo y parece que no están usando "Asignación normal de espacio tangente por píxel".
Según esta publicación , Sketchfab espera definiciones tangentes en los activos o estos datos son
generar basado en coordenadas uv. Eso corresponde a lo que he visto en el código GLSL.
Si agrego tangentes al modelo a través de BufferGeometryUtils.computeTangents()
y establezco Material.vertexTangents
en true
, el resultado parece correcto:
Por cierto: ¿Está bien compartir fragmentos de código de Sketchfab en esta publicación ^^? Después de todo, no es de código abierto.
Para mayor coherencia, aquí está Sketchfab con 1 luz direccional moviéndose hacia adelante y hacia atrás:
Sí, una cosa a tener en cuenta es que Sketchfab procesa en su extremo cuando subes un modelo, por lo que es muy probable que estén generando o cambiando cosas. Lo que está viendo no es un glTF sino un archivo glTF convertido a su propio formato.
@pushmatrix ¿Puede
three.js calcula tangentes en el sombreador de fragmentos. Creo que funciona correctamente si se elimina un truco para acomodar ciertas GPU Adreno con errores. Ver # 17958.
//
Sketchfab calcula tangentes en la CPU cuando se requieren tangentes y no las proporciona el modelo. ( @donmccurdy Esto es lo que requiere la especificación glTF).
three.js también puede hacer eso, pero significará agregar tangentes correctas a todas las geometrías integradas. three.js también tendrá que implementar el algoritmo MIKKTSpace para reemplazar ComputeTangents()
. Dado que three.js admite geometrías indexadas y no indexadas, espero que esto requiera un esfuerzo considerable.
¡Lo arregla!
Bien, parece que la solución aquí es revertir la solución alternativa de Adreno (# 17958) y recomendar a las personas que usen BufferGeometryUtils.computeTangents()
cuando el modelo no tiene tangentes y su objetivo es admitir las GPU de Adreno (# 15850) .
¿Suena bien?
Otra solución es llamar BufferGeometryUtils.computeTangents()
en el motor automáticamente cuando no se proporciona y eliminar todo el código que calcula tangentes en el sombreador de fragmentos ... 🤔
BufferGeometryUtils.computeTangents()
actualmente requiere un índice, por lo que no se puede usar en el núcleo. Sin embargo, creo que sería preferible si three.js
pudiera generar tangentes según MIKKTSpace en algún momento y luego eliminar perturbNormal2Arb()
.
@WestLangley escribió:
significará agregar tangentes correctas a todas las geometrías integradas.
Cambiando de opinión ... Las tangentes no son necesariamente necesarias. En su lugar, restauraría el método BufferGeometry.computeTangents()
y "anularía" ese método para todas las geometrías integradas para las que podemos establecer tangentes exactas analíticamente.
//
Otra solución es llamar a BufferGeometryUtils.computeTangents () en el motor automáticamente cuando no se proporciona y eliminar todo el código que calcula tangentes en el sombreador de fragmentos ...
Suena bien para mi.
BufferGeometryUtils.computeTangents () actualmente requiere un índice, por lo que no se puede usar en el núcleo.
Creo que se soluciona fácilmente. Y tendrá que arreglarse para admitir https://github.com/mrdoob/three.js/issues/17804#issuecomment -557135610.
sería preferible si three.js pudiera generar tangentes de acuerdo con MIKKTSpace en algún momento y luego eliminar perturbNormal2Arb () ...
No sé si MikkTSpace debería reemplazar necesariamente el cálculo del sombreador de fragmentos. El sombreador casi no tiene costo de rendimiento y funciona bien para la mayoría de modelos. La precomputación de tangentes tiene un costo inicial por vértice cada vez, y ningún beneficio excepto en estos casos específicos. 😕 A pesar de lo que dice la especificación glTF, me cuesta mucho justificar hacerlo de forma predeterminada.
Sería bueno si BufferGeometryUtils.computeTangents
pudiera implementar el enfoque MikkTSpace; ese es el mejor algoritmo, si debe calcularlos previamente. Pero probablemente sería más fácil poner MikkTSpace en herramientas como glTF-Pipeline o gltfpack, que pueden usar la implementación nativa existente y hacer el cálculo por adelantado, sin conexión.
@donmccurdy
Pero, digamos ... en el caso de uso <model-viewer>
, no creo que haya una forma confiable de saber si el usuario tiene una GPU Adreno, pero nos gustaría ver bien (https: // github. com / GoogleWebComponents / model-viewer / issues / 740).
¿Debería <model-viewer>
(y otros proyectos que quieran compatibilidad con x-gpu) llamar a BufferGeometryUtils.computeTangents
cuando no se proporcionan tangentes, o debería Tres?
@pushmatrix
Jaja, me acabo de dar cuenta de dónde son estas ruedas 😁
@mrdoob 🕵
Bien, revertiremos la solución por ahora.
Comentario más útil
¡Lo arregla!