2010-12-26 15 views

Odpowiedz

7

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.

+0

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

+0

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

+0

Wow, dziękuję bardzo. – sharvey