11
votes

GLSL Uniforme seulement étant mis à jour par des appels non liés

J'ai un programme GLSL extrêmement basique qui ne parvient pas à mettre à jour correctement une valeur uniforme après le premier appel de tirage. Aucune erreur n'est reçue à partir de Glgeterror code>, aucune erreur n'est rapportée dans les journaux d'information lors de la compilation et du reliant les shaders, et tous les emplacements uniformes sont valides.

Vertex Shader: P>

GLint mvpLoc = glGetUniformLocation(program, "mvp");
GLint nmvLoc = glGetUniformLocation(program, "nmv");
GLint lightDirLoc = glGetUniformLocation(program, "lightDir");
GLint lightColorLoc = glGetUniformLocation(program, "lightColor");
GLint materialColorLoc = glGetUniformLocation(program, "materialColor");
  • appelant GluseProgram (programme) code> dans la boucle. LI>
  • Réglage du MVP code> ou du NMV code> Uniformes dans la boucle. LI>
  • Réglage du LightDir Code> Uniforme dans la boucle. LI>
  • Suppression de l'un des Uniforme Vec3 Code> S du programme de shader. LI> ul>

    Veuillez noter que le réglage de l'uniforme code> l'uniforme de la boucle sera pas strong> mettre à jour le matériauColor code> uniforme. J'ai également vérifié GL_CURRENT_PROGRAM code> dans la boucle, et le shader reste lié partout. P>

    J'ai essayé de résoudre ce problème pendant des heures et ne peut absolument pas trouver le problème. Cette configuration de shader est si simple que je ne crois pas que ce soit un bug de conducteur. J'utilise OpenGL 2.1 sur Mac OS X 10.8.3 avec une nvidia geforce 9400m. P>

    Voici une trace d'appel pour une seule image: P>

    #version 120
    
    uniform vec3 lightDir;
    uniform vec3 lightColor;
    uniform vec3 materialColor;
    
    varying vec3 v_normal;
    
    void main()
    {
        vec3 n = normalize(v_normal);
        float nDotL = max(0.0, dot(n, lightDir));
    
        gl_FragColor = vec4(materialColor * lightColor * nDotL, 1.0);
    }
    


12 commentaires

Il me semble que la seule différence entre les uniformes LightColor et LightDir est leur emplacement dans le shader. Avez-vous essayé de changer de place et de voir si la lumièreColor déclenche effectivement le changement? J'essaierais également de voir si un GPU ATI ou Intel produit le même comportement.


Je viens d'essayer de changer de commande et que le comportement reste exactement le même. LightColor ne déclenche toujours pas le changement. Malheureusement, je n'ai pas accès à un autre GPU à ce moment-là.


J'ai remarqué que l'échange de l'ordre de déclaration ou de leurs positions dans les opérations a entraîné des emplacements uniformes restants inchangés.


Curieux et curieux. :) Est-il possible pour vous d'envoyer un échantillon de travail complet, je peux compiler / exécuter sur différentes plates-formes de matériel / pilote? Ou aurait-il trop de travail pour extraire de votre application actuelle?


Il serait assez difficile d'extraire et de vous fournir un échantillon de travail de cette application. Toutefois, si vous souhaitez tenter de dupliquer le comportement, vous devriez pouvoir utiliser les données de trace d'appel pour effectuer exactement les mêmes opérations.


Voici un test simple que vous pouvez assurer que la couleur de matériau n'est en réalité pas mise à jour: définissez GL_FRAGCOLOR sur la couleur matérielle. De ce que je vois en ce moment, je ne suis pas convaincu que vos conclusions sont correctes. Je ne dis pas que vous avez tort, je dis simplement que ce test serait de conclusions que la couleur matérielle n'est en fait pas mise à jour.


J'ai essayé cela et la couleur matérielle ne change pas.


Pouvons-nous voir le code que vous utilisez pour trouver les emplacements uniformes?


Le code utilisé pour obtenir des emplacements uniformes vient d'être ajouté. Comme vous pouvez le constater, c'est très standard. Je soupçonne maintenant un bug de conducteur.


C'est une très vieille question, avez-vous déjà résolu? Je vais d'abord aller avec après avoir regardé l'impossible, c'est maillage.color en train de changer? Et pointer vers la bonne valeur? Surtout après le dernier test d'Aeskreis.


Avez-vous essayé de déplacer les appels GlgeTuniformLocation au début de chaque image (pas d'appel qu'une seule fois) ... Certains pilotes en particulier ATI peuvent changer d'emplacement et avoir beaucoup de comportement étrange s'il y a une fuite de mémoire dans votre code


