IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

FBO et texture array [OpenGL 3.x]


Sujet :

OpenGL

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut FBO et texture array
    Bonjour,

    dans le cadre de la création d'ombres en 2D avec des sources de lumières multiples, j'ai décidé d'utiliser un texture array 2d pour y stocker toutes les textures d'ombres de chacune de mes sources.
    Mes FBO, eux, vont s'occuper de dessiner dans ces textures.

    J'ai passé pas mal de temps à revoir le code, mais impossible de mettre la main sur l'élément ou les éléments qui posent problème dans mon code, sachant que gDEBugger m'indique des GL_INVALID_FRAMEBUFFER_OPERATION à chaque action effectuée pendant le rendu des FBO sur mes textures.

    Je crée un FBO comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    bool FrameBuffer::load(ng::TextureArray textureArray, int textureId)
    {
    	// Removal of the last frame buffer
    	glDeleteFramebuffers(1, &m_id);
    	glDeleteRenderbuffers(1, &m_depthBufferId);
    	glDeleteTextures(1, &m_textureId);
     
     
    	// Initialization of the frame buffer
    	glGenFramebuffers(1, &m_id);
    	glBindFramebuffer(GL_FRAMEBUFFER, m_id);
     
     
    	/// Initialization of the depth buffer
    	glGenRenderbuffers(1, &m_depthBufferId);
    	glBindRenderbuffer(GL_RENDERBUFFER, m_depthBufferId);
    	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, textureArray.getSize().x, textureArray.getSize().y);
    	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBufferId);
    	glBindRenderbuffer(GL_RENDERBUFFER, 0);
     
     
    	// Initialization of the render buffer
    	glBindTexture(GL_TEXTURE_2D_ARRAY, textureArray.getId());
     
    	glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureArray.getId(), 0, textureId);
    	GLenum buffersToDraw[1] = {GL_COLOR_ATTACHMENT0};
    	glDrawBuffers(1, buffersToDraw);
     
    	glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
    	glBindFramebuffer(GL_FRAMEBUFFER, 0);
     
    	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    	{
    		glDeleteFramebuffers(1, &m_id);
    		glDeleteRenderbuffers(1, &m_depthBufferId);
     
    		ng::logs.saveDebugMessage("ERROR", FUNC_NAME, "Frame buffer initialization failed.");
    		return false;
    	}
     
    	m_size = textureArray.getSize();
    	return true;
    }
    J'initialise mon array de textures comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    std::vector<GLubyte> texels(textureSize.x * textureSize.y * textureCount, 0);
     
    glGenTextures(1, &m_id);
    glBindTexture(GL_TEXTURE_2D_ARRAY, m_id);
    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R8, textureSize.x, textureSize.y, textureCount);
    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, textureSize.x, textureSize.y, textureCount, GL_RED, GL_UNSIGNED_BYTE, &texels[0]);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_2D_ARRAY, 0);

    L'utilisation de tout ça lors du rendu est effectuée comme avec un FBO et une texture "simple".
    Je bind le FBO de la nième texture, je fais le rendu, et je l'unbind ensuite.
    Et pour l'utilisation de la texture (même si pour le moment je pense pas que le problème vienne de là), je bind/unbind l'array texture comme si c'était une simple texture (en oubliant pas d'utiliser un sampler2DArray dans mon shader) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D_ARRAY, textureArrayId);
    glUniform1i(glGetUniformLocation(shader.getId(), "texture0"), 0);
     
    // rendu dans la fenetre
     
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D_ARRAY, 0);

    Si les GL_INVALID_FRAMEBUFFER_OPERATION se produisent, c'est sans doute qu'il y a eu un problème soit lors de la création de l'array texture (mais normalement il est bien créé, il est bien présent dans le viewer de gDEGugger), soit lors de la création du framebuffer.
    Mais en comparant mon code à une tripotée d'autres sur le net, je ne trouve toujours pas ce qui cloche.



    Je vous remercie d'avance pour toute piste que vous pourriez m'apporter.



    PS : j'ai testé sur deux marques de cartes graphiques différentes (Nvidia et AMD), le problème reste le même. Les deux PC sont sous Windows 10.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Première tentative, vous unbindé votre FBO avant de vérifier son état :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    lBindFramebuffer(GL_FRAMEBUFFER, 0);
     
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Tout d'abord, merci de prêter attention à mon problème.

    Effectivement, je n'avais pas fait attention à ça. J'ai donc corrigé cette erreur, et l'intérieur du "if" est bien exécuté. Donc le problème vient bien de l’initialisation du framebuffer.
    Reste à savoir quel est précisément le problème.

  4. #4
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 476
    Points
    11 476
    Billets dans le blog
    11
    Par défaut
    Salut!

    J'aimerais bien voir le code de ton fragment shader, si c'est possible.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Oui bien sûr !
    J'utilise deux shaders, un premier qui met les ombres (polygones noirs) d'une source lumineuse sur une texture.
    Le vertex shader :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #version 330
     
    in vec2 in_position;
     
    uniform mat4 transformationMatrix;
     
    void main()
    {
    	gl_Position = vec4(in_position, 0, 1) * transformationMatrix;
    }
    Le fragment shader :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #version 330
     
    out vec4 finalColor;
     
    void main()
    {
    	finalColor = vec4(0, 0, 0, 1);
    }
    L'autre shader prend les textures d'ombres de chaque source lumineuse, et va les "fusionner" (en multipliant leur intensité) pour donner le rendu d'ombre final. Le rendu est fait sur un rectangle noir prenant tout l'écran, et ce qui va donner de la lumière ça va être le niveau d'alpha.
    Voici le vertex shader :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #version 330
     
    in vec2 in_position;
     
    out vec2 textureVertexPosition;
    out vec2 position;
     
    void main()
    {
    	gl_Position = vec4(in_position, 0, 1);
    	position = in_position;
    	textureVertexPosition = in_position / 2 + vec2(0.5, 0.5);
    }
    Et le fragment shader :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #version 330
     
    in vec2 textureVertexPosition;
    in vec2 position;
     
    uniform sampler2DArray texture0;
     
    uniform float windowSize;
     
    out vec4 finalColor;
     
    layout (std140) uniform Light
    { 
    	vec4 data[1000];
    };
     
     
    void main()
    {
    	float finalLight = 1;
     
    	for (int lightId = 0; lightId < 2; ++lightId)
    	{
    		float color = texture(texture0, vec3(textureVertexPosition, float(lightId))).x;
    		float distanceToLight = distance(data[lightId].xy, position) / (data[lightId].z / windowSize);
     
    		if (distanceToLight < 1 && color > 0.5)
    			finalLight *= distanceToLight;
    	}
     
    	finalColor = vec4(0, 0, 0, finalLight);
    }
    Pour le moment je ne teste qu'avec deux sources lumineuses.

  6. #6
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 476
    Points
    11 476
    Billets dans le blog
    11
    Par défaut
    Est-ce que tu sais exactement à quelle ligne apparaît cette erreur?
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Justement non. Mais je ne pense pas que ça vienne des shaders, ou tout du moins pas dans l'immédiat.
    Pour moi, ça vient du code d'initialisation des framebuffers (le premier code que j'avais posté). Ce qui me fait dire ça, c'est que le test "glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE" est vérifié, ce qui ne doit pas être le cas pour que ça fonctionne.

    D'ailleurs j'avais corrigé légèrement le code d'initialisation des framebuffers, en prenant en compte la remarque de LittleWhite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    bool FrameBuffer::load(ng::TextureArray textureArray, int textureId)
    {
    	// Removal of the last frame buffer
    	glDeleteFramebuffers(1, &m_id);
    	glDeleteRenderbuffers(1, &m_depthBufferId);
    	glDeleteTextures(1, &m_textureId);
     
     
    	// Initialization of the frame buffer
    	glGenFramebuffers(1, &m_id);
    	glBindFramebuffer(GL_FRAMEBUFFER, m_id);
     
     
    	/// Initialization of the depth buffer
    	glGenRenderbuffers(1, &m_depthBufferId);
    	glBindRenderbuffer(GL_RENDERBUFFER, m_depthBufferId);
    	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, textureArray.getSize().x, textureArray.getSize().y);
    	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBufferId);
    	glBindRenderbuffer(GL_RENDERBUFFER, 0);
     
     
    	// Initialization of the render buffer
    	glBindTexture(GL_TEXTURE_2D_ARRAY, textureArray.getId());
     
    	glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureArray.getId(), 0, textureId);
    	GLenum buffersToDraw[1] = {GL_COLOR_ATTACHMENT0};
    	glDrawBuffers(1, buffersToDraw);
     
    	glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     
    	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    	{
    		glDeleteFramebuffers(1, &m_id);
    		glDeleteRenderbuffers(1, &m_depthBufferId);
     
    		ng::logs.saveDebugMessage("ERROR", FUNC_NAME, "Frame buffer initialization failed.");
    		glBindFramebuffer(GL_FRAMEBUFFER, 0);
    		return false;
    	}
     
    	glBindFramebuffer(GL_FRAMEBUFFER, 0);
     
    	m_size = textureArray.getSize();
    	return true;
    }

  8. #8
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 476
    Points
    11 476
    Billets dans le blog
    11
    Par défaut
    Avant de supposer, je te conseille de découvrir quelle ligne exactement provoque l'erreur (un appel à glGetError par appel OpenGL)
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    C'est bon, j'ai trouvé ce qui n'allait pas !

    J'avais deux GL_INVALID_OPERATION, un lors du bind du deuxième framebuffer (mais pas le premier), et un autre lors du bind de ma texture. Quand j'ai retiré le deuxième framebuffer, le GL_INVALID_OPERATION était toujours présent pour la texture. C'est là que j'ai compris d'où ça venait.
    Le problème était en fait que dans ma fonction load qui initialise un FBO, je passe mon TextureArray en tant que valeur et non en tant que référence. La copie en tant que telle se passe bien (l'id de la texture est bien passé), mais c'est quand on sort de la fonction, l'objet de type TextureArray est détruit, et j'ai placé un glDeleteTextures dans le destructeur.
    Cela explique donc l'invalidation du deuxième framebuffer et de la texture.


    Merci beaucoup d'avoir pris le temps de m'aider

  10. #10
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bien joué
    J'osais croire que gDEBugger indiquait les erreurs OpenGL (comme glGetError()) pour chaque appel.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [OpenGL 3.x] Probléme avec les texture array
    Par aigle_biskra dans le forum OpenGL
    Réponses: 7
    Dernier message: 26/08/2015, 16h32
  2. [OpenGL 3.x] Problème d'initialisation avec les textures array
    Par Nikogram dans le forum OpenGL
    Réponses: 6
    Dernier message: 11/05/2014, 13h50
  3. FBO: Depth Texture vide
    Par LastSpear dans le forum OpenGL
    Réponses: 5
    Dernier message: 14/10/2010, 22h17
  4. FBO, et rendu 2D dans texture
    Par Rastacouéne dans le forum OpenGL
    Réponses: 1
    Dernier message: 10/12/2008, 11h44
  5. [FBO+GLSL]rendu dans plus d'une texture à la fois
    Par Kurisu dans le forum OpenGL
    Réponses: 4
    Dernier message: 20/06/2008, 18h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo