Lesson 1 : Basics

Le but de ce cours est de rafraichir la mémoire de l’étudiant avant de démarrer l’implémentation d’algorithmes plus complexes. Vous découvrirez le code qui servira de base aux exercices, et vous redécouvrirez la soumission de géométrie à l’API, une technique simple d’instanciation, et trois des 6 étapes programmable du pipeline.

Exercice 1 : OpenGL

1) Consultez les documents de la section “OpenGL Essentials” de la bibliographie.

Au début de certains exercices vous trouverez la liste des fonctions OpenGL nécessaires. Habituez vous à consulter la documentation pour chaque nouvelle fonction.

2) Identifiez la version d’OpenGL supportée par votre machine.
Sous Linux vous pouvez utiliser la commande glxinfo. Sur Windows, rendez vous dans le panneau de configuration du driver. Pour MacOSX, consultez la documentation, chaque version de MacOSX utilise une implémentation particulière.

3) Identifiez toutes les parties programmable du pipeline OpenGL. Quelles sont les deux principales parties qui ne sont pas programmables?

4) OpenGL est encore très largement une machine à états. Qu’entend-on par là?

Exercice 2 : Code Template

1) Suivez les instructions pour récupérer le code de base. Vérifier que la compilation s’effectue correctement.

2) Parcourez le fichier aogl.cpp ainsi que les fichier aogl.vert et aogl.frag.

Repérez la boucle de rendu, le code de chargement des shaders, ainsi que les fonctions de base du toolkit d’interface graphique imgui.

Exercice 3 : Vertex Buffer Objects et Vertex Array Objects


glGenBuffers, glBindVertexArray, glBindBuffer, glEnableVertexAttribArray, glVertexAttribPointer, glBufferData, glDrawElements

1) Observez les deux codes suivants. Quel objets décrivent ces deux codes? A quoi servent chacun des tableaux ?

2) Affichez le premier objet à l’écran.

Voici un exemple de code pour initialiser et rendre le premier des deux objets, modifiez le code pour rendre les deux objets. Identifiez quelles parties du code sont de l’ordre de l’initialisation, et quelles parties doivent être exécutées à chaque rendu.

Familiarisez vous avec le système de caméra.

3) Affichez le second objet à l’écran.

4) A fin d’y voir plus clair, modifiez les shaders pour passez les positions, les normales, et les coordonnées uvs du vertex shader vers le fragment shader et affichez les successivement.

uv

5) Observez l’utilisation de la matrice MVP. De quelles matrices est-elle composée? Quels sont les espaces dans lesquels la géométrie est successivement transformée?

Exercice 4 : Vertex Shader

glProgramUniform1f, glGetUniformLocation

1) Passer un uniform contenant le temps et utiliser cette variable pour animer votre object directement dans le vertex shader.

Code C :

Code glsl :

2) Modifiez le vertex shader pour que les objets tournent sur eux-mêmes.

3) Utilisez la variable glsl builtin gl_VertexID pour n’animer qu’une partie de l’objet.

anim

4) Quelle est la différence entre un uniform et un vertex attribute ?

Exercice 5 : Instanciation

1) Utilisez l’instanciation pour rendre plusieurs cubes.
Remplacez un des deux appels glDrawElements par un appel à glDrawElementsInstanced.

Utilisez la variable builtin du Vertex Shader gl_InstanceID, pour discriminez les instances entre elle et modifier leur position.

2) Faites en sorte que chacun de ces cubes soit animé différemment.
instanced

Exercice 6 : Fragment Shader

1) Générez procéduralement une texture.

Utilisez les fonctions mathématiques accessibles en glsl (c.f. reference card) et particulièrement :
sin(), cos(), abs(), int(), pow(), exp()

Essayez d’approcher le résultat de l’image ci-contre, ou bien créez votre propre motif.

procedural

2) Animez votre texture.

Exercice 7 : Textures


glGenTextures, glActiveTexture, glBindTexture, glTexImage2D, glTexParameteri

1) Affichez une texture issue d’un fichier sur la surface des objets.

Utilisez la fonction stbi_load pour charger les images présentes dans le dossier textures :

Créez une texture OpenGL et chargez les données de l’image :

Créez un uniform de type Sampler2D et passez lui 0.

Selectionnez la texture pour le rendu :

Dans le fragment shader, lisez la texture via le sampler2D :

2) Affichez une seconde texture, puis combinez les deux textures.

Utilisez les unités de textures pour combiner les deux textures dans le fragment shader.

N’oubliez pas de passer le numéro de l’unité de texture à chaque sampler2D.

texture

3) Activez le filtrage trilinéaire

Le filtrage trilinéaire consiste a utiliser un filtrage des textures sur trois dimensions. La troisième dimension est constituée par un tableau de textures similaires à la texture courante mais à des résolutions différentes, on appelle ces niveaux de résolutions des mipmaps.

On modifie d’abord la fonction de filtrage GL_TEXTURE_MIN_FILTER

On demande ensuite à l’API de calculer les mipmaps en utilisant glGenerateMipmap.

Il est possible de calculer soit-même les niveaux de détails de la texture, ou bien d’utiliser un format qui les supporte nativement (dds, exr, tx), auquel cas on utilisera plutôt des appels successifs à glTexImage2D en changeant le paramètre level.

Ces  fonctions s’appliquent sur la texture 2d courante.

Exercice 8 : Illumination basique

1) Implémentez une illumination diffuse.

Blinn_Vectors

On peut calculer l’illumination diffuse en multipliant la couleur de la surface par le produit scalaire de la normale n et du vecteur normalisé partant de la surface vers la lumière l : n.l

Soit en glsl :

Passez la normale du vertex shader au fragment shader, attention si vous avez animé votre géométrie, vous devez peutêtre animer la normale. Quelles opérations doivent être reportée sur la normale?

Passez ensuite la position de la lumière en uniform et construisez le vecteur l.

2) Implémentez une illumination speculaire de type BlinnPhong.

Le calcul du lobe spéculaire dépend du point de vue, vous avez donc besoin du vecteur v normalisé partant de la surface et vers la caméra. On calcule le half-vector, qui est le vecteur median entre l et v. Comment allez vous calculer v? Vous pouvez utiliser l’espace monde ou caméra pour ce calcul, lequel est le plus simple?

Utilisez la seconde texture comme specularColor, et passez en uniform le specularPower entre 0 et 100.

basic

Exercice 9 : Geometry shader

1) Ajoutez une etape de geometry shader à votre code

Compilez le shader suivant et ajoutez le au link. Modifiez le code pour que le résultat ne change pas.

2) Utilisez la variable gl_PrimitiveIDIn pour animer séparément les triangles composant vos objets.

geometry

Student work

 

Leave a Reply