Débogage - GLSL

Ce site ne vous enseigne pas le GLSL, tout comme il ne vous enseigne pas le JavaScript. Ce sont des sujets très vastes. Si vous souhaitez apprendre le GLSL, consultez ces articles comme point de départ.

Si vous connaissez déjà le GLSL, voici quelques conseils pour le débogage.

Lorsque je crée un nouveau shader GLSL et que rien n'apparaît, la première chose que je fais généralement est de modifier le shader de fragment pour qu'il renvoie une couleur unie. Par exemple, tout en bas du shader, je pourrais mettre

void main() {

  ...

  gl_FragColor = vec4(1, 0, 0, 1);  // red
}

Si je vois l'objet que j'essayais de dessiner, je sais que le problème est lié à mon shader de fragment. Cela peut être n'importe quoi, comme de mauvaises textures, des uniforms non initialisés, des uniforms avec les mauvaises valeurs, mais au moins j'ai une direction où chercher.

Pour tester certains de ces points, je pourrais commencer par essayer de dessiner certaines des entrées. Par exemple, si j'utilise des normales dans le shader de fragment, je pourrais ajouter

gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);

Les normales vont de -1 à +1, donc en multipliant par 0,5 et en ajoutant 0,5, nous obtenons des valeurs qui vont de 0,0 à 1,0, ce qui les rend utiles pour les couleurs.

Essayez ceci avec des choses dont vous savez qu'elles fonctionnent et vous commencerez à avoir une idée de ce à quoi ressemblent les normales normalement. Si vos normales ne semblent pas normales, vous avez une piste où chercher. Si vous manipulez les normales dans le shader de fragment, vous pouvez utiliser la même technique pour dessiner le résultat de cette manipulation.

De même, si nous utilisons des textures, il y aura des coordonnées de texture et nous pouvons les dessiner avec quelque chose comme

gl_FragColor = vec4(fract(vUv), 0, 1);

Le fract est là au cas où nous utiliserions des coordonnées de texture qui dépassent la plage 0 à 1. C'est courant si texture.repeat est défini sur une valeur supérieure à 1.

Vous pouvez faire des choses similaires pour toutes les valeurs de votre shader de fragment. Déterminez quelle est leur plage probable, ajoutez du code pour définir gl_FragColor avec cette plage mise à l'échelle de 0,0 à 1,0

Pour vérifier les textures, essayez un CanvasTexture ou un DataTexture dont vous savez qu'il fonctionne.

Inversement, si après avoir défini gl_FragColor sur rouge je ne vois toujours rien, alors j'ai une indication que mon problème pourrait être lié aux choses relatives au shader de vertex. Certaines matrices pourraient être incorrectes ou mes attributs pourraient contenir de mauvaises données ou être mal configurés.

Je regarderais d'abord les matrices. Je pourrais mettre un point d'arrêt juste après mon appel à renderer.render(scene, camera) et commencer ensuite à développer les éléments dans l'inspecteur. La matrice monde et la matrice de projection de la caméra ne sont-elles pas au moins pleines de NaNs ? En développant la scène et en regardant ses children, je vérifierais que les matrices monde semblent raisonnables (pas de NaNs) et que les 4 dernières valeurs de chaque matrice semblent raisonnables pour ma scène. Si j'attends que ma scène fasse 50x50x50 unités et qu'une matrice affiche 552352623.123, il est clair que quelque chose ne va pas.

Tout comme nous l'avons fait pour le shader de fragment, nous pouvons également dessiner les valeurs du shader de vertex en les passant au shader de fragment. Déclarez une variable varying dans les deux et passez la valeur dont vous n'êtes pas sûr qu'elle soit correcte. En fait, si mon shader utilise des normales, je modifierai le shader de fragment pour les afficher comme mentionné ci-dessus, puis je définirai simplement vNormal à la valeur que je souhaite afficher, mais mise à l'échelle de sorte que les valeurs aillent de 0,0 à 1,0. Je regarde ensuite les résultats et vois s'ils correspondent à mes attentes.

Une autre bonne chose à faire est d'utiliser un shader plus simple. Pouvez-vous dessiner vos données avec un MeshBasicMaterial ? Si oui, essayez-le et assurez-vous qu'il s'affiche comme prévu.

Sinon, quel est le shader de vertex le plus simple qui vous permettra de visualiser votre géométrie ? Généralement, c'est aussi simple que

gl_Position = projection * modelView * vec4(position.xyz, 1);

Si cela fonctionne, commencez à ajouter vos modifications petit à petit.

Une autre chose que vous pouvez faire est d'utiliser l'extension Shader Editor pour Chrome ou similaire pour d'autres navigateurs. C'est un excellent moyen de voir comment fonctionnent d'autres shaders. C'est aussi pratique car vous pouvez apporter certaines des modifications suggérées ci-dessus en direct pendant que le code s'exécute.