M2PRO - Images
Année 2009-2010
TP 3 - Mon premier shader
Préambule
Téléchargez et installez les libraries objtoy et sdlkit fournies en Annexes.
Configurez également votre éditeur pour compiler les shaders avec shadercc (inclus dans sdlkit)
Vérifiez le bon fonctionnement du sdlkit_testmain et de glsl_testmain.
Documentation :
openGL
Programming Guide
openGL Shading Language Specification
openGL man pages
GLSL quick reference guide
libSDL Programming Guide
Partie 1 : mon premier vertex shader
On souhaite animer un point dont on connait la
position de départ et celle d'arrivée. La solution
consiste à
interpoler (linéairement) la position du point en fonction du temps.
A l'instant t0, le point se trouve en x0, à l'instant t1, le point devra se trouver en x1.
Connaissant t (compris entre 0 et 1), comment déterminer la position x du point ?
Ecrivez le vertex shader permettant de
réaliser cette animation.
Quels paramètres doit connaitre
le shader ? Comment les lui transmettre ?
Ecrivez l'application utilisant le shader.
Voici le vertex shader minimal :
// simple.vsl : vertex shader minimal
void main(void)
{
gl_Position= gl_ModelViewProjectionMatrix * gl_Vertex;
}
Que faut-il ajouter dans l'application pour l'utiliser ?
#include "glsl2.h"
glsl_init()
program= glsl_program_init("simple.vsl", "simple.fsl");
if(program==0)
return -1;
/* active le programme */
glUseProgram(program);
et glsl_quit() à la fin du programme avant sdlkit_quit().
Partie 2 : prise en main
Q1. écrivez un vertex shader qui donne une couleur
constante à tous les sommets qu'il traite. L'application doit
pouvoir modifier la couleur.
Q2. fixez les valeurs des parametres :
quels sont les paramètres transmis par
l'application ?
comment fixer la valeur d'un paramètre float
? mat4 ?
comment transmettre les positions des sommets ?
Q3. faut-il écrire un fragment shader ?
Partie 3 : plus de paramètres
Q1. écrivez un fragment shader qui multiplie la couleur du fragment par une autre fournie par l'application.
remarque : la couleur est utilisée par le pixel shader, comment
transmettre un paramètre a ce type de shader ?
- que faut-il modifier dans l'application (et / ou dans les
shaders) pour transmettre une couleur constante pour tout l'objet ?
- que faut-il modifier dans l'application (et / ou dans les
shaders) pour transmettre une couleur pour chaque sommet ?
Partie 4 : lumière !
Q1. modifiez votre/vos shader/s pour représenter la position d'une
source de lumière ponctuelle ainsi que sa couleur. Faut-il
utiliser un paramètre uniform ? ou un attribut de sommet ?
Q2. calculez la lumière réfléchie par l'objet (cf. TP lancer de rayons) :
La physique fournit une solution simple : selon
l'orientation de la surface sur laquelle le point P se trouve, le point
P ne reçoit pas la même quantité
d'énergie : elle est maximale lorsque la normale au point P est
orientée vers la source de
lumière et décroit proportionnellement au cosinus de
l'angle (entre la normale et la direction de la source) dans les autres
cas. Ce qui se résume à calculer dot(N, L) pour N et L
unitaires, cf. le schema pour l'orientation et la signification des
vecteurs N et L.
- dans quel shader faire le calcul ? y aurait-il des
différences entre le résultat calculé par le
vertex shader et celui obtenu avec un fragment shader ?
- dans quel repère travailler ? pour évaluer dot(N,
L), les 2 vecteurs doivent se "trouver" dans le même
repère, lequel ?
- quelles sont les coordonnées du point P ? dans quel repère ?
- quelles sont les coordonnées de la source de lumière ? dans quel repère ? comment calculer le vecteur L ?
- quelles sont les coordonnées de l'oeil / comment calculer V ? dans quel repère ?
- il faut connaitre la normale de la surface au point P, un point quelconque des triangles dessinés, comment l'obtenir ?
- comment tenir compte de la couleur de la source de lumière
? de la couleur de la matière associée à la
surface ? comment transmettre ces propriétés au(x)
shader(s) ?
Q3. écrire un shader correspondant à l'autre solution
(calculs dans le vertex shader ou calculs dans le pixel shader).
Justifiez les différences.
remarques :
- la matrice MODELVIEW permet de transformer les points du
repère local vers le repère camera,
quelle transformation utiliser pour les normales ?
la solution et les démonstrations sont la : "Normal Transformations"
- openGL fait le travail pour vous : utilisez gl_NormalMatrix.
exemples :
|
|
exemple : éclairage calculé dans un vertex shader
|
exemple : éclairage calculé dans un pixel shader
|
les figures de ce sujet sont issues de : "the Cg tutorial", nvidia.
Annexe : utilitaires
Installation de sdlkit
Téléchargez sdlkit (build 116, mise à jour du 19/01/2009, fonctionne avec les drivers >= 180.11)
créez un répertoire et dézippez l'archive dedans
cd <répertoire>
tar -zxvf sdlkit_latest.tar.gz
make
make install
si vous souhaitez installer les exemples :
créez un répertoire tests dans le répertoire sdlkit et dézippez l'archive dedans
cd tests
tar -zxvf sdlkit_tests_latest.tar.gz
make
Installation de objtoy
Objtoy est fourni avec sdlkit, dans le répertoire ... objtoy.
tar -zxvf objtoy_latest.tar.gz
make
make install
shadercc
Pour compiler vos shaders et vérifier qu'il
n'y a pas d'erreurs de syntaxe et de casts avant
d'éxécuter votre programme complet :
~/local/bin/shadercc -c shader.vsl
Pensez à ajouter #version 120 au début du source des shaders pour détecter le maximum d'erreurs / warnings. shadercc
affiche également la ligne du source correspondant à
l'erreur détectée par le driver et en utilisant le format
d'erreur de gcc, résultat, il s'intègre facilement à un éditeur ...
Démonstration :
Intégration de shadercc dans SciTE
Ouvrez les propriétés utilisateur : menu 'Options', option 'Open User Options File', copiez - collez les lignes suivantes :
# extensions de fichiers reconnues
file.patterns.cpp=*.c;*.cpp;*.cs;*.h;*.hpp;*.fsl;*.vsl
# compilation des shaders glsl
shadercc=shadercc -c $(FileNameExt)
command.compile.*.vsl=$(shadercc)
command.compile.*.fsl=$(shadercc)
Enregistrez le fichier, fermez SciTE, rouvrez-le et
éditez un shader (utilisez une extension .v?? pour un vertex shader et .f?? pour un fragment shader). Dans le menu Tools, l'option Compile est
maintenant disponible (Ctrl-F7). Appuyez ensuite sur F4 pour visualiser
les différentes erreurs (éventuelles, bien sur !).
Intégration de shadercc dans Gedit
Ouvrez le menu Tools / External Tools. Creez un
nouvel outil (bouton new), appelez-le shadercc, il ne reste plus qu'à le
configurer.
Copiez-collez le script suivant dans la zone commande :
#!/bin/sh
$HOME/local/bin/shadercc -c $GEDIT_CURRENT_DOCUMENT_NAME
et sélectionnez les options d'exécution :
input : current
document,
ouput : display in bottom pane,
applicability : all documents
Par contre, gedit n'a pas l'air d'interpréter
les messages d'erreurs ... utilisez plutot scite qui est nettement plus
complet et présente une ergonomie plus efficace ...