W mojej grze jest teren podobny do Minecrafta wykonany z kostek. Generuję bufor wierzchołków na podstawie danych wokseli i używam atlasu tekstur dla wyglądu różnych bloków:
Problem polega na tym, że tekstura odległych kostek interpoluje z sąsiadującymi płytkami w atlasie tekstur. Powoduje to powstawanie linii niewłaściwych kolorów między sześcianami (może być konieczne wyświetlenie poniższego zrzutu ekranu w pełnym rozmiarze, aby zobaczyć wady graficzne):
Na razie korzystam z tych ustawień interpolacji, ale wypróbowałem każdą kombinację, a nawet GL_NEAREST
bez mipmapy nie daje lepszych wyników.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Próbowałem także dodać przesunięcie we współrzędnych tekstury, aby wybrać nieco mniejszy obszar płytki, ale ponieważ niepożądany efekt zależy od odległości do kamery, nie może to całkowicie rozwiązać problemu. I tak na dalekie odległości pojawiają się paski.
Jak mogę rozwiązać problem krwawienia z tekstury? Ponieważ korzystanie z atlasu tekstur jest popularną techniką, może istnieć wspólne podejście. Niestety, z kilku powodów wyjaśnionych w komentarzach, nie mogę przejść na inne tekstury lub tablice tekstur.
GL_LINEAR
co daje podobny wynik, lub wybiera najbliższy piksel,GL_NEAREST
który i tak skutkuje pasami między blokami. Ostatnia wspomniana opcja zmniejsza się, ale nie eliminuje wady pikseli.Odpowiedzi:
Okej, myślę, że masz tutaj dwa problemy.
Pierwszy problem dotyczy mipmapowania. Ogólnie rzecz biorąc, nie chcesz naiwnie mieszać atlasingu z mipmapowaniem, ponieważ jeśli wszystkie twoje podteksty nie będą miały dokładnie rozmiaru 1 x 1 piksela, wystąpi krwawienie tekstury. Dodanie dopełnienia spowoduje po prostu przeniesienie problemu na niższy poziom mip.
Zasadniczo w przypadku 2D, czyli tam, gdzie zwykle wykonujesz atlasing, nie mipmapujesz; podczas gdy w 3D, w którym mipmapujesz, nie atlasujesz (w rzeczywistości masz skórę w taki sposób, że krwawienie nie będzie problemem)
Jednak myślę, że w twoim programie dzieje się teraz to, że prawdopodobnie nie używasz prawidłowych współrzędnych tekstury i dlatego krwawią tekstury.
Załóżmy, że jest to tekstura 8x8. Prawdopodobnie dostajesz lewy górny kwartał, używając współrzędnych UV od (0,0) do (0,5, 0,5):
Problem polega na tym, że przy współrzędnej U 0,5 próbnik interpoluje docelowy fragment przy użyciu połowy lewego texela i połowy prawego texel. To samo wydarzy się przy współrzędnej u 0, i to samo dla współrzędnych v. Wynika to z faktu, że zajmujesz się granicami między teksturami, a nie środkami.
To, co powinieneś zamiast tego zrobić, to skierować środek każdego texla. W tym przykładzie są to współrzędne, których chcesz użyć:
W takim przypadku zawsze będziesz próbkować środek każdego tekstu i nie powinieneś krwawić ... Chyba że użyjesz mipmapowania, w którym to przypadku zawsze zaczniesz krwawić, zaczynając od poziomu mip, w którym skalowana podtekst nie jest starannie mieści się w siatce pikseli .
Aby uogólnić, jeśli chcesz uzyskać dostęp do konkretnego tekstu, współrzędne są obliczane jako:
Nazywa się to „poprawką o pół piksela”. Jest bardziej szczegółowe wyjaśnienie w tutaj jeśli jesteś zainteresowany.
źródło
Jedną z opcji, która będzie o wiele łatwiejsza niż manipulowanie mipmapami i dodawanie współczynników fuzji współrzędnych tekstury, jest użycie tablicy tekstur. Tablice tekstur są podobne do tekstur 3D, ale bez mipmapowania w trzecim wymiarze, dlatego idealnie nadają się do atlasów tekstur, w których „podtekstury” są tego samego rozmiaru.
http://www.opengl.org/wiki/Array_Texture
źródło
Po wielu problemach z tym problemem w końcu znalazłem rozwiązanie.
Aby użyć zarówno atlasu tekstur, jak i mipmapowania, muszę wykonać próbkowanie w dół, ponieważ OpenGL inaczej interpolowałby poza granice kafelków w atlasie. Ponadto musiałem ustawić odpowiednie parametry tekstury, ponieważ interpolacja między mipmapami spowodowałaby również krwawienie tekstury.
Przy tych parametrach nie występuje krwawienie.
Jedną z rzeczy, na które musisz zwrócić uwagę, dostarczając niestandardowe mipmapy. Ponieważ nie ma sensu zmniejszać atlasu, nawet jeśli każdy kafelek już jest
1x1
, maksymalny poziom mipmapy musi być ustawiony zgodnie z tym, co podajesz.Dziękujemy za wszystkie pozostałe odpowiedzi i bardzo pomocne komentarze! Nawiasem mówiąc, wciąż nie wiem, jak używać liniowego skalowania w górę, ale myślę, że nie ma mowy.
źródło
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_NEAREST_MIPMAP_LINEAR);
GL_TEXTURE_MAX_FILTER
doGL_NEAREST_MIPMAP_LINEAR
przyczyn nie krwawienia z przyczyny mipmappingu, ale z powodu interpolacji. Więc w tym przypadku jest to równoważne,GL_LINEAR
ponieważ i tak używany jest najniższy poziom mipmap.glTexImage2D()
. GPU automatycznie wybiera odpowiedni poziom w oparciu o rozmiar obiektów na ekranie.Wygląda na to, że problem może być spowodowany przez MSAA. Zobacz tę odpowiedź i powiązany artykuł :
Rozwiązaniem jest użycie próbkowania centroid. Jeśli obliczasz zawijanie współrzędnych tekstury w module cieniującym wierzchołki, przeniesienie tej logiki do modułu cieniującego fragmenty może również rozwiązać problem.
źródło
To jest stary temat i miałem podobny problem do tematu.
Miałem współrzędne tekstury w porządku, ale przez zmianę położenia kamery (która zmieniła pozycje mojego elementu) tak:
Cały problem polegał na tym, że Util.lerp () zwraca liczbę zmiennoprzecinkową lub podwójną. Było to złe, ponieważ kamera tłumaczyła poza siecią i powodowała dziwne problemy z fragmentami tekstur, w których> 0 w X i> 0 w Y.
TLDR: nie animuj ani nie używaj pływaków
źródło