Lumieres
- Un peu de MFC de nouveau avant d'illuminer la scene : pour faire bouger le cube, il est
preferable de temporiser precisement les deplacements. La classe CCube est deja prevue
pour cela (avec Update).
Lorsque l'application n'a plus rien a faire (la file des messages est vide), la fonction
OnIdle de l'application est appelee. Probleme : la classe CWinApp ne peut pas (ou en tout
cas je ne sais pas comment faire) connaitre l'instance CView actuellement affichee. Par
contre la vue peut connaitre son application. Une solution est donc de rajouter a la
classe application un pointeur qui sera initialisee par la vue.
Dans la classe de vue, rajouter :
void * pView;
l'initialiser a NULL dans le constructeur.
Ajouter la fonction OnIdle (ClassWizard), et pour declencher un message OnPaint utiliser
InvalidateRect :
BOOL CTutorialApp::OnIdle(LONG lCount)
{
// TODO: Add your specialized code here and/or call the base class
if (pView)
((CTutorialView
*)pView)->InvalidateRect(NULL, FALSE);
return 1;
}
Dans le constructeur de la classe vue, initialiser pView :
CTutorialView::CTutorialView()
{
// TODO: add construction code here
m_hGLContext = NULL;
m_GLPixelIndex = 0;
((CTutorialApp *)AfxGetApp())->pView = this;
}
Changer OnPaint :
void CTutorialView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
static DWORD last_t = GetTickCount();
DWORD t = GetTickCount() - last_t;
if (t == 0)
return;
last_t = GetTickCount();
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
static CCube c(1, 0, 0, -8, 30, 35, 0, 0, 0, 0, 0.1, 0.2, -0.3);
c.Draw(0, 0, 0);
c.Update(t);
glFlush();
SwapBuffers(dc.m_ps.hdc);
// Do not call CView::OnPaint() for painting messages
}
- Les effets de lumieres sont parametres par deux choses : la source lumineuse et le
materiau d'un objet. Chacun dispose de parametres pour la lumiere ambiante, reflechie...
C'est la meme chose lorsque l'on eclaire un surface rouge avec un lumiere blanche : on la
voit rouge. Si la lumiere est bleue, la surface est noire.
La composante la plus importante pour la lumiere et la surface celle qui caracterise la
lumiere ambiente. Les autres sevrent a donner une impression metallique, plastique ou de
pierre, ou bien pour faire des spots.
Pour parametrer la source lumineuse, utiliser glLight, pour les objets glMaterial (plein
d'explications dans les pages man).
Les effets de spots sont un peu plus difficiles a realiser, il y en a des exemples en
multi-texturing.
Par exemple pour ajouter une lumiere jaune :
void CTutorialView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
GLsizei width, height;
GLdouble aspect;
width = cx;
height = cy;
if (cy==0)
aspect = (GLdouble)width;
else
aspect = (GLdouble)width/(GLdouble)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, aspect, 1, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDrawBuffer(GL_BACK);
glEnable(GL_DEPTH_TEST);
GLfloat ambientProperties[] = {0.8f, 0.8f, 0.08f,
1.0f};
GLfloat positionProperties[] = {2.0f, 2.0f, -2.0f, 0.0f};
glLightfv( GL_LIGHT0, GL_AMBIENT, ambientProperties);
glLightfv( GL_LIGHT0, GL_POSITION, positionProperties);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientProperties);
}
Voila ce que cela donne :
Code source : Tutorial4.zip
Etape precedente Etape suivante