Télécharger la version PDF
Transcription
Télécharger la version PDF
U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Objets et rendu Leçon n°3 :définition d'objets élémentaires et rendu élémentaire. Année universitaire 2004-2005 Pascal Mignot [email protected] Couleurs et alpha U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Lors de l'écriture d'un programme DirectX, les couleurs sont déclarées sous forme d'un quadruplet (alpha, rouge, vert, bleu). Types associés: D3DCOLOR (DWORD, 32 bits au format A8R8G8B8) Utilisation: dans le format des sommets, textures, rasterization. D3DCOLORVALUE (structure de 4 floats dont les champs sont r,g,b,a) Utilisation: définition des matériaux, des lampes (ambiante excepté). Qu'est-ce-que le alpha? paramètre supplémentaire pouvant être utilisé pour mélanger des couleurs (dans les étages de texture, à la rasterization). Utilisation classique: comme facteur de transparence (ex: mélange d’une couleur C1 avec une couleur (α,C2) : couleur résultat = (1-α).C1 + α.C2 ). Désignation d'une couleur Utiliser les macros suivantes pour construire une D3DCOLOR: D3DCOLOR_ARGB(a,r,g,b) où r,g,b,a sont des UCHARs (0 à 255). D3DCOLOR_XRGB(r,g,b) où r,g,b sont des UCHARs (0 à 255). D3DCOLOR_COLORVALUE(r,g,b,a) où r,g,b,a sont des floats (0 à 1). Orientation des normales et culling U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E L'ordre dans lesquels les sommets d’une facette sont déclarés a un impact important car il détermine la direction de sa normale. Orientation D3DCULL_CCW 0 2 1 sens inverse des aiguilles d'une montre. Orientation D3DCULL_CW 0 1 2 sens des aiguilles d'une montre. On appelle backface-culling l'action d'effectuer un rejet trivial sur les facettes non visibles (normale non orientée vers l'observateur). Remarque: il est important d'activer le culling si possible (en moyenne, on se débarasse de 50% des facettes). Mode par défaut : D3DCULL_CCW Désactivation: D3DCULL_NONE (les deux faces sont visibles). Comment le changer: avec la méthode SetRenderState du Device exemple: pDEV->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW) Objets élémentaires U N IVERSIT É D E R EIMS définis dans DirectX C H AMP AGN E-A RD EN N E Trois types d'objets élémentaires: • le point (ou sommet) • le segment (ou arête entre deux sommets) • la facette (ou triangle = surface délimitée par 3 sommets + 3 segments). Deux familles d'objets 3D: • Les maillages (meshes) = ensemble de facettes. • Les surfaces de type Bézier ou patches (facettisées pour le pipeline). Ces objets sont basés sur des sommets, et peuvent définis de manière indexée. Exemple: le trièdre. P3 Définition non indexée: Liste des faces = { {P0, P2, P1}, {P0, P1, P3}, {P1, P2, P3} , {P2, P0, P3 } } P0 P2 P1 Définition indexée: Liste des sommets = {P0, P1, P2, P3 } Liste indexée des faces = {{0,2,1} , {0,1,3}, {1,2,3}, {2,0,3}} Rendu d'objets U N IVERSIT É D E R EIMS sous DirectX C H AMP AGN E-A RD EN N E Afin de donner un aspect réaliste aux objets géométriques ou les animer, il faut leurs ajouter des propriétés supplémentaires (couleur, coordonnées dans l’espace de la texture, …). Ces propriétés supplémentaires sont: • attachées aux sommets. • interpolées sur le reste de la facette à partir des valeurs aux sommets. Exemple: couleur d'une facette obtenue par interpolation des couleurs aux sommets. P0 Exemple: définition d'un trièdre indexé avec propriété de couleur: Liste des sommets = { (P0, vert), (P1, rouge), (P2, bleu), (P3, blanc) } Liste indexée des faces = {{0,2,1} , {0,1,3}, {1,2,3}, {2,0,3}} P2 P1 Propriétés d'une facette U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E locale ou globale? Pour des raisons d'efficacité, on souhaiterait: • si une propriété est constante sur un groupe de facette, – à l'initialisation, ne pas attacher la propriété à chaque sommet. – lors du rendu, on fixe la propriété. Le rendu de toutes les facettes qui suivent se fera avec cette propriété. • si la propriété est locale à chaque facette, – à l'initialisation, on définit la propriété en chaque sommet de chaque facette. – lors du rendu, les valeurs dans chaque facette sont interpolées à partir des sommets. Exemple: pour la couleur d'une facette. Approche globale Initialisation: définition des facettes. Rendu: fixer couleur 1. dessiner le groupe 1 de facettes. fixer couleur 2. dessiner le groupe 2 de facettes. … Approche locale Initialisation: définition des facettes. pour chaque sommet, définir la couleur. Rendu: dessiner le groupe 1 de facettes. dessiner le groupe 2 de facettes. … Ces deux approches sont possibles (et non exclusive)! Format de sommet flexible U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E • • • Justification suivant les cas, les différentes propriétés des facettes sont chacune soit locales, soit globales. si une propriété globale est stocké comme une propriété locale, on perd (un peu) de la place mémoire et (un peu) de la bande passante. il n'est pas pratique de gérer une propriété locale de la même façon d'une propriété globale. Conclusion: il est donc intéressant de disposer d'un format de sommet qui soit exactement adapté au contexte. Avantages: pratique, performance, stockage. Ce principe porte le nom de FVF (flexible vertex format). REMARQUE: Il reste possible avec DirectX de ne pas utiliser les propriétés locales même si elles sont définies (et donc d'utiliser des propriétés globales). NOTE : il existe une autre façon de déclarer les formats des sommets (avec des déclarations), mais leurs pleines possibilités n’est utilisable qu’avec des shaders. Les déclarations seront étudiées à ce moment. Format de sommet flexible U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E comment le définir Phase d'initialisation: • créer une structure (au sens struct du C) contenant l'ensemble des propriétés à définir. définit le format utilisé pour stocker les sommets. • définir un masque contenant exactement les champs définis dans cette structure (aussi appelé type du sommet). permet aux fonctions DirectX qui utilisent ce format de savoir quelles sont les propriétés disponibles et où aller les chercher. • disposer de la taille de la structure (au sens sizeof du C). permet aux fonctions de connaître la taille d'un sommet. Phase de rendu: • définir le format de rendu (méthode SetFVF de IDirect3DDevice9). • il est possible de changer de format de rendu au cours d'une même phase de rendu (en général: lent). Format de sommet flexible composition de la structure U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Commentaires: • Position: position du sommet. • RWH: inverse de la coordonnée W (homogène) du sommet (1/W). • Blending Weight Data: poids pour mélanger les transformations sur les sommets. • Vertex Normal: normale au sommet (nécessaire pour lumières). • Diffuse Color: couleur du sommet ou couleur diffuses si lumière. • Specular Color: couleurs spéculaire (si lumière). • Texture Coordinate Set x: coordonnées du sommet dans l'espace de la texture. Format de sommet flexible U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E contraintes sur la structure et exemple Contraintes sur la construction de la structure: 1. Le champ position est obligatoire. 2. Tous les champs doivent apparaître exactement dans cet ordre. 3. Le type des champs doit absolument être respecté aux équivalences de type près*. Par contre, les noms utilisés pour les champs n'ont aucune importance. 4. Le champs "RHW" est incompatible avec le champ "Vertex Normal". 5. Le champs "Vertex Normal" est nécessaire lors de l'utilisation de lumières. Exemples: deux formats de sommets strictement équivalent pour DirectX (il est impossible d'intervertir deux lignes sinon la contrainte 2 n'est plus respectée). struct { float float float DWORD float } VERTEX; x,y,z; b1,b2; nx,ny,nz; diffuse; tu,tv; struct { D3DXVECTOR3 float D3DXVECTOR3 D3DCOLOR float } VERTEX; p; b1,b2; n; diffus; tu,tv; * Par exemple: 3 floats = D3DXVECTOR3, DWORD = D3DCOLOR, 4 floats (Position+RWH) = D3DVECTOR4. U N IVERSIT É D E R EIMS Format de sommet flexible élément du masque définissant le contenu de la structure VERTEX. C H AMP AGN E-A RD EN N E Couleur Géométrie du sommet D3DFVF_DIFFUSE couleur diffuse D3DFVF_XYZ Position D3DFVF_SPECULAR couleur spéculaire D3DFVF_XYZRHW Position + RHW D3DFVF_NORMAL Normale Autre D3DFVF_PSIZE Taille du sommet (particules) Transformation des sommets D3DFVF_XYZBn n=1..5 floats utilisés pour le vertex blending. D3DFVF_LASTBETA_UBYTE4 le dernier de ces floats est utilisé comme un tableau de 4 uchar. Textures D3DFVF_TEXn (où n=1…8) nombre de textures utilisées pour ce sommet. D3DFVF_TEXCOORDSIZEn(p) (où n=1…8, p=1…4) pour la nème texture, utiliser p coordonnées (défaut=2). Exemple (masque et taille associées à l'exemple précédent): VERTEXfmt = D3DFVF_XYZ|D3DFVF_XYZB2|D3DFVF_NORMAL| D3DFVF_DIFFUSE|D3DFVF_TEX1; VERTEXsiz = sizeof(VERTEX); Rendu d'une primitive U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Tableau de sommets et principe d'utilisation Les primitives ou les maillages sont définis par: • un tableau de sommets (+ un tableau de numéros d'index dans le cas indexé). • une option de la fonction de rendu indiquant comment "assembler" ce(s) tableau(x). En pratique, • une zone mémoire est définie dans la mémoire gérée par le périphérique graphique pour contenir ce(s) tableau(x). • cette zone mémoire est insérée dans le flux de sommets pour être traitée par le périphérique graphique. • une fonction de rendu traite alors ce flux avec les options spécifiées. Rendu d'une primitive U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Gestion d'un tableau de sommets (VertexBuffer) Création: d'un objet IDirect3DVertexBuffer9 contenant un tableau de N sommets (méthode de IDirect3DDevice): CreateVertexBuffer(mlen, use, fmt, muse, pptr, NULL) mlen : mémoire à réserver (typiquement N*sizeof(VERTEX)). use: 0 ou flag indiquant que ce buffer est utilisé de façon particulière (cf doc.) fmt: format du FVF. muse: gestion mémoire de la ressource. D3DPOOL_MANAGED ou cf page suivante. pptr: adresse du pointeur contenant le pointeur sur l'objet IDirect3DVertexBuffer9 crée. Méthodes principales de manipulation d'un objet VertexBuffer: • l'écriture ou la lecture (memcpy) doivent se faire "sous protection", car son emplacement mémoire peut changer. Lock(offset,size,pptr,ltype): verrouille la zone mémoire indiquée. offset: décalage (en octets) depuis le début du VertexBuffer. size: taille (en octets) à verrouiller (0 verrouille la totalité). pptr: adresse mémoire à laquelle écriture/lecture seront possibles (position temporaire). ltype: type du verrou: 0 ou cf doc. Unlock(): déverrouille la zone précédement vérrouillé. • tout VertexBuffer crée doit être libéré lorsqu'il n'est plus utilisé et attaché à un flux. Release(): libération des ressources attribuées aux VertexBuffer. Gestion mémoire des ressources U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E où sont stocké mes objets? Utilisation de la mémoire Les données VertexBuffer, IndexBuffer, Texture, Mesh et PMesh sont créés avec un flag de type D3DPOOL_x qui indique dans quelle partie de la mémoire ils doivent être placés. DEFAULT : utiliser la mémoire de type la plus appropriée pour la donnée (en général la mémoire vidéo = mémoire vidéo locale + mémoire AGP). En cas de perte du Device, tous les objets créés dans ce mode doivent être libéré avant le Reset, puis recréés. MANAGED : les données seront automatiquement placées dans la mémoire appropriée lorsque cela sera nécessaire. Mode automatique conseillé. En cas de perte du Device, rien à faire (gestion automatique). SYSTEMMEM : les données sont placés dans la mémoire du système (non accessible par un Device 3D). La perte du Device n’a aucun impact sur ces données. Note: certains autres objets (StencilDepthBuffer, RenderTarget) sont nécessairement créés avec le flag D3DPOOL_DEFAULT (perte du Device à gérer nécessairement à la main). Utilisation générale D3DUSAGE_DYNAMIC : à préciser dans l’usage si le vertex/index buffer doit être remis à jour. Rendu d'une primitive U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E 2 3 4 1 0 5 D3DPT_POINTLIST 2 3 4 1 0 5 utilisation de la primitive lors du rendu En deux étapes (méthode de IDirect3DDevice9), • On indique au flux de sommets l'ensemble des VertexBuffers à charger pour le rendu suivant: SetStreamSource(num,pVB,offset,vsize) num: place dans le flux (en général 0). pVB: pointeur sur un VertexBuffer. offset: décalage (en octets) depuis le début du tableau de sommets. vsize (=sizeof(VERTEX)) taille de la structure FVF utilisée par le VertexBuffer. D3DPT_LINELIST 2 4 0 5 D3DPT_LINESTRIP DrawPrimitive(type,first,nb) type: comment traiter le flux (D3DPT_?) first: numéro d'ordre du premier sommet à traiter. nb: nombre total de primitives à dessiner. 3 4 1 0 5 D3DPT_TRIANGLELIST 4 5 2 3 1 0 D3DPT_TRIANGLESTRIP • On dessine la primitive (traitement du flux) en spécifiant le mode de rendu. 3 1 2 2 3 4 1 0 5 D3DPT_TRIANGLEFAN Rendu d'une primitive U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E exemple du trièdre // Définition FVF struct { D3DXVECTOR3 p; } VERT; const int Vfmt = D3DFVF_XYZ; const int Vsiz = sizeof(VERT); // Variables LPDIRECT3DDEVICE9 pDEV; // initialiser LPDIRECT3DVERTEXBUFFER9 pVB=NULL; // Lors de l'initialisation géométrique (pDEV déjà initialisé) VERT P0={1,1,0}, P1={-1,1,0}, P2={0,-1,0}, P3={0,0,1}; VERT obj[12]={P0,P2,P1, P0,P1,P3, P1,P2,P3, P2,P0,P3}; pDEV->CreateVertexBuffer(12*Vsiz,0,Vfmt,D3DPOOL_MANAGED,&pVB,NULL); void *ptr; pVB->Lock(0,12*Vsiz,&ptr,0); memcpy(ptr,obj,12*Vsiz); pVB->Unlock(); // Lors du rendu pDEV->SetFVF(Vfmt); pDEV->SetStreamSource(0,pVB,0,Vsiz); pDEV->DrawPrimitive(D3DPT_TRIANGLELIST,0,4); // 4 faces Rendu d'une primitive indexée U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Gestion d'un tableau d'index (IndexBuffer) Création: d'un tableau d'index de taille P avec l'aide de la méthode de IDirect3DDevice: CreateIndexBuffer(mlen, use, fmt, muse, pptr, NULL) mlen : mémoire à réserver (typiquement P*sizeof(DWORD)). use: 0 ou flag indiquant que ce buffer est utilisé de façon particulière (cf doc.) fmt: D3DFMT_INDEX16 pour un index 16 bits (short unsigned int) ou D3DFMT_INDEX32 pour un index 32 bits (unsigned int) [capacité à vérifier]. muse: gestion de la mémoire. D3DPOOL_MANAGED ou cf doc. pptr: adresse du pointeur contenant le Direct3DIndexBuffer9 créé. Méthodes principales de manipulation d'un IndexBuffer: • comme pour le VertexBuffer, l'écriture ou la lecture doivent se faire "sous protection". Même noms de méthodes (Lock et Unlock) et même arguments que pour VertexBuffer. • tout IndexBuffer créé doit être libéré. Utiliser Release(). Rendu d'une primitive indexée U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E utilisation de la primitive lors du rendu En trois étapes (méthode de IDirect3DDevice9), • On indique au flux l'ensemble des VertexBuffers à charger pour le rendu suivant avec SetStreamSource. • On indique au flux l'IndexBuffer à utiliser pour le rendu indexé suivant avec SetIndices (commun à toutes les sources): SetIndices(pIB) pIB: pointeur sur un IndexBuffer. • On dessine la primitive indexée en spécifiant le mode de rendu. DrawIndexedPrimitive(type,ioffset,imin,nvert,ifirst,nb) type: comment traiter le flux (D3DPT_?) ioffset: tous les indices sont relatifs à ce décalage (possiblement négatif). imin: valeur du plus petit indice qui sera utilisé. nvert: nombre de sommets utilisés lors de l'appel. ifirst: numéro d'ordre du premier indice à utiliser. nb: nombre total de primitives à dessiner. ensemble des sommets utilisés = ioffset + imin + {0, …, nvert-1} ensemble des indices utilisés = ifirst + {0, …, 3.nb-1} (cas TRIANGLELIST) ATTENTION: cette méthode lance le calcul des transformations sur l’ensemble des sommets dans l’ensemble des indices utilisés. Il faut donc éviter si possible d’appliquer plusieurs fois la même transformation sur un sommet, notamment en: – – limitant autant que possible l’intervalle dans l’IndexBuffer évitant les entrelacements d’objets dans un même VertexBuffer. Rendu d'une primitive indexée U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E exemple du trièdre // Lors de l'initialisation géométrique (pDEV déjà initialisé) VERT obj[4]={{1,1,0},{-1,1,0},{0,-1,0},{0,0,1}}; short unsigned int ind[12]={0,2,1,0,1,3,1,2,3,2,0,3}; void *ptr; pDEV->CreateVertexBuffer(4*Vsiz,0,Vfmt,D3DPOOL_MANAGED,&pVB,NULL); pVB->Lock(0,4*Vsiz,&ptr,0); memcpy(ptr,obj,4*Vsiz); pVB->Unlock(); pDEV->CreateIndexBuffer(sizeof(ind),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pIB,NULL); pIB->Lock(0,sizeof(ind),&ptr,0); memcpy(ptr,ind,sizeof(ind)); // Variables pIB->Unlock(); LPDIRECT3DDEVICE9 pDEV; // à initialiser LPDIRECT3DVERTEXBUFFER9 pVB=NULL; // Lors du rendu LPDIRECT3DINDEXBUFFER9 pIB=NULL; pDEV->SetFVF(Vfmt); pDEV->SetStreamSource(0,pVB,0,Vsiz); pDEV->SetIndices(pIB); pDEV->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,4); Illumination U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E principe Sous DirectX, le calcul d'illumination d'un objet nécessite: • un modèle de rendu (à pipeline graphique fixe, celui de Phong). • la définition de sources de lumière et de leurs propriétés. • la définition des propriétés géométriques et matérielles locales à la surface de l'objet (paramètres du modèle ou issus des textures). Le modèle permet de calculer le résultat de l'interaction entre la lumière et la matière de l'objet. En pratique sous DirectX: • la gestion des sources de lumière doit être activée, et au moins une source de lumière définie (minimum = la lumière ambiante). • la normale à la surface DOIT être intégrée au FVF. • TOUJOURS normaliser les normales placées dans le FVF. • les paramètres matériels de la surface doivent être définis. Remarque: s’il est nécessaire de placer des normales non normalisées dans le FVF, on peut activer la normalisation automatique en changeant l’état D3DRS_NORMALIZENORMALS (TRUE/FALSE) avec la méthode SetRenderState du Device. Illumination U N IVERSIT É D E R EIMS modèle de rendu C H AMP AGN E-A RD EN N E Le modèle de rendu par défaut utilisé par DirectX est une variation classique du modèle de Phong. La luminance réfléchie LR par la surface se calcule comme: LR = { LE + Ca .La + ∑i 123 émission ambiant r r r r n s Ca .L + Cd .L .( N .Li ) + Cs .Li .( N .H i ) s 3 123 142 4 43 4 144244 ambiant diffus 1 44444 4 42444spéculaire 4444 3 a i d i pour chaque source de lumière Pour simplifier, on n'a pas inclut ni le terme d'atténuation, ni le terme de contrôle du lobe (cas du spot). Paramètres (non géométriques) de ce modèle: LE , Ca , Cd , Cs , ns paramètres matériels de la surface Lai , Ldi , Lsi luminance de la ième source. La luminance ambiante. Illumination réflexion spéculaire U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Deux options de SetRenderState (méthode du Device) permettent de contrôler la réflexion spéculaire: • D3DRS_SPECULARENABLE (défaut = FALSE) La réflexion spéculaire doit donc être spécifiquement activée, et si possible, seulement lorsqu'elle est utilisée. • D3DRS_LOCALVIEWER (défaut = TRUE) La formule de calcul du vecteur Hi est: ( ) r r r r r H i = Li + V / Li + V V z – TRUE: V = direction de l'observateur (cas classique, cf figure de gauche). – FALSE: V = parallèle à l'axe z (correct si la projection est orthogonale, approximatif mais plus rapide sinon, cf figure de droite). V z Propriétés matérielles d'une surface structure D3DMATERIAL9 U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Les propriétés matérielles associées à la surface sont décrites dans la structure D3DMATERIAL9 dont les champs sont: Notation Champs Nom Signification LE Emissive couleur émissive intensité lumineuse de la surface si celle-ci est une source de lumière. Ca Ambiant couleur ambiante en général, égale à la couleur diffuse ou gris (scotopique). Cd Diffuse couleur diffuse couleur propre de l’objet (sous une lumière blanche) Cs Specular couleur spéculaire couleur des reflets spéculaires (plastique = blanc, métal = couleur de l’éclat métallique). Power exposant spéculaire largeur de la tache spéculaire (1 = tache large, 30=tache moyenne, 200 = tache ponctuelle). ns Remarques: si la gestion des sources n'est pas active, la définition d’un matériau est sans effet sur la couleur d’un objet (dans ce cas, la couleur utilisée est celle contenue dans le FVF). Propriétés matérielles d'une surface U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E • création et mise à disposition d'une matière cas local: seuls 2 paramètres (Diffuse, Specular) peuvent être intégrés au FVF, la valeur par défaut de tous les autres paramètres est 0 (ou noir). • cas global: en deux étapes: 1. création d'une variable de type D3DMATERIAL9 et remplissage de cette structure. 2. mise à disposition: avec la méthode SetMaterial du Device. Exemple: // Lors de l'initialisation D3DMATERIAL9 mat1; memset(&mat1,sizeof(D3DMATERIAL9),0); // tout à zéro mat1.Diffuse = D3DCOLORVALUE(1,0,0,1); mat1.Specular = D3DCOLORVALUE(1,1,1,1); mat1.Power = 20.0f; // Lors du rendu (avant un Draw). pDEV->SetRenderState(D3DRS_SPECULARENABLE,TRUE); pDEV->SetMaterial(&mat1); Propriétés matérielles d'une surface U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E gestion locale et globale Le mode de gestion se règle avec SetRenderState (méthode de Device): • Par défault, la gestion des matériaux est locale (par sommet). D3DRS_COLORVERTEX (défaut = TRUE) TRUE = gestion par sommet (FVF). FALSE = gestion globale (SetMaterial, valeurs FVF ignorés). • Gestion plus fine: pour chaque caractéristique matérielle d’un objet, on choisit si sa valeur est lue dans le FVF ou dans le matériau actuellement défini: D3DRS_DIFFUSEMATERIALSOURCE définir comment on obtient la couleur diffuse (défaut = D3DMCS_COLOR1). D3DRS_SPECULARMATERIALSOURCE définir comment on obtient la couleur spéculaire (défaut = D3DMCS_COLOR2). D3DRS_AMBIENTMATERIALSOURCE définir comment on obtient la couleur ambiante (défaut = D3DMCS_MATERIAL). D3DRS_EMISSIVEMATERIALSOURCE définir comment on obtient la couleur émissive (défaut = D3DMCS_MATERIAL). en spécifiant la source parmi: D3DMCS_MATERIAL = la lire dans le matériau courant. D3DMCS_COLOR1 = la lire dans la couleur diffuse du FVF. D3DMCS_COLOR2 = la lire dans la couleur spéculaire du FVF. Illumination Généralité U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E DirectX gère: • pour les sources directes: (en provenance d'une source ponctuelle lointaine) sources directionnelles sources ponctuelles spot • pour les sources indirectes: la lumière ambiante. Remarque: les textures, notamment les cartes de luminance (lightmaps) ou les cartes de réflexion (reflexion maps), permettent d'améliorer le modèle de rendu. Illumination U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E activation et lumière ambiante La méthode SetRenderState du Device permet: • D3DRS_LIGHTING (défault=TRUE) d'activer ou de désactiver complètement les calculs d'illumination. note: pour des raisons de performance, l'activation ne doit être faite que lorsqu'elle est nécessaire au rendu. • D3DRS_AMBIENT (défaut=(0,0,0,0)) fixer la couleur de la lumière ambiante (qui est son seul et unique paramètre). Exemple: // Lors de l'initialisation pDEV->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.2,0.2,0.2,1.0)); Illumination structure D3DLIGHT9 U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E La structure de données unique D3DLIGHT9 permet de stocker les caractéristiques d'une source indépendamment de son type. L'ensemble des champs sont toujours définis, qu'ils soient ou non utiles: champs \ type directionnelle ponctuelle spot Type D3DLIGHT_DIRECTIONAL D3DLIGHT_POINT D3DLIGHT_SPOT Diffuse, Specular, Ambient 9 9 9 Position 8 9 9 Direction 9 8 9 Range 8 9 9 Attenuation0, Attenuation1, Attenuation2 8 9 9 Falloff, Theta, Phi 8 8 9 Illumination U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E contenu de la structure D3DLIGHT9 • Diffuse, Specular, Ambient Il est possible de régler indépendament les couleurs diffuse, spéculaire et ambiante (bien que cela soit physiquement absurde). • Position (ponctuel, spot) Attention, la position d'une source est donnée dans le repère global. Les transformation sur le repère global sont sans effet sur la position d'une source. • Direction (directionnelle, spot) Comme pour la position, la direction est donnée dans le repére global et est invariante par transformation. • Range (ponctuel, spot) Distance maximale à laquelle la source est visible. Illumination U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E • contenu de la structure D3DLIGHT9 Atténuation (ponctuel, spot): la fonction d'atténuation utilisée est: f (d ) = 1 a0 + a1.d + a2 .d 2 où a0, a1 et a2 sont les 3 paramètres d'atténuation (Attenuation0, Attenuation1, Attenuation2). Attention: les 3 valeurs par défaut de ces paramètres sont 0, donc f(d)=0, et la source paraîtra inactive. Il est donc absolument nécessaire d'initialiser correctement ces paramètres (exemple: choisir a0=1, a1=0 et a2=0, pour ne pas avoir d’atténuation). • Paramètres du spot (spot) ٛϕ θٛ La luminance: – est enchangée (x1) si on se trouve dans le cône d'ouverture Theta. – est nulle (x0) si on est à l'extérieur du cône d'ouverture Phi. – varie continuement (avec la loi pFalloff) lorsque l'on passe du cône intérieur au cône extérieur (voir cicontre). 1 p0.25 p p4 0 1 Illumination U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E création d'une lumière En trois étapes: 1. Créer une structure D3DLIGHT9 et initialiser ses champs en fonction du type de source souhaité. 2. Affecter la source à un numéro d'index avec la méthode SetLight du Device. SetLight(ind,pLight) ind: numéro d'index affecté à cette source. Ce numéro est compris entre 0 et le nombre maximal de sources gérable par le Device (cf DevCaps.MaxActiveLights, en général 8). pLight: un pointeur sur la structure D3DLIGHT9 initialisée. Si ce numéro est déjà affecté à une source, la nouvelle source remplace la source existante. Si la caractéristique de la lumière change (position, couleur, …), il faut refaire un SetLight. 3. Activer la source avec la méthode LightEnable du Device. LightEnable(ind,bool) ind: numéro d'index de la source à activer/désactiver. bool: TRUE pour l'activer (FALSE pour la désactiver). Attention, si ind n'est affecté à aucune source, une source directionnelle blanche de direction z est crée. Lampes et matériaux U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E accès mémoires aux structures ATTENTION : lorsqu’un SetMaterial(&mat) ou un SetLight(n,&light) est effectué, DirectX continue à faire référence aux structures (mat et light) passées. Conséquences: • n’utiliser qu’une seule structure par matériau ou par lampe (i.e. ne pas réutiliser la même structure pour deux objets différents). • les structures doivent rester un permanence accessibles tant que le matériau ou la lampe associé reste utilisé dans la boucle de rendu, même si son état ne change pas. Notes: • le non-respect de ces règles entraîne des comportements anormaux qui dépendent de la carte graphique utilisée. • ATTENTION: la modification de la structure ne suffit pas pour changer les propriétés de l’objet correspondant et DOIT être suivi du SetMaterial ou SetLight adéquat. • une façon simple de respecter ces règles est de passer toutes les structures concernées en global. U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Illumination Exemple Définition de: • la lumière ambiante. • une source de lumière directionnelle, de couleur blanche, et diffuse. • une source de lumière ponctuelle, sans atténuation, de couleur rouge. Le calcul d'illumination est supposé être nécessaire pour tous les objets. // Lors de l'initialisation des sources D3DLIGHT9 light1,light2; D3DCOLORVALUE Lcolor={1.f,1.f,1.f,1.f}; // source directionnelle memset(&light1,sizeof(D3DLIGHT9),0); D3DVECTOR Ldir={0.f,0.f,1.f}; light1.Type = D3DLIGHT_DIRECTIONAL; light1.Diffuse = Lcolor; light1.Direction =Ldir; // source ponctuelle memset(&light2,sizeof(D3DLIGHT9),0); D3DVECTOR Lpos={10.f,10.f,10.f}; light2.Type = D3DLIGHT_POINT; light2.Position =Lpos; light2.Diffuse = Lcolor; light2.Specular = light2.Diffuse; light2.Range = 100.f; light2.Attenuation0 = 1.f; // Phase de pré-rendu pDEV->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.2f,0.2f,0.2f,1.0f)); pDEV->SetRenderState(D3DRS_SPECULARENABLE,TRUE); pDEV->SetRenderState(D3DRS_LIGHTING,TRUE); pDEV->SetLight(0,&light1); pDEV->SetLight(1,&light2); pDEV->LightEnable(0,TRUE); pDEV->LightEnable(1,TRUE); Lectures et codes U N IVERSIT É D E R EIMS C H AMP AGN E-A RD EN N E Livres: Testud : chapitre 11 et 13 Dempski : chapitre 8,10, et 11. Codes: SDK: Tut02_Vertices Tut04_Lights CodeSampler: cube.cpp Vertex_Buffer.cpp dx9_primitive_types dx9_Lighting dx9_Material