Beim Upgrade von 107 auf 108 habe ich festgestellt, dass Teile meines Modells jetzt so aussehen, als hätten sie Normalen umgedreht. Dies tritt nur bei doppelseitigen Materialien auf.
Siehe hier: https://vaulted-jonquil.glitch.me/
So sollte es aussehen, wobei das Muster auf beiden Rädern eingerückt ist. So war es in 107
Im Jahr 108 sieht eines der Räder so aus, als würde es herausspringen:
@pushmatrix Können Sie bestätigen, ob dieses Modell seine eigenen Tangenten liefert oder nicht? Ich bin gespannt, ob dies mit # 11438 zusammenhängt.
Ich glaube nicht, dass es seine eigenen Tangenten spezifiziert
Unter Verwendung eines anderen Testfalls zeigt git bisect auf # 17586 als PR, die das Problem ausgelöst hat, wenn das Netz doppelseitig ist und eine negative Skala X aufweist. Dies war jedoch in r.109, nicht in r.108.
Dies wurde an dem Modell aus dieser PR nicht getestet, da dieses Modell nicht verfügbar ist.
Hier ist der Test glb
rad.glb.zip
Von vor 3 Jahren: https://github.com/mrdoob/three.js/issues/10331#issue -194807426
Grundsätzlich scheint es, dass ... gl_FrontFace mit doppelseitigen Materialien auf Adreno-GPUs nicht richtig funktioniert.
Ist dies immer noch ein Problem, das wir berücksichtigen müssen?
// //
Dieses Modell scheint auf meinem Computer korrekt zu rendern, wenn wir die Adreno-Problemumgehung in normalmap_pars_fragment
entfernen:
#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, ich erinnere mich, dass ich diesen Kommentar auch gelesen habe; Ich glaube, ich bin darauf gestoßen, als ich mir diesen Fehler angesehen habe, der anscheinend in r108 behoben wurde (zumindest das Upgrade hat ihn für uns behoben): https://github.com/GoogleWebComponents/model-viewer/issues/740
Vielleicht ist es verwandt? FWIW, ich habe einige Rückmeldungen zu alten Adreno-GPUs erhalten, daher sind sie anscheinend immer noch ziemlich verbreitet.
Nur zur Bestätigung, dies geschieht immer noch in dev
:
Nur um zu bestätigen, passiert dies immer noch in dev:
Recht. Aber nicht, wenn Sie die Adreno-Fehlerumgehung entfernen.
Aber nicht, wenn Sie die Adreno-Fehlerumgehung entfernen.
Wie wäre es, wenn Sie die Problemumgehung vorerst entfernen und dann nach einer anderen Lösung suchen? Die aktuelle Implementierung führt zu falschen Grafiken, unabhängig davon, welche Plattform Sie verwenden.
@ Mugen87 In diesem speziellen Fall glaube ich, dass die Geometrien Spiegel voneinander sind, aber sie haben dieselbe normale Karte.
Ich stimme mit Ihnen ein. Ich habe viele Stunden investiert, um eine Adreno-kompatible Problemumgehung zu finden, die in jedem Anwendungsfall korrekt ist.
Bei der Inspektion des Radmodellmodells hat jedes Rad seine eigene UV-Schale. Es teilt keinen.
Und die Scheitelpunktreihenfolge ist entgegengesetzt.
Die Gesichtsausrichtung ist jedoch zumindest in Blender gleich.
Ich bin mir also nicht sicher, ob es sich um einen Fehler in r108 handelt oder ob r108 jetzt die Dinge richtig macht. ¯_ (ツ) _ / ¯
@pushmatrix kannst du mit Unity oder Blender vergleichen?
@mrdoob
@ Pushhmatrix
Unity ist schwer zu erkennen, da das Licht in die gleiche Richtung wie die Kamera gerichtet ist, aber sieht es so aus, als ob Unity auch falsch ist? 🤔
@mrdoob
Ja, es hängt ein bisschen von der Beleuchtung ab, die letztendlich eine Illusion ist und so aussieht, als wäre sie an einigen Stellen aufgetaucht. Aber wenn Sie sich drehen, verschwindet es.
Hier ist es in einem anderen Licht, wo es richtig erscheint
@mrdoob Die Vorderseite hat eine Wicklungsreihenfolge gegen den Uhrzeigersinn in drei.js. Typischerweise haben die UVs der 3 Eckpunkte jeder Fläche auch eine Wicklungsreihenfolge gegen den Uhrzeigersinn auf der UV-Karte.
In diesem Beispiel ist meine Vermutung, dass das Modell links UVs gegen den Uhrzeigersinn und das Modell rechts UVs im Uhrzeigersinn hat. Das Modell rechts wird in three.js falsch gerendert, wenn doubleSide
true
.
AFAIK, das Entfernen der Adreno-Problemumgehung behebt das Problem für Nicht-Adreno-GPUs.
@pushmatrix Ihr Unity-Beispiel scheint Richtungslichter aus zwei Richtungen zu haben. Das macht es schwierig zu erkennen, was los ist. Ein einzelnes Licht kann vorzuziehen sein.
@WestLangley Ich verwende dieselbe Umgebungskarte, die der Modellbetrachter verwendet, aber wahrscheinlich hat sie nicht dieselbe Drehung. Ich werde es mit einem einzigen Licht versuchen.
@WestLangley Licht in einer Richtung, das sich dreht. Ich habe das Gefühl, eine optische Täuschung zu betrachten
Scheint, als würde Unity die Rillen ein- und ausblenden lassen, je nachdem, wie das Licht darauf trifft, aber zumindest ist es für beide gleich.
Threejs ist auch konsistent, aber man sieht definitiv immer herausgesprungen aus:
Ich habe das Gefühl, dass in der Einheit etwas nicht stimmt ...
Als ob es so etwas braucht. material.normalMapScale.x = -1
.
@ WestLangley
@mrdoob Die Vorderseite hat eine Wicklungsreihenfolge gegen den Uhrzeigersinn in drei.js. Typischerweise haben die UVs der 3 Eckpunkte jeder Fläche auch eine Wicklungsreihenfolge gegen den Uhrzeigersinn auf der UV-Karte.
In diesem Beispiel ist meine Vermutung, dass das Modell links UVs gegen den Uhrzeigersinn und das Modell rechts UVs im Uhrzeigersinn hat. Das Modell rechts wird in three.js falsch gerendert, wenn
doubleSide
true
.AFAIK, das Entfernen der Adreno-Problemumgehung behebt das Problem für Nicht-Adreno-GPUs.
Danke, das macht Sinn. Ich denke, es verdient noch mehr Nachforschungen. Wenn Sketchfab auf allen Geräten korrekt aussieht, müssen wir uns möglicherweise deren Shader ansehen.
Ich habe mir heute den jeweiligen Shader-Code angesehen und es scheint, dass sie nicht "Per-Pixel Tangent Space Normal Mapping" verwenden.
Laut diesem Beitrag erwartet Sketchfab tangentiale Definitionen in Assets oder diese Daten sind
generieren basierend auf UV-Koordinaten. Das entspricht dem, was ich im GLSL-Code gesehen habe.
Wenn ich dem Modell über BufferGeometryUtils.computeTangents()
Tangenten hinzufüge und Material.vertexTangents
auf true
setze, scheint das Ergebnis in Ordnung zu sein:
Übrigens: Ist es in Ordnung, Codefragmente von Sketchfab in diesem Beitrag zu teilen ^^? Immerhin ist es nicht Open Source.
Aus Gründen der Konsistenz ist hier Sketchfab mit 1 Richtungslicht, das sich hin und her bewegt:
Ja, eine Sache, die Sie beachten sollten, ist, dass Sketchfab die Verarbeitung am Ende durchführt, wenn Sie ein Modell hochladen. Es ist also sehr wahrscheinlich, dass sie Dinge generieren / ändern. Was Sie anzeigen, ist keine glTF-Datei, sondern eine in ihr eigenes Format konvertierte glTF-Datei.
@pushmatrix Können Sie bitte zeigen, dass # 17958 für Ihr Modell funktioniert?
three.js berechnet Tangenten im Fragment-Shader. Ich glaube, es funktioniert richtig, wenn ein Hack zur Aufnahme bestimmter fehlerhafter Adreno-GPUs entfernt wird. Siehe # 17958.
// //
Sketchfab berechnet Tangenten auf der CPU, wenn Tangenten erforderlich sind und nicht vom Modell bereitgestellt werden. ( @donmccurdy Dies ist, was die glTF-Spezifikation erfordert.)
three.js kann das auch, aber es bedeutet, allen eingebauten Geometrien korrekte Tangenten hinzuzufügen. three.js muss auch den MIKKTSpace-Algorithmus implementieren, um ComputeTangents()
zu ersetzen. Da three.js sowohl indizierte als auch nicht indizierte Geometrien unterstützt, gehe ich davon aus, dass dies einen erheblichen Aufwand erfordert.
Behebt es!
Okay, die Lösung hier scheint also darin zu bestehen, die Adreno-Problemumgehung (# 17958) zurückzusetzen und den Leuten zu empfehlen, BufferGeometryUtils.computeTangents()
wenn das Modell keine Tangenten aufweist und Adreno-GPUs unterstützen sollen (# 15850). .
Klingt gut?
Eine andere Lösung besteht darin, BufferGeometryUtils.computeTangents()
in der Engine automatisch aufzurufen, wenn dies nicht bereitgestellt wird, und den gesamten Code zu entfernen, der Tangenten im Fragment-Shader berechnet ... 🤔
BufferGeometryUtils.computeTangents()
benötigt derzeit einen Index, sodass er nicht im Kern verwendet werden kann. Ich denke jedoch, es wäre vorzuziehen, wenn three.js
irgendwann Tangenten gemäß MIKKTSpace erzeugen und dann perturbNormal2Arb()
entfernen könnte.
@ WestLangley schrieb:
Dies bedeutet, dass allen integrierten Geometrien korrekte Tangenten hinzugefügt werden.
Meine Meinung ändern ... Tangenten sind nicht unbedingt erforderlich. Stattdessen würde ich die Methode BufferGeometry.computeTangents()
wiederherstellen und diese Methode für alle integrierten Geometrien "überschreiben", für die wir genaue Tangenten analytisch festlegen können.
// //
Eine andere Lösung besteht darin, BufferGeometryUtils.computeTangents () in der Engine automatisch aufzurufen, wenn dies nicht bereitgestellt wird, und den gesamten Code zu entfernen, der Tangenten im Fragment-Shader berechnet ...
Das klingt für mich richtig.
BufferGeometryUtils.computeTangents () benötigt derzeit einen Index, sodass er nicht im Kern verwendet werden kann.
Ich denke das ist leicht zu beheben. Und es muss behoben werden, um https://github.com/mrdoob/three.js/issues/17804#issuecomment -557135610 zu unterstützen.
Es wäre vorzuziehen, wenn three.js irgendwann Tangenten gemäß MIKKTSpace erzeugen und dann perturbNormal2Arb () entfernen könnte ...
Ich weiß nicht, ob MikkTSpace die Fragment-Shader-Berechnung unbedingt ersetzen sollte. Der Shader hat fast keine Leistungskosten und funktioniert für die meisten Modelle einwandfrei. Das Berechnen von Tangenten hat jedes Mal Vorabkosten pro Scheitelpunkt und keinen Vorteil, außer in diesen speziellen Fällen. 😕 Trotz der Angaben in der glTF-Spezifikation fällt es mir schwer, dies standardmäßig zu rechtfertigen.
Es wäre schön, wenn BufferGeometryUtils.computeTangents
den MikkTSpace-Ansatz implementieren könnte - das ist der beste Algorithmus, wenn Sie sie vorberechnen müssen. Es wäre jedoch wahrscheinlich einfacher, MikkTSpace in Tools wie glTF-Pipeline oder gltfpack zu integrieren, die die vorhandene native Implementierung verwenden können, und die Berechnung im Voraus offline durchzuführen.
@donmccurdy
Aber sagen wir ... im Anwendungsfall <model-viewer>
gibt es meines Erachtens keinen zuverlässigen Weg, um festzustellen, ob der Benutzer eine Adreno-GPU hat, aber wir möchten richtig aussehen (https: // github. com / GoogleWebComponents / model-viewer / issue / 740).
Sollte <model-viewer>
(und andere Projekte, die x-gpu-Unterstützung wünschen) BufferGeometryUtils.computeTangents
aufrufen, wenn keine Tangenten bereitgestellt werden, oder sollte Three?
@ Pushhmatrix
Haha, ich habe gerade gemerkt, woher diese Räder kommen 😁
@mrdoob 🕵
Okay, dann lassen Sie uns die Problemumgehung vorerst zurücksetzen.
Hilfreichster Kommentar
Behebt es!