OpenGL


pipeline                        api



création d'objets opengl :


configuration du pipeline :



création d'objets opengl :


buffers :

création des identifiants :
GLuint buffers[];
glGenBuffers(n, buffers);    // generation des identifiants de buffers

glBindBuffer(target, buffer);    // activer un buffer
glBufferData(target, size, data, usage);    // creer un buffer et initialiser son contenu

destruction :
glDeleteBuffers(n, buffers);

activation (cf configuration du pipeline) :
glBindBuffer(target, buffer);

modification d'une partie du contenu du buffer après sa création :
glBindBuffer(target, buffer);    // activer le buffer, si necessaire
glBufferSubData(target, offset, size, data);

copie entre 2 buffers :
glCopyBufferSubData(read_target, write_target, read_offset, write_offset, length);
    éventuellement, on peut activer les buffers sur GL_COPY_READ_BUFFER ou GL_COPY_WRITE_BUFFER, s'il ne sont pas deja actifs, cf glBindBuffer()

adressage virtuel :
void *glMapBuffer(target, access);    // obtient une adresse "cpu" sur le debut du buffer
void *glMapBufferRange(target, offset, length, access);    // obtient une adresse "cpu" sur une region du buffer

glUnmapBuffer(target);    // transfere les modifications apportees au contenu du buffer

glFlushMappedBufferRange(target, offset, length);    // transfere les modifications apportees a une region du buffer, a utiliser avec glMapBufferRange()

textures :

création des identifiants :
GLuint textures[];
glGenTextures(n, textures);    // generation des identifiants de textures

creation d'une texture 1d :
glBindTexture(GL_TEXTURE_1D, texture);    // activer une texture 1d (sur l'unite de texture courante)
glTexImage1D(GL_TEXTURE_1D, level, internal, width, border, format, type, data);

creation d'une texture 2d :
glBindTexture(GL_TEXTURE_2D, texture);    // activer une texture 2d (sur l'unite de texture courante)
glTexImage2D(GL_TEXTURE_2D, level, internal, width, height, border, format, type, data);

creation d'une texture 3d :
glBindTexture(GL_TEXTURE_3D, texture);    // activer une texture 2d (sur l'unite de texture courante)
glTexImage3D(GL_TEXTURE_3D, level, internal, width, height, depth, border, border, format, type, data);

création des versions pre-filtrées / pyramide de mipmaps :
glActiveTexture(GL_TEXTURE0 + unit);    // activer une unite de texture, si necessaire
glBindTexture(target, texture);    // activer la texture sur l'unite de texture, si necessaire
glGenerateMipmap(target);    // construire la pyramide de mipmap

destruction :
glDeleteTextures(n, textures);

activation sur l'unité de texture courante (cf configuration du pipeline) :
glBindTexture(target, texture);

activation d'une texture sur une unité de texture d'indice 'unit' (cf configuration du pipeline) :
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(target, texture);

modification d'une partie du contenu de la texture apres sa creation :
glTexSubImage1D(GL_TEXTURE_1D, level, xoffset, width, format, type, data);
glTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset, width, height, format, type, data);
glTexSubImage3D(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);

samplers :

création des identifiants :
GLuint samplers[];
glGenSamplers(n, samplers);

destruction :
glDeleteSamplers(n, samplers);

paramètres de filtrage :
glSamplerParameter(sampler, name, value);

par défaut, les parametres de filtrage sont configures pour utiliser la pyramide de mipmaps de la texture, cf. glGenerateMipmap() dans la section texture.

activation sur l'unité de texture d'indice 'unit' (cf configuration du pipeline) :
glBindSampler(unit, sampler);

utilisation avec un shader program (cf configuration du pipeline) :
le sampler doit etre parametre et active sur une unite de texture d'indice 'unit', cf glBindSampler()
une texture doit etre activee sur la meme unite de texture, cf. glActiveTexture() et glBindTexture()

GLint location= glGetUniformLocation(program, "sampler");
glUniform1i(location, unit);    // le shader program doit etre actif, cf glUseProgram() ou glProgramUniform().


