web-dev-qa-db-fra.com

GLSL: Comment obtenir la position mondiale des pixels x, y, z?

Je veux ajuster les couleurs en fonction de la position xyz dans laquelle elles se trouvent.

J'ai essayé ceci dans mon fragment shader:

varying vec4 verpos;

void main(){
    vec4 c;
    c.x = verpos.x;
    c.y = verpos.y;
    c.z = verpos.z;
    c.w = 1.0;

    gl_FragColor = c;
}

mais il semble que les couleurs changent en fonction de l'angle/de la position de ma caméra, comment puis-je rendre les cordons indépendants de la position/de l'angle de ma caméra?

Voici mon vertex shader:

varying vec4 verpos;

void main(){
    gl_Position = ftransform();
    verpos = gl_ModelViewMatrix*gl_Vertex;
}

Edit2: a changé de titre, donc je veux des accords mondiaux, pas des accords d'écran!

Edit3: a ajouté mon code complet

25
Rookie

Dans vertex shader, vous avez gl_Vertex (ou autre chose si vous n'utilisez pas de pipeline fixe) qui est la position d'un sommet dans les coordonnées du modèle. Multipliez la matrice du modèle par gl_Vertex et vous obtiendrez la position du sommet en coordonnées mondiales. Attribuez-le à une variable variable, puis lisez sa valeur dans le fragment shader et vous obtiendrez la position du fragment en coordonnées universelles.

Maintenant, le problème est que vous n'avez pas nécessairement de matrice de modèle si vous utilisez la matrice de visualisation de modèle par défaut d'OpenGL, qui est une combinaison de matrices de modèle et de vue. Je résout généralement ce problème en ayant deux matrices distinctes au lieu d'une seule matrice modelview:

  1. matrice du modèle (mappe les coordonnées du modèle aux coordonnées mondiales), et
  2. voir la matrice (mappe les coordonnées du monde aux coordonnées de la caméra).

Passez donc deux matrices différentes à votre vertex shader séparément. Vous pouvez le faire en définissant

uniform mat4 view_matrix;
uniform mat4 model_matrix;

Au début de votre vertex shader. Et puis au lieu de ftransform (), dites:

gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex;

Dans le programme principal, vous devez écrire des valeurs dans ces deux nouvelles matrices. Tout d'abord, pour obtenir la matrice de vue, effectuez les transformations de caméra avec glLoadIdentity (), glTranslate (), glRotate () ou gluLookAt () ou ce que vous préférez comme vous le feriez normalement, mais appelez ensuite glGetFloatv (GL_MODELVIEW_MATRIX, & array); afin d'obtenir les données de la matrice dans un tableau. Et d'autre part, de manière similaire, pour obtenir la matrice du modèle, appelez également glLoadIdentity (); et faire les transformations d'objets avec glTranslate (), glRotate (), glScale () etc. et enfin appeler glGetFloatv (GL_MODELVIEW_MATRIX, & array); pour extraire les données de la matrice d'OpenGL, afin que vous puissiez les envoyer à votre vertex shader. Notez en particulier que vous devez appeler glLoadIdentity () avant de commencer à transformer l'objet. Normalement, vous devez d'abord transformer la caméra, puis transformer l'objet, ce qui entraînerait une matrice qui remplit à la fois les fonctions de vue et de modèle. Mais comme vous utilisez des matrices distinctes, vous devez réinitialiser la matrice après les transformations de la caméra avec glLoadIdentity ().

gl_FragCoord sont les coordonnées des pixels et non les coordonnées du monde.

31
kynnysmatto

Ou vous pouvez simplement diviser la coordonnée z par la coordonnée w, ce qui annule essentiellement la projection en perspective; vous donnant vos coordonnées du monde d'origine.

c'est à dire.

depth = gl_FragCoord.z / gl_FragCoord.w;

Bien sûr, cela ne fonctionnera que pour les coordonnées non écrêtées.

Mais qui se soucie de ceux coupés de toute façon?

11
uofc

Vous devez passer la matrice Monde/Modèle en tant qu'uniforme au vertex shader, puis la multiplier par la position du vertex et l'envoyer en tant que variable au fragment shader:

/*Vertex Shader*/

layout (location = 0) in vec3 Position

uniform mat4 World;
uniform mat4 WVP;

//World FragPos
out vec4 FragPos;

void main()
{
 FragPos = World * vec4(Position, 1.0);
 gl_Position = WVP * vec4(Position, 1.0);
}

/*Fragment Shader*/

layout (location = 0) out vec4 Color;

... 

in vec4 FragPos

void main()
{
 Color = FragPos;
}
2
Gerard097