En passant la coutume de type (struct) uniforme de l'intervalle Qt à GLSL à l'aide de QGLShaderProgram
J'ai défini une structure pour les paramètres de la lumière qui contient deux vecteurs. La structure est définie en C++ et GLSL d'une manière analogue (note: QVector3D
encapsule 3 float
s, pas double
s):
C++ programme d'accueil:
struct LightParameters {
QVector3D pos;
QVector3D intensity;
};
Fragment Shader:
struct LightParameters {
vec3 pos;
vec3 intensity;
};
Dans le fragment shader, j'ai aussi de définir les uniformes. Le nombre de feux est limité à 8, de sorte que l'uniforme tableau a une taille constante (mais seulement numLights
sont effectivement utilisées):
const int maxLights = 8;
uniform int numLights;
uniform LightParameters lights[maxLights];
Dans le programme d'accueil, j'définir les lumières et les transmettre à l'shader (QGLShaderProgram
):
static const int maxLights = 8;
LightParameters lights[maxLights];
int numLights = 1;
lights[0].pos = {0, 1, 0};
lights[0].intensity = {1, 1, 1};
shaderProgram->bind();
shaderProgram->setUniformValue("numLights", numLights);
shaderProgram->setUniformValueArray("lights", reinterpret_cast<GLfloat*>(lights), maxLights, 6);
shaderProgram->release();
La 6
dans le dernier paramètre doit indiquer que chaque élément du tableau utilise 6 GLfloat
s de la crue float array, aka "tuple de taille".
Selon la documentation de Qt, il ne devrait pas être possible d'utiliser un tuple de taille de 6 (1, 2, 3, 4 sont autorisés). De l'autre côté, QGLShaderProgram permet de passer dans une matrice avec jusqu'à 4x4 entrées. GLSL permet également de structures pour les uniformes qui ont plus de 4 flotteurs (selon cet exemple).
Cela conduit à la question:
Comment puis-je passer des structures de flotteurs /vecteurs comme un uniforme tableau à l'aide de Qt? Si il n'est pas possible à l'aide de Qt, je vais appeler la GL fonction pour faire cela, mais je suis intéressé si Qt peut le faire pour moi commodément.
Bien sûr, j'ai essayé le code ci-dessus, de toute façon. Il en résulte dans tous les vecteurs de la struct être mis à 0.
Quand je baisse la deuxième paramètre dans la structure et l'utilisation d'un n-uplet de la taille de 3, le code ne fonctionne toujours pas! Cependant, quand il vient à l'aide de vec3
dans le shader (encore la structure avec un QVector3D dans le programme d'accueil, d'un tuple de taille = 3), il fonctionne.
Donc le problème semble être que les types personnalisés sont traitées différemment dans l'OpenGL hôte du programme de l'API, mais Qt ne semble pas le supporter. J'utilise actuellement deux uniformes tableaux (un pour le pos, l'un pour l'intensité) comme une solution de contournement.
OriginalL'auteur leemes | 2013-05-24
Vous devez vous connecter pour publier un commentaire.
Qt n'a rien à voir avec cela.
Vous ne peut pas passer des tableaux de les structures comme s'il s'agissait d'un tableau de valeurs. Si vous avez un réseau uniforme dont le type n'est pas un type de base, puis tous les index de tableau et de chaque membre de cette structure a un distinct uniforme emplacement avec un distinct uniforme nom. Par conséquent, vous devez passer chaque membre séparément.
Vous devez faire ceci:
Et ainsi de suite.
Ou vous pouvez simplement utiliser un bon uniforme bloc et de renoncer à tout cela.
Ou si vous utilisez un bloc uniforme. Vraiment, plus les gens ont besoin de les utiliser.
Merci de m'avoir montré les solutions de rechange. 🙂 Je suppose que des blocs homogènes sont aussi la solution du nombre limité des uniformes?
OriginalL'auteur Nicol Bolas
- Je utiliser une fonction de modèle:
et dans le programme :
c_str
temporairestd::string
, qui invoque un comportement indéfini, comme vous l'avez balançant un pointeur puisque la chaîne est supprimée avant l'appel OpenGL qui se passe. La suppression de valeurs temporaires qui se passe juste après l'exécution de l'instruction qu'ils font partie d' (ici l'initialisation de la variablename
). Pour corriger cela, vous avez besoin de mettre lastd::string
dans une variable locale à le maintenir en vie jusqu'à ce que lec_str
a été utilisé dans l'appel OpenGL. Voir cette version corrigée.Un autre indice: le paramètre de modèle n'est pas besoin d'être explicitement écrit lors de l'appel de votre fonction. Il est automatiquement déduit par le paramètre de type de
T
(ouconst T&
dans ce cas).Merci pour la version corrigée. J'ai utilisé ma version pour un temps et n'a jamais eu aucun problème avec elle...pour la deuxième astuce, si vous n'utilisez pas explicitement le paramètre de modèle, vous obtiendrez une erreur de compilation (j'utilise mingw avec les options standard) avec lit double et float paramètres par exemple (Si vous regardez le QVariant::Type enum, il y a seulement le type double, pas de type float). Ici, l'erreur de compilation : appel de surcharge de 'setUniformValue(const char*, const double&)' est ambigu
"Un comportement indéfini" signifie que tout peut arriver. Il peut travailler. Mais il n'a pas besoin de travailler à chaque fois. Je vous suggère fortement de corriger l'erreur si vous ne voulez pas que votre programme de crash très difficile de trouver la raison dans l'avenir. Pour le problème de l'ambiguïté, je ne vois pas comment ajoutant explicitement
<double>
à l'appel de votre fonction résout ce, qui définit simplementT := double
, ce qui se passe exactement de la même manière lors de l'appel avec undouble
valeur.OriginalL'auteur Bertrand