framebuffers :

creation des identifiants :
GLuint framebuffers[];
glGenFramebuffers(n, framebuffers);

destruction :
glDeleteFramebuffers(n, frambuffers);

activation (cf configuration du pipeline) :
glBindFramebuffer(target, framebuffer);

attacher une texture à un framebuffer :
glFramebufferTexture(target, attachement, texture, level);

vérifier que la configuration du framebuffer est valide :
glCheckFramebufferStatus(target);

vertex array objects :

création des identifiants :
GLuint arrays[];
glGenVertexArrays(n, arrays);

activation (cf. configuration du pipeline) :
          glBindVertexArray(array);

associer un vertex buffer et un attribut du vertex shader  (cf. configuration du pipeline / assemblage d'attributs de sommets ) :
          glBindVertexArray();    // si necessaire
          glBindBuffer(GL_ARRAY_BUFFER, buffer);    // d'autre choix de target sont possibles
          glVertexAttribPointer();
          glEnableVertexAttribArray();

associer un index buffer (cf. configuration du pipeline / assemblage de primitives indexees ) :
          glBindVertexArray();    // si necessaire
          glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);    // d'autre choix de target sont possibles

       

shader objects :

création d'un identifiant :
GLuint shader= glCreateShader(type);   
    avec type GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, etc.

destruction:
glDeleteShader(shader);

compiler un shader :
glShaderSource(shader, count, cstrings, NULL);
glCompileShader(shader);

état de la compilation :
GLint status;
glGetShader(shader, GL_COMPILE_STATUS, &status);
    si status == GL_TRUE la compilation a reussi,
    sinon recuperer les messages d'erreurs et les afficher.

récupérer les erreurs de compilation en cas d'echec :
GLint length;
glGetShader(shader, GL_INFO_LOG_LENGTH, &length);
if(length > 0)
{
    GLchar *log= new GLchar[length];
    glGetShaderInfoLog(shader, length, NULL, log);
    printf("status:\n%s\ncompilation failed.\n", log);
    delete [] log;
}
 

shader programs :

creation d'un identifiant :
GLuint program= glCreateProgram();

destruction :
glDeleteProgram(program);

attacher un shader au program :
glAttachShader(program, shader);

pre-déclarer / imposer l'indice d'un attribut (avant le link) :
glBindAttribLocation(program, index, name);
on peut obtenir le meme résultat en modifiant la déclaration de l'attribut dans le source du vertex shader :
    layout(location= index) in type name;

pre-déclarer / imposer le draw buffer d'un varying du fragment shader (avant le link) :
glBindFragDataLocation(program, index, name);
    on peut obtenir le meme résultat en modifiant la déclaration du varying dans le source du fragment shader :
    layout(location= index) out type name;

glBindFragDataLocationIndexed(program, index, blend_index, name);

transform feedback, déclarer les varyings à enregistrer :
glTransformFeedbackVaryings(program, count, varyings, mode);
    l'ordre des varyings definit leur indexation pour tout le pipeline, par exemple l'index a utiliser pour activer un buffer, cf configuration du pipeline, glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index, ...)

édition des liens (link) des shaders attaches au program :
glLinkProgram(program);


état de l'édition de liens (link) :
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
    si status == GL_TRUE l'edition de liens a reussi,
    sinon recuperer les erreurs et les afficher.

récupérer les erreurs d'édition de liens :
GLint length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
if(length > 0)
{
    GLchar *log= new GLchar[length];
    glGetProgramInfoLog(program, length, NULL, log);
    printf("status:\n%s\nlink failed.\n", log);
    delete [] log;
}

activation (cf configuration du pipeline)
glUseProgram(program);

paramétrer un uniform du shader program (le shader program doit etre actif, cf configuration du pipeline) :
GLint location= glGetUniformLocation(program, "uniform");
glUseProgram(program);    // activer le shader program, si necessaire
glUniformXX(location, value);

paraméter un tableau d'uniforms du shader program (le shader program doit etre actif, cf configuration du pipeline) :
GLint location= glGetUniformLocation(program, "uniforms[0]");
glUseProgram(program);    // activer le shader program, si necessaire
glUniformXXv(location, count, values);

cas particuliers pour les matrices (le shader program doit etre actif, cf configuration du pipeline) :
GLint location= glGetUniformLocation(program, "uniform_mat");
glUseProgram(program);    // activer le shader program, si necessaire
glUniformMatrixXXv(location, 1, transpose, matrix);

    remarque: le booleen  transpose indique qu'il est nécessaire (ou pas) de transposer la matrice au format interne utilisé par openGL,
    ce qui est le cas pour une matrice représentée par float mat[lignes][colonnes];

(GL4) paramétrer un uniform du shader program (le shader program n'a pas besoin d'etre actif sur le pipeline):
glProgramUniformXXX(program, location, value);

(GL4) transform feedback objects :

création :
GLuint feedbacks[];
glGenTransformFeedbacks(count, feedbacks);

destruction :
glDeleteTransformFeedbacks(count, feedbacks);

activation (cf configuration du pipeline) :
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback);




configuration du pipeline :


shader program :

activation :
glUseProgram(program);

déterminer les attributs nécessaires à l'exécution du vertex shader (connaissant leur nom) :
GLint location= glGetAttribLocation(program, name);
    si location < 0, l'attribut n'est pas utilisé par le shader program.

itération sur les attributs réellement utilisés par le vertex shader :
GLint length;
glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &length);
GLchar *name= new GLchar[length];

GLint attribute_count;
glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attribute_count);
for(int index= 0; index < attribute_count; index++)
{
    // recupere les informations sur l'attribut
    GLenum glsl_size= 0;
    GLint glsl_type= 0;
    glGetActiveAttrib(program, index, NULL, length, glsl_size, glsl_type, name);
    GLint location= glGetAttribLocation(program, name);
   
    // glsl_size > 1 pour les tableaux,
    // glsl_type est le type GLSL de l'attribut : GL_FLOAT_VEC3 pour un vec3, par exemple.

    // attention: openGL et GLSL n'utilisent pas la meme convention pour decrire les types, un vec3 correspond a :
    // gl_size= 3
    // gl_type= GL_FLOAT
   
    // on peut maintenant associer l'attribut au contenu d'un vertex buffer :
    glVertexAttribPointer(location, gl_size, gl_type, GL_FALSE, stride, offset);
    glEnableVertexAttribArray(location);
}

delete [] name;

assemblage d'attributs de sommets :

associer un buffer à un attribut utilisé par le shader program :
GLint location= glGetAttribLocation(program, name);
    ou parcourir les attributs utilisés par le program.

glBindVertexArray(array);    // selectionne le vertex array contenant l'association attribut / buffer
glBindBuffer(GL_ARRAY_BUFFER, buffer);    // selectionne le buffer contenant les donnees
glVertexAttribPointer(location, size, type, normalized, stride, offset);    // associe le buffer a l'attribut et indique comment interpreter le contenu du buffer
glEnableVertexAttribArray(location);    // active l'utilisation du buffer
glDisableVertexAttribArray(location);    // desactive l'utilisation du buffer

les paramètres size, type permettent d'interpréter le contenu du buffer. attention : ce sont les representations openGL, pas GLSL !
les paramètres stride, offset permettent d'itérer sur le contenu du buffer selectionné par le glBindBuffer.

cf exemples d'utilisation complet : exemple1, exemple2


selection d'un ensemble d'attributs (déja configurés) :
glBindVertexArray(array);

remarque: un vertex array peut aussi conserver un index buffer:
glBindVertexArray(array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);

assemblage d'attributs d'instances :

