2017-10-12 22 views
0

Après une session Google assez longue, j'en ai assez!Est-il possible d'utiliser gluLookAt avec un Vertex Shader?

J'ai eu une application python/opengl avec quelques simples Quad où j'ai utilisé gluLookAt pour se déplacer sur la scène. Ensuite, j'avais juste besoin d'une texture sur l'un de ces quads, alors j'utilise évidemment un programme de shaders pour ce seul Quad maintenant. Maintenant, quand j'utilise gluLookAt, le Quad avec la Texture ne bouge pas, ce que je peux aussi comprendre.

Maintenant, y a-t-il un moyen d'utiliser la fonction gluLookAt pour travailler avec le programme shader, obtenir la pile de matrice actuelle pour pouvoir alimenter le programme shader ou dois-je réécrire l'application trou et réinventer la fonction glulookup like he did (dans le shader ou sur le CPU)?

EDIT1: j'utilise:

EDIT2 (Ma Solution):

Depuis j'ai ouvert ce fil, certaines choses ont changé, mais avec l'guideance de vous, je réussi à obtenir une solution stable & moderne.

Il y a 3 composants principaux que je dois dessiner. Un champ statique, quelques lignes (pour une meilleure visualisation) et quelques Quads mobiles.

Le champ est maintenant écrit une fois à un VBO dans un tableau. (amélioration majeure par rapport aux commandes de dessin uniques)

Les carrés et les lignes mobiles fonctionnent sur le même principe, mais ils sont dynamiques et doivent être déplacés à chaque image.

Type d'objet Foreach J'ai un programme vertex + fragment shader. Je suis conscient que je ne pourrais en utiliser qu'un seul, mais ce n'est pas comme ça. Chaque matrice (modèle, vue, projection) est affectée à un uniforme qui est ensuite multiplié avec les sommets du VBO dans le vertex shader.

Champ Vertex Shader (Exemple):

#version 330 

uniform mat4 uniform_Model; 
uniform mat4 uniform_View; 
uniform mat4 uniform_Projection; 

in vec3 Quad_Color_Attrib; 
in vec3 Quad_Size_Attrib; 

out vec3 frag_ColorId; 

void main() 
{ 
    // Pass the tex coord straight through to the fragment shader 
    frag_ColorId = Quad_Color_Attrib; 

    // Remember : inverted ! 
    gl_Position = uniform_Projection * uniform_View * uniform_Model * vec4(Quad_Size_Attrib,1); 
} 

Ce que j'ai demandé était pas la bonne façon de le faire.(Combinaison anciens et nouveaux OpenGL) Unfortunatly Je ne peux pas partager le code de trou comme il est, mais je vous trouverez ici tous les codes clés opengl:

Vertex/Fragment Shader Programme Loader:

Link to a gist

Initialize Vertex/Fragment shader (dans ce cas pour le champ)