@Chrishoward APRÈS VOTRE AJOUTME Le CPU Side Mesh Draw Code associé Il est clair que vous avez clairement codé sur toutes les positions VBO et uniformes, mais votre fragment et vos mèches de sommet n'ont pas d'emplacement statique nulle part ... Voir Exemple complet GL + GLSL + VAO / VBO C ++ et rechercher GlgeTuniformlocation Utilisation ... aussi dans les shaders, vous pouvez énoncer quelque chose comme ceci: mise en page (Emplacement = 0) dans Vec3 Pos; Mais c'est pour plus récent GLSL dans la version plus ancienne, cela pourrait être un peu différent ...


3 Réponses :


0
votes
  1. Parfois, un conducteur optimisera certains de vos uniformes (même s'il ne doit pas particulièrement avec les conducteurs plus âgés). Pour tester cela, essayez d'utiliser la couleur de votre matériau dans le shader de sommet (copiez-la sur une variable variable et une utilisation de la variable de fragment que la variable variable au lieu d'uniforme, cela fonctionne parfois pour moi, ... bien sûr de réduire les performances un peu)

  2. Essayez d'utiliser une version de profil différente. Dans certains cas, les nouveaux conducteurs n'émulent pas correctement versions plus anciennes. Avez-vous essayé un profil de base? (Je sais que c'est très délicat à mettre en œuvre avec le code plus ancien)

  3. Vous pouvez essayer NVemulate de tester différents paramètres de pilote

    Glende parfois oublié (); Donne beaucoup de mal à essayer d'ajouter ce code avant votre code de rendu de trame: xxx

    si cela aide que vous n'oubliez pas à appeler Glend (); quelque part ou avoir gonfler; au lieu de gonfler ();

    [EDIT1]

    Après que vous ajoutez le code associé Code associé, c'est clair que Vous avez un codé dur tout VO et uniforme Les positions, mais votre fragment et votre sommet Shaders n'ont pas d'emplacement statique nulle part sur

    • Exemple complet GL + GLSL + VAO / VBO C ++

      et recherchez GLGETUniformlocation Utilisation. Aussi dans des shaders, vous pouvez indiquer quelque chose comme ceci: xxx

      mais c'est pour plus récent glsl dans la version plus ancienne, il pourrait être un peu différent et aussi paresseux de rechercher la syntaxe et le mot-clé ...


4 commentaires

Un problème Glend aurait déclenché une erreur GL, que l'OP énonce avoir vérifié.


OP utilise GL moderne, Glend est obsolète


@ MACKYCHEESE21 Eh bien qui est spécifié maintenant mais pas de retour dans les jours où cela a été répondu, ... et comme l'auteur de l'OP n'a pas notifié, je n'ai aucun moyen de le savoir que ... toujours Glend est Juste une partie de la réponse ... Après avoir examiné la trace d'appel, il est probablement un problème avec des emplacements car tous les Vbos et les uniformes sont codés en dur au code secondaire CPU mais pas dans la partie GLSL ...


Oh pardon! Je n'ai pas vu les dates de poste.



0
votes

Toujours pas résolu?

Quel est le type de maillage.color

En regardant les adresses passées dans la trace d'appel, ils semblent plutôt élevés, vous devriez peut-être passer à une adresse aux données et non les données réelles, 0x7Fab823000BC

gluniform3fv (matériauColorloc, 1, et maillage.color); peut-être essayer le codage dur et utiliser gluniform3f ()


0 commentaires

0
votes

de toutes les adresses de la trace, je suppose que tout Vec3 que vous envoyez à GL est de type nom de flotteur [3] , n'est-ce pas? En supposant que je ne peux pas repérer une erreur dans votre code. Comme vous l'avez dit, il n'y a pas d'état d'erreur renvoyé par Glgeterror, ce doit être un bug de pilote.

J'ai vu dans la trace que vous démarrez chaque maillage faire un GLBindbuffer (GL_ARRAY_BUFFER, 0) - Ce n'est pas vraiment nécessaire. Mais de toute façon, je ne peux pas imaginer que ceci soit la source, non plus.

Malheureusement, vous ne pouvez pas tester des trucs comme GLBinduniformlocation avant de relier, car cela ne fait pas partie de OpenGL.

Mon expérience montre: Si vous émettez un gluniform3fv et que tous les paramètres sont corrects, l'uniforme est mis à jour et que le changement est visible immédiatement. Comme ce n'est pas le cas, ici, il doit s'agir d'un bug de pilote, de sorte que les seules choses que vous pouvez éventuellement faire est: ajoutez d'autres appels inutiles à votre boucle de rendu afin de rendre le changement visible (que vous avez déjà fait si je l'ai lu correctement) .


0 commentaires