associer un buffer à un attribut d'instance utilisé par le shader program :
    GLint location= glGetAttribLocation(program, name);
        ou parcourir les attributs utilisés par le program.

    glBindVertexArray(array);    // selectionne le vertex array contenant l'association attribut / buffer
    glBindBuffer(GL_ARRAY_BUFFER, buffer);    // selectionne le buffer contenant les donnees
    glVertexAttribPointer(location, size, type, normalized, stride, offset);    // associe le buffer a l'attribut et indique comment interpreter le contenu du buffer
    glEnableVertexAttribArray(location);    // active l'utilisation du buffer
    glVertexAttribDivisor(location, 1);    // spécifie que l'attribut est lié à une instance


    c'est la meme chose que pour les attributs de sommets, seul glVertexAttribDivisor(..., 1) permet de differencier un attribut d'instance.

assemblage de primitives non indexées + exécution du pipeline :

glBindVertexArray(array);    // selectionne un ensemble d'attributs et de buffers deja configure, cf assemblage d'attributs de sommets.
glDrawArrays(primitive_mode, first, count);

exemple complet:

GLuint position_buffer;    // identifiant d'un buffer contenant les positions des sommets
GLuint program;            // identifiant d'un shader program. le vertex shader declare un attribut: in vec3 position;

GLuint buffers;            // identifiant d'un vertex array

int init( ) {
    ...
    glGenVertexArrays(1, &buffers);
    glBindVertexArray(buffers);

    GLint location= glGetAttribLocation(program, "position");
    if(location < 0)
        return "erreur l'attribut n'existe pas."

    glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
    glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(location);

    // nettoyage
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);    // desactiver le vertex array avant, sinon on modifie son etat.
    ...
}

int draw( ) {
    glUseProgram(program);
    ...
    glBindVertexArray(buffers);
    glDrawArrays(GL_TRIANGLES, 0, count);

    // nettoyage
    glBindVertexArray(0);
    glUseProgram(0);
    ...
}

assemblage de primitives indexées + exécution du pipeline :

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);    // selectionne un ensemble d'attributs et de buffers deja configure, cf assemblage d'attributs de sommets.
glBindVertexArray(array);
glDrawElements(primitive_mode, count, type, offset);
    type est souvent GL_UNSIGNED_INT, les indices sont non signés et GL_INT n'est pas utilisable.

exemple complet:

GLuint position_buffer;    // identifiant d'un buffer contenant les positions des sommets
GLuint index_buffer;       // identifiant d'un buffer contenant les indices des triangles
GLuint program;            // identifiant d'un shader program. le vertex shader declare un attribut: in vec3 position;

GLuint buffers;            // identifiant d'un vertex array

int init( ) {
    ...
    glGenVertexArrays(1, &buffers);
    glBindVertexArray(buffers);

    GLint location= glGetAttribLocation(program, "position");
    if(location < 0)
        return "erreur l'attribut n'existe pas."

    glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
    glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(location);
   
    // associe egalement l'index buffer au vertex array
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
   
    // nettoyage
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);            // desactiver le vertex array avant, sinon on modifie son etat.
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);    // desactiver le vertex array avant, sinon on modifie son etat.
    ...
}

int draw( ) {
    glUseProgram(program);
    ...
    glBindVertexArray(buffers);
    glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);

    // nettoyage
    glBindVertexArray(0);
    glUseProgram(0);
    ...
}

visibilité des primitives :

glEnable(GL_CULL_FACE);    // active le test de visibilite des primitives
glDisable(GL_CULL_FACE);    // desactive le test de visibilite des primitives
glCullFace(mode);    // configure le test de visibilite des primitives
glFrontFace(mode);    // indique quelle orientation conserver / eliminer

fragmentation :

glPolygonMode( )    // remplir les primitives (GL_FILL), ne dessiner que les aretes (GL_LINE) ou que les sommets (GL_POINT)

tests et mélange :

activer / desactiver l'écriture des composantes r, g, b, a, z dans le framebuffer :
glColorMask(r, g, b, a);    // active / desactive l'ecriture des composantes r, g, b, a dans le framebuffer
glColorMaski(index, r, g, b,a);    // active / desactive l'ecriture des composantes r, g, b, a dans le drawbuffer 'index' du framebuffer

