Ich habe gerade angefangen, openGL zu lernen und bekomme dieses Artefakt, wenn ich eine Kugel mit Mipmaps texturiere. Wenn das Fragment den Rand meiner Textur abtastet, erkennt es die Diskontinuität (z. B. von 1 bis 0) und wählt die kleinste Mipmap aus, wodurch diese hässliche Naht entsteht:
hässliche Naht http://cdn.imghack.se/images/6bbe0ad0173cac003cd5dddc94bd43c7.png
Also habe ich versucht, die Verläufe manuell mit texturGrad zu überschreiben:
//fragVert is the original vertex from the vertex shader
vec2 ll = vec2((atan(fragVert.y, fragVert.x) / 3.1415926 + 1.0) * 0.5, (asin(fragVert.z) / 3.1415926 + 0.5));
vec2 ll2 = ll;
if (ll.x < 0.01 || ll.x > 0.99)
ll2.x = .5;
vec4 surfaceColor = textureGrad(material.tex, ll, dFdx(ll2), dFdy(ll2));
Jetzt bekomme ich zwei Nähte statt einer. Wie kann ich sie loswerden? Und warum erzeugt der obige Code 2 Nähte?
2 eams http://cdn.imghack.se/images/44a38ef13cc2cdd801967c9223fdd2d3.png
Sie können es nicht an den beiden Bildern erkennen, aber die beiden Nähte befinden sich auf beiden Seiten der ursprünglichen Naht.
Antworten:
Basierend auf dem Shader-Code, den Sie veröffentlicht haben, interpolieren Sie nicht die UVs von den Scheitelpunkten, sondern es scheint, dass Sie die 3D-Position interpolieren (
fragVert
) und berechnen dann die UVs durch Transformation in sphärische Koordinaten.Ihre Analyse ist insofern korrekt, als die kleinste Mipmap ausgewählt wird, wenn eine Diskontinuität vorliegt, da die Auswahl der Mipmap auf Ableitungen basiert, die numerisch aus den in benachbarten Pixeln verwendeten UVs geschätzt werden. Wenn ein Pixel u = 0 und ein anderes u = 1 hat, erhalten Sie eine sehr große Ableitung. Ihr versuchter Fix hat das gleiche Problem, da große Ableitungen um u = 0,01 und u = 0,99 auftreten, weshalb zwei Nähte auf beiden Seiten der ursprünglichen Naht erscheinen.
Ein relativ einfacher Ansatz zur Behebung des Problems wäre die Entscheidung, welche Mip-Ebene Sie verwenden und anrufen möchten
textureLod
, um sie direkt zu testen. Wenn sich der Planet immer ziemlich nahe an der Kamera befindet, können Sie den Mip-Pegel einfach auf 0 fest codieren (oder die Mip-Pegel überhaupt nicht in die Textur aufnehmen). Andernfalls könnte es auf dem log2 der Entfernung des Punkts von der Kamera basieren, skaliert durch einige geeignete Faktoren. Beachten Sie, dass dadurch die anisotrope Filterung effektiv deaktiviert wird.Ein "korrekterer" Ansatz wäre die Berechnung einiger Derivate höherer Qualität. Anstatt
dFdx
unddFdy
auf den UVs zu verwenden, die aufgrund der Diskontinuitäten aufweisenatan2
, können SiedFdx
unddFdy
auffragVert
(die rund um die Kugel kontinuierlich sind) anwenden und dann einen Kalkül (Kettenregel) verwenden, um die Formel zu finden, um die UV-Derivate zu erhalten aus den Positionsderivaten. Dies ist komplizierter und langsamer, hat jedoch den Vorteil, dass die anisotrope Filterung funktionieren sollte.Da Sie OpenGL noch nicht kennen, möchte ich nur darauf hinweisen, dass die Berechnung von UV-Strahlen aus sphärischen Koordinaten zwar eine absolut gültige Methode zur Texturierung einer Kugel darstellt, die meisten Menschen jedoch nicht die "übliche" Methode wählen. Es ist üblicher, ein Kugelnetz zu erstellen, bei dem UVs pro Scheitelpunkt angegeben und einfach vom Scheitelpunkt-Shader zum Pixel-Shader übergeben werden (linear über jedes Dreieck interpoliert). Scheitelpunkte werden entlang der Naht so platziert , dass zwei Kopien jedes Scheitelpunkts an genau denselben Positionen vorhanden sind, wobei die Hälfte mit u = 0 auf einer Seite mit den Dreiecken verbunden ist und die andere Hälfte mit u = 1 verbunden ist die Dreiecke auf der anderen Seite. Dies eliminiert jede sichtbare Naht und erfordert keine Tricks im Pixel-Shader.
quelle