def init_field(self, p_VertexShaderPath, p_FragmentShaderPath, p_FieldList, p_FieldCount): 
    # ############### Field Shader ############### 

    # Shader Program 
    self.m_FieldShader = LoadShaders(p_VertexShaderPath, p_FragmentShaderPath) 
    glUseProgram(self.m_FieldShader) 

    # VAO 
    self.m_FieldVAO = glGenVertexArrays(1) 
    glBindVertexArray(self.m_FieldVAO) 

    # Field Definition   
    self.m_FieldCount = p_FieldCount 
    t_Vertices = [] 

    for t_FieldNr in p_FieldList: 
     x = p_FieldList[t_FieldNr].m_XPos 
     y = p_FieldList[t_FieldNr].m_YPos 
     cr = p_FieldList[t_FieldNr].m_Color[0]/255 
     cg = p_FieldList[t_FieldNr].m_Color[1]/255 
     cb = p_FieldList[t_FieldNr].m_Color[2]/255 

     t_Vertices.extend([ 
      x - 0.5, y + 0.5, 0.0, cr, cg, cb, # 0----1 
      x + 0.5, y + 0.5, 0.0, cr, cg, cb, # | | 
      x + 0.5, y - 0.5, 0.0, cr, cg, cb, # | | 
      x - 0.5, y - 0.5, 0.0, 0, 0, 0 # 3----2 
     ]) 

    t_FieldVerticesBuffer = numpy.array(t_Vertices, dtype = numpy.float32) 

    # VBO 
    self.m_FieldVBO = glGenBuffers(1) 
    glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO) 
    glBufferData(GL_ARRAY_BUFFER, t_FieldVerticesBuffer.nbytes, t_FieldVerticesBuffer, GL_STATIC_DRAW) 

    # VBO Size Attrib 
    self.m_FieldVerticesAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Size_Attrib") 
    glEnableVertexAttribArray(self.m_FieldVerticesAttrib) 
    glVertexAttribPointer(self.m_FieldVerticesAttrib, 
          3, 
          GL_FLOAT, 
          GL_FALSE, 
          ctypes.sizeof(6*GLfloat), 
          ctypes.c_void_p(0)) 

    # VBO Color Attrib      
    self.m_FieldColorAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Color_Attrib") 
    glEnableVertexAttribArray(self.m_FieldColorAttrib) 
    glVertexAttribPointer(self.m_FieldColorAttrib, 
          3, 
          GL_FLOAT, 
          GL_FALSE, 
          ctypes.sizeof(6*GLfloat), 
          ctypes.c_void_p(12)) 

    # Uniform Locations 
    self.m_Field_ModelMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Model') 
    self.m_Field_ViewMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_View') 
    self.m_Field_ProjectionMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Projection') 

    # Detach Shader & VAO 
    glBindVertexArray(0) # unbind the VAO 
    glUseProgram(0) # Disable shader 

écran Dessin Cycle

Ceci est maintenant juste psydo code:

OpenGLEnv.Clear() 
OpenGLEnv.SetCamera() 
OpenGLEnv.DrawField() 
OpenGLEnv.FlipBuffer() 

Alors SetCamera est le ViewMat mis et ProjectionMat.

def SetCamera(self, camera, zoom_distance): 
    self.m_ViewMat = lookAt(glm.vec3(-camera[0], -camera[1], zoom_distance), # Camera is at (x,x,x), in World Space 
          glm.vec3(-camera[0], -camera[1], -100), # and looks at the origin 
          glm.vec3(0, 1, 0)) # Head is up (set to 0,-1,0 to look upside-down) 
    self.m_ProjectionMat = perspective(45, self.m_AspectRatio, 1, 1000.0) 

Dessiner routine sur le terrain

Avec cette fonction je tirerai les sommets du VBO.

def DrawField(self): 
    glUseProgram(self.m_FieldShader)  # Use shader 

    self.m_ModelMat = glm.mat4(1) # Reset ModelMat 
    # ############################ 
    # 1. Scale   self.ModelMat = scale(self.ModelMat,glm.vec3(10,10,10)) 
    # 2. Rotation  self.ModelMat = rotate(self.ModelMat, self.test, glm.vec3(0,1,0)) 
    # 3. Translate  self.ModelMat = translate(self.ModelMat,glm.vec3(0,0,0)) 
    #################################### 

    glUniformMatrix4fv(self.m_Field_ModelMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ModelMat.value))) 
    glUniformMatrix4fv(self.m_Field_ViewMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ViewMat.value))) 
    glUniformMatrix4fv(self.m_Field_ProjectionMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ProjectionMat.value))) 

    glBindVertexArray(self.m_FieldVAO) 
    glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO) 

    # Draw Field 
    glDrawArrays(GL_QUADS, 0, 4*self.m_FieldCount) 

    # Disable shader and unbind VAO 
    glBindVertexArray(0) 
    glUseProgram(0) 

occasion Librarys:

+4

