[GLSL - fragment shader] indéxer une texture

indéxer une texture [GLSL - fragment shader] - C++ - Programmation

Marsh Posté le 17-11-2009 à 14:58:44    

Bonjour,
 
je souhaite encoder une structure de données dans une texture 3D et y accéder dans un fragment shader en GLSL.
En GLSL on ne dispose pas de pointeur et il n'y a pas non plus de facon propre d'accéder par index. Il me semble que le seul moyen d'accéder à une texture est d'envoyer des coordonnées scalaires.
 
Imaginons le cas simple d'une texture 1D de taille N. Je souhaite accéder à la valeur de la case numéro k de ma texture.  
La case k pourrait par exemple contenir le numéro d'un fils ou d'un voisin dans ma structure de données. Il est très important que j'obtienne exactement la valeur stockée à cet endroit dans la texture et pas une valeur interpolée.  
 
Est-ce que texture1D(id, k / (float) N) fonctionnerait ?
 
Est-ce que lors des accès aux données il ne fait pas une interpolation ou autre filtrage qui risque de bousiller ma valeur ?
 
Merci :-)

Reply

Marsh Posté le 17-11-2009 à 14:58:44   

Reply

Marsh Posté le 17-11-2009 à 15:26:20    

Ca dépends comment est configuré le sampler je dirais. (il faut le mettre en nearest)
Après sur la mise en forme de la coordonnée, il faut regarder les conventions utilisées en OpenGl.


Message édité par bjone le 17-11-2009 à 15:54:57
Reply

Marsh Posté le 17-11-2009 à 18:40:55    

Tu pourrais m'indiquer un peu plus en détail ce que signifie le mettre en nearest et ce que ca implique ?
En tout cas merci pour ta réponse bjone.

Reply

Marsh Posté le 18-11-2009 à 10:40:46    

l'échantillonnage dans la texture, il peut se faire en nearest sampling, filtrage bilinéaire, avec mipmapping, trilinéaire, aniso bili/trili.
 
en toute logique pour y accéder sans filtrage il faut être en nearest (sans mipmap).
 
http://www.manpagez.com/man/3/glTexParameteri/
 
 

Reply

Marsh Posté le 25-11-2009 à 17:58:54    

OK j'ai fait ca et ca marche :-)
Merci !

Reply

Marsh Posté le 25-11-2009 à 18:13:57    

:)

Reply

Marsh Posté le 26-11-2009 à 01:48:18    

Par contre, maintenant j'ai un autre problème :-(
Tu sauras peut-être m'aider :
 
Pour faire mes index j'utilise des flottants, et j'ai des problèmes de précisions avec ce qui est stocké dans les textures.
 
Disons que je veux stocker un entier n dans une case de la texture.
Je stocke un flottant : n / coef où je m'assure que le flottant coef sera toujours plus grand que tous les n possibles de facon a toujours avoir une valeur flottante entre 0 et 1.
 
Ensuite dans mon fragment shader je chope cette valeur et je la remultiplie par coef. Je devrais ainsi retrouver n. Mais ca ne marche pas bien du tout. Quand n et coef sont de l'ordre de 1000 la valeur de mon n est du genre +- 20% de la vraie valeur ! Pour faire de l'indéxage c'est vraiment pas top...
 
Tu as une idée d'où ca peut venir et comment regler ca ?
Malheureusement j'ai aussi besoin de stocker des flottants dans ma texture donc je ne peux pas utiliser une texture entière.
 
edit: Je viens de tester en faisant le coup de la division puis multiplication dans le shader et je n'ai pas de problème de précision. Ce qui signie que mes données perdent en précision quelque part dans le transfert.
Je fais un glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16,
                                      arraySize[0],arraySize[1],arraySize[2],
                                      0,GL_RGBA,GL_FLOAT,array);


Message édité par erikkarls le 26-11-2009 à 01:57:50
Reply

Marsh Posté le 26-11-2009 à 02:30:48    

avec le GL_RGBA16, tu as des entiers 16bits coté format interne.
Essaye déjà en RGBA32F, sans faire ta conversion, voir si ça marche.

Reply

Marsh Posté le 26-11-2009 à 03:06:07    

bjone a écrit :

avec le GL_RGBA16, tu as des entiers 16bits coté format interne.
Essaye déjà en RGBA32F, sans faire ta conversion, voir si ça marche.


 
 
