2017-07-09 6 views
0

J'utilise une texture flottante WebGL pour stocker des matrices. Chaque rangée a N matrices.WebGL - Utilisation d'une texture pour des données binaires arbitraires et des erreurs en virgule flottante

Dans le shader, j'obtiens ces matrices, compte tenu de la taille relative de chaque vecteur et de chaque ligne de texture.

Par exemple, si je 10 matrices par ligne et 10 lignes, le shader obtient:

u_vector_size = 1/(10 * 4) 
u_row_size = 1/10 

Avec cette information, je vais chercher 4 pixels de la texture:

uniform sampler2D u_boneMap; 
uniform float u_vector_size; 
uniform float u_row_size; 

mat4 boneAtIndex(float column, float row) { 
    column *= u_vector_size * 4.0; 
    row *= u_row_size; 

    return mat4(texture2D(u_boneMap, vec2(column, row)), 
       texture2D(u_boneMap, vec2(column + u_vector_size, row)), 
       texture2D(u_boneMap, vec2(column + u_vector_size * 2.0, row)), 
       texture2D(u_boneMap, vec2(column + u_vector_size * 3.0, row))); 
} 

Le problème? Cela ne fonctionne pas avec certains pilotes.

Je le vois principalement sur Mac, mais c'est aussi arrivé sur Windows, où les extractions obtiennent des données erronées, et tout devient fou. Je suppose que cela est dû à des erreurs en virgule flottante.

Principalement en raison du fait que les résultats changent si j'utilise une texture avec la puissance de deux dimensions ou non. Les données sont toutes les mêmes, juste la taille de chaque vecteur et la ligne par rapport à la taille de la texture complète change.

Normalement, j'utiliserais un tampon de texture, cependant c'est du code WebGL, et WebGL ne supporte que les textures.

Y at-il un moyen de rendre ce type de matrices de récupération d'une texture fiable et cohérente?

+0

Avez-vous défini le filtrage des textures sur GL_NEAREST? –

+0

Je l'ai fait. Je peux même télécharger le test, s'il intéresse quelqu'un, en supposant que l'on peut télécharger des fichiers sur SO – user2503048

+0

Après une enquête plus approfondie, il semble que cela se passe uniquement sur Hacintosh, donc je suppose qu'il y a un bug de pilote traitant les textures NPOT. Je ne suis pas tout à fait sûr comment fonctionne Hacintosh, jamais installé Mac ou avait un Mac. Je vais vérifier à qui je peux signaler ce bug. – user2503048

Répondre

0

Si cela intéresse quelqu'un, le problème réel était en effet des erreurs à virgule flottante. Depuis que j'ai échantillonné directement sur la frontière entre les pixels, même une minuscule erreur de virgule flottante pourrait provoquer l'échantillonnage du mauvais pixel. La solution consiste à échantillonner au milieu du pixel.

uniform sampler2D u_boneMap; 
uniform float u_vector_size; 
uniform float u_row_size; 

mat4 boneAtIndex(float column, float row) { 
    column *= u_vector_size * 4.0; 
    row *= u_row_size; 
    column += 0.5 * u_vectorSize; 
    row += 0.5 * u_rowSize; 

    return mat4(texture2D(u_boneMap, vec2(column, row)), 
       texture2D(u_boneMap, vec2(column + u_vector_size, row)), 
       texture2D(u_boneMap, vec2(column + u_vector_size * 2.0, row)), 
       texture2D(u_boneMap, vec2(column + u_vector_size * 3.0, row))); 
} 
+0

Le problème n'est pas une erreur numérique car l'échantillonnage à la frontière même d'un texel ne garantit aucun résultat spécifique, donc même dans un monde sans erreur numérique, vous auriez toujours été à la merci de l'implémentation spécifique du pilote graphique. –

+0

Voir aussi https://stackoverflow.com/a/27439675/128511 – gman

+0

Je ne le savais pas, merci. C'est très bizarre de penser, parce que je regarde mes textures comme des tableaux de données avec des indices entiers clairs, des sortes de textures oubliées et l'échantillonnage est un peu plus complexe :) – user2503048