Autor Wątek: [Android] FBO depth texture i MRT  (Przeczytany 1677 razy)

Offline PsichiX (ΨΧΞ)

  • Użytkownik
    • PsichiX Website

# Grudzień 18, 2012, 00:28:06
Witam,
przeszukalem przez ostatnie 3 dni internety na rozne mozliwe sposoby w celu dowiedzenia sie, jak uzyskac mozliwosc renderowania glebi na androidzie w OpenGL ES 2.0 i wnioski znalazlem nastepujace:
1. nie mozna renderowac do tekstury o formacie Depth Component.
- wpadlem zatem na pomysl, aby uzyc MRT i do jednej tekstury zapisywac kolor, a do drugiej glebie (takze jako kolor, czyli fbo w postaci: 2x rgba texture + depth render buffer), niestety:
2. w OglEs 2.0 mozna zapisywac jednoczesnie tylko do jednej tekstury, no chyba, ze masz Tegre, ale malo kto ma, a ja na pewno nie.

Zasmucilo mnie to niezmiernie i w akcie desperacji przyszedlem tu zasiegnac Waszego doswiadczenia.
Czy jest jakikolwiek sposob na wyrenderowanie glebi do tekstury? Ewentualnie co mozecie mi doradzic w kwestii MRT - da sie go trickiem jakims uzyskac?
Chyba, ze moje wnioski sa bledne, to bylbym rad takze za wytkniecie mi tego i mozliwe nakierowanie mnie na materialy traktujace o rozwiazaniu mojego problemu.
Z gory ogromne dzieki!

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline koirat

  • Użytkownik

# Grudzień 18, 2012, 01:33:24
RTT - Prawdopodobnie będziesz musiał wyrenderować do tekstury samą głębie . Czyli ponownie wyrenderować wszystkie modele.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Grudzień 18, 2012, 01:34:35
Nie wiem co próbujesz zrobić, ale z perspektywy komórek najwyraźniej robisz to nieoptymalnie. :)

Offline PsichiX (ΨΧΞ)

  • Użytkownik
    • PsichiX Website

# Grudzień 18, 2012, 01:39:47
Krzysku, probuje zachowac informacje o glebi. Jak moge to zrobic optymalnie? pomysl koirata jest dobry, aczkolwiek powolny.

Offline Armageddon

  • Użytkownik

# Grudzień 18, 2012, 02:06:35
Depth pre-pass. Przed normalnych rysowaniem sceny najpierw rysujemy samą głebie do osobnego rt. Obecnie na telefonach nie da się nic lepszego zrobić. Ewentualnie zaczekać na urządzenia wspierające Opengl ES 3 ;). Z tego co wyczytałem chcesz też zapisywać kolor, więc celujesz coś w rodzaju deffered renderingu, proponuje zapoznaj się z tym linkiem: http://www.altdevblogaday.com/2012/03/01/light-pre-pass-renderer-on-iphone/.

Offline Dab

  • Redaktor
    • blog

# Grudzień 18, 2012, 02:38:29
Można renderować depth pod warunkiem, że masz rozszerzenie OES_depth_texture. Haczyk jest taki, że teksturę określasz jako GL_DEPTH_COMPONENT, GL_UNSIGNED_INT (a nie float jak w desktopowym). Bez tego rozszerzenia musisz renderować do RGBA8 spakowany depth.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Grudzień 18, 2012, 03:09:04
Krzysku, probuje zachowac informacje o glebi. Jak moge to zrobic optymalnie? pomysl koirata jest dobry, aczkolwiek powolny.
Stworzyć kilka powierzchni na depth component i je przełączać - zakładając, że nie masz zamiaru wykorzystać wartości głębi bezpośrednio w pixel shaderze.

Offline PsichiX (ΨΧΞ)

  • Użytkownik
    • PsichiX Website

# Grudzień 18, 2012, 10:48:00
Dab: Próbowałem przed napisanem posta sposobu z [GL_DEPTH_COMPONENT, GL_UNSIGNED_INT], ale najwyraźniej nie posiada moje urządzenie rozszerzenia OES_depth_texture, jednak jeśli motyw z RGBA8 i spakowaną głębią nie stosuje się jako color attachment > 0, to jak mógłbym podejść do tego? Próbowałem zastosować po prostu zapis głębi do color attachment 1 i sprzęt nie pozwolił mi na to niestety :<

Offline mihu

  • Użytkownik
    • mihu

# Grudzień 18, 2012, 10:56:57
Dab: Próbowałem przed napisanem posta sposobu z [GL_DEPTH_COMPONENT, GL_UNSIGNED_INT], ale najwyraźniej nie posiada moje urządzenie rozszerzenia OES_depth_texture, jednak jeśli motyw z RGBA8 i spakowaną głębią nie stosuje się jako color attachment > 0, to jak mógłbym podejść do tego? Próbowałem zastosować po prostu zapis głębi do color attachment 1 i sprzęt nie pozwolił mi na to niestety :<
MRT jak zauważyłeś nie ma, więc ta głębia w RGBA8 musi iść w jedyny, domyślny rendertarget. Koloru w tym samym czasie nie narysujesz.

