Bufor głębokości jest bardziej zasłonięty niż myślisz w OpenGL ES; nie tylko jest nieobecny glDrawPixels, ale gl_FragDepth został usunięty z GLSL. Nie można więc pisać niestandardowego modułu cieniującego do buforowania wartości do bufora głębi, ponieważ może to spowodować przesunięcie kolorów.
Najbardziej oczywistym rozwiązaniem jest spakowanie informacji o głębi do tekstury i użycie niestandardowego modułu cieniującego fragmentu, który dokonuje porównania głębi między fragmentem, który generuje, a jednym, na podstawie dostarczonej tekstury. Tylko wtedy, gdy wygenerowany fragment jest bliżej, można kontynuować. Normalny bufor głębi będzie wychwytywał inne przypadki okluzji i - w zasadzie - możesz użyć obiektu framebuffer do stworzenia tekstury głębi, co zapewni kompletny trip podczas GPU, chociaż nie jest bezpośrednio związany z twoim problem.
Wady polegają na tym, że rysunek będzie kosztować dodatkową jednostkę tekstur, a tekstury będą zawierać elementy całkowite.
EDYCJA: w celu zachowania prostego przykładu, załóżmy, że pakujesz wszystkie informacje o głębi w czerwonym kanale tekstury. Że daje bufor bardzo niskiej głębi precyzja, ale tylko do przechowywania rzeczy jasne, można napisać krótki fragment shader jak:
void main()
{
// write a value to the depth map
gl_FragColor = vec4(gl_FragCoord.w, 0.0, 0.0, 1.0);
}
głębokości Przechowywać w czerwonym kanale. Częściowo ponownie utworzyłeś stare rozszerzenie głębi - otrzymasz obraz, który będzie miał jaśniejszą czerń w pikselach, które są bliższe, ciemniejsze czerwone w pikselach, które są dalej. Myślę, że w twoim pytaniu faktycznie załadowałbyś ten obraz z dysku.
Aby następnie użyć tekstury w przyszłej cieniującego fragmentu, można zrobić coś takiego:
uniform sampler2D depthMap;
void main()
{
// read a value from the depth map
lowp vec3 colourFromDepthMap = texture2D(depthMap, gl_FragCoord.xy);
// discard the current fragment if it is less close than the stored value
if(colourFromDepthMap.r > gl_FragCoord.w) discard;
... set gl_FragColor appropriately otherwise ...
}
Edit2: widać wiele mądrzejszy mapowanie z głębokości do wartości RGBA here. Aby powiązać bezpośrednio z tym dokumentem, OES_depth_texture zdecydowanie nie jest obsługiwany na iPadzie lub iPodzie trzeciej generacji. Nie przeprowadziłem pełnego testu w innym miejscu.
Dziękuję za odpowiedź. Czy mogłabyś omówić nieco temat podróży w GPU, o której mówisz? Nie jestem do końca pewien, że rozumiem tę część. – sharvey
Nie jest to całkowicie związane z pytaniem, które zadajesz - jest ono bardziej odpowiednie w przypadku pytania "Jak używać mapy głębi do cieniowania", gdzie faktycznie narysujesz coś, aby utworzyć mapę głębi na GPU i zachować mapę na później, zamiast ładować go z dysku. Ale dodałem krótki przykładowy kod, który może być nieco niejasny? – Tommy
Wow, dziękuję bardzo. – sharvey