YES ! Ca marche !! Merci merci merci merci merci :-) :-) tu sais pas à quel point tu m'aides là !!!! J'avais passé toute la journée à chercher sans succès !
 
Je suppose le problème vient du fait que les flottants CPU sont sur 32bits sur ma machine et il doit me les bousiller à la conversion 16bits sur le GPU. La conversion doit quand même être bien crade, parce que perdre 20% sur un truc de l'ordre de 10^-3 c'est chaud...
 
Encore merci bjone ! (Je saurai qui harceler en cas d'autres soucis ;-))

Reply

Marsh Posté le 26-11-2009 à 12:47:06    

Je te conseille de parcourir les specs de l'opengl 3.2:
http://www.opengl.org/registry/doc [...] 090803.pdf
Tu as la table des divers formats internes possibles :)
 
Par contre forcément en flottant 32bits, tu as plus d'occupation mémoire et plus de bande-passante mémoire consommée.
Donc à toi de voir les divers compromis que tu peux faire (enfin une fois que tout ce que tu veux faire marche :D)


Message édité par bjone le 26-11-2009 à 12:49:08
Reply

Marsh Posté le 26-11-2009 à 12:47:06   

Reply

Marsh Posté le 26-11-2009 à 23:23:43    

Bon en fait je viens encore demander un truc ...
 
Voilà mon nouveau problème c'est que GLSL décide tout seul que je n'ai pas besoin de certaines variables uniform.
J'ai lu que si une variable n'est pas utilisée, la phase de compilation la laisse de côté pour ne pas prendre de place mémoire inutilement. Sauf que la je les utilise mes variables ! Et je n'ai pas de problème de compilation ou de linkage.
 

Code :
  1. uniform sampler3D dataSetTexture;
  2. uniform float normalizeCoef;
  3. uniform int textureSizeX;
  4. uniform int textureSizeY;
  5. uniform int textureSizeZ;
  6. float current_ID;
  7. float current_IsLeaf;
  8. float current_value;
  9. vec4 getRGBA(float ID)
  10. {
  11.     float ID_int = floor(ID+0.5);
  12. float z = ID_int / (textureSizeX * textureSizeY);
  13. float y = (ID_int - z*textureSizeY*textureSizeX) / textureSizeX ;
  14. float x = ID_int - (z*textureSizeY + y)*textureSizeX ;
  15. return texture3D( dataSetTexture, vec3( x / (textureSizeX-1.0) , y / (textureSizeY-1.0) , z / (textureSizeZ-1.0)) );
  16. }
  17. void getOctreeCell(float ID)
  18. {
  19. vec4 RGBA = getRGBA(ID);
  20. current_ID = RGBA.r * normalizeCoef;
  21. current_IsLeaf = RGBA.g;
  22. current_value = RGBA.b;
  23. }
  24. void main()
  25. {
  26. getOctreeCell(0.0);
  27. gl_FragColor = vec4(current_value,0,0,1);
  28. }


 
GLSL décide tout seul que je n'ai pas besoin des variables uniformes normalizeCoef et textureSizeZ. Pourtant les deux sont bien utilisées dans le programme.  
Une idée d'où ca peut venir ?

Reply

Marsh Posté le 27-11-2009 à 01:13:52    

Ah oui sinon, encore un truc :
Je viens de me rendre compte que l'accès à une texture dans un shader se fait de facon "modulo 1.0".
 
Par exemple l'accès aux coordonnées (1.5, 0, 0) est équivalent à l'accès à (0.5 , 0 , 0). Ce qui est embêtant car l'accès à (1.0, 0, 0) donne le même que (0,0,0).
Comme je voulais utiliser comme formule d'indexage n / (N+1) pour la case n avec N la taille de la texture, ca pose un problème sur la dernière case (= 1.0).
Il y a un moyen d'arranger ca ?

Reply

Marsh Posté le 27-11-2009 à 18:43:49    

erikkarls a écrit :

Bon en fait je viens encore demander un truc ...
 
Voilà mon nouveau problème c'est que GLSL décide tout seul que je n'ai pas besoin de certaines variables uniform.
J'ai lu que si une variable n'est pas utilisée, la phase de compilation la laisse de côté pour ne pas prendre de place mémoire inutilement. Sauf que la je les utilise mes variables ! Et je n'ai pas de problème de compilation ou de linkage.
 