BTW, sprawdź czy się nie kopsłeś, bo wydaje mi się że rozszerzenie depth_texture jest już dziś praktycznie wszędzie, więc jeśli nie masz trzyletniego telefonu, to powinno być i u ciebie.

Offline PsichiX (ΨΧΞ)

  • Użytkownik
    • PsichiX Website

# Grudzień 18, 2012, 11:08:24
Samsung Galaxy Pocket, nie sprawdzalem, ale zaraz postaram sie wylistowac swoje rozszerzenia. btw. jesli okazaloby sie, ze jednak mam, to czy trzeba jakos aktywowac owo rozszerzenie, czy ja po prostu skopalem inicjalizacje tekstury i kontekstu? :D

PS. Dodam, ze nie pisze natywnie, tylko całośc po stronie javy i GLES20

Offline .:NOXY:.

  • Użytkownik
    • Profil

  • +1
# Grudzień 18, 2012, 11:29:21
Jak reszta mowi nie da sie ogarnac DEPTH + COLOR w jednym passie aktualnie :) co do tworzenia glebi mi sie udalo z tym RGBA8 ale jest wolniejsze od zwyklego: Cienie RGBA8 co do tworzenia textury DEPTH to ja to robie tak:

bool FrameBufferObject::CreateDepth(GLuint width, GLuint height)
{
   
    m_nWidth = width;
m_nHeight = height;

    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &m_oldBuffer);

    glGenTextures(1, &m_nTexId);
    glBindTexture(GL_TEXTURE_2D, m_nTexId);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_OES, width, height,
                 0,
                 GL_DEPTH_STENCIL_OES,
                 GL_UNSIGNED_INT_24_8_OES,
                 NULL);

//JAK NIE DZIALA TO WYZEJ TO DAJ ZWYKLY 16bitowy

//    glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT,width,height,
//                 0,
//                 GL_DEPTH_COMPONENT,
//                 GL_UNSIGNED_SHORT,
//                 NULL );
   
    glBindTexture(GL_TEXTURE_2D, 0);
   
    glGenFramebuffers(1, &m_nFrameBufferHandle);
    glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBufferHandle);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_nTexId, 0);
   
    CheckStatus();
   
glBindFramebuffer(GL_FRAMEBUFFER, m_oldBuffer);
   
    return true;
}

a przy wersji RGBA8 robisz FBO zwykly RGBA

PAKOWANIE:

//VS
precision highp float;

uniform mat4 projection;
uniform mat4 modelViewWorld;

attribute vec4 aPosition;

varying vec4 position;

void main() {
gl_Position = projection * modelViewWorld * aPosition;
    position = gl_Position;
}

//PS
precision highp float;

varying vec4 position;

void main() {
float normalizedDistance  = position.z / position.w;
normalizedDistance = (normalizedDistance + 1.0) * 0.5;
    //normalizedDistance += 0.0000000001;
   
    const vec4 packFactors = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
const vec4 bitMask     = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
   
vec4 packedValue = vec4(fract(packFactors*normalizedDistance));
packedValue -= packedValue.xxyz * bitMask;
gl_FragColor  = packedValue;   
}

/*

 0.431211921 Przykladowa liczba do spakowania
 
 Mnozymy liczbe razy encoder
 
 (0.431211921, 0.431211921, 0.431211921, 0.431211921) * (1.0, 256.0, 65536.0, 16777216.0) =

 wynikiem tego dzialania bedzie:
 (0.431211921, 110.3902518, 28259.90445, 7234535.54)

 //interesuje nas tylko wartosc po przecinku wiec uzyjemy funkcji: x - floor(x) aka Fract
 (0.431211921, 0.3902518, 0.90445, 0.54).
 
 teraz wystarczy przekonvertowac je na RGB
 (110/256, 99/256, 231/256, 138/256).
 
 co da nam przyswajalna wartosc (110, 99, 231, 138).
 
 Dekodowanie to nic innego jak DOT 4 (a.x * b.x + ... + a.w * b.w)
 (110/256, 99/256, 231/256, 138/256) ^
 (1.0, 0.00390625, 0.0000152587890625, 0.000000059604644775390625) =
 0.4296875 + 0.00151062 + 0.000013767 + 0.000000031 =
 0.431211918

 //Oryginalna wartosc to:
 0.431211921
 
 */

ODCZYTYWANIE:

//PS
float getShadowFactor(vec4 lightZ)
{
    vec4 packedZValue = texture2D(shadowtex, lightZ.st);
    vec4 bitShifts = vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1.0);

float unpacked = dot(packedZValue , bitShifts);
return float(unpacked > lightZ.z);
}

Offline Dab

  • Redaktor
    • blog

# Grudzień 18, 2012, 16:56:20
Dab: Próbowałem przed napisanem posta sposobu z [GL_DEPTH_COMPONENT, GL_UNSIGNED_INT], ale najwyraźniej nie posiada moje urządzenie rozszerzenia OES_depth_texture, jednak jeśli motyw z RGBA8 i spakowaną głębią nie stosuje się jako color attachment > 0, to jak mógłbym podejść do tego? Próbowałem zastosować po prostu zapis głębi do color attachment 1 i sprzęt nie pozwolił mi na to niestety :<

MRT jest tylko na OpenGL ES 3.0 i w nowszych Tegrach.