Autor Wątek: Rekonstrukcja pozycji z depthmapy problem  (Przeczytany 998 razy)

Offline JacekCichy

  • Użytkownik

# Styczeń 26, 2012, 15:09:44
Witam,
Ostatnio sobie analizuje różne sposoby rekonstrukcji pozycji i szczególną uwagę zwróciłem na jeden w którym pozycjaXYZ = EyeVec * DepthValue. Sprytne natomiast nie do końca to rozumiem, a mianowicie:
1. Do napisanej funkcji przekazuje współrzędne tekstury u i v dla których to wartości chcę zrekonstruować pozycje.
2. Wektor "oka" tworzę jako vec3((2*u-1)*aspect, 2*(1-v)-1, 1/tg(fov/2))
3. Powyższy wektor normalizuje

I po tym kroku pojawia się cały problem bo jeżeli przyjmiemy że np. nearClipPlane(n) = 0.1, a farClipPlane(f) = 1000 to wyjmując wartość głębi dla danego u i v a następnie ją linearyzując powinno się ją z zakresu [0, 1] przenieść do zakresu [0.1, 1000] przy pomocy bardzo prostego wzoru a mianowicie: DepthValue*(f-n) + n i po tym kroku dopiero wymnarzać przez wartość "wektora oka". No właśnie a w żadnym pseudokodzie ani też w prawdziwym kodzie jaki udało mi się znaleźć w sieci czegoś takiego nie ma. Jedyne co jest wykonywane to mnożenie wektora oka razy wartość zlinearyzowanej głębi czyli defacto wartości z przedziału [0 1]. No i stąd moje pytanie czy to ja coś źle myśle czy może w pseudokodach jest jakiś ukryty trik z np. wartością w i moje myślenie nie jest złe. Tak ogólnie chciałem zapytać co o tym myślicie no i zrozumieć wreszcie jak to działa do końca :) Z góry dzięki za zainteresowanie.   

Offline Mr. Spam

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

Offline KriS

  • Użytkownik
    • KriS

# Styczeń 26, 2012, 22:33:44
Myślenie jest dobre. DepthValue to ZBufferValue*(f-n) + n. Idea polega na tym aby zapisać taką głębokość do render targetu i używać go później do dekodowania.

Offline JacekCichy

  • Użytkownik

# Styczeń 28, 2012, 23:46:05
KriS dzieki za zainteresowanie :). Dziś ostatecznie udało mi się osiągnąć cel tj. zrekonstruować pozycje, jednak nie przy pomocy depthmapy, a mapy typu R32F w ktorej zapisana jest wartość length(gl_ModelViewMatrix*gl_Vertex). Nie zmienia to jednak sytuacji że fajnie by było zrobić to tylko na depthmapie. Stąd moje kolejne pytanie:
- czy to prawda że w OGL'u depthmapa jest zapisana w przedziale [0,1] (wykorzystuje DepthComponent24)?
- czy wzor do linearyzacji w postaci 2n/(n+f-d*(f-n)) gdzie d to wartosc z depthmapy jest dobry? Bo przyznam szczerze że nie bardzo wiem dlaczego akurat tak wygląda a nie inaczej :)

Offline KriS

  • Użytkownik
    • KriS

# Styczeń 29, 2012, 00:21:21
- czy to prawda że w OGL'u depthmapa jest zapisana w przedziale [0,1] (wykorzystuje DepthComponent24)?

Tak.

- czy wzor do linearyzacji w postaci 2n/(n+f-d*(f-n)) gdzie d to wartosc z depthmapy jest dobry? Bo przyznam szczerze że nie bardzo wiem dlaczego akurat tak wygląda a nie inaczej :)

Nie bardzo rozumiem o co chodzi. Jeżeli kombinujesz by zapisywać linową głębokość w przestrzeni  kamery do zbuffora to nie tędy droga. Wymaga to zapisywania głębokości z pixel shaderów. Szkoda mocy. Lepiej dodać kilka instrukcji i dekodować z normalnego zbuffora.

Offline JacekCichy

  • Użytkownik

# Styczeń 29, 2012, 13:50:08
Hehe aż tak bardzo nie kombinuje :) Depthmapę tradycyjnie renderuje do MRT i w shaderze światła(fragment shader) aby odtworzyć pozycję linearyzuje jej wartość przy pomocy wzoru:
2n/(n+f-d*(f-n))
Gdzie: d - wartość z depthmapy
n - near clip plane
f - far clip plane
A następnie jej wartość przeskalowywuje z zakresu [0 1] do [n f] przy pomocy wzorku: d*(f-n) + n.
Z racji że jedyne co nie wiem skąd sie bierze to wzór do linearyzacji czyli 2n/(n+f-d*(f-n)). Stąd moje pytanie czy jest to dobry wzór ewentualnie prośba o pomoc w zrozumieniu go lub odesłanie do jakiegoś artykułu który to tłumaczy jeżeli takowy istnieje :)

Offline KriS

  • Użytkownik
    • KriS

# Styczeń 29, 2012, 19:52:19
Wydaje mi się, że wzór jest zły. Szukasz głębokości w view/camera space (cameraSpacePos.z).

Najpierw transformacja z przestrzeni NDC do przestrzeni view:
vec4 cameraSpacePosHom = vec4(..., ...., 2 * zbufferVal - 1, 1) * invProj

Następnie konwersja ze współrzędnych homogenicznych na zwykłe:
vec3 cameraSpacePos = viewSpacePosHom.xyz / viewSpacePosHom.w

proj =
[  a,  0,  0,  0]
[  0,  b,  0,  0]
[  0,  0,  c, -1]
[  0,  0,  d,  0]

c =  -(f+n)/(f-n)
d = -2fn/(f-n)

invProj = proj^-1 =
[ 1/a,   0,   0,   0]
[   0, 1/b,   0,   0]
[   0,   0,   0, 1/d]
[   0,   0,  -1, c/d]

cameraSpacePosHom.z = -1
cameraSpacePosHom.w = ( 2 * zbufferVal - 1 + c ) / d
cameraSpacePos.z = -d/(2 * zbufferVal - 1 + c)

Offline JacekCichy

  • Użytkownik

# Styczeń 30, 2012, 12:57:10
O właśnie o coś takiego mi chodziło :D Dzięki wielkie bardzo mi to pomogło :) BTW. Dla wszystkich którzy mają podobny problem polecam również stronkę: http://www.songho.ca/opengl/gl_projectionmatrix.html