Właśnie zacząłem uczyć się openGL i otrzymuję ten artefakt podczas teksturowania kuli za pomocą mipmap. Zasadniczo, gdy fragment próbkuje krawędź mojej tekstury, wykrywa nieciągłość (powiedzmy od 1 do 0) i wybiera najmniejszą mipmapę, która tworzy ten brzydki szew:
brzydki szew http://cdn.imghack.se/images/6bbe0ad0173cac003cd5dddc94bd43c7.png
Więc próbowałem ręcznie zastąpić gradienty za pomocą textureGrad:
//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));
Teraz dostaję dwa szwy zamiast jednego. Jak mogę się ich pozbyć? I dlaczego powyższy kod generuje 2 szwy?
2 eams http://cdn.imghack.se/images/44a38ef13cc2cdd801967c9223fdd2d3.png
Nie widać na podstawie dwóch zdjęć, ale 2 szwy znajdują się po obu stronach oryginalnego szwu.
Odpowiedzi:
W oparciu o opublikowany kod modułu cieniującego nie interpolujesz promieni UV z wierzchołków - raczej wydaje się, że interpolujesz pozycję 3D (
fragVert
), a następnie obliczasz promieniowanie UV, przekształcając je we współrzędne sferyczne.Twoja analiza jest poprawna, ponieważ najmniejszą mipmapę wybiera się, gdy występuje nieciągłość, ponieważ wybór mipmapy opiera się na pochodnych, które są szacowane liczbowo na podstawie UVs używanych w sąsiednich pikselach. Gdy jeden piksel ma u = 0, a drugi ma u = 1, otrzymujesz bardzo dużą pochodną. Twoja próba naprawy ma ten sam problem, ponieważ duże pochodne występują około u = 0,01 iu = 0,99, dlatego dwa szwy pojawiają się po obu stronach miejsca, w którym znajdował się pierwotny szew.
Stosunkowo proste podejście do rozwiązania problemu polegałoby na podjęciu decyzji, który poziom mipa użyć samemu i wywołaniu w
textureLod
celu jego bezpośredniego pobrania. Jeśli planeta zawsze będzie dość blisko kamery, możesz po prostu zakodować poziom mip na 0 (lub, w tym przypadku, po prostu nie zawierać poziomów mip w teksturze). W przeciwnym razie może być oparty na log2 odległości punktu od kamery, skalowanej przez niektóre odpowiednie czynniki. Zauważ, że to skutecznie wyłączy filtrowanie anizotropowe.Bardziej „poprawnym” podejściem byłoby obliczenie niektórych instrumentów pochodnych wyższej jakości. Zamiast używać
dFdx
idFdy
na UV, które mają nieciągłości z powoduatan2
, możesz zastosowaćdFdx
idFdy
dofragVert
(który będzie ciągły przez całą kulę), a następnie użyj rachunku różniczkowego (reguła łańcuchowa), aby znaleźć wzór na uzyskanie pochodnych UV z pozycji instrumentów pochodnych. Będzie to bardziej skomplikowane i wolniejsze, ale ma tę zaletę, że powinno działać filtrowanie anizotropowe.Wreszcie, ponieważ jesteś nowy w OpenGL, po prostu zauważę, że podczas obliczania UV ze współrzędnych sferycznych jest doskonale poprawnym sposobem na teksturowanie kuli, nie jest to „zwykły” sposób wybierany przez większość ludzi. Bardziej powszechne jest budowanie siatki sferycznej, która ma UV określone dla wierzchołka i po prostu przechodzi z modułu cieniującego wierzchołek do modułu cieniującego piksele (interpolowana liniowo w każdym trójkącie). Wierzchołki są umieszczone wzdłuż szwu, tak , że są dwie kopie każdego wierzchołka, dokładnie w tych samych pozycjach, ale połowa z u = 0 połączona z trójkątami po jednej stronie, a druga połowa z u = 1 połączona z trójkąty po drugiej stronie. Eliminuje to wszelkie widoczne szwy i nie wymaga żadnych sztuczek w module cieniującym piksele.
źródło