Je suggère d'utiliser une bibliothèque de maths au lieu d'essayer de bidouiller avec la pile de matrice. [glm] (https://glm.g-truc.net/0.9.8/index.html) pourrait être un bon choix et fournit également une fonction lookat. Pour le reste de votre question: Cela dépend de la version et du profil que vous utilisez. – BDL

+0

Désolé de ne pas le mentionner, je travaille avec Python ^^ Ok vous iriez avec un calcul manuel des Matrices ... Merci pour vos conseils. – noscript

+1

Il existe aussi une version python de glm. S'il vous plaît voir le lien suivant https://github.com/mackst/glm. Il n'est pas aussi complet que GLM mais a les fonctions dont vous avez besoin. –

Répondre

1

Vous pouvez de cide:

  1. Vous pouvez utiliser OpenGL 2, ce qui rend les choses beaucoup plus faciles et signifie pas de programmation de shader mais moins d'efficacité.

  2. Si vous devez dessiner au moins 1000 triangles ou si vous voulez ajouter un effet de bosses ou d'autres effets spéciaux, vous devriez peut-être envisager de créer un shader. Cela signifie:

  3. Ne pas utiliser Python & pyopengl si vous visez un rendement élevé (expérience)

    • Id vous suggère Java et jogl (Ma configuration actuellement). Ensuite, je pourrais vous fournir mon cours de caméra.
  4. Je vais peut-être le port de ma classe de la caméra à Python, mais cela dépend de la classe jogl Matrix4 et ainsi de suite, mais il est facile si pyopengl offre également cette classe d'aide en mathématiques (Matrix4, Quaternion, ...)

EDIT:

Vertex Shader:

#version 330 

uniform mat4 uniform_Transformation; 
uniform mat4 uniform_Modelview; 
uniform mat4 uniform_Projection; 

in vec4 attribute_Position; 
in vec4 texcoords; 

out vec4 texcoords_pass; 

void main(void) 
{ 
    texcoords_pass=texcoords; 
    vec4 transformedPoint=attribute_Position*uniform_Transformation; 
    vec4 toCamera=transformedPoint*uniform_Modelview; 
    gl_Position = vec4(toCamera*uniform_Projection); 
} 

Fragment Shader:

#version 330 

uniform sampler2D tex; 

in vec2 texcoords_pass; 

out vec4 mgl_FragColor; 

void main (void) 
{ 
    vec4 texture_color = texture(tex,texcoords_pass); 
    if (texture_color.w == 0) { 
     discard; 
    } 
    mgl_FragColor=vec4(texture_color.x,texture_color.y,texture_color.z,1.0f); 
} 

A propos des matrices:

  • uniform_Transformation est la matrice de transformation. Il est utilisé pour faire pivoter, mettre à l'échelle, retourner, mettre en miroir et déplacer vos modèles, dans votre cas quads.

  • uniform_Modelview est la matrice de vue. C'est essentiellement l'appareil photo. Il définit comment la caméra est tournée et où elle se trouve.

  • uniform_Projection est la matrice de projection. C'est à propos de la projection de perspective. En savoir plus à ce sujet ici: http://www.songho.ca/opengl/gl_projectionmatrix.html

Espérons que ça aide!

+1

"OpenGL 2 ... signifie pas de shaders" OpenGL 2.0 et 2.1 avaient tous les deux des shaders. – genpfault

+0

Je dois dessiner environ 800 à 1000 Quads avec cette solution.En fait, c'est un environnement 2D sans aucun doute, mais je dois pouvoir me déplacer, zoomer, etc. Il y a un script beaucoup plus grand derrière et cette partie est juste la partie de l'interface graphique, alors changer c'est de la peine ^^ Si j'avais su cela depuis le début Ce serait en C++. Je pense que vous connaissez tous cette chose avec des objectifs changeants ... Il ne semble pas prometteur après un google rapide que pyopengl fournira ce mais peut-être d'autres lib. Maintenant, je dois décider de quelle façon je vais prendre. – noscript

+0

@genpfault Oui, je sais, mais pour GL 2, vous avez des shaders par défaut, vous ne devez pas les faire vous-même. – user7185318