Partage
  • Partager sur Facebook
  • Partager sur Twitter

Appliquer une même texture sur deux triangles

Sujet résolu
    16 août 2019 à 16:27:13

    Bonjour,

    J’essaye d’appliquer une texture sur deux triangles.

    Pour se faire, j’ai suivi les tutoriels suivants :

    Lors de l’affichage de mes deux triangles, si j’utilise glDrawArrays(GL_TRIANGLES, 0, 6) j’ai un seul triangle qui s’affiche et si j’utilise glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0) alors aucun triangle s’affiche.

    Vous trouverez mon code complet ci-dessous, je suis à court d’idées alors merci de votre aide.

    #!coding: utf-8
    from __future__ import print_function, division
    
    from OpenGL.GL import *
    from OpenGL.GL import shaders
    import ctypes
    import pygame
    
    from vecutils import * # téléchargez vecutils ici
    
    vertexShader = """
    #version 330 core
    layout (location = 0) in vec3 attrPosition;
    layout (location = 1) in vec3 attrColor;
    layout (location = 2) in vec2 attrTexCoords;
    
    out vec3 vsColor;
    out vec2 vsTexCoords;
    
    void main()
    {
        gl_Position = vec4(attrPosition, 1.0);
        vsColor = attrColor;
        vsTexCoords = attrTexCoords;
    }   
    """
    
    fragmentShader = """
    #version 330 core
    uniform sampler2D texUniform;
    
    in vec3 vsColor;
    in vec2 vsTexCoords;
    
    out vec4 FragColor;
    void main()
    {
        FragColor = vec4(texture(texUniform, vsTexCoords).rgb, 1);
    }
    """
    
    
    NB_POSITION_AXES = 3
    NB_COLOR_AXES = 3
    NB_TEX_COORDS_AXES = 2
    
    vertices1 = farray([
        # positions        # colors         # texture coords
         0.5,  0.5, 0.0,   1.0, 0.0, 0.0,   1.0, 1.0,   # top right
         0.5, -0.5, 0.0,   0.0, 1.0, 0.0,   1.0, 0.0,   # bottom right
        -0.5, -0.5, 0.0,   0.0, 0.0, 1.0,   0.0, 0.0,   # bottom left
        -0.5,  0.5, 0.0,   1.0, 1.0, 0.0,   0.0, 1.0,   # top left 
    ])
    
    indices1 = farray([
        0, 1, 3, # first triangle
        1, 2, 3,  # second triangle
    ])
    
    def createObject(shaderProgram, vertices, indices):
    
        # Create a new VAO (Vertex Array Object) 
        VAO = glGenVertexArrays(1)
        VBO = glGenBuffers(1)
        EBO = glGenBuffers(1)
    
        # Bind the Vertex Array Object first
        glBindVertexArray(VAO)
    
        # Bind the Vertex Buffer
        glBindBuffer(GL_ARRAY_BUFFER, VBO)
        glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(vertices), vertices, GL_STATIC_DRAW)
    
        # Bind the Entity Buffer
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(indices), indices, GL_STATIC_DRAW)
    
        # Configure vertex attribute
    
        # - Position attribute
        glVertexAttribPointer(0, NB_POSITION_AXES, GL_FLOAT, GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)
    
        # - Color attribute
        glVertexAttribPointer(1, NB_COLOR_AXES, GL_FLOAT, GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float)))
        glEnableVertexAttribArray(1)
    
        # - Texture coordinates attribute
        glVertexAttribPointer(2, NB_TEX_COORDS_AXES, GL_FLOAT, GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(6 * ctypes.sizeof(ctypes.c_float)))
        glEnableVertexAttribArray(2)
    
    
        # Texture
        
        texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, texture)
        # Set the texture wrapping parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) # Set texture wrapping to GL_REPEAT (default wrapping method)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        # Set texture filtering parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    
        image = pygame.image.load('images/wall.jpg').convert_alpha()
        imageData = pygame.image.tostring(image, 'RGBA', 1)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.get_width(), image.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData)
        glGenerateMipmap(GL_TEXTURE_2D)
    
        # Unbind the VAO
        glBindVertexArray(0)
    
        # Unbind the VBO
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glDisableVertexAttribArray(0)
        glDisableVertexAttribArray(1)
        glDisableVertexAttribArray(2)
        
        # Unbind the EBO
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
    
        return VAO, texture
    
    def initDisplay(shaderProgram):
        glEnable(GL_DEPTH_TEST)
    
        glUseProgram(shaderProgram)
        textureUniformIndex = glGetUniformLocation(shaderProgram, 'texUniform')
        glUniform1i(textureUniformIndex, 0)
    
    def prepareDisplay():
        glClearColor(0.2, 0.3, 0.3, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    
    def drawObject(shaderProgram, VAO, texture):
    
        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_2D, texture)
    
        glUseProgram(shaderProgram)
        glBindVertexArray(VAO)
        #glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
        glDrawArrays(GL_TRIANGLES, 0, 6)
    
    def display():
        glBindVertexArray(0)
        glUseProgram(0)
    
    def main():
        pygame.init()
        screen = pygame.display.set_mode((800, 600), pygame.OPENGL|pygame.DOUBLEBUF)
    
        shaderProgram = shaders.compileProgram(
            shaders.compileShader(vertexShader, GL_VERTEX_SHADER),
            shaders.compileShader(fragmentShader, GL_FRAGMENT_SHADER))
        
        initDisplay(shaderProgram)
    
        VAO, texture = createObject(shaderProgram, vertices1, indices1)
    
        clock = pygame.time.Clock()
    
        done = False
        while not done:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    done = True
    
            prepareDisplay()
            drawObject(shaderProgram, VAO, texture)
            display()
            pygame.display.flip()
            clock.tick(60)
    
    if __name__ == '__main__':
        try:
            main()
        finally:
            pygame.quit()


    vecutils : https://robertvandeneynde.be/parascolaire/vecutils.py.html

    -
    Edité par loacast 16 août 2019 à 16:28:08

    • Partager sur Facebook
    • Partager sur Twitter
      18 août 2019 à 12:07:31

      Salut,

      J'ai passé un bon moment à chercher les erreurs, mais j'y suis finalement arrivé ! :)

      Tout d'abord, pour glDrawArrays(GL_TRIANGLES, 0, 6), il va utiliser ton VBO qui ne contient que 4 points et non 6. Donc il va trouver les 3 premiers et dessiner le premier triangle puis il va s'arrêter car il n'a qu'un seul point - le 4éme - pour dessiner le deuxième triangle.

      Afin de voir le carré en utilisant glDrawArrays, il faut utiliser un autre mode, comme GL_TRIANGLE_STRIP. Il faudra toutefois intervertir les 2 derniers points de ton array pour voir le carré entier. Teste et tu verras les différents résultats.

      Pour l'utilisation de EBO, tu as définis ton buffer d'indices avec cette fonction farray ! Hors ça doit être des entiers ! Ma solution utilise simplement numpy pour créer le buffer avec les éléments dedans. Il reste un dernier problème, le 4ème argument de glDrawElements. Tu as mis un 0. Hors ça doit être un pointeur c_void_p. Donc soit tu mets c_void_p(0) ou alors tu peux aussi mettre None. ctype convertira None en c_void_p(0). Avec ces deux changements, ça fonctionne.

      Voici mon code. Note qu'étant sous Linux, j'ai du utiliser pygame-2.0.0-dev3 afin de mettre le contexte OpenGL à 3.3. Sans ça je ne peux pas utiliser GLSL 330. Tu es probablement sous Windows qui accepte comme contexte de base une version OpenGL plus haute. Je pense que c'est important de te le dire, ainsi tu sauras que ton code ne fonctionnera pas sous Mac ou Linux tel quel.

      # -*- coding: utf-8 -*-
      
      from __future__ import print_function, division
       
      from OpenGL.GL import *
      from OpenGL.GL import shaders
      import ctypes
      import pygame
      import numpy as np
       
      from vecutils import * # téléchargez vecutils ici
       
      vertexShader = """
      #version 330 core
      layout (location = 0) in vec3 attrPosition;
      layout (location = 1) in vec3 attrColor;
      layout (location = 2) in vec2 attrTexCoords;
       
      out vec3 vsColor;
      out vec2 vsTexCoords;
       
      void main()
      {
          gl_Position = vec4(attrPosition, 1.0);
          vsColor = attrColor;
          vsTexCoords = attrTexCoords;
      }  
      """
       
      fragmentShader = """
      #version 330 core
      uniform sampler2D texUniform;
       
      in vec3 vsColor;
      in vec2 vsTexCoords;
       
      out vec4 FragColor;
      void main()
      {
          FragColor = vec4(texture(texUniform, vsTexCoords).rgb, 1);
      }
      """
       
       
      NB_POSITION_AXES = 3
      NB_COLOR_AXES = 3
      NB_TEX_COORDS_AXES = 2
       
      vertices1 = farray([
          # positions        # colors         # texture coords
           0.5,  0.5, 0.0,   1.0, 0.0, 0.0,   1.0, 1.0,   # top right
           0.5, -0.5, 0.0,   0.0, 1.0, 0.0,   1.0, 0.0,   # bottom right
          -0.5,  0.5, 0.0,   1.0, 1.0, 0.0,   0.0, 1.0,   # top left
          -0.5, -0.5, 0.0,   0.0, 0.0, 1.0,   0.0, 0.0,   # bottom left
      ])
       
      indices1 = np.array([
          0, 1, 2,  # first triangle
          1, 3, 2,  # second triangle
      ], dtype=np.uint32)
       
      def createObject(shaderProgram, vertices, indices):
       
          # Create a new VAO (Vertex Array Object)
          VAO = glGenVertexArrays(1)
          VBO = glGenBuffers(1)
          EBO = glGenBuffers(1)
       
          # Bind the Vertex Array Object first
          glBindVertexArray(VAO)
       
          # Bind the Vertex Buffer
          glBindBuffer(GL_ARRAY_BUFFER, VBO)
          glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(vertices), vertices, GL_STATIC_DRAW)
       
          # Bind the Element Buffer
          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
          glBufferData(GL_ELEMENT_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(indices), indices, GL_STATIC_DRAW)
       
          # Configure vertex attribute
       
          # - Position attribute
          glVertexAttribPointer(0, NB_POSITION_AXES, GL_FLOAT, GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0))
          glEnableVertexAttribArray(0)
       
          # - Color attribute
          glVertexAttribPointer(1, NB_COLOR_AXES, GL_FLOAT, GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float)))
          glEnableVertexAttribArray(1)
       
          # - Texture coordinates attribute
          glVertexAttribPointer(2, NB_TEX_COORDS_AXES, GL_FLOAT, GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(6 * ctypes.sizeof(ctypes.c_float)))
          glEnableVertexAttribArray(2)
       
       
          # Texture
           
          texture = glGenTextures(1)
          glBindTexture(GL_TEXTURE_2D, texture)
          # Set the texture wrapping parameters
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) # Set texture wrapping to GL_REPEAT (default wrapping method)
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
          # Set texture filtering parameters
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
       
          image = pygame.image.load('images/wall.jpg').convert_alpha()
          imageData = pygame.image.tostring(image, 'RGBA', 1)
          glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.get_width(), image.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData)
          glGenerateMipmap(GL_TEXTURE_2D)
       
          # Unbind the VAO
          glBindVertexArray(0)
       
          # Unbind the VBO
          glBindBuffer(GL_ARRAY_BUFFER, 0)
          glDisableVertexAttribArray(0)
          glDisableVertexAttribArray(1)
          glDisableVertexAttribArray(2)
           
          # Unbind the EBO
          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
       
          return VAO, texture
       
      def initDisplay(shaderProgram):
          glEnable(GL_DEPTH_TEST)
       
          glUseProgram(shaderProgram)
          textureUniformIndex = glGetUniformLocation(shaderProgram, 'texUniform')
          glUniform1i(textureUniformIndex, 0)
       
      def prepareDisplay():
          glClearColor(0.2, 0.3, 0.3, 1.0)
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
       
      def drawObject(shaderProgram, VAO, texture):
       
          glActiveTexture(GL_TEXTURE0)
          glBindTexture(GL_TEXTURE_2D, texture)
       
          glUseProgram(shaderProgram)
          glBindVertexArray(VAO)
          glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
          # glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
       
      def display():
          glBindVertexArray(0)
          glUseProgram(0)
       
      def main():
          pygame.init()
      
          pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MAJOR_VERSION, 3)
          pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MINOR_VERSION, 3)
          pygame.display.gl_set_attribute(pygame.GL_CONTEXT_PROFILE_MASK, pygame.GL_CONTEXT_PROFILE_CORE)
          screen = pygame.display.set_mode((800, 600), pygame.OPENGL|pygame.DOUBLEBUF)
       
          shaderProgram = shaders.compileProgram(
              shaders.compileShader(vertexShader, GL_VERTEX_SHADER),
              shaders.compileShader(fragmentShader, GL_FRAGMENT_SHADER))
           
          initDisplay(shaderProgram)
       
          VAO, texture = createObject(shaderProgram, vertices1, indices1)
       
          clock = pygame.time.Clock()
       
          done = False
          while not done:
              for event in pygame.event.get():
                  if event.type == pygame.QUIT:
                      done = True
       
              prepareDisplay()
              drawObject(shaderProgram, VAO, texture)
              display()
              pygame.display.flip()
              clock.tick(60)
       
      if __name__ == '__main__':
          try:
              main()
          finally:
              pygame.quit()





      • Partager sur Facebook
      • Partager sur Twitter
        19 août 2019 à 10:00:40

        Bonjour Dan,

        Vraiment un grand merci, j'étais à des kilomètres de trouver.

        Est-ce que tu peux étayer sur la raison pour laquelle mon code ne fonctionnera que sur Windows. En effet, je vais recevoir bientôt le Raspberry 4 et je souhaiterais faire tourner python avec OpenGL dessus.

        Cdt,

        • Partager sur Facebook
        • Partager sur Twitter
          19 août 2019 à 11:23:34

          Salut,

          Là je m'aventure aussi en terrain moins connu. Par expérience, lorsque tu demandes un contexte OpenGL avec la fonction pygame pygame.display.set_mode((800, 600), pygame.OPENGL|pygame.DOUBLEBUF), tu reçois un context différent dépendant de l'OS. Comme pygame 1.9 est construit sur SDL1.2, tu n'as pas la possibilité de spécifier le contexte désiré.

          Le contexte désiré est un contexte core profile avec la version 3.3 minimum. Sous Windows, je pense que pygame te donne un contexte qui te permet d'obtenir les fonctionnalités de la version 3.3+. Hors sous Mac OS et Linux, je pense que pygame te donne un compatibility profile qui malheureusement ne supporte que la version 3.0 max, à moins que ce ne soit la version 3.2. Plus d'info sur les OpenGL profiles : https://www.khronos.org/opengl/wiki/OpenGL_Context

          pygame est actuellement en train de migrer vers une version 2.0 qui sera basé sur la SDL2.0 Elle permet de spécifier le type de contexte OpenGL et la version requise. Pour l'installer, il suffit de faire python3 -m pip install pygame==2.0.0.dev3 --pre. Cependant c'est une version de développement qui peut foirer à tout moment...

          • Partager sur Facebook
          • Partager sur Twitter
            19 août 2019 à 13:55:35

            Ok, merci, c'est bon à savoir.

            • Partager sur Facebook
            • Partager sur Twitter

            Appliquer une même texture sur deux triangles

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown