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 :

Uniform Buffer Object marche pas


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2008
    Messages : 31
    Par défaut Uniform Buffer Object marche pas
    Bonjour,

    J'ai besoin de passer un tableau de 256 entiers dans la mémoire global de mes shader et je n'y parvient pas.

    J'ai tenté d'utiliser un Uniform Buffer Object.

    EDIT : Voir la totalité 2 post plus bas

    Voila mon code c++ (résumé)
    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
     
    PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = 0;
    PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = 0;
    glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) ctx->getProcAddress("glGetUniformBlockIndex"); // Ok : non nul
    glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) ctx->getProcAddress("glUniformBlockBinding"); // Ok : non nul
    ...
    // p est mon ShaderProgram (il est compilé et linké)
    GLuint uniformIndex = glGetUniformBlockIndex(p.programId(), "perm0");
    ...
    QGLBuffer ubo((QGLBuffer::Type)GL_UNIFORM_BUFFER); // Création du buffer
    ubo.create(); // Retourne true
    ubo.bind(); // Retourne true
    ubo.allocate(256 * sizeof (GLint));
    ubo.release();
    ...
    GLint perm[256];
    initRandomPerm(perm, 256);
    ubo.bind(); // Retourne true
    ubo.write(0, perm, 256 * sizeof (GLint));
    glUniformBlockBinding(p.programId(), uniformIndex, 0);
    ubo.release();
    // ici je dessine des rectangles...
    Et voila le code de mon fichier vertex
    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
     
    #version 140
    in vec2 vertex;
     
    uniform perm0
    {
        int perm[256];
    };
     
    void main(void)
    {
        ...
        int gi0 = perm[(ii + perm[jj]) % 256] % 8; // A partir d'ici je ne peux pas verifier mais d'après le résultat qui est de couleur uniforme, perm ne contient pas les bonnes valeurs
        ...
    }
    Je n'ai plus aucune piste pour résoudre mon problème.
    Un peu d'aide serait la bienvenue.

    A+

  2. #2
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Par défaut
    Bonjours,


    Tu n'a pas fais attention à l'alignement des donnés ... il faut spécifié le std140 sur l'uniforme dans le shader, et tu crée un tableau en C non pas de 256 int mais de 1024 int, dont tu vient modifié simplement les indice 0, 4, 8, ... , 4*N pour que les valeur qui devait être à l'indice N dans le shader.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2008
    Messages : 31
    Par défaut
    Salut,
    Ok pour le std140, par contre l'histoire de 4 je comprends pas d’où sa sort... Et d’ailleurs si je veux maintenant envoyer des vec4 il faut aussi les dupliquer 4 fois ?
    J'ai fait un projet minimal pour essayer de faire fonctionner (au moins une fois) un UBO.
    Mais c'est pas encore sa.

    glwidget.h
    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
    #ifndef GLWIDGET_H
    #define GLWIDGET_H
     
    #include <QtOpenGL/QGLWidget>
    #include <QtOpenGL/QGLShaderProgram>
    #include <QtOpenGL/QGLBuffer>
     
    class GLWidget : public QGLWidget
    {
        Q_OBJECT
     
    public:
        GLWidget(QWidget *parent = 0);
        ~GLWidget();
     
    protected:
        void initializeGL();
        void resizeGL(int w, int h);
        void paintGL();
     
    private:
        QGLShaderProgram *_shader;
        QGLBuffer _uniformBuffer;
    };
     
    #endif // GLWIDGET_H
    glwidget.cpp
    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #include "glwidget.h"
    #include <QDebug>
     
    GLWidget::GLWidget(QWidget *parent)
        : QGLWidget(parent),
          _uniformBuffer((QGLBuffer::Type)GL_UNIFORM_BUFFER)
    {
    }
     
    GLWidget::~GLWidget()
    {
        delete _shader;
    }
     
    void GLWidget::initializeGL()
    {
        _shader = new QGLShaderProgram(context(), this);
        _shader->addShaderFromSourceFile(QGLShader::Vertex, ":/glsl.vert");
        _shader->addShaderFromSourceFile(QGLShader::Fragment, ":/glsl.frag");
        _shader->bindAttributeLocation("vertex", 0);
        _shader->link();
        _shader->bind();
     
     
        const QGLContext *ctx = context();
        PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = 0;
        PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = 0;
        glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) ctx->getProcAddress("glGetUniformBlockIndex");
        glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) ctx->getProcAddress("glUniformBlockBinding");
        if (glGetUniformBlockIndex == 0 || glUniformBlockBinding == 0)
            qDebug("ERROR getProcAddress");
     
        GLuint uniformIndex = glGetUniformBlockIndex(_shader->programId(), "test");
        qDebug() << uniformIndex << (glGetError() == GL_NO_ERROR);
     
        static GLfloat const triangleColors[] = {
            1.0f, 0.0f, 0.0f, 1.0f,
            0.0f, 1.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f, 1.0f
        };
        _uniformBuffer.create();
        _uniformBuffer.bind();
        _uniformBuffer.allocate(triangleColors, 3 * 4 * sizeof (GLfloat));
        glUniformBlockBinding(_shader->programId(), uniformIndex, 0);
        _uniformBuffer.release();
    }
     
    void GLWidget::resizeGL(int w, int h)
    {
        glViewport(0, 0, w, h);
    }
     
    void GLWidget::paintGL()
    {
        glClear(GL_COLOR_BUFFER_BIT);
     
        static GLfloat const triangleVertices[] = {
            0.0,    1.0,   0.0,    1.0,
            -1.0,   0.0,   0.0,    1.0,
            1.0,   -1.0,   0.0,    1.0,
        };
        _shader->setAttributeArray(0, triangleVertices, 4);
     
        _shader->enableAttributeArray(0);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        _shader->disableAttributeArray(0);
    }
    glsl.vert
    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
    #version 150
    in vec4 vertex;
     
    layout(std140) uniform test
    {
        vec4 vertexColor[3];
    };
     
    out vec4 color;
     
    void main(void)
    {
        gl_Position = vertex;
     
        int i = int(vertex.x) + 1;
        color = vertexColor[i];
    }
    glsl.frag
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #version 150
    in vec4 color;
     
    out vec4 fragColor;
     
    void main(void)
    {
        fragColor = color;
    }

  4. #4
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Par défaut
    En vérité, c'est que les cartes graphiques utilisent essentiellement des registres 128bit pour pouvoir faire des opération vectoriel le plus rapidement possible. Donc il faut impérativement aligné sur 128bit les informations dans un uniform buffer. Mais pour des vec4, ce sont 4 float donc 4x32 bit = 128 bit, donc c'est alignement est respecté et le souci disparait tout simplement.

    Voici ci dessous 3 exemples de tableau dans un uniform buffer avec des int, des vec2 et vec4 pour bien montré ce qu'est l'alignement.

    Tableau d'integer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // GLSL
    layout(std140) uniform test
    {
        int IntegerArray[2];
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // chaque lignes représente une zone de 128 bits de l'uniform buffer
     IntegerArray[0] | unused 32 bit | unused 32 bit | unused 32 bit
     IntegerArray[1] | unused 32 bit | unused 32 bit | unused 32 bit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // C/C++
    int Array[2 * 4];
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // chaque lignes représente une zone de 128 bits de l'uniform buffer
     Array[0] | Array[1] | Array[2] | Array[3]
     Array[4] | Array[5] | Array[6] | Array[7]
    Vouala pourquoi lorsque tu créé un tableau d'intèger, il en faut 4x plus, et il faudra utilisé que les multiple de 4. Parce que la dans cet exemple, on voit bienque Array[1], Array[2], Array[3], Array[5], Array[6], Array[7] ne serviront pas.


    Tableau de vec2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // GLSL
    layout(std140) uniform test
    {
        vec2 Vector2Array[2];
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // chaque lignes représente une zone de 128 bits de l'uniform buffer
     Vector2Array[0].x | Vector2Array[0].y | unused 32 bit | unused 32 bit
     Vector2Array[1].x | Vector2Array[1].y | unused 32 bit | unused 32 bit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // C/C++
    float2 Array[2 * 2];
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // chaque lignes représente une zone de 128 bits de l'uniform buffer
     Array[0].x | Array[0].y | Array[1].x | Array[1].y
     Array[2].x | Array[2].y | Array[3].x | Array[3].y
    Là il en faut 2x plus, et il faudra utilisé que les multiple de 2. Parce que la dans cet exemple, on voit bienque Array[1] et Array[3] ne serviront pas.

    Tableau de vec4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // GLSL
    layout(std140) uniform test
    {
        vec4 Vector4Array[2];
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // chaque lignes représente une zone de 128 bits de l'uniform buffer
     Vector4Array[0].x | Vector4Array[0].y | Vector4Array[0].z | Vector4Array[0].w
     Vector4Array[1].x | Vector4Array[1].y | Vector4Array[1].z | Vector4Array[1].w
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // C/C++
    float4 Array[2];
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // chaque lignes représente une zone de 128 bits de l'uniform buffer
     Array[0].x | Array[0].y | Array[0].z | Array[0].w
     Array[1].x | Array[1].y | Array[1].z | Array[1].w
    Là, plus besoin de se soucier d'alignement, car la taille des float4 est de 128 bit.

    EXPLICITATION de float2 et float4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class float2
    {
    public:
        float x, y ;
     
    };
     
    class float4
    {
    public:
        float x, y, z, w ;
     
    };
    En espérant avoir aidé.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Novembre 2008
    Messages : 31
    Par défaut
    Merci beaucoup pour cette explication très détaillée ! J'en demandais pas tant
    Par contre, malheureusement, le code que j'ai posté ne fonctionne pas, en tout cas sur ma carte graphique...
    Si quelqu'un qui utilise Qt pourrait voir si sa fonctionne chez lui ?
    Histoire de savoir si c'est une question de code ou de hardware.

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


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

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 131
    Billets dans le blog
    150
    Par défaut
    Bonjour,

    Citation Envoyé par Aratox Voir le message
    Merci beaucoup pour cette explication très détaillée ! J'en demandais pas tant
    Par contre, malheureusement, le code que j'ai posté ne fonctionne pas, en tout cas sur ma carte graphique...
    Si quelqu'un qui utilise Qt pourrait voir si sa fonctionne chez lui ?
    Histoire de savoir si c'est une question de code ou de hardware.
    Pour le test, pouvez vous donner le projet dans une archive avec le .pro, s'il vous plait.
    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. À la découverte des Uniform Buffer Objects d'OpenGL 3.1
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 0
    Dernier message: 19/07/2014, 21h19
  2. object.equals et arraylist.contains ne marche pas
    Par bobby51 dans le forum Windows Forms
    Réponses: 0
    Dernier message: 10/03/2009, 10h36
  3. affichage dans le front buffers ne marche pas!
    Par jamal24 dans le forum OpenGL
    Réponses: 3
    Dernier message: 22/08/2003, 19h14
  4. Sysdate qui marche pas ??
    Par StouffR dans le forum Langage SQL
    Réponses: 4
    Dernier message: 28/08/2002, 13h23

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