2017-10-16 11 views
1

Je m'intéresse à un programme C++ OpengL et des shaders GLSL Vertex et Fragment.Calcul d'un correctif de traduction depuis la position directement dans le shader avec GLSL

Je crée plusieurs instances du même objet. Je dois juste changer la position de l'objet entre les instances.

Voici ce que j'ai fait: Je travaille avec une variable uniforme qui est un tableau de matrice de transformation. Chaque matrice représente une instance d'objet. MVP est également une matrice de transformation, mais MVP est défini par la position, l'orientation et les propriétés de la caméra.

Voici mon vertex shader:

#version 330 core 
    layout(location = 0) in vec3 vertex_position; 
    layout(location = 1) in vec3 vertex_color; 

    uniform mat4 object_positions[20]; 
    out vec3 fragment_color; 
    uniform mat4 MVP; 

    void main() 
    { 
     gl_Position = object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0); 
     fragment_color = vertex_color; 
    } 

Voici ce que je dois faire en C++ programme pour définir les positions des objets:

glm::mat4 object_positions[20]; 
    object_positions[0] = glm::translate(glm::mat4(1), glm::vec3(0.4f,0.2f,0.0f)); 
    object_positions[1] = glm::translate(glm::mat4(1), glm::vec3(0.5f,1.4f,0.0f)); 
    ... 
    object_positions[19] = glm::translate(glm::mat4(1), glm::vec3(-10.6f,0.2f,0.0f)); 
    GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions"); 
    ... 
    glUniformMatrix4fv(object_positions_id, 7, GL_FALSE, glm::value_ptr(object_positions[0])); 

Le vec3 vous voyez comme deuxième argument de GLM :: translate contient la position de chaque objet. Tout fonctionne bien à ce stade.

Ce que je veux faire est de calculer glm :: translte dans shader. Ce que je veux en fait c'est d'envoyer un vec3 au lieu d'un mat4 pour chaque position. Je veux que le GPU calcule la matrice de transformation au lieu du CPU. Tout ce que j'ai essayé ne fonctionne pas.

Merci

+0

Non, il ne fonctionne pas. C'est exactement le même résultat. object_positions devrait être une matrice de transformation dans ce cas, pas une position – Bob5421

+1

Pourquoi voulez-vous une matrice quand il suffit d'ajouter le décalage est beaucoup plus simple et plus rapide? –

+0

Oui c'est une bonne idée mais que dois-je mettre dans w? – Bob5421

Répondre

0

Vous ne pouvez absolument pas faire object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0); (même si les object_positions étaient matrices), car ce serait la traduction après l'application de la matrice de projection.

Si vous ne faites aucune rotation des cas, il n'y a aucune raison de ne pas le faire ce

gl_Position = MVP * vec4(vertex_position + object_positions[gl_InstanceID],1.0); 
1

pour la matrice de transformation OpenGL est juste un tableau à deux dimensions de 16 entrées (en parlant de la matrice 4X4). Dans cette matrice, 13ème, 14ème, 15ème entrée définit votre composant de traduction. Donc, si vous stockez des matrices en rangée majeures de la 4ème rangée, la 1ère et la 2ème entrée doivent être les composantes vectorielles x, y, z que vous envoyez au shader. Vous pouvez créer votre matrice de traduction dans shader de cette façon. S'il vous plaît assurez-vous que si vous avez une matrice principale de ligne, alors pour transformer le sommet, vous devez premultiply par matrice pour voir l'effet de la traduction.

gl_Position = Translation Matrix * gl_Vertex; 

Si votre matrice est une colonne majeure, vous devez la multiplier.

3

A 4 * 4 matrice ressemble à ceci:

c0 c1 c2 c3   c0 c1 c2 c3 
[ Xx Yx Zx Tx ]  [ 0 4 8 12 ]  
[ Xy Yy Zy Ty ]  [ 1 5 9 13 ]  
[ Xz Yz Zz Tz ]  [ 2 6 10 14 ]  
[ 0 0 0 1 ]  [ 3 7 11 15 ] 

En GLSL les colonnes d'un mat4 m; sont traités comme ceci:

vec4 c0 = m[0].xyzw; 
vec4 c1 = m[1].xyzw; 
vec4 c2 = m[2].xyzw; 
vec4 c3 = m[3].xyzw; 

Vous pouvez configurer un mat4 dans le vertex shader comme ceci:

#version 330 core 
layout(location = 0) in vec3 vertex_position; 
layout(location = 1) in vec3 vertex_color; 

out vec3 fragment_color; 
uniform mat4 MVP; 

uniform vec3 object_positions[20]; 

void main() 
{ 
    mat4 posMat = mat4(
     vec4(1.0, 0.0, 0.0, 0.0), 
     vec4(0.0, 1.0, 0.0, 0.0), 
     vec4(0.0, 0.0, 1.0, 0.0), 
     vec4(object_positions[gl_InstanceID], 1.0)); 

    gl_Position = MVP * posMat * vec4(vertex_position,1.0); 
    fragment_color = vertex_color; 
} 


Mais si vous voulez seulement manipuler la position du vertex par un offset, alors vous n'avez pas besoin d'une matrice de transformation.Vous pouvez simplement ajouter le décalage à la position du sommet (à condition que le décalage est un repère cartésien et non une coordonnée homogène, comme dans votre cas):

void main() 
{ 
    gl_Position = MVP * vec4(object_positions[gl_InstanceID] + vertex_position, 1.0); 
    fragment_color = vertex_color; 
} 


Et vous devez mettre en place la uniforme comme celui-ci:

glm::vec3 object_positions[20]; 
object_positions[0] = glm::vec3(0.4f,0.2f,0.0f); 
object_positions[1] = glm::vec3(0.5f,1.4f,0.0f); 
... 
object_positions[19] = glm::vec3(-10.6f,0.2f,0.0f); 
GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions"); 
... 
glUniform3fv(object_positions_id, 20, glm::value_ptr(object_positions[0])); 


Voir plus:

+1

n'est pas 'posMat * vec4 (vertex_position, 1.0)' juste l'équivalent de 'vec4 (object_position [gl_InstanceID] + vertex_position, 1.0)'? – Jherico