Code :
  1. uniform sampler3D dataSetTexture;
  2. uniform float normalizeCoef;
  3. uniform int textureSizeX;
  4. uniform int textureSizeY;
  5. uniform int textureSizeZ;
  6. float current_ID;
  7. float current_IsLeaf;
  8. float current_value;
  9. vec4 getRGBA(float ID)
  10. {
  11.     float ID_int = floor(ID+0.5);
  12. float z = ID_int / (textureSizeX * textureSizeY);
  13. float y = (ID_int - z*textureSizeY*textureSizeX) / textureSizeX ;
  14. float x = ID_int - (z*textureSizeY + y)*textureSizeX ;
  15. return texture3D( dataSetTexture, vec3( x / (textureSizeX-1.0) , y / (textureSizeY-1.0) , z / (textureSizeZ-1.0)) );
  16. }
  17. void getOctreeCell(float ID)
  18. {
  19. vec4 RGBA = getRGBA(ID);
  20. current_ID = RGBA.r * normalizeCoef;
  21. current_IsLeaf = RGBA.g;
  22. current_value = RGBA.b;
  23. }
  24. void main()
  25. {
  26. getOctreeCell(0.0);
  27. gl_FragColor = vec4(current_value,0,0,1);
  28. }


 
GLSL décide tout seul que je n'ai pas besoin des variables uniformes normalizeCoef et textureSizeZ. Pourtant les deux sont bien utilisées dans le programme.  
Une idée d'où ca peut venir ?


 
Normalement si le code GLSL utilise bien l'uniform, glGetUniformLocation doit te retourner une "location" correcte. Soit tu as glissé sur le nom de l'uniform, soit l'uniform n'est pas utilisé, soit tu as un bug driver.
 

Reply

Marsh Posté le 27-11-2009 à 19:12:38    

erikkarls a écrit :

Ah oui sinon, encore un truc :
Je viens de me rendre compte que l'accès à une texture dans un shader se fait de facon "modulo 1.0".
 
Par exemple l'accès aux coordonnées (1.5, 0, 0) est équivalent à l'accès à (0.5 , 0 , 0). Ce qui est embêtant car l'accès à (1.0, 0, 0) donne le même que (0,0,0).
Comme je voulais utiliser comme formule d'indexage n / (N+1) pour la case n avec N la taille de la texture, ca pose un problème sur la dernière case (= 1.0).
Il y a un moyen d'arranger ca ?


 
Ta mise en forme de la coordonnée est peut-être foireuse.
 
Avec le mode de wrapping (page 159 des specs OpenGl 3.2), tu peux désactiver le wrapping des coordonnées.
=> glTexParameteri avec GL_TEXTURE_WRAP_bidule et un GL_CLAMP_TO_EDGE.

Message cité 1 fois
Message édité par bjone le 27-11-2009 à 19:13:16
Reply

Marsh Posté le 27-11-2009 à 19:33:12    

bjone a écrit :


 
Ta mise en forme de la coordonnée est peut-être foireuse.
 
Avec le mode de wrapping (page 159 des specs OpenGl 3.2), tu peux désactiver le wrapping des coordonnées.
=> glTexParameteri avec GL_TEXTURE_WRAP_bidule et un GL_CLAMP_TO_EDGE.


 
J'ai pourtant bien fait  

Code :
  1. glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
  2. glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
  3. glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);


 
Edit: OK en fait il faut bien penser à charger les paramètres de textures après l'envoie de la texture. Je le faisais avant et c'est pour ca que ca ne marchait pas.

Message cité 1 fois
Message édité par erikkarls le 27-11-2009 à 19:41:56
Reply

Marsh Posté le 28-11-2009 à 13:43:49    

erikkarls a écrit :


Edit: OK en fait il faut bien penser à charger les paramètres de textures après l'envoie de la texture. Je le faisais avant et c'est pour ca que ca ne marchait pas.


 
Truc merdique à propos de l'OpenGl. ça bind à tour de bras. (Perso je préfère le D3D, j'ai l'impression d'être amputé d'un bras en OpenGl :D)


Message édité par bjone le 28-11-2009 à 13:44:29
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed