Il suffit de deriver de la classe gk::App pour profiter de la
creation du contexte openGL, de la creation de la fenetre et de la
gestion d'evenements :
class TP : public gk::App
{
public:
TP( ) : gk::App()
{
// specifie le
type de contexte openGL a creer :
gk::AppSettings settings;
settings.setGLVersion(3,3); //
version 3.3
settings.setGLCoreProfile(); // core
profile
settings.setGLDebugContext(); // version debug
pour obtenir les messages d'erreur en cas de probleme
// cree le
contexte et une fenetre
if(createWindow(512, 512, settings) < 0)
closeWindow();
}
}
et de séparer la creation des objets opengl (cf gk::App::init(
)
) de leur utilisation (cf. gk::App::draw( )
).
La methode draw( ) est appelee regulierement pour dessiner une nouvelle image, 60 fois par seconde, par defaut.
La methode update( ) est appellee juste avant draw( ) et permet
d'animer quelquechose avant de le dessiner.
tutorial3.cpp
est un code de depart illustrant une
application tres simple.
Chargez un objet, bigguy.obj
, par exemple, et
affichez-le.
Utilisez le shader par defaut : dFnormal.glsl
// compilation
simplifiee d'un shader program
gk::programPath("shaders");
m_program=
gk::createProgram("dFnormal.glsl");
if(m_program == gk::GLProgram::null())
return -1;
Le shader est pre-configure pour lire la position des sommets sur
l'attribut numero 0...
remarques :
la camera par defaut est placee en (0, 0,
0) et regarde -z (0, 0, -1).
l'objet est centre en (0, 0, 0), conclusion ?
pour le voir, il faut soit le reculer, soit bouger la camera...
Déplacez la camera ou l'objet avec les fleches du clavier, par
exemple.
Modifiez la transformation Model ou View avec gk::Translate( ) ou
gk::RotateY( ).
remarque :
utilisez gk::App::key( const SDL_Keycode ) pour
connaitre l'etat d'une touche du clavier.
le keycode de chaque touche se trouve dans la
doc de sdl2
: SDLK_LEFT, SDLK_RIGHT, SDLK_UP, SDLK_DOWN...
Chargez plusieurs objets, placez-les dans la scene et
affichez-les.
La solution la plus directe consiste a creer un vertex buffer, un
index buffer et un vertex array object par objet.
Conservez egalement une transformation Model pour placer et
orienter l'objet dans la scene.
vous pouvez utiliser les modeles : bigguy.tar.gz
Verifiez que la boite englobante d'un objet est, au moins,
partiellement visible, avant d'afficher l'objet.
indications :
la boite englobante d'un objet est disponible
dans gk::Mesh::bbox
dans quel espace est-il le plus simple de
faire le test de visibilite ?
dans le repere du monde ?
ou dans le repere projectif
de la camera ?
le principe du test de visibilite est toujours
le meme :
si les 8 sommets de la boite englobante de
l'objet sont tous à l'exterieur d'un plan du volume visible,
l'objet ne peut pas etre visible.
construire les 8 sommets d'une boite englobante :
gk::Point vertex[8];
for(int i= 0; i < 8; i++)
{
vertex[i]= bbox.pMin;
if(i & 1) vertex[i].x= bbox.pMax.x
;
if(i & 2) vertex[i].y= bbox.pMax.y;
if(i & 4) vertex[i].z= bbox.pMax.z;
}
rappel : gk::Transform, gk::Point et gk::HPoint
gk::Transform T;
gk::Point q=
T(p); // transforme le
point p et renvoie le point 3d q
gk::HPoint h; T(p, h);
// transforme le point p et renvoie le point homogene h.
La premiere solution utilisee consiste en general a creer un
vertex buffer et un index buffer par chaque objet. Cette
organisation des donnees a une consequence assez directe sur
l'affichage d'un ensemble d'objets :
Cettte solution est tres souple mais egalement la plus lente : pour chaque draw, l'ensemble des buffers est change ainsi que le shader program.pour chaque objet
activer le vertex array de l'objet
{ // ce qui provoque :
activer le vertex buffer de l'objet
activer l'index buffer de l'objet
}
activer le shader program
parametrer le shader program
draw( )
Comment organiser les buffers pour eviter de changer de
buffers/vao a chaque fois ? et obtenir une solution de ce type :
pour chaque objet
parametrer le shader program
draw( )
Quel gain pouvez-vous esperer ? un affichage plus rapide pour le gpu, ou une utilisation cpu moins importante ?
Placez une source lumiere dans la scene. Ecrivez un shader
program permettant de calculer la lumiere reflechie par une
matiere diffuse.
Quelles sont les informations necessaires pour realiser le calcul
dans le fragment shader ? Comment les transmettre aux shaders ?
Memes questions pour une matiere plus reflechissante.
Le principe des shadow maps est tres simple :
1. dessiner les objets de la scene du point de
vue de la source de lumiere, et conserver le zbuffer (la distance
entre la source et le point visible et eclaire),
2. dessiner les objets de la scene du point de
vue de la camera et recalculer leur position par rapport a la
source de lumiere pour verifier s'ils sont eclaires ou pas.
Memes questions que dans la partie precedente, quelles
informations sont necessaires pour realiser chaque etape, comment
les transmettre aux shaders ?
Combien de shader programs sont necessaires ?
Comment "conserver" le zbuffer de l'etape 1 ?
Comment verifier qu'un point de la scene est visible par la source
de lumiere en utilisant le zbuffer de l'etape 1 ? Quelles
transformations doivent etre connues ?
D'ou viennent les differents defauts de cette methode ?