glDepthMask(flag);    // active / desactive l'ecriture du z / de la profondeur dans le framebuffer

glEnable(GL_DEPTH_TEST);    // active / desactive le test de visibilite sur le z / la profondeur
glDepthFunc(GL_LESS);    // configure le test de profonduer utilise

activer / desactiver le mélange entre les varyings du fragment shader et le contenu du framebuffer :
glEnable(GL_BLEND);    // active / desactive le melange des couleurs du fragment avec le pixel du framebuffer
glBlendColor(red, green, blue, alpha);    // configure le melange

glBlendFunc(sfactor, dfactor);    // configure le melange
glBlendFuncSeparate(sRGB, dRGB, sAlpha, dAlpha);    // configure le melange pour les composantes rgb et alpha

glBlendEquation(mode);    // configure le melange
glBlendEquationSeparate(modeRGB, modeAlpha);    // configure le melange pour les composantes rgb et alpha

framebuffer :

dessiner dans un framebuffer :
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);

dessiner dans le framebuffer par defaut (cree lors de la creation du contexte / de la fenetre de l'application) :
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

sélectionner quels buffers / textures du framebuffer sont modifiés par l'éxecution du pipeline :
glDrawBuffers(count, buffers);   
    buffers est un tableau de constantes GL_NONE ou GL_COLOR_ATTACHMENT0 + index permettant d'associer un varying du fragment shader à une texture attachee au framebuffer, si un framebuffer est actif, cf glBindFramebuffer.

effacer le framebuffer :
glClear(buffer_flags);    // efface les buffers du framebuffer actif
glClearBuffer(buffer_type, drawbuffer, value);    // efface un seul type de buffer (color, depth, stencil) du framebuffer actif

glClearColor(r, g, b, a);    // couleur utilisee pour effacer les buffers
glClearDepth(depth);    // profondeur utilisee pour effacer les zbuffers

transform feedback :

sélectionner les buffers utilisés pour enregistrer les varyings :
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index, buffer);
    index est la position du varying dans la liste de varyings déclarée lors de l'édition de lien du shader program, cf glTransformFeedbackVaryings()

commencer le transform feedback :
glBeginTransformFeedback(primitive_mode);
    primitive_mode doit correspondre au type de primitives émises par le geometry shader, ou GL_POINTS s'il n'y a pas de geometry shader dans le shader program actif.

arreter :
glEndTransformFeedback( );

(GL4) activer / desactiver l'enregistrement 'auto' du nombre d'éléments stockés dans les buffers par le transform feedback :
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback);    // activer
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);    // desactiver

(GL4) dessiner les primitives stockées dans les buffers par le transform feedback
(plus efficace que la version GL3 qui nécessite une requete et une synchronisation entre cpu et gpu) :

glDrawTransformFeedback(primitive_mode, feedback);
    primitive_mode est le meme que pour glDraw(),
    le nombre de primitives dessinées est stocké dans l'objet feedback qui etait actif lors de l'enregistrement dans les buffers :

exemple:
// activer les buffers pour stocker le resultat
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index, buffer);
...

GLuint feedback;
glGenTransformFeedback(1, &feedback);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback);
glBeginTransformFeedback(primitive_mode);
    glDrawXXX();    // dessiner quelquechose
glEndTransformFeedback();

// activer buffer comme 'source' de donnees / d'index, etc.
glBindBuffer(XXX, buffer);
glDrawTransformFeedback(primitive_mode, feedback);

unités de textures :

activer une unité 'index' :
glActiveTexture(GL_TEXTURE0 + index);

activer une texture sur l'unité de texture active :
glBindTexture(target, texture);

activer un sampler / paramètres de filtrage sur une unité de texture 'index' :
glBindSampler(index, sampler);

associer une unité de texture à un sampler du shader program :
GLint location= glUniformLocation(program, "sampler");
glUseProgram(program);    // active le program, si nécessaire
glUniform1i(location, unit);    // le shader program doit etre actif, cf glUseProgram() ou utiliser glProgramUniform().