2010-04-07 22 views
5

Pour autant que je sache, nous ne pouvons pas lire la valeur Z (profondeur) dans OpenGL ES 2.0. Alors je me demande comment on peut obtenir les coordonnées du monde 3D à partir d'un point sur l'écran 2D?OpenGL es 2.0 Buffer de profondeur de lecture

En fait, j'ai des pensées aléatoires qui pourraient fonctionner. Puisque nous pouvons lire la valeur RGBA en utilisant glReadPixels, que diriez-vous de dupliquer le tampon de profondeur et de le stocker dans un tampon de couleur (disons ColorforDepth). Bien sûr, il doit y avoir une bonne convention afin que nous ne perdions aucune information sur le tampon de profondeur. Et puis, quand nous avons besoin des coordonnées du monde d'un point, nous attachons ce tampon de couleur ColorforDepth au framebuffer, puis nous le restituons. Donc, quand nous utilisons glReadPixels pour lire les informations de profondeur à ce cadre. Cependant, cela conduira à 1 frame flash puisque le colorbuffer est un tampon bizarre traduit du buffer de profondeur. Je me demande toujours s'il existe un moyen standard pour obtenir la profondeur dans OpenGL es 2.0?

Thx à l'avance! :)

Répondre

7

Si vous êtes dans ES 2.0, votre fragment shader peut accéder à la profondeur du fragment courant (dans les coordonnées de la fenêtre) dans gl_FragCoord, donc vous pouvez écrire cela dans le buffer de couleur, utilisez glReadPixels pour récupérer le résultat et continuer. Alternativement, vous pouvez charger z de l'espace-monde comme variable et l'écrire à partir de votre fragment shader, au cas où cela serait plus facile. Pour vous convaincre, essayez d'écrire un shader rapide qui met rapidement gl_FragCoord.z ​​en basse précision, par ex.

gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0); 

Vous devez obtenir une échelle de gris avec l'intensité de la couleur représentant la profondeur. Parce que vous êtes dans les coordonnées de la fenêtre, l'intensité va de 0,0 (fragment le plus rapproché possible) à 1,0 (fragment le plus éloigné possible). Afin de ne pas perdre beaucoup de précision, il est probablement plus utile de répartir la valeur entre les composants, car votre fournisseur ne supporte presque certainement pas les tampons de cible à virgule flottante.

+0

Tommy, pourriez-vous en dire un peu plus sur la division de gl_FragCoord.z ​​entre les composants. Ne pas suivre. À votre santé. – dugla

+1

@dugla Si la profondeur était un entier de 32 bits, vous ne pourriez en obtenir que 8 bits dans R, G, B et A. Donc, en pratique, ce que vous feriez serait quelque chose comme multiplier le vecteur '(1, 256 , 65536, 16777216) ', puis stocker chaque composant de ce vecteur mod 1.0 dans les canaux concernés. Vous pouvez recombiner plus tard en divisant par les composants pertinents et en ajoutant ensemble. – Tommy

0

J'utilise un rayon de base coulée pour ramasser un objet 3D à partir d'un écran tactile. En fait, je calcule l'intersection entre l'écran normal au point de contact et une sphère contenant mon objet. Pour une cueillette très précise ou une forme compliquée, vous devez utiliser plusieurs sphères.

Vous pouvez également projeter certains points clés de votre objet dans l'espace 2D de votre écran (en multipliant votre point 3D par votre matrice de transformation) et ensuite effectuer une comparaison 2D (distance) avec votre point de contact.

0

Je voudrais aussi pouvoir lire les valeurs dans le tampon de profondeur, mais la recherche indique qu'il ne peut pas être fait.

Comme le suggère Vincent, si vous avez des formes simples comme des sphères, le lancer de rayon est probablement meilleur.

pour des formes plus complexes Tho, Je pense à rendre l'objet à un (potentiellement plus petit) offscreen tampon, attribuer manuellement l'une des composantes de couleur de chaque sommet de la profondeur de ce sommet, puis lire les valeurs de couleur. ceci est quelque peu inélégant et ennuyeux, et vous oblige à être capable de convertir l'espace-objet en espace d'écran (j'utilise mes propres quaternions pour piloter les matrices, donc ça s'occupe de ça). il peut y avoir un moyen avec les shaders d'écrire les informations de profondeur dans la couleur ou dans le tampon stencil (est-ce que GL ES a même un tampon stencil?)

Si quelqu'un a une approche plus propre, j'aimerais l'entendre. En utilisant un FBO, vous pouvez rendre le rendu sans afficher les résultats.